├── .babelrc ├── .dockerignore ├── .eslintrc ├── .gitignore ├── .stylelintrc ├── Dockerfile ├── LICENSE ├── README.md ├── bin ├── extract_lang.sh ├── gettext.zip └── po2json.sh ├── docs ├── CHANGES.md ├── ROADMAP.md ├── basic │ └── README.md ├── design(architecture) │ └── structure.md ├── readme.md └── styleguide │ ├── concepts.md │ ├── js.md │ ├── react.md │ └── readme.md ├── favicon.ico ├── lang ├── en.json ├── en.po ├── messages.pot ├── ru.json └── ru.po ├── nightwatch ├── nightwatch.conf.js ├── package.json ├── server.js ├── src ├── actions │ ├── entity │ │ ├── entity.spec.js │ │ └── index.js │ ├── users │ │ ├── index.js │ │ └── users.spec.js │ └── view │ │ ├── index.js │ │ └── view.spec.js ├── assets │ ├── normalize.css │ └── typography.css ├── components │ ├── Charts │ │ └── Chart │ │ │ ├── Chart.css │ │ │ ├── Chart.js │ │ │ └── index.js │ ├── Editor │ │ ├── Editor.css │ │ ├── Editor.js │ │ └── index.js │ ├── FontIcon │ │ ├── FontIcon.css │ │ ├── FontIcon.js │ │ ├── images │ │ │ └── logout.svg │ │ └── index.js │ ├── Forms │ │ └── renders.js │ ├── Message │ │ ├── Message.css │ │ ├── Message.js │ │ └── index.js │ ├── Spinner │ │ ├── Spinner.css │ │ ├── Spinner.js │ │ └── index.js │ ├── ViewStateWrapper │ │ ├── ViewStateWrapper.css │ │ ├── ViewStateWrapper.js │ │ └── index.js │ ├── Widget │ │ ├── Widget.css │ │ ├── Widget.js │ │ └── index.js │ └── common │ │ ├── AppBar │ │ ├── AppBar.js │ │ ├── AppBar.spec.js │ │ └── index.js │ │ ├── Button │ │ ├── Button.js │ │ ├── Button.spec.js │ │ └── index.js │ │ ├── Checkbox │ │ ├── Checkbox.js │ │ └── index.js │ │ ├── FontIcon │ │ ├── FontIcon.js │ │ └── index.js │ │ ├── Input │ │ ├── Input.js │ │ └── index.js │ │ ├── Menu │ │ ├── Menu.js │ │ └── index.js │ │ └── Navigation │ │ ├── Navigation.js │ │ ├── Navigation.spec.js │ │ └── index.js ├── config │ └── config.js ├── constants │ ├── Api.js │ ├── Constants.js │ ├── Delays.js │ ├── EntityTypes.js │ ├── MappersTypes.js │ ├── Pages.js │ └── ViewStates.js ├── containers │ ├── App │ │ ├── App.css │ │ ├── App.js │ │ ├── components │ │ │ └── HeaderBar │ │ │ │ ├── HeaderBar.css │ │ │ │ ├── HeaderBar.js │ │ │ │ ├── components │ │ │ │ └── Logo │ │ │ │ │ ├── Logo.css │ │ │ │ │ ├── Logo.js │ │ │ │ │ ├── img │ │ │ │ │ └── logo.png │ │ │ │ │ └── index.js │ │ │ │ └── index.js │ │ └── index.js │ ├── Root │ │ ├── DevTools.js │ │ ├── Root.dev.js │ │ ├── Root.prod.js │ │ └── index.js │ └── pages │ │ ├── AppsPage │ │ ├── AppsPage.js │ │ └── index.js │ │ └── AuthenticationPage │ │ ├── AuthenticationPage.js │ │ ├── components │ │ └── LoginForm │ │ │ ├── LoginForm.css │ │ │ ├── LoginForm.js │ │ │ └── index.js │ │ └── index.js ├── i18n │ ├── Provider.js │ ├── Tools.js │ └── index.js ├── index.dev.html ├── index.html ├── index.js ├── mappers │ ├── apps.js │ └── users.js ├── mockApi │ ├── CALL_MOCK_API.js │ ├── index.js │ └── middleware.js ├── reducers │ ├── dataLayout.js │ ├── entityReducers │ │ ├── index.js │ │ └── users.js │ ├── index.js │ ├── routing.js │ └── view.js ├── routes.js ├── sagas │ ├── entitie.js │ └── sagas.js ├── schemas │ ├── app.js │ └── authUser.js ├── selectors │ ├── apps.js │ ├── users.js │ └── view.js ├── store │ ├── commonMiddlewares.js │ ├── configureStore.dev.js │ ├── configureStore.js │ └── configureStore.prod.js ├── styles.css ├── uiTheme │ ├── media.js │ ├── pallete.js │ └── sizes.js └── utils │ ├── analytic.js │ ├── authWrappers.js │ ├── dom │ └── scrollUtils.js │ ├── forms │ └── validation.js │ ├── localStorageUtils.js │ ├── schemaUtils.js │ └── userUtils.js ├── test ├── e2e │ └── runTest.js └── testHelper.js ├── testserver.js ├── vendorModules └── flot │ ├── API.md │ ├── CONTRIBUTING.md │ ├── FAQ.md │ ├── LICENSE.txt │ ├── Makefile │ ├── NEWS.md │ ├── PLUGINS.md │ ├── README.md │ ├── examples │ ├── ajax │ │ ├── data-eu-gdp-growth-1.json │ │ ├── data-eu-gdp-growth-2.json │ │ ├── data-eu-gdp-growth-3.json │ │ ├── data-eu-gdp-growth-4.json │ │ ├── data-eu-gdp-growth-5.json │ │ ├── data-eu-gdp-growth.json │ │ ├── data-japan-gdp-growth.json │ │ ├── data-usa-gdp-growth.json │ │ └── index.html │ ├── annotating │ │ └── index.html │ ├── axes-interacting │ │ └── index.html │ ├── axes-multiple │ │ └── index.html │ ├── axes-time-zones │ │ ├── date.js │ │ ├── index.html │ │ └── tz │ │ │ ├── africa │ │ │ ├── antarctica │ │ │ ├── asia │ │ │ ├── australasia │ │ │ ├── backward │ │ │ ├── etcetera │ │ │ ├── europe │ │ │ ├── factory │ │ │ ├── iso3166.tab │ │ │ ├── leapseconds │ │ │ ├── northamerica │ │ │ ├── pacificnew │ │ │ ├── solar87 │ │ │ ├── solar88 │ │ │ ├── solar89 │ │ │ ├── southamerica │ │ │ ├── systemv │ │ │ ├── yearistype.sh │ │ │ └── zone.tab │ ├── axes-time │ │ └── index.html │ ├── background.png │ ├── basic-options │ │ └── index.html │ ├── basic-usage │ │ └── index.html │ ├── canvas │ │ └── index.html │ ├── categories │ │ └── index.html │ ├── examples.css │ ├── image │ │ ├── hs-2004-27-a-large-web.jpg │ │ └── index.html │ ├── index.html │ ├── interacting │ │ └── index.html │ ├── navigate │ │ ├── arrow-down.gif │ │ ├── arrow-left.gif │ │ ├── arrow-right.gif │ │ ├── arrow-up.gif │ │ └── index.html │ ├── percentiles │ │ └── index.html │ ├── realtime │ │ └── index.html │ ├── resize │ │ └── index.html │ ├── selection │ │ └── index.html │ ├── series-errorbars │ │ └── index.html │ ├── series-pie │ │ └── index.html │ ├── series-toggle │ │ └── index.html │ ├── series-types │ │ └── index.html │ ├── shared │ │ └── jquery-ui │ │ │ ├── jquery-ui.min.css │ │ │ └── jquery-ui.min.js │ ├── stacking │ │ └── index.html │ ├── symbols │ │ └── index.html │ ├── threshold │ │ └── index.html │ ├── tracking │ │ └── index.html │ ├── visitors │ │ └── index.html │ └── zooming │ │ └── index.html │ ├── excanvas.js │ ├── excanvas.min.js │ ├── jquery.colorhelpers.js │ ├── jquery.colorhelpers.min.js │ ├── jquery.flot.canvas.js │ ├── jquery.flot.canvas.min.js │ ├── jquery.flot.categories.js │ ├── jquery.flot.categories.min.js │ ├── jquery.flot.crosshair.js │ ├── jquery.flot.crosshair.min.js │ ├── jquery.flot.errorbars.js │ ├── jquery.flot.errorbars.min.js │ ├── jquery.flot.fillbetween.js │ ├── jquery.flot.fillbetween.min.js │ ├── jquery.flot.image.js │ ├── jquery.flot.image.min.js │ ├── jquery.flot.js │ ├── jquery.flot.min.js │ ├── jquery.flot.navigate.js │ ├── jquery.flot.navigate.min.js │ ├── jquery.flot.pie.js │ ├── jquery.flot.pie.min.js │ ├── jquery.flot.resize.js │ ├── jquery.flot.resize.min.js │ ├── jquery.flot.selection.js │ ├── jquery.flot.selection.min.js │ ├── jquery.flot.stack.js │ ├── jquery.flot.stack.min.js │ ├── jquery.flot.symbol.js │ ├── jquery.flot.symbol.min.js │ ├── jquery.flot.threshold.js │ ├── jquery.flot.threshold.min.js │ ├── jquery.flot.time.js │ ├── jquery.flot.time.min.js │ ├── jquery.js │ └── jquery.min.js ├── webpack.config.js └── webpackConfigFiles ├── commonLoaders.js ├── commonPlugins.js ├── webpack.config.dev.js └── webpack.config.prod.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react", "stage-0"], 3 | "plugins": [ 4 | "transform-decorators-legacy", 5 | "transform-runtime" 6 | ], 7 | "env": { 8 | "development": { 9 | "plugins": [ 10 | "transform-react-jsx-source", 11 | "react-hot-loader/babel", 12 | ] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | snapshots 4 | e2eTestLog 5 | npm-debug.log 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "hardcore-react", 3 | "parser": "babel-eslint", 4 | "rules": { 5 | "linebreak-style": [0, "unix"], 6 | }, 7 | "globals": { 8 | "describe": true, 9 | "it": true, 10 | "path": true, 11 | "ga": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | snapshots 4 | e2eTestLog 5 | npm-debug.log 6 | dist 7 | .nyc_output 8 | output/** 9 | *.class 10 | *.iml 11 | */.idea/** 12 | .idea/** 13 | .idea 14 | *.log 15 | *.log.[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 16 | */.classpath 17 | .classpath 18 | */.project 19 | .project 20 | .cache/** 21 | target/ 22 | .settings/ 23 | logs 24 | coverage 25 | stats.json 26 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "at-rule-empty-line-before": [ "always", { 4 | "except": [ "blockless-group", "first-nested" ], 5 | "ignore": ["after-comment"], 6 | } ], 7 | "block-closing-brace-newline-after": "always", 8 | "block-closing-brace-newline-before": "always-multi-line", 9 | "block-closing-brace-space-before": "always-single-line", 10 | "block-no-empty": true, 11 | "block-opening-brace-newline-after": "always-multi-line", 12 | "block-opening-brace-space-after": "always-single-line", 13 | "block-opening-brace-space-before": "always", 14 | "color-hex-case": [ "lower", { "severity": "warning" } 15 | ], 16 | "color-hex-length": "short", 17 | "color-no-invalid-hex": true, 18 | "comment-empty-line-before": [ "always", { 19 | "except": ["first-nested"], 20 | "ignore": ["stylelint-commands"], 21 | } ], 22 | "comment-whitespace-inside": "always", 23 | "declaration-bang-space-after": "never", 24 | "declaration-bang-space-before": "always", 25 | "declaration-block-no-shorthand-property-overrides": true, 26 | "declaration-block-semicolon-newline-after": "always-multi-line", 27 | "declaration-block-semicolon-space-after": "always-single-line", 28 | "declaration-block-semicolon-space-before": "never", 29 | "declaration-block-single-line-max-declarations": 1, 30 | "declaration-block-trailing-semicolon": "always", 31 | "declaration-colon-newline-after": "always-multi-line", 32 | "declaration-colon-space-after": "always-single-line", 33 | "declaration-colon-space-before": "never", 34 | "font-family-name-quotes": "always-unless-keyword", 35 | "function-calc-no-unspaced-operator": true, 36 | "function-comma-newline-after": "always-multi-line", 37 | "function-comma-space-after": "always-single-line", 38 | "function-comma-space-before": "never", 39 | "function-linear-gradient-no-nonstandard-direction": true, 40 | "function-parentheses-newline-inside": "always-multi-line", 41 | "function-parentheses-space-inside": "never-single-line", 42 | "function-whitespace-after": "always", 43 | "indentation": 2, 44 | "length-zero-no-unit": true, 45 | "max-empty-lines": 1, 46 | "media-feature-colon-space-after": "always", 47 | "media-feature-colon-space-before": "never", 48 | "media-feature-no-missing-punctuation": true, 49 | "media-feature-parentheses-space-inside": "never", 50 | "media-feature-range-operator-space-after": "always", 51 | "media-feature-range-operator-space-before": "always", 52 | "media-query-list-comma-newline-after": "always-multi-line", 53 | "media-query-list-comma-space-after": "always-single-line", 54 | "media-query-list-comma-space-before": "never", 55 | "no-eol-whitespace": true, 56 | "no-invalid-double-slash-comments": true, 57 | "no-missing-end-of-source-newline": true, 58 | "number-leading-zero": "always", 59 | "number-no-trailing-zeros": true, 60 | "rule-non-nested-empty-line-before": [ "always-multi-line", { 61 | "ignore": ["after-comment"], 62 | } ], 63 | "selector-combinator-space-after": "always", 64 | "selector-combinator-space-before": "always", 65 | "selector-list-comma-space-before": "never", 66 | "selector-pseudo-element-colon-notation": "double", 67 | "string-no-newline": true, 68 | "string-quotes": "double", 69 | "value-list-comma-newline-after": "always-multi-line", 70 | "value-list-comma-space-after": "always-single-line", 71 | "value-list-comma-space-before": "never", 72 | }, 73 | } 74 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:boron 2 | 3 | # Make ssh dir 4 | RUN mkdir /root/.ssh/ 5 | 6 | # Copy over private key, and set permissions 7 | ADD id_rsa /root/.ssh/id_rsa 8 | 9 | # Create known_hosts 10 | RUN touch /root/.ssh/known_hosts 11 | # Add bitbuckets key 12 | RUN ssh-keyscan github.com >> /root/.ssh/known_hosts 13 | 14 | # Create app directory 15 | RUN mkdir -p /usr/src/react-redux-webpack2-starterkit 16 | WORKDIR /usr/src/react-redux-webpack2-starterkit 17 | 18 | # Install app dependencies 19 | COPY package.json /usr/src/react-redux-webpack2-starterkit/ 20 | RUN npm install 21 | 22 | # Bundle app source 23 | COPY . /usr/src/react-redux-webpack2-starterkit 24 | 25 | EXPOSE 3001 26 | 27 | CMD [ "npm", "run", "testserver" ] 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Andrii 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bin/extract_lang.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pushd `dirname $0` > /dev/null; 4 | ROOT_DIR=`pwd`'/..'; 5 | popd > /dev/null; 6 | 7 | # Transpile to ES5 8 | node "${ROOT_DIR}/node_modules/babel-cli/bin/babel" "${ROOT_DIR}/src" -d "${ROOT_DIR}/src_es5"; 9 | find "${ROOT_DIR}/src_es5" -type f \( -name '*.js' \) -print > "${ROOT_DIR}/list"; 10 | 11 | # Extract phrases from source code and update exising PO files 12 | xgettext --keyword="l:1" \ 13 | --keyword="l:1,2c" \ 14 | --keyword="nl:1,2" \ 15 | --keyword="nl:1,2,4c" \ 16 | --files-from="${ROOT_DIR}/list" \ 17 | --language=JavaScript \ 18 | --no-location \ 19 | --from-code=UTF-8 \ 20 | --output="${ROOT_DIR}/lang/messages.pot"; 21 | 22 | msgmerge --backup=off -U "${ROOT_DIR}/lang/ru.po" "${ROOT_DIR}/lang/messages.pot"; 23 | msgmerge --backup=off -U "${ROOT_DIR}/lang/en.po" "${ROOT_DIR}/lang/messages.pot"; 24 | 25 | # Cleanup 26 | rm -rf "${ROOT_DIR}/src_es5"; 27 | rm -rf "${ROOT_DIR}/list"; 28 | -------------------------------------------------------------------------------- /bin/gettext.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/bin/gettext.zip -------------------------------------------------------------------------------- /bin/po2json.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pushd `dirname $0` > /dev/null; 4 | ROOT_DIR=`pwd`'/..'; 5 | popd > /dev/null; 6 | 7 | # node "${ROOT_DIR}/node_modules/po2json/bin/po2json" "${ROOT_DIR}/lang/en.po" -f jed1.x -p "${ROOT_DIR}/public/static/lang/en.json"; 8 | node "${ROOT_DIR}/node_modules/po2json/bin/po2json" "${ROOT_DIR}/lang/ru.po" -f jed1.x -p "${ROOT_DIR}/lang/ru.json"; 9 | node "${ROOT_DIR}/node_modules/po2json/bin/po2json" "${ROOT_DIR}/lang/en.po" -f jed1.x -p "${ROOT_DIR}/lang/en.json"; 10 | -------------------------------------------------------------------------------- /docs/CHANGES.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/docs/CHANGES.md -------------------------------------------------------------------------------- /docs/ROADMAP.md: -------------------------------------------------------------------------------- 1 | # Roadmap 2 | 3 | The roadmap is a living document, and it is likely that priorities will change, but the list below should give some indication of our plans for the next major release, and for the future. 4 | 5 | ## v0.3.0 6 | 7 | We are mainly focusing on 8 | - Basic functionality 9 | - Architecture 10 | 11 | ## Future 12 | 13 | - unit tests. 14 | - e2e tests. 15 | - continuous integration 16 | -------------------------------------------------------------------------------- /docs/design(architecture)/structure.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/docs/design(architecture)/structure.md -------------------------------------------------------------------------------- /docs/readme.md: -------------------------------------------------------------------------------- 1 | # Navigation 2 | - [Styleguide](/docs/styleguide) 3 | - [Design (architecture)](/docs/design(architecture)) 4 | - [Design (screens)](/docs/design(architecture)) 5 | - [Basic readme](/docs/basic) 6 | - [Changelog](/docs/CHANGES.md) 7 | - [Roadmap](/docs/ROADMAP.md) 8 | -------------------------------------------------------------------------------- /docs/styleguide/readme.md: -------------------------------------------------------------------------------- 1 | # Navigation 2 | - [JS](/docs/styleguide/js.md) 3 | - [React](/docs/styleguide/react.md) 4 | - [Concepts](/docs/styleguide/concepts.md) 5 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/favicon.ico -------------------------------------------------------------------------------- /lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "domain": "messages", 3 | "locale_data": { 4 | "messages": { 5 | "": { 6 | "domain": "messages", 7 | "lang": "en" 8 | }, 9 | "html detailed": [ 10 | "" 11 | ] 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /lang/en.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: \n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2016-09-20 12:59+0300\n" 6 | "PO-Revision-Date: \n" 7 | "Last-Translator: \n" 8 | "Language-Team: \n" 9 | "Language: en\n" 10 | "MIME-Version: 1.0\n" 11 | "Content-Type: text/plain; charset=iso-8859-1\n" 12 | "Content-Transfer-Encoding: 8bit\n" 13 | "X-Generator: Poedit 1.8.8\n" 14 | 15 | msgid "html detailed" 16 | msgstr "" 17 | 18 | #~ msgid "Detail about app" 19 | #~ msgstr "Detail about app" 20 | -------------------------------------------------------------------------------- /lang/messages.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2016-09-20 12:59+0300\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | msgid "html detailed" 21 | msgstr "" 22 | -------------------------------------------------------------------------------- /lang/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "domain": "messages", 3 | "locale_data": { 4 | "messages": { 5 | "": { 6 | "domain": "messages", 7 | "plural_forms": "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);", 8 | "lang": "ru" 9 | }, 10 | "html detailed": [ 11 | "" 12 | ] 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /lang/ru.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: \n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2016-09-20 12:59+0300\n" 6 | "PO-Revision-Date: \n" 7 | "Last-Translator: \n" 8 | "Language-Team: \n" 9 | "Language: ru\n" 10 | "MIME-Version: 1.0\n" 11 | "Content-Type: text/plain; charset=UTF-8\n" 12 | "Content-Transfer-Encoding: 8bit\n" 13 | "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" 14 | "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" 15 | "X-Generator: Poedit 1.8.8\n" 16 | 17 | msgid "html detailed" 18 | msgstr "" 19 | 20 | #~ msgid "Detail about app" 21 | #~ msgstr "Подробнее" 22 | -------------------------------------------------------------------------------- /nightwatch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('nightwatch/bin/runner.js'); 3 | -------------------------------------------------------------------------------- /nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/ 2 | var path = require("path"); 3 | 4 | const outputDirectory = process.env.NIGHTWATCH_OUTPUT || "./e2eTestLog"; 5 | 6 | module.exports = { 7 | "src_folders" : ["test/e2e"], 8 | "output_folder" : outputDirectory, 9 | "custom_commands_path" : "", 10 | "custom_assertions_path" : "", 11 | "page_objects_path" : "", 12 | "globals_path" : "", 13 | 14 | "selenium" : { 15 | "start_process" : !(/^win/.test(process.platform)), 16 | "server_path" : require("selenium-server").path, 17 | "log_path" : path.join(outputDirectory, "logs"), 18 | "host" : "127.0.0.1", 19 | "port" : 4444, 20 | "cli_args" : { 21 | "webdriver.chrome.driver" : console.log(require('chromedriver').path) && require('chromedriver').path, 22 | "webdriver.chrome.logfile" : '/tmp/chromedriver.log', 23 | "webdriver.chrome.verboseLogging" : true, 24 | "webdriver.ie.driver" : "" 25 | } 26 | }, 27 | 28 | "test_settings" : { 29 | "default" : { 30 | "launch_url" : "http://localhost:3001", 31 | "selenium_port" : 4444, 32 | "selenium_host" : "127.0.0.1", 33 | "silent": true, 34 | "disable_colors": true, 35 | "screenshots" : { 36 | "enabled" : true, 37 | "on_failure" : true, 38 | "path" : path.join(outputDirectory, "snapshots") 39 | }, 40 | "desiredCapabilities" : { 41 | "browserName" : "chrome", 42 | "javascriptEnabled" : true, 43 | "acceptSslCerts" : true 44 | } 45 | } 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-commonjs */ 2 | /* eslint-disable global-require */ 3 | /* eslint-disable import/no-nodejs-modules */ 4 | /* eslint-disable import/no-extraneous-dependencies */ 5 | 6 | const PORT = 3002; 7 | const NOT_FOUND = -1; 8 | 9 | const path = require('path'); 10 | const webpack = require('webpack'); 11 | const webpackDevMiddleware = require('webpack-dev-middleware'); 12 | const webpackHotMiddleware = require('webpack-hot-middleware'); 13 | const config = require('./webpack.config'); 14 | 15 | const express = require('express'); 16 | const app = express(); 17 | 18 | const compiler = webpack(config); 19 | 20 | app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath })); 21 | app.use(webpackHotMiddleware(compiler, { noInfo: true })); 22 | 23 | app.use((req, res) => { 24 | if (req.url.indexOf('config/config') !== NOT_FOUND) { 25 | return res.sendFile(path.join(__dirname, '/src/config/config.js')); 26 | } 27 | 28 | return res.sendFile(path.join(__dirname, '/src/index.dev.html')); 29 | }); 30 | 31 | app.listen(PORT, (error) => { 32 | if (error) { 33 | console.error(error); 34 | } else { 35 | console.info('==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.', PORT); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /src/actions/entity/entity.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | describe('apps action tests', () => { 4 | describe('test constants', () => { 5 | it('verify existence of LOAD_EXPLORE_GRAPH', () => { 6 | expect(true).to.eql(true); 7 | }); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /src/actions/entity/index.js: -------------------------------------------------------------------------------- 1 | // import { CALL_API } from 'redux-api-middleware'; TODO should replace CALL_MOCK_API, when real api will appear 2 | import { schema } from 'normalizr'; 3 | import { CALL_MOCK_API } from './../../mockApi'; 4 | import { API_URL } from './../../constants/Api'; 5 | import { APPS_VIEW_STATE } from './../../constants/ViewStates'; 6 | import { APPS } from './../../constants/MappersTypes'; 7 | import schemaUtils from './../../utils/schemaUtils'; 8 | import appSchema from './../../schemas/app'; 9 | 10 | const hash = { 11 | [APPS_VIEW_STATE]: { 12 | schema: new schema.Array(appSchema), 13 | viewId: APPS_VIEW_STATE, 14 | mapperType: APPS, 15 | mockResponse: [ 16 | { 17 | name: 'App1', 18 | title: 'This is first app title', 19 | description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit. 20 | Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi. 21 | Donec vulputate interdum sollicitudin`, 22 | }, 23 | { 24 | name: 'App2', 25 | title: 'This is second app title', 26 | description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit. 27 | Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi. 28 | Donec vulputate interdum sollicitudin`, 29 | }, 30 | ], 31 | }, 32 | }; 33 | 34 | 35 | export const LOAD_ENTITIES_START = 'LOAD_ENTITIES_START'; 36 | export const LOAD_ENTITIES_SUCCESS = 'LOAD_ENTITIES_SUCCESS'; 37 | export const LOAD_ENTITIES_FAILURE = 'LOAD_ENTITIES_FAILURE'; 38 | 39 | const fetchEntities = ({ href, type }) => { 40 | const infoAboutEntity = hash[type] || {}; 41 | const meta = { viewId: infoAboutEntity.viewId, mapperType: infoAboutEntity.mapperType }; 42 | 43 | return { 44 | [CALL_MOCK_API]: { 45 | types: [ 46 | { type: LOAD_ENTITIES_START, meta }, 47 | schemaUtils.getSuccessActionTypeWithSchema({ 48 | type: LOAD_ENTITIES_SUCCESS, 49 | schema: infoAboutEntity.schema, 50 | meta, 51 | }), 52 | { type: LOAD_ENTITIES_FAILURE, meta }, 53 | ], 54 | method: 'GET', 55 | mockResponse: { 56 | responseJSON: infoAboutEntity.mockResponse, 57 | }, 58 | endpoint: `${API_URL}${href}`, 59 | }, 60 | }; 61 | }; 62 | 63 | export const loadEntities = ({ href, type }) => (dispatch) => dispatch(fetchEntities({ href, type })); 64 | -------------------------------------------------------------------------------- /src/actions/users/index.js: -------------------------------------------------------------------------------- 1 | // import { CALL_API } from 'redux-api-middleware'; TODO should replace CALL_MOCK_API 2 | import { CALL_MOCK_API } from './../../mockApi'; 3 | import { USER } from './../../constants/MappersTypes'; 4 | import { API_URL } from './../../constants/Api'; 5 | import { LOGIN_VIEW_STATE } from './../../constants/ViewStates'; 6 | 7 | import schemaUtils from './../../utils/schemaUtils'; 8 | import authUserSchema from './../../schemas/authUser'; 9 | 10 | export const USER_LOGIN_STARTED = 'USER_LOGIN_STARTED'; 11 | export const USER_LOGIN_SUCCESS = 'USER_LOGIN_SUCCESS'; 12 | export const USER_LOGIN_FAILURE = 'USER_LOGIN_FAILURE'; 13 | 14 | const fetchUserLogin = ({ login, password }) => { 15 | const meta = { viewId: LOGIN_VIEW_STATE, mapperType: USER }; 16 | 17 | return { 18 | [CALL_MOCK_API]: { 19 | types: [ 20 | { type: USER_LOGIN_STARTED, meta }, 21 | schemaUtils.getSuccessActionTypeWithSchema({ type: USER_LOGIN_SUCCESS, schema: authUserSchema, meta }), 22 | { type: USER_LOGIN_FAILURE, meta }, 23 | ], 24 | method: 'POST', 25 | body: JSON.stringify({ 26 | login, 27 | password, 28 | }), 29 | mockResponse: { 30 | responseJSON: { 31 | login, 32 | password, 33 | roles: ['ADMIN'], 34 | }, 35 | }, 36 | endpoint: `${API_URL}/login`, 37 | }, 38 | }; 39 | }; 40 | 41 | export const loginUser = ({ login, password }) => (dispatch) => dispatch(fetchUserLogin({ login, password })); 42 | 43 | export const USER_LOGOUT_STARTED = 'USER_LOGOUT_STARTED'; 44 | export const USER_LOGOUT_SUCCESS = 'USER_LOGOUT_SUCCESS'; 45 | export const USER_LOGOUT_FAILURE = 'USER_LOGOUT_FAILURE'; 46 | 47 | const fetchUserLogout = () => ({ 48 | [CALL_MOCK_API]: { 49 | types: [USER_LOGOUT_STARTED, USER_LOGOUT_SUCCESS, USER_LOGOUT_FAILURE], 50 | method: 'POST', 51 | mockResponse: { responseJSON: {} }, 52 | endpoint: `${API_URL}/logout`, 53 | }, 54 | }); 55 | 56 | export const logoutUser = () => (dispatch) => dispatch(fetchUserLogout()); 57 | -------------------------------------------------------------------------------- /src/actions/users/users.spec.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/src/actions/users/users.spec.js -------------------------------------------------------------------------------- /src/actions/view/index.js: -------------------------------------------------------------------------------- 1 | export const REMOVE_NOTIFICATION = 'REMOVE_NOTIFICATION'; 2 | 3 | export const removeNotification = (id) => ({ 4 | type: REMOVE_NOTIFICATION, 5 | id, 6 | }); 7 | -------------------------------------------------------------------------------- /src/actions/view/view.spec.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/src/actions/view/view.spec.js -------------------------------------------------------------------------------- /src/components/Charts/Chart/Chart.css: -------------------------------------------------------------------------------- 1 | .chart { 2 | width: 100%; 3 | height: 100%; 4 | min-height: 250px; 5 | } 6 | -------------------------------------------------------------------------------- /src/components/Charts/Chart/Chart.js: -------------------------------------------------------------------------------- 1 | import { PureComponent, PropTypes } from 'react'; 2 | import $ from 'jquery'; 3 | 4 | /* eslint-disable */ 5 | 6 | import styles from './Chart.css'; 7 | 8 | class Chart extends PureComponent { 9 | static propTypes = { 10 | className: PropTypes.string, 11 | } 12 | 13 | static defaultProps = { 14 | className: '', 15 | } 16 | 17 | componentDidMount() { 18 | const data = [ 19 | [0, 4], 20 | [1, 6], 21 | [2, 3], 22 | [3, 8], 23 | ]; 24 | const options = { 25 | series: { 26 | bars: { 27 | show: true, 28 | barWidth: 0.3, 29 | align: 'center', 30 | lineWidth: 0, 31 | fill: 0.75, 32 | }, 33 | }, 34 | xaxis: { 35 | ticks: [ 36 | [0, 'First'], 37 | [1, 'Second'], 38 | [2, 'Third'], 39 | [3, 'Fourth'], 40 | ], 41 | mode: 'categories', 42 | tickLength: 0, 43 | }, 44 | yaxis: { 45 | max: 10, 46 | }, 47 | }; 48 | 49 | $.plot(this.chartNode, [data], options); 50 | } 51 | 52 | setChartRef = (node) => { 53 | this.chartNode = node; 54 | } 55 | 56 | render() { 57 | return ( 58 |
62 | ); 63 | } 64 | } 65 | 66 | export default Chart; 67 | -------------------------------------------------------------------------------- /src/components/Charts/Chart/index.js: -------------------------------------------------------------------------------- 1 | import Chart from './Chart'; 2 | 3 | export default Chart; 4 | -------------------------------------------------------------------------------- /src/components/Editor/Editor.css: -------------------------------------------------------------------------------- 1 | .editor { 2 | width: 100%; 3 | height: 100%; 4 | min-height: 250px; 5 | } 6 | -------------------------------------------------------------------------------- /src/components/Editor/Editor.js: -------------------------------------------------------------------------------- 1 | import { PureComponent, PropTypes } from 'react'; 2 | import Codemirror from 'react-codemirror'; 3 | 4 | import 'codemirror/mode/javascript/javascript'; 5 | import 'codemirror/addon/edit/matchbrackets'; 6 | import 'codemirror/addon/edit/closebrackets'; 7 | import 'codemirror/lib/codemirror.css'; 8 | 9 | import styles from './Editor.css'; 10 | 11 | class Editor extends PureComponent { 12 | static propTypes = { 13 | autoCloseBrackets: PropTypes.bool, 14 | gutters: PropTypes.array, 15 | lineNumbers: PropTypes.bool, 16 | lint: PropTypes.bool, 17 | matchBrackets: PropTypes.bool, 18 | mode: PropTypes.string, 19 | value: PropTypes.string, 20 | onChange: PropTypes.func, 21 | } 22 | 23 | static defaultProps = { 24 | autoCloseBrackets: true, 25 | value: '', 26 | matchBrackets: true, 27 | lineNumbers: false, 28 | lint: true, 29 | mode: 'application/json', 30 | gutters: [], 31 | } 32 | 33 | setEditorInstance = (node) => { this.editor = node && node.codeMirror; } 34 | getEditorInstance = () => this.editor 35 | 36 | handleChange = (value) => { 37 | if (this.props.onChange) { 38 | this.props.onChange(value); 39 | } 40 | } 41 | 42 | render() { 43 | return ( 44 |
45 | 59 |
60 | ); 61 | } 62 | } 63 | 64 | export default Editor; 65 | -------------------------------------------------------------------------------- /src/components/Editor/index.js: -------------------------------------------------------------------------------- 1 | import Editor from './Editor'; 2 | 3 | export default Editor; 4 | -------------------------------------------------------------------------------- /src/components/FontIcon/FontIcon.css: -------------------------------------------------------------------------------- 1 | .fontIcon { 2 | display: flex; 3 | align-items: center; 4 | } 5 | -------------------------------------------------------------------------------- /src/components/FontIcon/FontIcon.js: -------------------------------------------------------------------------------- 1 | import { PureComponent, PropTypes } from 'react'; 2 | import styles from './FontIcon.css'; 3 | 4 | class FontIcon extends PureComponent { 5 | static propTypes = { 6 | className: PropTypes.string, 7 | color: PropTypes.string, 8 | type: PropTypes.string.isRequired, 9 | onTouchTap: PropTypes.func, 10 | } 11 | 12 | static defaultProps = { 13 | className: '', 14 | color: '', 15 | } 16 | 17 | render() { 18 | return ( 19 |
23 | 27 | {this.props.type} 28 | 29 |
30 | ); 31 | } 32 | } 33 | 34 | export default FontIcon; 35 | -------------------------------------------------------------------------------- /src/components/FontIcon/images/logout.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/FontIcon/index.js: -------------------------------------------------------------------------------- 1 | import FontIcon from './FontIcon'; 2 | 3 | export default FontIcon; 4 | -------------------------------------------------------------------------------- /src/components/Forms/renders.js: -------------------------------------------------------------------------------- 1 | import { PropTypes } from 'react'; 2 | import Input from './../common/Input'; 3 | import Checkbox from './../common/Checkbox'; 4 | 5 | export const renderTextField = ({ input, label, meta: { touched, error }, ...custom }) => ( 6 | 13 | ); 14 | 15 | renderTextField.propTypes = { 16 | input: PropTypes.object, 17 | label: PropTypes.string, 18 | meta: PropTypes.object, 19 | }; 20 | 21 | export const renderCheckboxField = ({ input, label, ...custom }) => ( 22 | 27 | ); 28 | 29 | renderCheckboxField.propTypes = { 30 | input: PropTypes.object, 31 | label: PropTypes.string, 32 | meta: PropTypes.object, 33 | }; 34 | -------------------------------------------------------------------------------- /src/components/Message/Message.css: -------------------------------------------------------------------------------- 1 | .message { 2 | display: flex; 3 | align-items: center; 4 | padding: 5px; 5 | width: 100%; 6 | border-bottom: 1px rgba(0, 0, 0, 0.05) solid; 7 | border-radius: 1; 8 | user-select: text; 9 | max-height: 50; 10 | position: relative; 11 | overflow-y: hidden; 12 | } 13 | 14 | .msgWrap { 15 | line-height: 24px; 16 | min-width: 150; 17 | } 18 | 19 | .close { 20 | justify-content: center; 21 | display: flex; 22 | align-items: center; 23 | height: 24px; 24 | width: 24px; 25 | top: 50%; 26 | margin-top: -10; 27 | right: 5; 28 | position: absolute; 29 | } 30 | 31 | .dismissBtn { 32 | cursor: pointer; 33 | } 34 | -------------------------------------------------------------------------------- /src/components/Message/Message.js: -------------------------------------------------------------------------------- 1 | import { PureComponent, PropTypes } from 'react'; 2 | import { UNDEFINED_VALUE } from './../../constants/Constants'; 3 | 4 | import styles from './Message.css'; 5 | 6 | const inlineStyles = { 7 | error: { 8 | backgroundColor: 'rgb(255, 64, 129)', 9 | }, 10 | }; 11 | 12 | export default class Message extends PureComponent { 13 | 14 | static MESSAGE_TYPES = ['info', 'ok', 'warning', 'error']; 15 | 16 | static defaultProps = { 17 | messageType: 'info', 18 | }; 19 | 20 | static propTypes = { 21 | children: PropTypes.node, 22 | dismissed: PropTypes.bool, 23 | message: PropTypes.string, 24 | messageType: PropTypes.string, 25 | onDismiss: PropTypes.func, 26 | }; 27 | 28 | state = { 29 | dismissed: false, 30 | } 31 | 32 | componentWillReceiveProps(nextProps) { 33 | if (nextProps.message !== this.props.message || nextProps.messageType !== this.props.messageType) { 34 | this.setState({ dismissed: false }); 35 | } 36 | } 37 | 38 | handleDismiss = () => { 39 | this.setState({ dismissed: true }); 40 | if (this.props.onDismiss) { 41 | this.props.onDismiss(); 42 | } 43 | } 44 | 45 | handleMouseUp(e) { 46 | e.preventDefault(); 47 | e.stopPropagation(); 48 | } 49 | 50 | renderIcon(messageType) { 51 | switch (messageType) { 52 | case 'error': 53 | return ; 54 | case 'warning': 55 | return ; 56 | case 'info': 57 | return ; 58 | case 'ok': 59 | return ; 60 | default: 61 | return null; 62 | } 63 | } 64 | 65 | render() { 66 | const { message, messageType } = this.props; 67 | 68 | if (this.props.dismissed || this.props.dismissed === UNDEFINED_VALUE && this.state.dismissed) { 69 | return null; 70 | } 71 | 72 | return ( 73 |
77 | {this.renderIcon(messageType)} 78 |
79 | {message} 80 |
81 | {this.props.children} 82 |
83 | 87 |
88 |
89 | ); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/components/Message/index.js: -------------------------------------------------------------------------------- 1 | import Message from './Message'; 2 | 3 | export default Message; 4 | -------------------------------------------------------------------------------- /src/components/Spinner/Spinner.css: -------------------------------------------------------------------------------- 1 | .spinner { 2 | left: 0; 3 | top: 0; 4 | position: absolute; 5 | display: flex; 6 | justify-content: center; 7 | align-items: center; 8 | width: 100%; 9 | height: 100%; 10 | z-index: 99; 11 | } 12 | -------------------------------------------------------------------------------- /src/components/Spinner/Spinner.js: -------------------------------------------------------------------------------- 1 | import { PureComponent, PropTypes } from 'react'; 2 | import CircularProgress from 'material-ui/CircularProgress'; 3 | 4 | import styles from './Spinner.css'; 5 | 6 | class Spinner extends PureComponent { 7 | static propTypes = { 8 | className: PropTypes.string, 9 | size: PropTypes.number, 10 | } 11 | 12 | render() { 13 | return ( 14 |
15 | 19 |
20 | ); 21 | } 22 | } 23 | 24 | export default Spinner; 25 | -------------------------------------------------------------------------------- /src/components/Spinner/index.js: -------------------------------------------------------------------------------- 1 | import Spinner from './Spinner'; 2 | 3 | export default Spinner; 4 | -------------------------------------------------------------------------------- /src/components/ViewStateWrapper/ViewStateWrapper.css: -------------------------------------------------------------------------------- 1 | .viewStateWrapper { 2 | height: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/ViewStateWrapper/ViewStateWrapper.js: -------------------------------------------------------------------------------- 1 | import { PureComponent, PropTypes } from 'react'; 2 | import Immutable from 'immutable'; 3 | 4 | import Spinner from './../Spinner'; 5 | import Message from './../Message'; 6 | 7 | import styles from './ViewStateWrapper.css'; 8 | 9 | export default class ViewStateWrapper extends PureComponent { 10 | static propTypes = { 11 | children: PropTypes.node, 12 | className: PropTypes.string, 13 | showMessage: PropTypes.bool, 14 | spinnerClassName: PropTypes.string, 15 | viewState: PropTypes.instanceOf(Immutable.Map), 16 | visibleChildren: PropTypes.bool, 17 | }; 18 | 19 | static defaultProps = { 20 | showMessage: true, 21 | className: '', 22 | visibleChildren: true, 23 | }; 24 | 25 | render() { 26 | const { viewState, children, showMessage, className, visibleChildren } = this.props; 27 | 28 | if (viewState.get('isInProgress') && visibleChildren) { 29 | return ( 30 |
31 | 32 |
33 | {children} 34 |
35 |
36 | ); 37 | } 38 | 39 | if (viewState.get('isInProgress')) { 40 | return ; 41 | } 42 | 43 | if (viewState.get('isFailed') && showMessage) { 44 | return ( 45 | 50 | ); 51 | } 52 | 53 | return ( 54 |
55 | {children} 56 |
57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/components/ViewStateWrapper/index.js: -------------------------------------------------------------------------------- 1 | import ViewStateWrapper from './ViewStateWrapper'; 2 | 3 | export default ViewStateWrapper; 4 | -------------------------------------------------------------------------------- /src/components/Widget/Widget.css: -------------------------------------------------------------------------------- 1 | .widget { 2 | width: 600px; 3 | height: 400px; 4 | margin: 20px; 5 | background-color: rgb(43, 43, 43); 6 | box-shadow: rgba(0, 0, 0, 0.156863) 0 3px 10px, rgba(0, 0, 0, 0.227451) 0 3px 10px; 7 | border-radius: 2px; 8 | text-align: center; 9 | display: inline-block; 10 | } 11 | -------------------------------------------------------------------------------- /src/components/Widget/Widget.js: -------------------------------------------------------------------------------- 1 | import { PureComponent, PropTypes } from 'react'; 2 | 3 | import styles from './Widget.css'; 4 | 5 | class Widget extends PureComponent { 6 | static propTypes = { 7 | children: PropTypes.node, 8 | } 9 | 10 | render() { 11 | return ( 12 |
13 | {this.props.children} 14 |
15 | ); 16 | } 17 | } 18 | 19 | export default Widget; 20 | -------------------------------------------------------------------------------- /src/components/Widget/index.js: -------------------------------------------------------------------------------- 1 | import Widget from './Widget'; 2 | 3 | export default Widget; 4 | -------------------------------------------------------------------------------- /src/components/common/AppBar/AppBar.js: -------------------------------------------------------------------------------- 1 | import { PureComponent, PropTypes } from 'react'; 2 | import AppBar from 'react-toolbox/lib/app_bar/AppBar'; 3 | 4 | class AppBarWrapper extends PureComponent { 5 | static propTypes = { 6 | children: PropTypes.node, 7 | className: PropTypes.string, 8 | leftIcon: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), 9 | theme: PropTypes.object, 10 | title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), 11 | } 12 | 13 | render() { 14 | return ( 15 | 21 | {this.props.children} 22 | 23 | ); 24 | } 25 | } 26 | 27 | export default AppBarWrapper; 28 | -------------------------------------------------------------------------------- /src/components/common/AppBar/AppBar.spec.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/src/components/common/AppBar/AppBar.spec.js -------------------------------------------------------------------------------- /src/components/common/AppBar/index.js: -------------------------------------------------------------------------------- 1 | import AppBar from './AppBar'; 2 | 3 | export default AppBar; 4 | -------------------------------------------------------------------------------- /src/components/common/Button/Button.js: -------------------------------------------------------------------------------- 1 | import { PureComponent, PropTypes } from 'react'; 2 | import { Button } from 'react-toolbox/lib/button/Button'; 3 | 4 | class ButtonWrapper extends PureComponent { 5 | static propTypes = { 6 | accent: PropTypes.bool, 7 | className: PropTypes.string, 8 | disabled: PropTypes.bool, 9 | icon: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), 10 | label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), 11 | onTouchTap: PropTypes.func, 12 | } 13 | 14 | render() { 15 | return ( 16 |
60 | 61 | ); 62 | } 63 | } 64 | 65 | const LoginFormWrapped = reduxForm({ 66 | form: 'LoginForm', 67 | validate: loginValidation, 68 | })(LoginForm); 69 | 70 | const mapStateToProps = (state) => ({ 71 | viewState: getViewState(state, LOGIN_VIEW_STATE), 72 | }); 73 | 74 | export default connect(mapStateToProps, { loginUser })(LoginFormWrapped); 75 | -------------------------------------------------------------------------------- /src/containers/pages/AuthenticationPage/components/LoginForm/index.js: -------------------------------------------------------------------------------- 1 | import LoginForm from './LoginForm'; 2 | export default LoginForm; 3 | -------------------------------------------------------------------------------- /src/containers/pages/AuthenticationPage/index.js: -------------------------------------------------------------------------------- 1 | import AuthenticationPage from './AuthenticationPage'; 2 | export default AuthenticationPage; 3 | -------------------------------------------------------------------------------- /src/i18n/Provider.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Provider extends React.Component { 4 | static propTypes = { 5 | children: React.PropTypes.object.isRequired, 6 | i18n: React.PropTypes.object.isRequired, 7 | setLanguage: React.PropTypes.func, 8 | }; 9 | 10 | static childContextTypes = { 11 | i18n: React.PropTypes.object, 12 | setLanguage: React.PropTypes.func, 13 | }; 14 | 15 | getChildContext() { 16 | return { 17 | i18n: this.props.i18n, 18 | setLanguage: this.props.setLanguage, 19 | }; 20 | } 21 | 22 | render() { 23 | return React.Children.only(this.props.children); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/i18n/Tools.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-invalid-this */ 2 | 3 | import Jed from 'jed'; 4 | 5 | export default class Tools { 6 | constructor({ localeData, locale }) { 7 | this.setLanguage({ localeData, locale }); 8 | } 9 | 10 | setLanguage = ({ localeData, locale }) => { 11 | this.jed = new Jed(localeData); 12 | this.locale = locale; 13 | } 14 | 15 | l = (text) => this.jed.gettext(text); 16 | 17 | ngettext = (singular, plural, amount) => this.jed.ngettext(singular, plural, amount); 18 | 19 | getLocale = () => this.locale.toLowerCase(); 20 | } 21 | -------------------------------------------------------------------------------- /src/i18n/index.js: -------------------------------------------------------------------------------- 1 | import Provider from './Provider.js'; 2 | import Tools from './Tools'; 3 | 4 | export default { 5 | Provider, 6 | Tools, 7 | }; 8 | -------------------------------------------------------------------------------- /src/index.dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Boilerplate 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Boilerplate 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-deprecated */ 2 | /* eslint-disable import/imports-first */ 3 | /* eslint-disable global-require */ 4 | 5 | import 'jquery'; 6 | import './../vendorModules/flot/jquery.flot.min.js'; 7 | 8 | import Immutable from 'immutable'; 9 | import { render } from 'react-dom'; 10 | import { browserHistory } from 'react-router'; 11 | import injectTapEventPlugin from 'react-tap-event-plugin'; 12 | import { syncHistoryWithStore } from 'react-router-redux'; 13 | import { AppContainer } from 'react-hot-loader'; 14 | 15 | import Root from './containers/Root'; 16 | import configureStore from './store/configureStore'; 17 | import localStorageUtils from './utils/localStorageUtils'; 18 | 19 | import './assets/normalize.css'; 20 | // import './assets/media.less'; 21 | import './assets/typography.css'; 22 | import './styles.css'; 23 | 24 | const authUser = localStorageUtils.getAuthinticatedUser(); 25 | 26 | const initialState = authUser 27 | ? Immutable.fromJS({ 28 | entities: { 29 | authUser: { 30 | [authUser.login]: authUser, 31 | }, 32 | }, 33 | }) 34 | : new Immutable.Map(); 35 | 36 | const store = configureStore(initialState); 37 | const history = syncHistoryWithStore(browserHistory, store, { 38 | selectLocationState(state) { 39 | return state.get('routing').toJS(); 40 | }, 41 | }); 42 | 43 | /* 44 | we require next line to support onTouchTap event 45 | which will solve a lot of "click" problems for mobile devices 46 | */ 47 | injectTapEventPlugin(); 48 | 49 | render( 50 | 51 | 55 | , 56 | document.getElementById('content') 57 | ); 58 | 59 | if (module.hot) { 60 | module.hot.accept('./containers/Root', () => { 61 | const NextApp = require('./containers/Root').default; 62 | 63 | render( 64 | 65 | 69 | , 70 | document.getElementById('content') 71 | ); 72 | }); 73 | } 74 | -------------------------------------------------------------------------------- /src/mappers/apps.js: -------------------------------------------------------------------------------- 1 | export const mapApps = (payload) => payload.map((item) => { 2 | const uiProperties = { 3 | id: item.name, 4 | links: { 5 | open: `/apps/${item.name}`, 6 | }, 7 | }; 8 | 9 | return { 10 | ...uiProperties, 11 | ...item, 12 | }; 13 | }); 14 | -------------------------------------------------------------------------------- /src/mappers/users.js: -------------------------------------------------------------------------------- 1 | export const mapUser = (payload) => { 2 | const uiProperties = { 3 | links: {}, 4 | }; 5 | 6 | return { ...uiProperties, ...payload }; 7 | }; 8 | -------------------------------------------------------------------------------- /src/mockApi/CALL_MOCK_API.js: -------------------------------------------------------------------------------- 1 | const CALL_MOCK_API = Symbol('Call Mock API'); 2 | 3 | export default CALL_MOCK_API; 4 | -------------------------------------------------------------------------------- /src/mockApi/index.js: -------------------------------------------------------------------------------- 1 | import CALL_MOCK_API_IMPORTED from './CALL_MOCK_API'; 2 | import mockApiMiddlewareImported from './middleware'; 3 | 4 | export const CALL_MOCK_API = CALL_MOCK_API_IMPORTED; 5 | export const mockApiMiddleware = mockApiMiddlewareImported; 6 | -------------------------------------------------------------------------------- /src/reducers/dataLayout.js: -------------------------------------------------------------------------------- 1 | import Immutable from 'immutable'; 2 | 3 | const isSuccessAction = (action) => !action.error && (action.payload || action.meta.success); 4 | 5 | const isStartAction = (action) => !action.error && !action.payload; 6 | 7 | const getErrorMessage = (action) => { 8 | const { payload } = action; 9 | 10 | if (payload) { 11 | if (payload.response && payload.response.errorMessage) { 12 | return payload.response.errorMessage; 13 | } 14 | if (payload.statusText) { 15 | return `${payload.status} - ${payload.statusText}`; 16 | } 17 | } 18 | 19 | return 'Unknown error'; 20 | }; 21 | 22 | const invalidateViewIds = (state, action) => { 23 | const viewIds = action.meta && action.meta.invalidateViewIds; 24 | 25 | if (!viewIds || isStartAction(action)) { 26 | return state; 27 | } 28 | 29 | return state.mergeDeep(viewIds.reduce( 30 | (previous, current) => previous.set(current, new Immutable.Map({ invalidated: true })), 31 | new Immutable.Map()) 32 | ); 33 | }; 34 | 35 | const updateLoadingViewId = (state, action) => { 36 | const { viewId } = action.meta; 37 | 38 | if (!viewId) { 39 | return state; 40 | } 41 | 42 | if (isStartAction(action)) { 43 | return state.mergeIn([viewId], { isInProgress: true, isFailed: false, invalidated: false }); 44 | } 45 | 46 | if (isSuccessAction(action)) { 47 | return state.mergeIn([viewId], { 48 | isInProgress: false, 49 | isFailed: false, 50 | }); 51 | } 52 | 53 | return state.mergeIn([viewId], { 54 | isInProgress: false, 55 | isFailed: true, 56 | message: getErrorMessage(action), 57 | }); 58 | }; 59 | 60 | export default function view(state = new Immutable.Map(), action) { 61 | if (!action.meta) { 62 | return state; 63 | } 64 | 65 | return updateLoadingViewId( 66 | invalidateViewIds(state, action), 67 | action 68 | ); 69 | } 70 | -------------------------------------------------------------------------------- /src/reducers/entityReducers/index.js: -------------------------------------------------------------------------------- 1 | export users from './users'; 2 | -------------------------------------------------------------------------------- /src/reducers/entityReducers/users.js: -------------------------------------------------------------------------------- 1 | import Immutable from 'immutable'; 2 | import { USER_LOGIN_STARTED, USER_LOGIN_SUCCESS, USER_LOGOUT_STARTED } from './../../actions/users'; 3 | import localStorageUtils from './../../utils/localStorageUtils'; 4 | import { getAuthenticatedUser } from './../../selectors/users'; 5 | 6 | const users = (state, action) => { 7 | switch (action.type) { 8 | case USER_LOGIN_STARTED: { 9 | return state.set('authUser', new Immutable.Map()); 10 | } 11 | case USER_LOGIN_SUCCESS: { 12 | localStorageUtils.setAuthinticatedUser(getAuthenticatedUser(action.payload)); 13 | 14 | return state; 15 | } 16 | case USER_LOGOUT_STARTED: { 17 | localStorageUtils.setAuthinticatedUser({}); 18 | 19 | return state.set('authUser', new Immutable.Map()); 20 | } 21 | default: 22 | return state; 23 | } 24 | }; 25 | 26 | export default users; 27 | -------------------------------------------------------------------------------- /src/reducers/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable fp/no-let */ 2 | /* eslint-disable fp/no-mutation */ 3 | 4 | import { combineReducers } from 'redux-immutablejs'; 5 | import Immutable from 'immutable'; 6 | import { reducer as formReducer } from 'redux-form/immutable'; 7 | 8 | import routing from './routing'; 9 | import view from './view'; 10 | import dataLayout from './dataLayout'; 11 | import analytic from './../utils/analytic'; 12 | 13 | import * as entityReducers from './entityReducers'; 14 | 15 | const applyEntitiesToState = (state, action) => { 16 | const entities = action.payload.get('entities'); 17 | 18 | let result = state; 19 | 20 | entities.forEach((theEntities, entityType) => { 21 | theEntities.forEach((entity, entityId) => { 22 | result = result.mergeIn([entityType, entityId], entity); 23 | }); 24 | }); 25 | 26 | return result; 27 | }; 28 | 29 | const isActionWithEntities = (action) => action.payload && action.payload.get && action.payload.get('entities'); 30 | 31 | const initialState = Immutable.fromJS({ 32 | authUser: {}, 33 | }); 34 | 35 | const entities = (state = initialState, action) => { 36 | analytic.handleEvent(action); 37 | 38 | const nextState = isActionWithEntities(action) 39 | ? applyEntitiesToState(state, action) 40 | : state; 41 | 42 | return Object.keys(entityReducers).reduce((prev, key) => entityReducers[key](prev, action), nextState); 43 | }; 44 | 45 | export default combineReducers({ 46 | entities, 47 | routing, 48 | view, 49 | dataLayout, 50 | form: formReducer, 51 | }); 52 | -------------------------------------------------------------------------------- /src/reducers/routing.js: -------------------------------------------------------------------------------- 1 | import Immutable from 'immutable'; 2 | import { LOCATION_CHANGE } from 'react-router-redux'; 3 | 4 | const initialState = Immutable.fromJS({ 5 | locationBeforeTransitions: null, 6 | }); 7 | 8 | export default (state = initialState, action) => { 9 | if (action.type === LOCATION_CHANGE) { 10 | return state.merge({ 11 | locationBeforeTransitions: action.payload, 12 | }); 13 | } 14 | 15 | return state; 16 | }; 17 | -------------------------------------------------------------------------------- /src/reducers/view.js: -------------------------------------------------------------------------------- 1 | import Immutable from 'immutable'; 2 | import uuid from 'uuid'; 3 | 4 | import { REMOVE_NOTIFICATION } from './../actions/view'; 5 | 6 | const MAX_NOTIFICATION_NUMBER = 6; 7 | 8 | const getNextNotificationMessage = (data) => (Immutable.fromJS({ 9 | message: data.error ? `Something went wrong in ${data.type}` : data.message, 10 | type: data.error ? 'error' : data.type, 11 | id: uuid.v4(), 12 | })); 13 | 14 | const initialState = Immutable.fromJS({ 15 | notifications: [], 16 | }); 17 | 18 | export default (state = initialState, action) => { 19 | if (action.error) { 20 | const nextNotification = state.get('notifications').unshift(getNextNotificationMessage(action)); 21 | 22 | return state.set('notifications', 23 | nextNotification.size > MAX_NOTIFICATION_NUMBER 24 | ? nextNotification.setSize(MAX_NOTIFICATION_NUMBER) 25 | : nextNotification 26 | ); 27 | } else if (action.notification) { 28 | const nextNotification = state.get('notifications').unshift(getNextNotificationMessage(action.notification)); 29 | 30 | return state.set('notifications', 31 | nextNotification.size > MAX_NOTIFICATION_NUMBER 32 | ? nextNotification.setSize(MAX_NOTIFICATION_NUMBER) 33 | : nextNotification 34 | ); 35 | } 36 | 37 | switch (action.type) { 38 | case REMOVE_NOTIFICATION: { 39 | const notifications = state.get('notifications').filter((notification) => notification.get('id') !== action.id); 40 | 41 | return state.set('notifications', notifications); 42 | } 43 | default: { 44 | return state; 45 | } 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /src/routes.js: -------------------------------------------------------------------------------- 1 | import { Route, IndexRedirect } from 'react-router'; 2 | 3 | import App from './containers/App'; 4 | import AppsPage from './containers/pages/AppsPage'; 5 | import AuthenticationPage from './containers/pages/AuthenticationPage'; 6 | import { userIsAuthenticated } from './utils/authWrappers.js'; 7 | 8 | export default ( 9 | 13 | 14 | 18 | 22 | 23 | ); 24 | -------------------------------------------------------------------------------- /src/sagas/entitie.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable func-style*/ 2 | 3 | import { takeEvery } from 'redux-saga/effects'; 4 | 5 | function *handleSomething() { 6 | console.info('HANDLERRR'); 7 | yield null; 8 | } 9 | 10 | export function *entitie() { 11 | yield [ 12 | takeEvery('someactiontype', handleSomething), 13 | ]; 14 | } 15 | 16 | export default entitie; 17 | -------------------------------------------------------------------------------- /src/sagas/sagas.js: -------------------------------------------------------------------------------- 1 | import entitie from './entitie'; 2 | 3 | export default function *rootSaga() { 4 | yield [ 5 | entitie(), 6 | ]; 7 | } 8 | -------------------------------------------------------------------------------- /src/schemas/app.js: -------------------------------------------------------------------------------- 1 | import { schema } from 'normalizr'; 2 | 3 | const app = new schema.Entity('app'); 4 | 5 | export default app; 6 | -------------------------------------------------------------------------------- /src/schemas/authUser.js: -------------------------------------------------------------------------------- 1 | import { schema } from 'normalizr'; 2 | 3 | const user = new schema.Entity('authUser'); 4 | 5 | export default user; 6 | -------------------------------------------------------------------------------- /src/selectors/apps.js: -------------------------------------------------------------------------------- 1 | import { createSelector } from 'reselect'; 2 | import Immutable from 'immutable'; 3 | 4 | // TODO in future this logic should be changed to get data by query from location 5 | const getFilteredAppsList = (state) => state.getIn(['entities', 'app']); 6 | 7 | export const getFilteredApps = createSelector( 8 | [getFilteredAppsList], 9 | (apps) => apps && apps.toList() || new Immutable.List() 10 | ); 11 | 12 | const getAppData = (state, props) => state.getIn(['entities', 'apps', props.routeParams.name]); 13 | 14 | export const getApp = createSelector( 15 | [getAppData], 16 | (app) => app || new Immutable.Map() 17 | ); 18 | -------------------------------------------------------------------------------- /src/selectors/users.js: -------------------------------------------------------------------------------- 1 | import { createSelector } from 'reselect'; 2 | import Immutable from 'immutable'; 3 | 4 | const getAuthenticatedUserData = (state) => state.getIn(['entities', 'authUser']).toList().first(); 5 | 6 | export const getAuthenticatedUser = createSelector( 7 | [getAuthenticatedUserData], 8 | (app) => app || new Immutable.Map() 9 | ); 10 | -------------------------------------------------------------------------------- /src/selectors/view.js: -------------------------------------------------------------------------------- 1 | import { createSelector } from 'reselect'; 2 | import Immutable from 'immutable'; 3 | 4 | const getNotificationsList = (state) => state.getIn(['view', 'notifications']); 5 | 6 | export const getNotifications = createSelector( 7 | [getNotificationsList], 8 | (notifications) => notifications || new Immutable.List() 9 | ); 10 | 11 | export const getViewState = (state, viewId) => state.getIn(['dataView', viewId]) || new Immutable.Map(); 12 | -------------------------------------------------------------------------------- /src/store/commonMiddlewares.js: -------------------------------------------------------------------------------- 1 | import thunk from 'redux-thunk'; 2 | import { apiMiddleware } from 'redux-api-middleware'; 3 | import { routerMiddleware } from 'react-router-redux'; 4 | import { browserHistory } from 'react-router'; 5 | import rootReducer from '../reducers'; 6 | import { mockApiMiddleware } from '../mockApi'; 7 | 8 | export const basicMiddleware = [ 9 | rootReducer, 10 | ]; 11 | 12 | export const middlewaresToApply = [ 13 | thunk, 14 | mockApiMiddleware, 15 | apiMiddleware, 16 | routerMiddleware(browserHistory), 17 | ]; 18 | -------------------------------------------------------------------------------- /src/store/configureStore.dev.js: -------------------------------------------------------------------------------- 1 | import { applyMiddleware, compose, createStore } from 'redux'; 2 | import createLogger from 'redux-logger'; 3 | import createSagaMiddleware from 'redux-saga'; 4 | 5 | import { basicMiddleware, middlewaresToApply } from './commonMiddlewares'; 6 | 7 | import DevTools from '../containers/Root/DevTools'; 8 | import rootSaga from '../sagas/sagas'; 9 | 10 | const sagaMiddleware = createSagaMiddleware(); 11 | 12 | export default function configureStore(preloadedState) { 13 | const store = createStore( 14 | ...basicMiddleware, 15 | preloadedState, 16 | compose( 17 | applyMiddleware(...middlewaresToApply, sagaMiddleware, createLogger()), 18 | DevTools.instrument() 19 | ) 20 | ); 21 | 22 | sagaMiddleware.run(rootSaga); 23 | 24 | return store; 25 | } 26 | -------------------------------------------------------------------------------- /src/store/configureStore.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable */ 2 | if (process.env.NODE_ENV === 'production') { 3 | module.exports = require('./configureStore.prod'); 4 | } else { 5 | module.exports = require('./configureStore.dev'); 6 | } 7 | -------------------------------------------------------------------------------- /src/store/configureStore.prod.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from 'redux'; 2 | import createSagaMiddleware from 'redux-saga'; 3 | 4 | import { basicMiddleware, middlewaresToApply } from './commonMiddlewares'; 5 | import rootSaga from '../sagas/sagas'; 6 | const sagaMiddleware = createSagaMiddleware(); 7 | 8 | export default function configureStore(preloadedState) { 9 | const store = createStore( 10 | ...basicMiddleware, 11 | preloadedState, 12 | applyMiddleware(...middlewaresToApply, sagaMiddleware) 13 | ); 14 | 15 | sagaMiddleware.run(rootSaga); 16 | 17 | return store; 18 | } 19 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | ~themeColors: "./uiTheme/pallete.js"; 2 | ~themeSizes: "./uiTheme/sizes.js"; 3 | 4 | html { 5 | background-color: ~themeColors.MAIN_BACKGROUND_COLOR; 6 | } 7 | 8 | body { 9 | min-height: 100vh; 10 | min-width: ~themeSizes.MIN_SUPPORT_SIZE; 11 | } 12 | 13 | ::-webkit-scrollbar { 14 | width: ~themeSizes.SCROLL_SIZE; 15 | } 16 | 17 | ::-webkit-scrollbar-thumb { 18 | background: ~themeColors.SCROLL_THUMB_COLOR; 19 | border-radius: ~themeSizes.DEFAULT_BORDER_RADIUS; 20 | } 21 | 22 | ::-webkit-scrollbar-track { 23 | background-color: ~themeColors.SCROLL_TRACK_COLOR; 24 | } 25 | 26 | ::-webkit-scrollbar:horizontal { 27 | height: ~themeSizes.SCROLL_SIZE; 28 | } 29 | -------------------------------------------------------------------------------- /src/uiTheme/media.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable fp/no-mutation */ 2 | /* eslint-disable import/no-commonjs */ 3 | module.exports = { 4 | media: { 5 | PHONE_MIN: '480px', 6 | PHONE_MAX: '768px', 7 | TABLE_MIN: '768px', 8 | TABLE_MAX: '992px', 9 | DESKTOP_MIN: '992px', 10 | DESKTOP_MAX: '1200px', 11 | LARGE_MIN: '1200px', 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /src/uiTheme/pallete.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable fp/no-mutation */ 2 | /* eslint-disable import/no-commonjs */ 3 | module.exports = { 4 | themeColors: { 5 | MAIN_BACKGROUND_COLOR: 'rgb(43, 43, 43)', 6 | ORANGE: '#f7ad41', 7 | WHITE: 'rgba(255, 255, 255, 0.871)', 8 | ERROR_COLOR: '#fbe3e4', 9 | SCROLL_TRACK_COLOR: '#ddd', 10 | SCROLL_THUMB_COLOR: '#666', 11 | JSON_DARK_BACKGROUND: '#363636', 12 | JSON_DARK_FONT_COLOR: '#797979', 13 | JSON_DARK_MATCH_COLOR: '#435968', 14 | SUB_HEADER_COLOR: '#3e3e3e', 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /src/uiTheme/sizes.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable fp/no-mutation */ 2 | /* eslint-disable import/no-commonjs */ 3 | module.exports = { 4 | themeSizes: { 5 | MIN_SUPPORT_SIZE: '350px', 6 | SCROLL_SIZE: '8px', 7 | DEFAULT_BORDER_RADIUS: '2px', 8 | MAX_BLOCK_WIDTH: '1200px', 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /src/utils/analytic.js: -------------------------------------------------------------------------------- 1 | import ReactGA from 'react-ga'; 2 | import { ANALYTYC_USER_ID } from './../constants/Api'; 3 | 4 | const CATEGORIES = { 5 | USER_ACTIONS: 'User actions', 6 | FORMS: 'Forms actions', 7 | }; 8 | 9 | const defaultConfig = process.env.NODE_ENV === 'production' ? {} : { 10 | options: { 11 | cookieDomain: 'none', 12 | }, 13 | }; 14 | 15 | const eventsHash = { 16 | '@@router/LOCATION_CHANGE': ({ action, sendPageView }) => ( 17 | sendPageView(action.payload.pathname + (action.payload.search || '')) 18 | ), 19 | 'redux-form/FOCUS': ({ action, sendEvent }) => ( 20 | sendEvent('FORMS', `Focus on ${action.meta.field} field in ${action.meta.form}`) 21 | ), 22 | 'redux-form/BLUR': ({ action, sendEvent }) => ( 23 | sendEvent('FORMS', `Blur on ${action.meta.field} field in ${action.meta.form}`) 24 | ), 25 | }; 26 | 27 | class Analytyc { 28 | constructor() { 29 | ReactGA.initialize(ANALYTYC_USER_ID, { 30 | ...defaultConfig, 31 | }); 32 | ReactGA.event({ 33 | category: CATEGORIES.USER_ACTIONS, 34 | action: 'User opened website', 35 | }); 36 | } 37 | 38 | sendPageView(path) { 39 | ReactGA.pageview(path); 40 | } 41 | 42 | sendEvent(category, action) { 43 | ReactGA.event({ 44 | category: CATEGORIES[category] || 'Unknown', 45 | action, 46 | }); 47 | } 48 | 49 | handleEvent(action) { 50 | if (eventsHash[action.type]) { 51 | eventsHash[action.type]({ 52 | action, 53 | sendEvent: this.sendEvent, 54 | sendPageView: this.sendPageView, 55 | }); 56 | } 57 | } 58 | } 59 | 60 | export default (new Analytyc()); 61 | -------------------------------------------------------------------------------- /src/utils/authWrappers.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable new-cap */ 2 | import { replace } from 'react-router-redux'; 3 | import { UserAuthWrapper } from 'redux-auth-wrapper'; 4 | 5 | import { getAuthenticatedUser } from './../selectors/users'; 6 | import userUtils from './userUtils'; 7 | 8 | export const userIsAuthenticated = UserAuthWrapper({ 9 | authSelector: getAuthenticatedUser, 10 | predicate: userUtils.isAuthenticated, 11 | redirectAction: replace, 12 | wrapperDisplayName: 'UserIsAuthenticated', 13 | }); 14 | -------------------------------------------------------------------------------- /src/utils/dom/scrollUtils.js: -------------------------------------------------------------------------------- 1 | import $ from 'jquery'; 2 | const SCROLL_DELAY = 1000; 3 | 4 | export const scrollToElement = ({ containerSelector = 'html, body', element }) => { 5 | $(containerSelector).animate({ 6 | scrollTop: $(element).offset() && $(element).offset().top, 7 | }, SCROLL_DELAY); 8 | }; 9 | -------------------------------------------------------------------------------- /src/utils/forms/validation.js: -------------------------------------------------------------------------------- 1 | const MIN_LOGIN_LENGTH = 4; 2 | const MIN_PASSWORD_LENGTH = 6; 3 | 4 | const validateLogin = (login) => { 5 | if (!login) { 6 | return 'Required'; 7 | } 8 | 9 | return login.length < MIN_LOGIN_LENGTH ? 'Login is too short' : ''; 10 | }; 11 | 12 | const validatePassword = (password) => { 13 | if (!password) { 14 | return 'Required'; 15 | } 16 | 17 | return password.length < MIN_PASSWORD_LENGTH ? 'Password is too short' : ''; 18 | }; 19 | 20 | export const loginValidation = (vals) => { 21 | const values = vals.toJS(); 22 | 23 | return { 24 | login: validateLogin(values.login), 25 | password: validatePassword(values.password), 26 | }; 27 | }; 28 | 29 | export const schemaConstructorValidation = (vals) => { 30 | const values = vals.toJS(); 31 | 32 | return { 33 | name: !values.name ? 'Required' : '', 34 | namespace: !values.namespace ? 'Required' : '', 35 | }; 36 | }; 37 | 38 | export const addFieldValidation = (vals) => { 39 | const values = vals.toJS(); 40 | 41 | return { 42 | fieldName: !values.fieldName ? 'Required' : '', 43 | fieldType: !values.fieldType ? 'Required' : '', 44 | }; 45 | }; 46 | -------------------------------------------------------------------------------- /src/utils/localStorageUtils.js: -------------------------------------------------------------------------------- 1 | import Immutable from 'immutable'; 2 | const APP_KEY = 'globalApp'; 3 | const emptyApp = { 4 | authUser: {}, 5 | customData: {}, 6 | }; 7 | 8 | class LocalStorageUtils { 9 | constructor() { 10 | const app = this.getApp(); 11 | 12 | if (!app) { 13 | this.safeSave(APP_KEY, emptyApp); 14 | } 15 | } 16 | 17 | setAuthinticatedUser(user) { 18 | const app = this.getApp(); 19 | 20 | this.setApp({ ...app, authUser: user && user.toJS && user.toJS() }); 21 | } 22 | 23 | getAuthinticatedUser() { 24 | const app = this.getApp(); 25 | 26 | return Immutable.fromJS(app.authUser); 27 | } 28 | 29 | getApp() { 30 | return this.safeParse(localStorage.getItem(APP_KEY)); 31 | } 32 | 33 | setApp(app) { 34 | this.safeSave(APP_KEY, app); 35 | } 36 | 37 | setCustomValue(key, value) { 38 | const app = this.getApp(); 39 | 40 | this.setApp({ ...app, customData: { ...app.customData, key: value } }); 41 | } 42 | 43 | getCustomValue(key) { 44 | const app = this.getApp(); 45 | 46 | return app.customData[key]; 47 | } 48 | 49 | safeParse(data) { 50 | try { 51 | return JSON.parse(data); 52 | } catch (err) { 53 | console.error('INVALID DATA TO PARSE'); 54 | 55 | return emptyApp; 56 | } 57 | } 58 | 59 | safeSave(key, data) { 60 | localStorage.setItem(key, JSON.stringify(data)); 61 | } 62 | } 63 | 64 | export default (new LocalStorageUtils()); 65 | -------------------------------------------------------------------------------- /src/utils/schemaUtils.js: -------------------------------------------------------------------------------- 1 | import { normalize } from 'normalizr'; 2 | import Immutable from 'immutable'; 3 | 4 | import { NOT_FOUND, EMPTY_VALUE } from './../constants/Constants'; 5 | import { APPS, USER } from './../constants/MappersTypes'; 6 | 7 | import { mapApps } from './../mappers/apps'; 8 | import { mapUser } from './../mappers/users'; 9 | 10 | const hash = { 11 | [APPS]: (data) => mapApps(data), 12 | [USER]: (data) => mapUser(data), 13 | }; 14 | 15 | class SchemaUtils { 16 | getSuccessActionTypeWithSchema({ type, schema, meta }) { 17 | return { 18 | type, 19 | meta, 20 | payload: (action, state, res) => { 21 | const contentType = res.headers.get('Content-Type'); 22 | 23 | if (contentType && contentType.indexOf('json') !== NOT_FOUND) { 24 | return res.json().then((json) => { 25 | const mappedData = (hash[meta.mapperType] && hash[meta.mapperType](json)) || json; 26 | 27 | return Immutable.fromJS(normalize(mappedData, schema)); 28 | }); 29 | } 30 | 31 | return EMPTY_VALUE; 32 | }, 33 | }; 34 | } 35 | } 36 | 37 | const schemaUtils = new SchemaUtils(); 38 | 39 | export default schemaUtils; 40 | -------------------------------------------------------------------------------- /src/utils/userUtils.js: -------------------------------------------------------------------------------- 1 | import moment from 'moment'; 2 | 3 | class UserUtils { 4 | isAuthenticated(userData) { 5 | if (!userData) { 6 | return false; 7 | } 8 | const now = moment(); 9 | const isExpired = userData.get('expires') && now.isBefore(moment(userData.get('expires'))); 10 | 11 | return userData.get('login') && !isExpired; 12 | } 13 | } 14 | 15 | 16 | export default new UserUtils(); 17 | -------------------------------------------------------------------------------- /test/e2e/runTest.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable dot-location */ 2 | /* eslint-disable import/no-commonjs */ 3 | /* eslint-disable strict */ 4 | /* eslint-disable fp/no-let */ 5 | /* eslint-disable fp/no-mutation */ 6 | 7 | 'use strict'; 8 | 9 | let url = 'http://localhost:3001'; 10 | 11 | module.exports = { 12 | before(browser) { 13 | url = browser.launch_url; 14 | }, 15 | 'Example run'(browser) { 16 | browser 17 | .url(url) 18 | .end(); 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /test/testHelper.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable fp/no-mutation */ 2 | import 'babel-polyfill'; 3 | import React from 'react'; 4 | import { jsdom } from 'jsdom'; 5 | 6 | import chai, { assert, expect } from 'chai'; 7 | import chaiString from 'chai-string'; 8 | import chaiAsPromised from 'chai-as-promised'; 9 | import sinon from 'sinon'; 10 | 11 | chai.use(chaiAsPromised); 12 | 13 | chai.use(chaiString); 14 | 15 | global.assert = assert; 16 | global.expect = expect; 17 | global.sinon = sinon; 18 | global.React = React; 19 | 20 | require.extensions['.scss'] = () => {}; 21 | require.extensions['.less'] = () => {}; 22 | require.extensions['.css'] = () => {}; 23 | require.extensions['.svg'] = () => {}; 24 | require.extensions['.png'] = () => {}; 25 | require.extensions['.jpg'] = () => {}; 26 | 27 | const exposedProperties = ['navigator', 'document']; 28 | 29 | global.document = jsdom(''); 30 | global.window = document.defaultView; 31 | 32 | Object.keys(document.defaultView).forEach((property) => { 33 | if (typeof global[property] === 'undefined') { 34 | exposedProperties.push(property); 35 | global[property] = document.defaultView[property]; 36 | } 37 | }); 38 | 39 | global.navigator = { 40 | userAgent: 'node.js', 41 | }; 42 | -------------------------------------------------------------------------------- /testserver.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-commonjs */ 2 | /* eslint-disable global-require */ 3 | /* eslint-disable import/no-nodejs-modules */ 4 | /* eslint-disable no-param-reassign */ 5 | /* eslint-disable callback-return */ 6 | /* eslint-disable fp/no-mutation */ 7 | /* eslint-disable import/no-extraneous-dependencies */ 8 | 9 | const PORT = 3001; 10 | 11 | const express = require('express'); 12 | const bodyParser = require('body-parser'); 13 | const path = require('path'); 14 | const app = express(); 15 | const ZERO = 0; 16 | 17 | app.use(bodyParser.urlencoded({ extended: false })); 18 | 19 | app.use((req, res, next) => { 20 | if (path.extname(req.path).length > ZERO) { 21 | next(); 22 | } else { 23 | req.url = '/index.html'; 24 | next(); 25 | } 26 | }); 27 | 28 | app.use(express.static(path.join(__dirname, '/dist'))); 29 | app.listen(PORT, (error) => { 30 | if (error) { 31 | console.error(error); 32 | } else { 33 | console.info('==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.', PORT); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /vendorModules/flot/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to Flot ## 2 | 3 | We welcome all contributions, but following these guidelines results in less 4 | work for us, and a faster and better response. 5 | 6 | ### Issues ### 7 | 8 | Issues are not a way to ask general questions about Flot. If you see unexpected 9 | behavior but are not 100% certain that it is a bug, please try posting to the 10 | [forum](http://groups.google.com/group/flot-graphs) first, and confirm that 11 | what you see is really a Flot problem before creating a new issue for it. When 12 | reporting a bug, please include a working demonstration of the problem, if 13 | possible, or at least a clear description of the options you're using and the 14 | environment (browser and version, jQuery version, other libraries) that you're 15 | running under. 16 | 17 | If you have suggestions for new features, or changes to existing ones, we'd 18 | love to hear them! Please submit each suggestion as a separate new issue. 19 | 20 | If you would like to work on an existing issue, please make sure it is not 21 | already assigned to someone else. If an issue is assigned to someone, that 22 | person has already started working on it. So, pick unassigned issues to prevent 23 | duplicated effort. 24 | 25 | ### Pull Requests ### 26 | 27 | To make merging as easy as possible, please keep these rules in mind: 28 | 29 | 1. Submit new features or architectural changes to the *<version>-work* 30 | branch for the next major release. Submit bug fixes to the master branch. 31 | 32 | 2. Divide larger changes into a series of small, logical commits with 33 | descriptive messages. 34 | 35 | 3. Rebase, if necessary, before submitting your pull request, to reduce the 36 | work we need to do to merge it. 37 | 38 | 4. Format your code according to the style guidelines below. 39 | 40 | ### Flot Style Guidelines ### 41 | 42 | Flot follows the [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines), 43 | with the following updates and exceptions: 44 | 45 | #### Spacing #### 46 | 47 | Use four-space indents, no tabs. Do not add horizontal space around parameter 48 | lists, loop definitions, or array/object indices. For example: 49 | 50 | ```js 51 | for ( var i = 0; i < data.length; i++ ) { // This block is wrong! 52 | if ( data[ i ] > 1 ) { 53 | data[ i ] = 2; 54 | } 55 | } 56 | 57 | for (var i = 0; i < data.length; i++) { // This block is correct! 58 | if (data[i] > 1) { 59 | data[i] = 2; 60 | } 61 | } 62 | ``` 63 | 64 | #### Comments #### 65 | 66 | Use [jsDoc](http://usejsdoc.org) comments for all file and function headers. 67 | Use // for all inline and block comments, regardless of length. 68 | 69 | All // comment blocks should have an empty line above *and* below them. For 70 | example: 71 | 72 | ```js 73 | var a = 5; 74 | 75 | // We're going to loop here 76 | // TODO: Make this loop faster, better, stronger! 77 | 78 | for (var x = 0; x < 10; x++) {} 79 | ``` 80 | 81 | #### Wrapping #### 82 | 83 | Block comments should be wrapped at 80 characters. 84 | 85 | Code should attempt to wrap at 80 characters, but may run longer if wrapping 86 | would hurt readability more than having to scroll horizontally. This is a 87 | judgement call made on a situational basis. 88 | 89 | Statements containing complex logic should not be wrapped arbitrarily if they 90 | do not exceed 80 characters. For example: 91 | 92 | ```js 93 | if (a == 1 && // This block is wrong! 94 | b == 2 && 95 | c == 3) {} 96 | 97 | if (a == 1 && b == 2 && c == 3) {} // This block is correct! 98 | ``` 99 | -------------------------------------------------------------------------------- /vendorModules/flot/FAQ.md: -------------------------------------------------------------------------------- 1 | ## Frequently asked questions ## 2 | 3 | #### How much data can Flot cope with? #### 4 | 5 | Flot will happily draw everything you send to it so the answer 6 | depends on the browser. The excanvas emulation used for IE (built with 7 | VML) makes IE by far the slowest browser so be sure to test with that 8 | if IE users are in your target group (for large plots in IE, you can 9 | also check out Flashcanvas which may be faster). 10 | 11 | 1000 points is not a problem, but as soon as you start having more 12 | points than the pixel width, you should probably start thinking about 13 | downsampling/aggregation as this is near the resolution limit of the 14 | chart anyway. If you downsample server-side, you also save bandwidth. 15 | 16 | 17 | #### Flot isn't working when I'm using JSON data as source! #### 18 | 19 | Actually, Flot loves JSON data, you just got the format wrong. 20 | Double check that you're not inputting strings instead of numbers, 21 | like [["0", "-2.13"], ["5", "4.3"]]. This is most common mistake, and 22 | the error might not show up immediately because Javascript can do some 23 | conversion automatically. 24 | 25 | 26 | #### Can I export the graph? #### 27 | 28 | You can grab the image rendered by the canvas element used by Flot 29 | as a PNG or JPEG (remember to set a background). Note that it won't 30 | include anything not drawn in the canvas (such as the legend). And it 31 | doesn't work with excanvas which uses VML, but you could try 32 | Flashcanvas. 33 | 34 | 35 | #### The bars are all tiny in time mode? #### 36 | 37 | It's not really possible to determine the bar width automatically. 38 | So you have to set the width with the barWidth option which is NOT in 39 | pixels, but in the units of the x axis (or the y axis for horizontal 40 | bars). For time mode that's milliseconds so the default value of 1 41 | makes the bars 1 millisecond wide. 42 | 43 | 44 | #### Can I use Flot with libraries like Mootools or Prototype? #### 45 | 46 | Yes, Flot supports it out of the box and it's easy! Just use jQuery 47 | instead of $, e.g. call jQuery.plot instead of $.plot and use 48 | jQuery(something) instead of $(something). As a convenience, you can 49 | put in a DOM element for the graph placeholder where the examples and 50 | the API documentation are using jQuery objects. 51 | 52 | Depending on how you include jQuery, you may have to add one line of 53 | code to prevent jQuery from overwriting functions from the other 54 | libraries, see the documentation in jQuery ("Using jQuery with other 55 | libraries") for details. 56 | 57 | 58 | #### Flot doesn't work with [insert name of Javascript UI framework]! #### 59 | 60 | Flot is using standard HTML to make charts. If this is not working, 61 | it's probably because the framework you're using is doing something 62 | weird with the DOM or with the CSS that is interfering with Flot. 63 | 64 | A common problem is that there's display:none on a container until the 65 | user does something. Many tab widgets work this way, and there's 66 | nothing wrong with it - you just can't call Flot inside a display:none 67 | container as explained in the README so you need to hold off the Flot 68 | call until the container is actually displayed (or use 69 | visibility:hidden instead of display:none or move the container 70 | off-screen). 71 | 72 | If you find there's a specific thing we can do to Flot to help, feel 73 | free to submit a bug report. Otherwise, you're welcome to ask for help 74 | on the forum/mailing list, but please don't submit a bug report to 75 | Flot. 76 | -------------------------------------------------------------------------------- /vendorModules/flot/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2014 IOLA and Ole Laursen 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendorModules/flot/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for generating minified files 2 | 3 | .PHONY: all 4 | 5 | # we cheat and process all .js files instead of an exhaustive list 6 | all: $(patsubst %.js,%.min.js,$(filter-out %.min.js,$(wildcard *.js))) 7 | 8 | %.min.js: %.js 9 | yui-compressor $< -o $@ 10 | 11 | test: 12 | ./node_modules/.bin/jshint *jquery.flot.js 13 | -------------------------------------------------------------------------------- /vendorModules/flot/README.md: -------------------------------------------------------------------------------- 1 | # Flot [![Build status](https://travis-ci.org/flot/flot.png)](https://travis-ci.org/flot/flot) 2 | 3 | ## About ## 4 | 5 | Flot is a Javascript plotting library for jQuery. 6 | Read more at the website: 7 | 8 | Take a look at the the examples in examples/index.html; they should give a good 9 | impression of what Flot can do, and the source code of the examples is probably 10 | the fastest way to learn how to use Flot. 11 | 12 | 13 | ## Installation ## 14 | 15 | Just include the Javascript file after you've included jQuery. 16 | 17 | Generally, all browsers that support the HTML5 canvas tag are 18 | supported. 19 | 20 | For support for Internet Explorer < 9, you can use [Excanvas] 21 | [excanvas], a canvas emulator; this is used in the examples bundled 22 | with Flot. You just include the excanvas script like this: 23 | 24 | ```html 25 | 26 | ``` 27 | 28 | If it's not working on your development IE 6.0, check that it has 29 | support for VML which Excanvas is relying on. It appears that some 30 | stripped down versions used for test environments on virtual machines 31 | lack the VML support. 32 | 33 | You can also try using [Flashcanvas][flashcanvas], which uses Flash to 34 | do the emulation. Although Flash can be a bit slower to load than VML, 35 | if you've got a lot of points, the Flash version can be much faster 36 | overall. Flot contains some wrapper code for activating Excanvas which 37 | Flashcanvas is compatible with. 38 | 39 | You need at least jQuery 1.2.6, but try at least 1.3.2 for interactive 40 | charts because of performance improvements in event handling. 41 | 42 | 43 | ## Basic usage ## 44 | 45 | Create a placeholder div to put the graph in: 46 | 47 | ```html 48 |
49 | ``` 50 | 51 | You need to set the width and height of this div, otherwise the plot 52 | library doesn't know how to scale the graph. You can do it inline like 53 | this: 54 | 55 | ```html 56 |
57 | ``` 58 | 59 | You can also do it with an external stylesheet. Make sure that the 60 | placeholder isn't within something with a display:none CSS property - 61 | in that case, Flot has trouble measuring label dimensions which 62 | results in garbled looks and might have trouble measuring the 63 | placeholder dimensions which is fatal (it'll throw an exception). 64 | 65 | Then when the div is ready in the DOM, which is usually on document 66 | ready, run the plot function: 67 | 68 | ```js 69 | $.plot($("#placeholder"), data, options); 70 | ``` 71 | 72 | Here, data is an array of data series and options is an object with 73 | settings if you want to customize the plot. Take a look at the 74 | examples for some ideas of what to put in or look at the 75 | [API reference](API.md). Here's a quick example that'll draw a line 76 | from (0, 0) to (1, 1): 77 | 78 | ```js 79 | $.plot($("#placeholder"), [ [[0, 0], [1, 1]] ], { yaxis: { max: 1 } }); 80 | ``` 81 | 82 | The plot function immediately draws the chart and then returns a plot 83 | object with a couple of methods. 84 | 85 | 86 | ## What's with the name? ## 87 | 88 | First: it's pronounced with a short o, like "plot". Not like "flawed". 89 | 90 | So "Flot" rhymes with "plot". 91 | 92 | And if you look up "flot" in a Danish-to-English dictionary, some of 93 | the words that come up are "good-looking", "attractive", "stylish", 94 | "smart", "impressive", "extravagant". One of the main goals with Flot 95 | is pretty looks. 96 | 97 | 98 | ## Notes about the examples ## 99 | 100 | In order to have a useful, functional example of time-series plots using time 101 | zones, date.js from [timezone-js][timezone-js] (released under the Apache 2.0 102 | license) and the [Olson][olson] time zone database (released to the public 103 | domain) have been included in the examples directory. They are used in 104 | examples/axes-time-zones/index.html. 105 | 106 | 107 | [excanvas]: http://code.google.com/p/explorercanvas/ 108 | [flashcanvas]: http://code.google.com/p/flashcanvas/ 109 | [timezone-js]: https://github.com/mde/timezone-js 110 | [olson]: http://ftp.iana.org/time-zones 111 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/ajax/data-eu-gdp-growth-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Europe (EU27)", 3 | "data": [[1999, 3.0], [2000, 3.9]] 4 | } 5 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/ajax/data-eu-gdp-growth-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Europe (EU27)", 3 | "data": [[1999, 3.0], [2000, 3.9], [2001, 2.0], [2002, 1.2]] 4 | } 5 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/ajax/data-eu-gdp-growth-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Europe (EU27)", 3 | "data": [[1999, 3.0], [2000, 3.9], [2001, 2.0], [2002, 1.2], [2003, 1.3], [2004, 2.5]] 4 | } 5 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/ajax/data-eu-gdp-growth-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Europe (EU27)", 3 | "data": [[1999, 3.0], [2000, 3.9], [2001, 2.0], [2002, 1.2], [2003, 1.3], [2004, 2.5], [2005, 2.0], [2006, 3.1]] 4 | } 5 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/ajax/data-eu-gdp-growth-5.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Europe (EU27)", 3 | "data": [[1999, 3.0], [2000, 3.9], [2001, 2.0], [2002, 1.2], [2003, 1.3], [2004, 2.5], [2005, 2.0], [2006, 3.1], [2007, 2.9], [2008, 0.9]] 4 | } 5 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/ajax/data-eu-gdp-growth.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Europe (EU27)", 3 | "data": [[1999, 3.0], [2000, 3.9], [2001, 2.0], [2002, 1.2], [2003, 1.3], [2004, 2.5], [2005, 2.0], [2006, 3.1], [2007, 2.9], [2008, 0.9]] 4 | } 5 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/ajax/data-japan-gdp-growth.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Japan", 3 | "data": [[1999, -0.1], [2000, 2.9], [2001, 0.2], [2002, 0.3], [2003, 1.4], [2004, 2.7], [2005, 1.9], [2006, 2.0], [2007, 2.3], [2008, -0.7]] 4 | } 5 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/ajax/data-usa-gdp-growth.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "USA", 3 | "data": [[1999, 4.4], [2000, 3.7], [2001, 0.8], [2002, 1.6], [2003, 2.5], [2004, 3.6], [2005, 2.9], [2006, 2.8], [2007, 2.0], [2008, 1.1]] 4 | } 5 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/annotating/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Adding Annotations 6 | 7 | 8 | 9 | 10 | 65 | 66 | 67 | 68 | 71 | 72 |
73 | 74 |
75 |
76 |
77 | 78 |

Flot has support for simple background decorations such as lines and rectangles. They can be useful for marking up certain areas. You can easily add any HTML you need with standard DOM manipulation, e.g. for labels. For drawing custom shapes there is also direct access to the canvas.

79 | 80 |
81 | 82 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/axes-interacting/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Interacting with axes 6 | 7 | 8 | 9 | 10 | 71 | 72 | 73 | 74 | 77 | 78 |
79 | 80 |
81 |
82 |
83 | 84 |

With multiple axes, you sometimes need to interact with them. A simple way to do this is to draw the plot, deduce the axis placements and insert a couple of divs on top to catch events.

85 | 86 |

Try clicking an axis.

87 | 88 |

89 | 90 |
91 | 92 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/axes-time-zones/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Time zones 6 | 7 | 8 | 9 | 10 | 11 | 12 | 83 | 84 | 85 | 86 | 89 | 90 |
91 | 92 |

UTC

93 |
94 |
95 |
96 | 97 |

Browser

98 |
99 |
100 |
101 | 102 |

Chicago

103 |
104 |
105 |
106 | 107 |
108 | 109 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/axes-time-zones/tz/etcetera: -------------------------------------------------------------------------------- 1 | #
 2 | # This file is in the public domain, so clarified as of
 3 | # 2009-05-17 by Arthur David Olson.
 4 | 
 5 | # These entries are mostly present for historical reasons, so that
 6 | # people in areas not otherwise covered by the tz files could "zic -l"
 7 | # to a time zone that was right for their area.  These days, the
 8 | # tz files cover almost all the inhabited world, and the only practical
 9 | # need now for the entries that are not on UTC are for ships at sea
10 | # that cannot use POSIX TZ settings.
11 | 
12 | Zone	Etc/GMT		0	-	GMT
13 | Zone	Etc/UTC		0	-	UTC
14 | Zone	Etc/UCT		0	-	UCT
15 | 
16 | # The following link uses older naming conventions,
17 | # but it belongs here, not in the file `backward',
18 | # as functions like gmtime load the "GMT" file to handle leap seconds properly.
19 | # We want this to work even on installations that omit the other older names.
20 | Link	Etc/GMT				GMT
21 | 
22 | Link	Etc/UTC				Etc/Universal
23 | Link	Etc/UTC				Etc/Zulu
24 | 
25 | Link	Etc/GMT				Etc/Greenwich
26 | Link	Etc/GMT				Etc/GMT-0
27 | Link	Etc/GMT				Etc/GMT+0
28 | Link	Etc/GMT				Etc/GMT0
29 | 
30 | # We use POSIX-style signs in the Zone names and the output abbreviations,
31 | # even though this is the opposite of what many people expect.
32 | # POSIX has positive signs west of Greenwich, but many people expect
33 | # positive signs east of Greenwich.  For example, TZ='Etc/GMT+4' uses
34 | # the abbreviation "GMT+4" and corresponds to 4 hours behind UTC
35 | # (i.e. west of Greenwich) even though many people would expect it to
36 | # mean 4 hours ahead of UTC (i.e. east of Greenwich).
37 | #
38 | # In the draft 5 of POSIX 1003.1-200x, the angle bracket notation allows for
39 | # TZ='+4'; if you want time zone abbreviations conforming to
40 | # ISO 8601 you can use TZ='<-0400>+4'.  Thus the commonly-expected
41 | # offset is kept within the angle bracket (and is used for display)
42 | # while the POSIX sign is kept outside the angle bracket (and is used
43 | # for calculation).
44 | #
45 | # Do not use a TZ setting like TZ='GMT+4', which is four hours behind
46 | # GMT but uses the completely misleading abbreviation "GMT".
47 | 
48 | # Earlier incarnations of this package were not POSIX-compliant,
49 | # and had lines such as
50 | #		Zone	GMT-12		-12	-	GMT-1200
51 | # We did not want things to change quietly if someone accustomed to the old
52 | # way does a
53 | #		zic -l GMT-12
54 | # so we moved the names into the Etc subdirectory.
55 | 
56 | Zone	Etc/GMT-14	14	-	GMT-14	# 14 hours ahead of GMT
57 | Zone	Etc/GMT-13	13	-	GMT-13
58 | Zone	Etc/GMT-12	12	-	GMT-12
59 | Zone	Etc/GMT-11	11	-	GMT-11
60 | Zone	Etc/GMT-10	10	-	GMT-10
61 | Zone	Etc/GMT-9	9	-	GMT-9
62 | Zone	Etc/GMT-8	8	-	GMT-8
63 | Zone	Etc/GMT-7	7	-	GMT-7
64 | Zone	Etc/GMT-6	6	-	GMT-6
65 | Zone	Etc/GMT-5	5	-	GMT-5
66 | Zone	Etc/GMT-4	4	-	GMT-4
67 | Zone	Etc/GMT-3	3	-	GMT-3
68 | Zone	Etc/GMT-2	2	-	GMT-2
69 | Zone	Etc/GMT-1	1	-	GMT-1
70 | Zone	Etc/GMT+1	-1	-	GMT+1
71 | Zone	Etc/GMT+2	-2	-	GMT+2
72 | Zone	Etc/GMT+3	-3	-	GMT+3
73 | Zone	Etc/GMT+4	-4	-	GMT+4
74 | Zone	Etc/GMT+5	-5	-	GMT+5
75 | Zone	Etc/GMT+6	-6	-	GMT+6
76 | Zone	Etc/GMT+7	-7	-	GMT+7
77 | Zone	Etc/GMT+8	-8	-	GMT+8
78 | Zone	Etc/GMT+9	-9	-	GMT+9
79 | Zone	Etc/GMT+10	-10	-	GMT+10
80 | Zone	Etc/GMT+11	-11	-	GMT+11
81 | Zone	Etc/GMT+12	-12	-	GMT+12
82 | 


--------------------------------------------------------------------------------
/vendorModules/flot/examples/axes-time-zones/tz/factory:
--------------------------------------------------------------------------------
 1 | # 
 2 | # This file is in the public domain, so clarified as of
 3 | # 2009-05-17 by Arthur David Olson.
 4 | 
 5 | # For companies who don't want to put time zone specification in
 6 | # their installation procedures.  When users run date, they'll get the message.
 7 | # Also useful for the "comp.sources" version.
 8 | 
 9 | # Zone	NAME	GMTOFF	RULES	FORMAT
10 | Zone	Factory	0	- "Local time zone must be set--see zic manual page"
11 | 


--------------------------------------------------------------------------------
/vendorModules/flot/examples/axes-time-zones/tz/leapseconds:
--------------------------------------------------------------------------------
  1 | # 
  2 | # This file is in the public domain, so clarified as of
  3 | # 2009-05-17 by Arthur David Olson.
  4 | 
  5 | # Allowance for leapseconds added to each timezone file.
  6 | 
  7 | # The International Earth Rotation Service periodically uses leap seconds
  8 | # to keep UTC to within 0.9 s of UT1
  9 | # (which measures the true angular orientation of the earth in space); see
 10 | # Terry J Quinn, The BIPM and the accurate measure of time,
 11 | # Proc IEEE 79, 7 (July 1991), 894-905.
 12 | # There were no leap seconds before 1972, because the official mechanism
 13 | # accounting for the discrepancy between atomic time and the earth's rotation
 14 | # did not exist until the early 1970s.
 15 | 
 16 | # The correction (+ or -) is made at the given time, so lines
 17 | # will typically look like:
 18 | #	Leap	YEAR	MON	DAY	23:59:60	+	R/S
 19 | # or
 20 | #	Leap	YEAR	MON	DAY	23:59:59	-	R/S
 21 | 
 22 | # If the leapsecond is Rolling (R) the given time is local time
 23 | # If the leapsecond is Stationary (S) the given time is UTC
 24 | 
 25 | # Leap	YEAR	MONTH	DAY	HH:MM:SS	CORR	R/S
 26 | Leap	1972	Jun	30	23:59:60	+	S
 27 | Leap	1972	Dec	31	23:59:60	+	S
 28 | Leap	1973	Dec	31	23:59:60	+	S
 29 | Leap	1974	Dec	31	23:59:60	+	S
 30 | Leap	1975	Dec	31	23:59:60	+	S
 31 | Leap	1976	Dec	31	23:59:60	+	S
 32 | Leap	1977	Dec	31	23:59:60	+	S
 33 | Leap	1978	Dec	31	23:59:60	+	S
 34 | Leap	1979	Dec	31	23:59:60	+	S
 35 | Leap	1981	Jun	30	23:59:60	+	S
 36 | Leap	1982	Jun	30	23:59:60	+	S
 37 | Leap	1983	Jun	30	23:59:60	+	S
 38 | Leap	1985	Jun	30	23:59:60	+	S
 39 | Leap	1987	Dec	31	23:59:60	+	S
 40 | Leap	1989	Dec	31	23:59:60	+	S
 41 | Leap	1990	Dec	31	23:59:60	+	S
 42 | Leap	1992	Jun	30	23:59:60	+	S
 43 | Leap	1993	Jun	30	23:59:60	+	S
 44 | Leap	1994	Jun	30	23:59:60	+	S
 45 | Leap	1995	Dec	31	23:59:60	+	S
 46 | Leap	1997	Jun	30	23:59:60	+	S
 47 | Leap	1998	Dec	31	23:59:60	+	S
 48 | Leap	2005	Dec	31	23:59:60	+	S
 49 | Leap	2008	Dec	31	23:59:60	+	S
 50 | Leap	2012	Jun	30	23:59:60	+	S
 51 | 
 52 | # INTERNATIONAL EARTH ROTATION AND REFERENCE SYSTEMS SERVICE (IERS)
 53 | #
 54 | # SERVICE INTERNATIONAL DE LA ROTATION TERRESTRE ET DES SYSTEMES DE REFERENCE
 55 | #
 56 | #
 57 | # SERVICE DE LA ROTATION TERRESTRE
 58 | # OBSERVATOIRE DE PARIS
 59 | # 61, Av. de l'Observatoire 75014 PARIS (France)
 60 | # Tel.      : 33 (0) 1 40 51 22 26
 61 | # FAX       : 33 (0) 1 40 51 22 91
 62 | # e-mail    : (E-Mail Removed)
 63 | # http://hpiers.obspm.fr/eop-pc
 64 | #
 65 | # Paris, 5 January 2012
 66 | #
 67 | #
 68 | # Bulletin C 43
 69 | #
 70 | # To authorities responsible
 71 | # for the measurement and
 72 | # distribution of time
 73 | #
 74 | #
 75 | # UTC TIME STEP
 76 | # on the 1st of July 2012
 77 | #
 78 | #
 79 | # A positive leap second will be introduced at the end of June 2012.
 80 | # The sequence of dates of the UTC second markers will be:
 81 | #
 82 | #                          2012 June 30,     23h 59m 59s
 83 | #                          2012 June 30,     23h 59m 60s
 84 | #                          2012 July  1,      0h  0m  0s
 85 | #
 86 | # The difference between UTC and the International Atomic Time TAI is:
 87 | #
 88 | # from 2009 January 1, 0h UTC, to 2012 July 1  0h UTC  : UTC-TAI = - 34s
 89 | # from 2012 July 1,    0h UTC, until further notice    : UTC-TAI = - 35s
 90 | #
 91 | # Leap seconds can be introduced in UTC at the end of the months of December
 92 | # or June, depending on the evolution of UT1-TAI. Bulletin C is mailed every
 93 | # six months, either to announce a time step in UTC or to confirm that there
 94 | # will be no time step at the next possible date.
 95 | #
 96 | #
 97 | # Daniel GAMBIS
 98 | # Head
 99 | # Earth Orientation Center of IERS
100 | # Observatoire de Paris, France
101 | 


--------------------------------------------------------------------------------
/vendorModules/flot/examples/axes-time-zones/tz/pacificnew:
--------------------------------------------------------------------------------
 1 | # 
 2 | # This file is in the public domain, so clarified as of
 3 | # 2009-05-17 by Arthur David Olson.
 4 | 
 5 | # From Arthur David Olson (1989-04-05):
 6 | # On 1989-04-05, the U. S. House of Representatives passed (238-154) a bill
 7 | # establishing "Pacific Presidential Election Time"; it was not acted on
 8 | # by the Senate or signed into law by the President.
 9 | # You might want to change the "PE" (Presidential Election) below to
10 | # "Q" (Quadrennial) to maintain three-character zone abbreviations.
11 | # If you're really conservative, you might want to change it to "D".
12 | # Avoid "L" (Leap Year), which won't be true in 2100.
13 | 
14 | # If Presidential Election Time is ever established, replace "XXXX" below
15 | # with the year the law takes effect and uncomment the "##" lines.
16 | 
17 | # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
18 | ## Rule	Twilite	XXXX	max	-	Apr	Sun>=1	2:00	1:00	D
19 | ## Rule	Twilite	XXXX	max	uspres	Oct	lastSun	2:00	1:00	PE
20 | ## Rule	Twilite	XXXX	max	uspres	Nov	Sun>=7	2:00	0	S
21 | ## Rule	Twilite	XXXX	max	nonpres	Oct	lastSun	2:00	0	S
22 | 
23 | # Zone	NAME			GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
24 | ## Zone	America/Los_Angeles-PET	-8:00	US		P%sT	XXXX
25 | ##				-8:00	Twilite		P%sT
26 | 
27 | # For now...
28 | Link	America/Los_Angeles	US/Pacific-New	##
29 | 


--------------------------------------------------------------------------------
/vendorModules/flot/examples/axes-time-zones/tz/southamerica:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/vendorModules/flot/examples/axes-time-zones/tz/southamerica


--------------------------------------------------------------------------------
/vendorModules/flot/examples/axes-time-zones/tz/systemv:
--------------------------------------------------------------------------------
 1 | # 
 2 | # This file is in the public domain, so clarified as of
 3 | # 2009-05-17 by Arthur David Olson.
 4 | 
 5 | # Old rules, should the need arise.
 6 | # No attempt is made to handle Newfoundland, since it cannot be expressed
 7 | # using the System V "TZ" scheme (half-hour offset), or anything outside
 8 | # North America (no support for non-standard DST start/end dates), nor
 9 | # the changes in the DST rules in the US after 1976 (which occurred after
10 | # the old rules were written).
11 | #
12 | # If you need the old rules, uncomment ## lines.
13 | # Compile this *without* leap second correction for true conformance.
14 | 
15 | # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
16 | Rule	SystemV	min	1973	-	Apr	lastSun	2:00	1:00	D
17 | Rule	SystemV	min	1973	-	Oct	lastSun	2:00	0	S
18 | Rule	SystemV	1974	only	-	Jan	6	2:00	1:00	D
19 | Rule	SystemV	1974	only	-	Nov	lastSun	2:00	0	S
20 | Rule	SystemV	1975	only	-	Feb	23	2:00	1:00	D
21 | Rule	SystemV	1975	only	-	Oct	lastSun	2:00	0	S
22 | Rule	SystemV	1976	max	-	Apr	lastSun	2:00	1:00	D
23 | Rule	SystemV	1976	max	-	Oct	lastSun	2:00	0	S
24 | 
25 | # Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
26 | ## Zone	SystemV/AST4ADT	-4:00	SystemV		A%sT
27 | ## Zone	SystemV/EST5EDT	-5:00	SystemV		E%sT
28 | ## Zone	SystemV/CST6CDT	-6:00	SystemV		C%sT
29 | ## Zone	SystemV/MST7MDT	-7:00	SystemV		M%sT
30 | ## Zone	SystemV/PST8PDT	-8:00	SystemV		P%sT
31 | ## Zone	SystemV/YST9YDT	-9:00	SystemV		Y%sT
32 | ## Zone	SystemV/AST4	-4:00	-		AST
33 | ## Zone	SystemV/EST5	-5:00	-		EST
34 | ## Zone	SystemV/CST6	-6:00	-		CST
35 | ## Zone	SystemV/MST7	-7:00	-		MST
36 | ## Zone	SystemV/PST8	-8:00	-		PST
37 | ## Zone	SystemV/YST9	-9:00	-		YST
38 | ## Zone	SystemV/HST10	-10:00	-		HST
39 | 


--------------------------------------------------------------------------------
/vendorModules/flot/examples/axes-time-zones/tz/yearistype.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/sh
 2 | 
 3 | : 'This file is in the public domain, so clarified as of'
 4 | : '2006-07-17 by Arthur David Olson.'
 5 | 
 6 | case $#-$1 in
 7 | 	2-|2-0*|2-*[!0-9]*)
 8 | 		echo "$0: wild year - $1" >&2
 9 | 		exit 1 ;;
10 | esac
11 | 
12 | case $#-$2 in
13 | 	2-even)
14 | 		case $1 in
15 | 			*[24680])			exit 0 ;;
16 | 			*)				exit 1 ;;
17 | 		esac ;;
18 | 	2-nonpres|2-nonuspres)
19 | 		case $1 in
20 | 			*[02468][048]|*[13579][26])	exit 1 ;;
21 | 			*)				exit 0 ;;
22 | 		esac ;;
23 | 	2-odd)
24 | 		case $1 in
25 | 			*[13579])			exit 0 ;;
26 | 			*)				exit 1 ;;
27 | 		esac ;;
28 | 	2-uspres)
29 | 		case $1 in
30 | 			*[02468][048]|*[13579][26])	exit 0 ;;
31 | 			*)				exit 1 ;;
32 | 		esac ;;
33 | 	2-*)
34 | 		echo "$0: wild type - $2" >&2 ;;
35 | esac
36 | 
37 | echo "$0: usage is $0 year even|odd|uspres|nonpres|nonuspres" >&2
38 | exit 1
39 | 


--------------------------------------------------------------------------------
/vendorModules/flot/examples/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/vendorModules/flot/examples/background.png


--------------------------------------------------------------------------------
/vendorModules/flot/examples/basic-options/index.html:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 | 	
 5 | 	Flot Examples: Basic Options
 6 | 	
 7 | 	
 8 | 	
 9 | 	
10 | 	
67 | 
68 | 
69 | 
70 | 	
73 | 
74 | 	
75 | 76 |
77 |
78 |
79 | 80 |

There are plenty of options you can set to control the precise looks of your plot. You can control the ticks on the axes, the legend, the graph type, etc.

81 | 82 |

Flot goes to great lengths to provide sensible defaults so that you don't have to customize much for a good-looking result.

83 | 84 |
85 | 86 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/basic-usage/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Basic Usage 6 | 7 | 8 | 9 | 10 | 33 | 34 | 35 | 36 | 39 | 40 |
41 | 42 |
43 |
44 |
45 | 46 |

You don't have to do much to get an attractive plot. Create a placeholder, make sure it has dimensions (so Flot knows at what size to draw the plot), then call the plot function with your data.

47 | 48 |

The axes are automatically scaled.

49 | 50 |
51 | 52 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/categories/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Categories 6 | 7 | 8 | 9 | 10 | 11 | 37 | 38 | 39 | 40 | 43 | 44 |
45 | 46 |
47 |
48 |
49 | 50 |

With the categories plugin you can plot categories/textual data easily.

51 | 52 |
53 | 54 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/examples.css: -------------------------------------------------------------------------------- 1 | * { padding: 0; margin: 0; vertical-align: top; } 2 | 3 | body { 4 | background: url(background.png) repeat-x; 5 | font: 18px/1.5em "proxima-nova", Helvetica, Arial, sans-serif; 6 | } 7 | 8 | a { color: #069; } 9 | a:hover { color: #28b; } 10 | 11 | h2 { 12 | margin-top: 15px; 13 | font: normal 32px "omnes-pro", Helvetica, Arial, sans-serif; 14 | } 15 | 16 | h3 { 17 | margin-left: 30px; 18 | font: normal 26px "omnes-pro", Helvetica, Arial, sans-serif; 19 | color: #666; 20 | } 21 | 22 | p { 23 | margin-top: 10px; 24 | } 25 | 26 | button { 27 | font-size: 18px; 28 | padding: 1px 7px; 29 | } 30 | 31 | input { 32 | font-size: 18px; 33 | } 34 | 35 | input[type=checkbox] { 36 | margin: 7px; 37 | } 38 | 39 | #header { 40 | position: relative; 41 | width: 900px; 42 | margin: auto; 43 | } 44 | 45 | #header h2 { 46 | margin-left: 10px; 47 | vertical-align: middle; 48 | font-size: 42px; 49 | font-weight: bold; 50 | text-decoration: none; 51 | color: #000; 52 | } 53 | 54 | #content { 55 | width: 880px; 56 | margin: 0 auto; 57 | padding: 10px; 58 | } 59 | 60 | #footer { 61 | margin-top: 25px; 62 | margin-bottom: 10px; 63 | text-align: center; 64 | font-size: 12px; 65 | color: #999; 66 | } 67 | 68 | .demo-container { 69 | box-sizing: border-box; 70 | width: 850px; 71 | height: 450px; 72 | padding: 20px 15px 15px 15px; 73 | margin: 15px auto 30px auto; 74 | border: 1px solid #ddd; 75 | background: #fff; 76 | background: linear-gradient(#f6f6f6 0, #fff 50px); 77 | background: -o-linear-gradient(#f6f6f6 0, #fff 50px); 78 | background: -ms-linear-gradient(#f6f6f6 0, #fff 50px); 79 | background: -moz-linear-gradient(#f6f6f6 0, #fff 50px); 80 | background: -webkit-linear-gradient(#f6f6f6 0, #fff 50px); 81 | box-shadow: 0 3px 10px rgba(0,0,0,0.15); 82 | -o-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 83 | -ms-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 84 | -moz-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 85 | -webkit-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 86 | } 87 | 88 | .demo-placeholder { 89 | width: 100%; 90 | height: 100%; 91 | font-size: 14px; 92 | line-height: 1.2em; 93 | } 94 | 95 | .legend table { 96 | border-spacing: 5px; 97 | } -------------------------------------------------------------------------------- /vendorModules/flot/examples/image/hs-2004-27-a-large-web.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/vendorModules/flot/examples/image/hs-2004-27-a-large-web.jpg -------------------------------------------------------------------------------- /vendorModules/flot/examples/image/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Image Plots 6 | 7 | 8 | 9 | 10 | 11 | 43 | 44 | 45 | 46 | 49 | 50 |
51 | 52 |
53 |
54 |
55 | 56 |

The Cat's Eye Nebula (picture from Hubble).

57 | 58 |

With the image plugin, you can plot static images against a set of axes. This is for useful for adding ticks to complex prerendered visualizations. Instead of inputting data points, you specify the images and where their two opposite corners are supposed to be in plot space.

59 | 60 |

Images represent a little further complication because you need to make sure they are loaded before you can use them (Flot skips incomplete images). The plugin comes with a couple of helpers for doing that.

61 | 62 |
63 | 64 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples 6 | 7 | 15 | 16 | 17 | 27 | 28 | 29 | 30 | 33 | 34 |
35 | 36 |

Here are some examples for Flot, the Javascript charting library for jQuery:

37 | 38 |

Basic Usage

39 | 40 | 46 | 47 |

Interactivity

48 | 49 | 56 | 57 |

Additional Features

58 | 59 | 72 | 73 |
74 | 75 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/interacting/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Interactivity 6 | 7 | 8 | 9 | 10 | 87 | 88 | 89 | 92 | 93 |
94 | 95 |
96 |
97 |
98 | 99 |

One of the goals of Flot is to support user interactions. Try pointing and clicking on the points.

100 | 101 |

102 | 103 | 104 | 105 |

106 | 107 |

A tooltip is easy to build with a bit of jQuery code and the data returned from the plot.

108 | 109 |

110 | 111 |
112 | 113 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/navigate/arrow-down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/vendorModules/flot/examples/navigate/arrow-down.gif -------------------------------------------------------------------------------- /vendorModules/flot/examples/navigate/arrow-left.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/vendorModules/flot/examples/navigate/arrow-left.gif -------------------------------------------------------------------------------- /vendorModules/flot/examples/navigate/arrow-right.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/vendorModules/flot/examples/navigate/arrow-right.gif -------------------------------------------------------------------------------- /vendorModules/flot/examples/navigate/arrow-up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faradey27/react-redux-webpack2-starterkit/c97a8768b9e3bf299dcad63b282e2e9c5662bb4d/vendorModules/flot/examples/navigate/arrow-up.gif -------------------------------------------------------------------------------- /vendorModules/flot/examples/realtime/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Real-time updates 6 | 7 | 8 | 9 | 10 | 98 | 99 | 100 | 101 | 104 | 105 |
106 | 107 |
108 |
109 |
110 | 111 |

You can update a chart periodically to get a real-time effect by using a timer to insert the new data in the plot and redraw it.

112 | 113 |

Time between updates: milliseconds

114 | 115 |
116 | 117 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/resize/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Resizing 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 50 | 51 | 52 | 53 | 56 | 57 |
58 | 59 |
60 |
61 |
62 | 63 |

64 | 65 |

Sometimes it makes more sense to just let the plot take up the available space. In that case, we need to redraw the plot each time the placeholder changes its size. If you include the resize plugin, this is handled automatically.

66 | 67 |

Drag the bottom and right sides of the plot to resize it.

68 | 69 |
70 | 71 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/series-types/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Series Types 6 | 7 | 8 | 9 | 10 | 68 | 69 | 70 | 71 | 74 | 75 |
76 | 77 |
78 |
79 |
80 | 81 |

Flot supports lines, points, filled areas, bars and any combinations of these, in the same plot and even on the same data series.

82 | 83 |
84 | 85 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/shared/jquery-ui/jquery-ui.min.css: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.10.0 - 2013-01-26 2 | * http://jqueryui.com 3 | * Includes: jquery.ui.core.css, jquery.ui.resizable.css 4 | * Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */ 5 | 6 | .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px} -------------------------------------------------------------------------------- /vendorModules/flot/examples/stacking/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Stacking 6 | 7 | 8 | 9 | 10 | 11 | 74 | 75 | 76 | 77 | 80 | 81 |
82 | 83 |
84 |
85 |
86 | 87 |

With the stack plugin, you can have Flot stack the series. This is useful if you wish to display both a total and the constituents it is made of. The only requirement is that you provide the input sorted on x.

88 | 89 |

90 | 91 | 92 |

93 | 94 |

95 | 96 | 97 | 98 |

99 | 100 |
101 | 102 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/symbols/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Symbols 6 | 7 | 8 | 9 | 10 | 11 | 54 | 55 | 56 | 57 | 60 | 61 |
62 | 63 |
64 |
65 |
66 | 67 |

Points can be marked in several ways, with circles being the built-in default. For other point types, you can define a callback function to draw the symbol. Some common symbols are available in the symbol plugin.

68 | 69 |
70 | 71 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/threshold/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Thresholds 6 | 7 | 8 | 9 | 10 | 11 | 48 | 49 | 50 | 51 | 54 | 55 |
56 | 57 |
58 |
59 |
60 | 61 |

With the threshold plugin, you can apply a specific color to the part of a data series below a threshold. This is can be useful for highlighting negative values, e.g. when displaying net results or what's in stock.

62 | 63 |

64 | 65 | 66 | 67 |

68 | 69 |
70 | 71 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/tracking/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Tracking 6 | 7 | 8 | 9 | 10 | 11 | 109 | 110 | 111 | 112 | 115 | 116 |
117 | 118 |
119 |
120 |
121 | 122 |

You can add crosshairs that'll track the mouse position, either on both axes or as here on only one.

123 | 124 |

If you combine it with listening on hover events, you can use it to track the intersection on the curves by interpolating the data points (look at the legend).

125 | 126 |

127 | 128 |
129 | 130 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /vendorModules/flot/examples/zooming/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flot Examples: Selection and zooming 6 | 7 | 8 | 9 | 10 | 11 | 121 | 122 | 123 | 124 | 127 | 128 |
129 | 130 |
131 |
132 |
133 |
134 | 135 |

Selection support makes it easy to construct flexible zooming schemes. With a few lines of code, the small overview plot to the right has been connected to the large plot. Try selecting a rectangle on either of them.

136 | 137 |
138 | 139 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /vendorModules/flot/jquery.colorhelpers.min.js: -------------------------------------------------------------------------------- 1 | (function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return valuemax?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery); -------------------------------------------------------------------------------- /vendorModules/flot/jquery.flot.canvas.min.js: -------------------------------------------------------------------------------- 1 | /* Javascript plotting library for jQuery, version 0.8.3. 2 | 3 | Copyright (c) 2007-2014 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | */ 7 | (function($){var options={canvas:true};var render,getTextInfo,addText;var hasOwnProperty=Object.prototype.hasOwnProperty;function init(plot,classes){var Canvas=classes.Canvas;if(render==null){getTextInfo=Canvas.prototype.getTextInfo,addText=Canvas.prototype.addText,render=Canvas.prototype.render}Canvas.prototype.render=function(){if(!plot.getOptions().canvas){return render.call(this)}var context=this.context,cache=this._textCache;context.save();context.textBaseline="middle";for(var layerKey in cache){if(hasOwnProperty.call(cache,layerKey)){var layerCache=cache[layerKey];for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey],updateStyles=true;for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var info=styleCache[key],positions=info.positions,lines=info.lines;if(updateStyles){context.fillStyle=info.font.color;context.font=info.font.definition;updateStyles=false}for(var i=0,position;position=positions[i];i++){if(position.active){for(var j=0,line;line=position.lines[j];j++){context.fillText(lines[j].text,line[0],line[1])}}else{positions.splice(i--,1)}}if(positions.length==0){delete styleCache[key]}}}}}}}context.restore()};Canvas.prototype.getTextInfo=function(layer,text,font,angle,width){if(!plot.getOptions().canvas){return getTextInfo.call(this,layer,text,font,angle,width)}var textStyle,layerCache,styleCache,info;text=""+text;if(typeof font==="object"){textStyle=font.style+" "+font.variant+" "+font.weight+" "+font.size+"px "+font.family}else{textStyle=font}layerCache=this._textCache[layer];if(layerCache==null){layerCache=this._textCache[layer]={}}styleCache=layerCache[textStyle];if(styleCache==null){styleCache=layerCache[textStyle]={}}info=styleCache[text];if(info==null){var context=this.context;if(typeof font!=="object"){var element=$("
 
").css("position","absolute").addClass(typeof font==="string"?font:null).appendTo(this.getTextLayer(layer));font={lineHeight:element.height(),style:element.css("font-style"),variant:element.css("font-variant"),weight:element.css("font-weight"),family:element.css("font-family"),color:element.css("color")};font.size=element.css("line-height",1).height();element.remove()}textStyle=font.style+" "+font.variant+" "+font.weight+" "+font.size+"px "+font.family;info=styleCache[text]={width:0,height:0,positions:[],lines:[],font:{definition:textStyle,color:font.color}};context.save();context.font=textStyle;var lines=(text+"").replace(/
|\r\n|\r/g,"\n").split("\n");for(var i=0;iindex)index=categories[v];return index+1}function categoriesTickGenerator(axis){var res=[];for(var label in axis.categories){var v=axis.categories[label];if(v>=axis.min&&v<=axis.max)res.push([v,label])}res.sort(function(a,b){return a[0]-b[0]});return res}function setupCategoriesForAxis(series,axis,datapoints){if(series[axis].options.mode!="categories")return;if(!series[axis].categories){var c={},o=series[axis].options.categories||{};if($.isArray(o)){for(var i=0;i=allseries.length){return null}return allseries[s.fillBetween]}return null}function computeFillBottoms(plot,s,datapoints){if(s.fillBetween==null){return}var other=findBottomSeries(s,plot.getData());if(!other){return}var ps=datapoints.pointsize,points=datapoints.points,otherps=other.datapoints.pointsize,otherpoints=other.datapoints.points,newpoints=[],px,py,intery,qx,qy,bottom,withlines=s.lines.show,withbottom=ps>2&&datapoints.format[2].y,withsteps=withlines&&s.lines.steps,fromgap=true,i=0,j=0,l,m;while(true){if(i>=points.length){break}l=newpoints.length;if(points[i]==null){for(m=0;m=otherpoints.length){if(!withlines){for(m=0;mqx){if(withlines&&i>0&&points[i-ps]!=null){intery=py+(points[i-ps+1]-py)*(qx-px)/(points[i-ps]-px);newpoints.push(qx);newpoints.push(intery);for(m=2;m0&&otherpoints[j-otherps]!=null){bottom=qy+(otherpoints[j-otherps+1]-qy)*(px-qx)/(otherpoints[j-otherps]-qx)}i+=ps}fromgap=false;if(l!==newpoints.length&&withbottom){newpoints[l+2]=bottom}}if(withsteps&&l!==newpoints.length&&l>0&&newpoints[l]!==null&&newpoints[l]!==newpoints[l-ps]&&newpoints[l+1]!==newpoints[l-ps+1]){for(m=0;m").load(handler).error(handler).attr("src",url)})};function drawSeries(plot,ctx,series){var plotOffset=plot.getPlotOffset();if(!series.images||!series.images.show)return;var points=series.datapoints.points,ps=series.datapoints.pointsize;for(var i=0;ix2){tmp=x2;x2=x1;x1=tmp}if(y1>y2){tmp=y2;y2=y1;y1=tmp}if(series.images.anchor=="center"){tmp=.5*(x2-x1)/(img.width-1);x1-=tmp;x2+=tmp;tmp=.5*(y2-y1)/(img.height-1);y1-=tmp;y2+=tmp}if(x1==x2||y1==y2||x1>=xaxis.max||x2<=xaxis.min||y1>=yaxis.max||y2<=yaxis.min)continue;var sx1=0,sy1=0,sx2=img.width,sy2=img.height;if(x1xaxis.max){sx2+=(sx2-sx1)*(xaxis.max-x2)/(x2-x1);x2=xaxis.max}if(y1yaxis.max){sy1+=(sy1-sy2)*(yaxis.max-y2)/(y2-y1);y2=yaxis.max}x1=xaxis.p2c(x1);x2=xaxis.p2c(x2);y1=yaxis.p2c(y1);y2=yaxis.p2c(y2);if(x1>x2){tmp=x2;x2=x1;x1=tmp}if(y1>y2){tmp=y2;y2=y1;y1=tmp}tmp=ctx.globalAlpha;ctx.globalAlpha*=series.images.alpha;ctx.drawImage(img,sx1,sy1,sx2-sx1,sy2-sy1,x1+plotOffset.left,y1+plotOffset.top,x2-x1,y2-y1);ctx.globalAlpha=tmp}}function processRawData(plot,series,data,datapoints){if(!series.images.show)return;datapoints.format=[{required:true},{x:true,number:true,required:true},{y:true,number:true,required:true},{x:true,number:true,required:true},{y:true,number:true,required:true}]}function init(plot){plot.hooks.processRawData.push(processRawData);plot.hooks.drawSeries.push(drawSeries)}$.plot.plugins.push({init:init,options:options,name:"image",version:"1.1"})})(jQuery); -------------------------------------------------------------------------------- /vendorModules/flot/jquery.flot.resize.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin for automatically redrawing plots as the placeholder resizes. 2 | 3 | Copyright (c) 2007-2014 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | It works by listening for changes on the placeholder div (through the jQuery 7 | resize event plugin) - if the size changes, it will redraw the plot. 8 | 9 | There are no options. If you need to disable the plugin for some plots, you 10 | can just fix the size of their placeholders. 11 | 12 | */ 13 | 14 | /* Inline dependency: 15 | * jQuery resize event - v1.1 - 3/14/2010 16 | * http://benalman.com/projects/jquery-resize-plugin/ 17 | * 18 | * Copyright (c) 2010 "Cowboy" Ben Alman 19 | * Dual licensed under the MIT and GPL licenses. 20 | * http://benalman.com/about/license/ 21 | */ 22 | (function($,e,t){"$:nomunge";var i=[],n=$.resize=$.extend($.resize,{}),a,r=false,s="setTimeout",u="resize",m=u+"-special-event",o="pendingDelay",l="activeDelay",f="throttleWindow";n[o]=200;n[l]=20;n[f]=true;$.event.special[u]={setup:function(){if(!n[f]&&this[s]){return false}var e=$(this);i.push(this);e.data(m,{w:e.width(),h:e.height()});if(i.length===1){a=t;h()}},teardown:function(){if(!n[f]&&this[s]){return false}var e=$(this);for(var t=i.length-1;t>=0;t--){if(i[t]==this){i.splice(t,1);break}}e.removeData(m);if(!i.length){if(r){cancelAnimationFrame(a)}else{clearTimeout(a)}a=null}},add:function(e){if(!n[f]&&this[s]){return false}var i;function a(e,n,a){var r=$(this),s=r.data(m)||{};s.w=n!==t?n:r.width();s.h=a!==t?a:r.height();i.apply(this,arguments)}if($.isFunction(e)){i=e;return a}else{i=e.handler;e.handler=a}}};function h(t){if(r===true){r=t||1}for(var s=i.length-1;s>=0;s--){var l=$(i[s]);if(l[0]==e||l.is(":visible")){var f=l.width(),c=l.height(),d=l.data(m);if(d&&(f!==d.w||c!==d.h)){l.trigger(u,[d.w=f,d.h=c]);r=t||true}}else{d=l.data(m);d.w=0;d.h=0}}if(a!==null){if(r&&(t==null||t-r<1e3)){a=e.requestAnimationFrame(h)}else{a=setTimeout(h,n[o]);r=false}}}if(!e.requestAnimationFrame){e.requestAnimationFrame=function(){return e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame||e.msRequestAnimationFrame||function(t,i){return e.setTimeout(function(){t((new Date).getTime())},n[l])}}()}if(!e.cancelAnimationFrame){e.cancelAnimationFrame=function(){return e.webkitCancelRequestAnimationFrame||e.mozCancelRequestAnimationFrame||e.oCancelRequestAnimationFrame||e.msCancelRequestAnimationFrame||clearTimeout}()}})(jQuery,this); 23 | 24 | (function ($) { 25 | var options = { }; // no options 26 | 27 | function init(plot) { 28 | function onResize() { 29 | var placeholder = plot.getPlaceholder(); 30 | 31 | // somebody might have hidden us and we can't plot 32 | // when we don't have the dimensions 33 | if (placeholder.width() == 0 || placeholder.height() == 0) 34 | return; 35 | 36 | plot.resize(); 37 | plot.setupGrid(); 38 | plot.draw(); 39 | } 40 | 41 | function bindEvents(plot, eventHolder) { 42 | plot.getPlaceholder().resize(onResize); 43 | } 44 | 45 | function shutdown(plot, eventHolder) { 46 | plot.getPlaceholder().unbind("resize", onResize); 47 | } 48 | 49 | plot.hooks.bindEvents.push(bindEvents); 50 | plot.hooks.shutdown.push(shutdown); 51 | } 52 | 53 | $.plot.plugins.push({ 54 | init: init, 55 | options: options, 56 | name: 'resize', 57 | version: '1.0' 58 | }); 59 | })(jQuery); 60 | -------------------------------------------------------------------------------- /vendorModules/flot/jquery.flot.resize.min.js: -------------------------------------------------------------------------------- 1 | /* Javascript plotting library for jQuery, version 0.8.3. 2 | 3 | Copyright (c) 2007-2014 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | */ 7 | (function($,e,t){"$:nomunge";var i=[],n=$.resize=$.extend($.resize,{}),a,r=false,s="setTimeout",u="resize",m=u+"-special-event",o="pendingDelay",l="activeDelay",f="throttleWindow";n[o]=200;n[l]=20;n[f]=true;$.event.special[u]={setup:function(){if(!n[f]&&this[s]){return false}var e=$(this);i.push(this);e.data(m,{w:e.width(),h:e.height()});if(i.length===1){a=t;h()}},teardown:function(){if(!n[f]&&this[s]){return false}var e=$(this);for(var t=i.length-1;t>=0;t--){if(i[t]==this){i.splice(t,1);break}}e.removeData(m);if(!i.length){if(r){cancelAnimationFrame(a)}else{clearTimeout(a)}a=null}},add:function(e){if(!n[f]&&this[s]){return false}var i;function a(e,n,a){var r=$(this),s=r.data(m)||{};s.w=n!==t?n:r.width();s.h=a!==t?a:r.height();i.apply(this,arguments)}if($.isFunction(e)){i=e;return a}else{i=e.handler;e.handler=a}}};function h(t){if(r===true){r=t||1}for(var s=i.length-1;s>=0;s--){var l=$(i[s]);if(l[0]==e||l.is(":visible")){var f=l.width(),c=l.height(),d=l.data(m);if(d&&(f!==d.w||c!==d.h)){l.trigger(u,[d.w=f,d.h=c]);r=t||true}}else{d=l.data(m);d.w=0;d.h=0}}if(a!==null){if(r&&(t==null||t-r<1e3)){a=e.requestAnimationFrame(h)}else{a=setTimeout(h,n[o]);r=false}}}if(!e.requestAnimationFrame){e.requestAnimationFrame=function(){return e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame||e.msRequestAnimationFrame||function(t,i){return e.setTimeout(function(){t((new Date).getTime())},n[l])}}()}if(!e.cancelAnimationFrame){e.cancelAnimationFrame=function(){return e.webkitCancelRequestAnimationFrame||e.mozCancelRequestAnimationFrame||e.oCancelRequestAnimationFrame||e.msCancelRequestAnimationFrame||clearTimeout}()}})(jQuery,this);(function($){var options={};function init(plot){function onResize(){var placeholder=plot.getPlaceholder();if(placeholder.width()==0||placeholder.height()==0)return;plot.resize();plot.setupGrid();plot.draw()}function bindEvents(plot,eventHolder){plot.getPlaceholder().resize(onResize)}function shutdown(plot,eventHolder){plot.getPlaceholder().unbind("resize",onResize)}plot.hooks.bindEvents.push(bindEvents);plot.hooks.shutdown.push(shutdown)}$.plot.plugins.push({init:init,options:options,name:"resize",version:"1.0"})})(jQuery); -------------------------------------------------------------------------------- /vendorModules/flot/jquery.flot.stack.min.js: -------------------------------------------------------------------------------- 1 | /* Javascript plotting library for jQuery, version 0.8.3. 2 | 3 | Copyright (c) 2007-2014 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | */ 7 | (function($){var options={series:{stack:null}};function init(plot){function findMatchingSeries(s,allseries){var res=null;for(var i=0;i2&&(horizontal?datapoints.format[2].x:datapoints.format[2].y),withsteps=withlines&&s.lines.steps,fromgap=true,keyOffset=horizontal?1:0,accumulateOffset=horizontal?0:1,i=0,j=0,l,m;while(true){if(i>=points.length)break;l=newpoints.length;if(points[i]==null){for(m=0;m=otherpoints.length){if(!withlines){for(m=0;mqx){if(withlines&&i>0&&points[i-ps]!=null){intery=py+(points[i-ps+accumulateOffset]-py)*(qx-px)/(points[i-ps+keyOffset]-px);newpoints.push(qx);newpoints.push(intery+qy);for(m=2;m0&&otherpoints[j-otherps]!=null)bottom=qy+(otherpoints[j-otherps+accumulateOffset]-qy)*(px-qx)/(otherpoints[j-otherps+keyOffset]-qx);newpoints[l+accumulateOffset]+=bottom;i+=ps}fromgap=false;if(l!=newpoints.length&&withbottom)newpoints[l+2]+=bottom}if(withsteps&&l!=newpoints.length&&l>0&&newpoints[l]!=null&&newpoints[l]!=newpoints[l-ps]&&newpoints[l+1]!=newpoints[l-ps+1]){for(m=0;m s = r * sqrt(pi)/2 24 | var size = radius * Math.sqrt(Math.PI) / 2; 25 | ctx.rect(x - size, y - size, size + size, size + size); 26 | }, 27 | diamond: function (ctx, x, y, radius, shadow) { 28 | // pi * r^2 = 2s^2 => s = r * sqrt(pi/2) 29 | var size = radius * Math.sqrt(Math.PI / 2); 30 | ctx.moveTo(x - size, y); 31 | ctx.lineTo(x, y - size); 32 | ctx.lineTo(x + size, y); 33 | ctx.lineTo(x, y + size); 34 | ctx.lineTo(x - size, y); 35 | }, 36 | triangle: function (ctx, x, y, radius, shadow) { 37 | // pi * r^2 = 1/2 * s^2 * sin (pi / 3) => s = r * sqrt(2 * pi / sin(pi / 3)) 38 | var size = radius * Math.sqrt(2 * Math.PI / Math.sin(Math.PI / 3)); 39 | var height = size * Math.sin(Math.PI / 3); 40 | ctx.moveTo(x - size/2, y + height/2); 41 | ctx.lineTo(x + size/2, y + height/2); 42 | if (!shadow) { 43 | ctx.lineTo(x, y - height/2); 44 | ctx.lineTo(x - size/2, y + height/2); 45 | } 46 | }, 47 | cross: function (ctx, x, y, radius, shadow) { 48 | // pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2 49 | var size = radius * Math.sqrt(Math.PI) / 2; 50 | ctx.moveTo(x - size, y - size); 51 | ctx.lineTo(x + size, y + size); 52 | ctx.moveTo(x - size, y + size); 53 | ctx.lineTo(x + size, y - size); 54 | } 55 | }; 56 | 57 | var s = series.points.symbol; 58 | if (handlers[s]) 59 | series.points.symbol = handlers[s]; 60 | } 61 | 62 | function init(plot) { 63 | plot.hooks.processDatapoints.push(processRawData); 64 | } 65 | 66 | $.plot.plugins.push({ 67 | init: init, 68 | name: 'symbols', 69 | version: '1.0' 70 | }); 71 | })(jQuery); 72 | -------------------------------------------------------------------------------- /vendorModules/flot/jquery.flot.symbol.min.js: -------------------------------------------------------------------------------- 1 | /* Javascript plotting library for jQuery, version 0.8.3. 2 | 3 | Copyright (c) 2007-2014 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | */ 7 | (function($){function processRawData(plot,series,datapoints){var handlers={square:function(ctx,x,y,radius,shadow){var size=radius*Math.sqrt(Math.PI)/2;ctx.rect(x-size,y-size,size+size,size+size)},diamond:function(ctx,x,y,radius,shadow){var size=radius*Math.sqrt(Math.PI/2);ctx.moveTo(x-size,y);ctx.lineTo(x,y-size);ctx.lineTo(x+size,y);ctx.lineTo(x,y+size);ctx.lineTo(x-size,y)},triangle:function(ctx,x,y,radius,shadow){var size=radius*Math.sqrt(2*Math.PI/Math.sin(Math.PI/3));var height=size*Math.sin(Math.PI/3);ctx.moveTo(x-size/2,y+height/2);ctx.lineTo(x+size/2,y+height/2);if(!shadow){ctx.lineTo(x,y-height/2);ctx.lineTo(x-size/2,y+height/2)}},cross:function(ctx,x,y,radius,shadow){var size=radius*Math.sqrt(Math.PI)/2;ctx.moveTo(x-size,y-size);ctx.lineTo(x+size,y+size);ctx.moveTo(x-size,y+size);ctx.lineTo(x+size,y-size)}};var s=series.points.symbol;if(handlers[s])series.points.symbol=handlers[s]}function init(plot){plot.hooks.processDatapoints.push(processRawData)}$.plot.plugins.push({init:init,name:"symbols",version:"1.0"})})(jQuery); -------------------------------------------------------------------------------- /vendorModules/flot/jquery.flot.threshold.min.js: -------------------------------------------------------------------------------- 1 | /* Javascript plotting library for jQuery, version 0.8.3. 2 | 3 | Copyright (c) 2007-2014 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | */ 7 | (function($){var options={series:{threshold:null}};function init(plot){function thresholdData(plot,s,datapoints,below,color){var ps=datapoints.pointsize,i,x,y,p,prevp,thresholded=$.extend({},s);thresholded.datapoints={points:[],pointsize:ps,format:datapoints.format};thresholded.label=null;thresholded.color=color;thresholded.threshold=null;thresholded.originSeries=s;thresholded.data=[];var origpoints=datapoints.points,addCrossingPoints=s.lines.show;var threspoints=[];var newpoints=[];var m;for(i=0;i0&&origpoints[i-ps]!=null){var interx=x+(below-y)*(x-origpoints[i-ps])/(y-origpoints[i-ps+1]);prevp.push(interx);prevp.push(below);for(m=2;m0){var origIndex=$.inArray(s,plot.getData());plot.getData().splice(origIndex+1,0,thresholded)}}function processThresholds(plot,s,datapoints){if(!s.threshold)return;if(s.threshold instanceof Array){s.threshold.sort(function(a,b){return a.below-b.below});$(s.threshold).each(function(i,th){thresholdData(plot,s,datapoints,th.below,th.color)})}else{thresholdData(plot,s,datapoints,s.threshold.below,s.threshold.color)}}plot.hooks.processDatapoints.push(processThresholds)}$.plot.plugins.push({init:init,options:options,name:"threshold",version:"1.2"})})(jQuery); -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | if (process.env.NODE_ENV === 'production') { 4 | module.exports = require('./webpackConfigFiles/webpack.config.prod'); 5 | } else { 6 | module.exports = require('./webpackConfigFiles/webpack.config.dev'); 7 | } 8 | -------------------------------------------------------------------------------- /webpackConfigFiles/commonLoaders.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-commonjs*/ 2 | /* eslint-disable import/no-nodejs-modules*/ 3 | /* eslint-disable fp/no-mutation*/ 4 | const path = require('path'); 5 | 6 | module.exports = [ 7 | { 8 | test: /\.svg/, 9 | loader: 'url-loader', 10 | query: { 11 | limit: 26000, 12 | mimetype: 'image/svg+xml', 13 | }, 14 | }, 15 | { 16 | test: /\.png/, 17 | loader: 'url-loader', 18 | query: { 19 | limit: 26000, 20 | mimetype: 'image/png', 21 | }, 22 | }, 23 | { 24 | test: /\.(woff|woff2|ttf|eot)/, 25 | loader: 'url-loader', 26 | query: { 27 | limit: 1, 28 | }, 29 | }, 30 | { 31 | test: /vendorModules\/.+\.(jsx|js)$/, 32 | loader: 'imports-loader?jQuery=jquery,$=jquery,this=>window', 33 | }, 34 | { 35 | test: /\.js$/, 36 | loader: 'babel-loader', 37 | exclude: /node_modules|bower_components|vendorModules/, 38 | include: path.resolve('./../'), 39 | }, 40 | { 41 | test: /\.js$/, 42 | loader: 'eslint-loader', 43 | exclude: /node_modules|bower_components|vendorModules/, 44 | include: path.resolve('./../'), 45 | }, 46 | { 47 | test: /\.json$/, 48 | loader: 'json-loader', 49 | }, 50 | ]; 51 | -------------------------------------------------------------------------------- /webpackConfigFiles/commonPlugins.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-commonjs*/ 2 | /* eslint-disable import/no-nodejs-modules*/ 3 | /* eslint-disable fp/no-mutation*/ 4 | const webpack = require('webpack'); 5 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | const autoprefixer = require('autoprefixer'); 7 | const postcssConstants = require('postcss-constants'); 8 | 9 | module.exports = [ 10 | new webpack.ProvidePlugin({ 11 | React: 'react', 12 | }), 13 | new webpack.ProvidePlugin({ 14 | jQuery: 'jquery', 15 | }), 16 | new HtmlWebpackPlugin({ 17 | template: './src/index.html', 18 | title: 'React redux boilerplate', 19 | favicon: './favicon.ico', 20 | inject: 'body', 21 | }), 22 | new webpack.LoaderOptionsPlugin({ 23 | test: /\.css/, 24 | options: { 25 | postcss: [ 26 | postcssConstants({ 27 | defaults: { 28 | colors: { 29 | primary: 'blue', 30 | }, 31 | }, 32 | }), 33 | autoprefixer({ 34 | browsers: [ 35 | 'last 3 version', 36 | 'ie >= 10', 37 | ], 38 | }), 39 | ], 40 | }, 41 | }), 42 | new webpack.optimize.OccurrenceOrderPlugin(), 43 | new webpack.NoEmitOnErrorsPlugin(), 44 | ]; 45 | -------------------------------------------------------------------------------- /webpackConfigFiles/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-commonjs*/ 2 | /* eslint-disable import/no-nodejs-modules*/ 3 | /* eslint-disable quote-props*/ 4 | /* eslint-disable fp/no-mutation*/ 5 | 6 | const StyleLintPlugin = require('stylelint-webpack-plugin'); 7 | const webpack = require('webpack'); 8 | const path = require('path'); 9 | 10 | const commonPlugins = require('./commonPlugins'); 11 | const commonLoaders = require('./commonLoaders'); 12 | 13 | module.exports = { 14 | devtool: 'eval-source-map', 15 | entry: [ 16 | 'react-hot-loader/patch', 17 | 'webpack-hot-middleware/client', 18 | './src/index.js', 19 | ], 20 | output: { 21 | path: path.resolve(__dirname, 'dist'), 22 | publicPath: '/', 23 | filename: 'bundle.js', 24 | }, 25 | plugins: [ 26 | new webpack.HotModuleReplacementPlugin(), 27 | ...commonPlugins, 28 | new StyleLintPlugin({ 29 | configFile: '.stylelintrc', 30 | context: './src/', 31 | files: '**/*.css', 32 | failOnError: false, 33 | }), 34 | new webpack.DefinePlugin({ 35 | '__DEVTOOLS__': false, 36 | 'process.env': { 37 | NODE_ENV: JSON.stringify('development'), 38 | }, 39 | }), 40 | ], 41 | module: { 42 | loaders: [ 43 | ...commonLoaders, 44 | { 45 | test: /\.css$/, 46 | exclude: /node_modules|bower_components|vendorModules/, 47 | use: [ 48 | { 49 | loader: 'style-loader', 50 | }, 51 | { 52 | loader: 'css-loader', 53 | options: { 54 | importLoaders: 1, 55 | modules: true, 56 | localIdentName: '[name]__[hash:base64:5]', 57 | }, 58 | }, 59 | { 60 | loader: 'postcss-loader', 61 | }, 62 | ], 63 | }, 64 | { 65 | test: /\.css$/, 66 | include: /node_modules|bower_components|vendorModules/, 67 | use: [ 68 | { 69 | loader: 'style-loader', 70 | }, 71 | { 72 | loader: 'css-loader', 73 | }, 74 | ], 75 | }, 76 | ], 77 | }, 78 | }; 79 | -------------------------------------------------------------------------------- /webpackConfigFiles/webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-commonjs*/ 2 | /* eslint-disable import/no-nodejs-modules*/ 3 | /* eslint-disable quote-props*/ 4 | /* eslint-disable fp/no-mutation*/ 5 | 6 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 7 | const webpack = require('webpack'); 8 | const path = require('path'); 9 | 10 | const commonPlugins = require('./commonPlugins'); 11 | const commonLoaders = require('./commonLoaders'); 12 | 13 | const cssmodulesScope = '?modules&importLoaders=1&localIdentName=[name]__[hash:base64:5]'; 14 | 15 | module.exports = { 16 | devtool: 'hidden-source-map', 17 | entry: { 18 | main: './src/index.js', 19 | vendor: [ 20 | 'react', 'react-dom', 21 | 'redux', 'redux-form', 'redux-api-middleware', 22 | 'immutable', 'moment', 'lodash', 23 | 'codemirror', 'jquery', 'redux-saga', 24 | ], 25 | }, 26 | output: { 27 | path: path.resolve(__dirname, '../dist'), 28 | publicPath: '/', 29 | filename: 'bundle.[hash].js', 30 | }, 31 | plugins: [ 32 | ...commonPlugins, 33 | new webpack.LoaderOptionsPlugin({ 34 | minimize: true, 35 | debug: false, 36 | }), 37 | new ExtractTextPlugin({ 38 | filename: 'style.[contentHash].css', 39 | allChunks: true, 40 | }), 41 | new webpack.DefinePlugin({ 42 | '__DEVTOOLS__': false, 43 | 'process.env': { 44 | NODE_ENV: JSON.stringify('production'), 45 | }, 46 | }), 47 | new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.[hash].js' }), 48 | ], 49 | module: { 50 | loaders: [ 51 | ...commonLoaders, 52 | { 53 | test: /\.css$/, 54 | loader: ExtractTextPlugin.extract({ 55 | fallbackLoader: 'style-loader', 56 | loader: `css-loader${cssmodulesScope}!postcss-loader`, 57 | }), 58 | }, 59 | ], 60 | }, 61 | }; 62 | --------------------------------------------------------------------------------