├── .eslintrc.js
├── LICENSE
├── README.md
├── React.15
├── Basic
│ ├── .babelrc
│ ├── README.md
│ ├── __tests__
│ │ ├── .setup.js
│ │ └── app.ctrl.test.jsx
│ ├── js
│ │ └── server.js
│ ├── package.json
│ ├── ui-src
│ │ ├── app.jsx
│ │ ├── components
│ │ │ ├── app.ctrl.jsx
│ │ │ ├── app.notes.jsx
│ │ │ └── app.text.js
│ │ ├── css
│ │ │ └── index.css
│ │ ├── img
│ │ │ └── favicon.ico
│ │ └── index.html
│ ├── webpack.config.js
│ └── webpack.config.json
├── BasicIsometric
│ ├── README.md
│ ├── js
│ │ └── server.js
│ ├── package.json
│ ├── ui-src
│ │ ├── app.jsx
│ │ ├── appiso.js
│ │ ├── components
│ │ │ └── app.ctrl.jsx
│ │ ├── css
│ │ │ └── index.css
│ │ └── img
│ │ │ └── favicon.ico
│ ├── views
│ │ └── index.ejs
│ ├── webpack.config.js
│ └── webpack.config.json
├── GoogleMaps
│ ├── README.md
│ ├── js
│ │ └── server.js
│ ├── package.json
│ ├── ui-src
│ │ ├── app.jsx
│ │ ├── components
│ │ │ ├── app.ctrl.jsx
│ │ │ ├── common
│ │ │ │ ├── app.colors.js
│ │ │ │ ├── app.style.jsx
│ │ │ │ └── nav1.bar.jsx
│ │ │ └── dashboard
│ │ │ │ ├── dashboard.page.jsx
│ │ │ │ ├── map.ctrl.jsx
│ │ │ │ └── mapStyle.js
│ │ ├── css
│ │ │ ├── Draft.css
│ │ │ └── index.css
│ │ ├── img
│ │ │ └── favicon.ico
│ │ ├── index.html
│ │ └── store
│ │ │ ├── App.Store.js
│ │ │ ├── app
│ │ │ ├── app.actions.js
│ │ │ └── app.reducer.js
│ │ │ └── map
│ │ │ ├── map.actions.js
│ │ │ └── map.reducer.js
│ ├── webpack.config.js
│ └── webpack.config.json
├── ReduxElectron
│ ├── README.md
│ ├── config.json
│ ├── data
│ │ └── basic.json
│ ├── js
│ │ └── mainipc.js
│ ├── main.js
│ ├── package.json
│ ├── ui-src
│ │ ├── app.jsx
│ │ ├── components
│ │ │ ├── app.ctrl.jsx
│ │ │ └── app.notes.jsx
│ │ ├── css
│ │ │ └── index.css
│ │ ├── img
│ │ │ └── favicon.ico
│ │ ├── index.html
│ │ └── store
│ │ │ ├── Actions.js
│ │ │ ├── App.Store.js
│ │ │ └── ipc.api.js
│ ├── webpack.config.js
│ ├── webpack.config.json
│ ├── windowstate.json
│ └── yarn.lock
├── ReduxFetch
│ ├── .babelrc
│ ├── README.md
│ ├── __tests__
│ │ ├── .setup.js
│ │ ├── app.ctrl.test.jsx
│ │ └── server.test.js
│ ├── cert.csr
│ ├── certificate.pem
│ ├── data
│ │ └── basic.json
│ ├── js
│ │ ├── routes.js
│ │ ├── routes
│ │ │ └── GetSetData.js
│ │ └── server.js
│ ├── package.json
│ ├── private.key
│ ├── ui-src
│ │ ├── app.jsx
│ │ ├── components
│ │ │ ├── app.ctrl.jsx
│ │ │ ├── app.notes.jsx
│ │ │ └── app.text.js
│ │ ├── css
│ │ │ └── index.css
│ │ ├── img
│ │ │ └── favicon.ico
│ │ ├── index.html
│ │ └── store
│ │ │ ├── App.Store.js
│ │ │ └── api.Actions.js
│ ├── webpack.config.js
│ └── webpack.config.json
├── ReduxPages
│ ├── README.md
│ ├── js
│ │ └── server.js
│ ├── package.json
│ ├── ui-src
│ │ ├── app.jsx
│ │ ├── components
│ │ │ ├── app.ctrl.jsx
│ │ │ ├── cache
│ │ │ │ └── cache.page.jsx
│ │ │ ├── common
│ │ │ │ ├── app.colors.js
│ │ │ │ ├── app.style.jsx
│ │ │ │ └── nav.bar.jsx
│ │ │ ├── event
│ │ │ │ └── event.page.jsx
│ │ │ ├── home
│ │ │ │ └── home.page.jsx
│ │ │ ├── object
│ │ │ │ └── object.page.jsx
│ │ │ └── radium
│ │ │ │ ├── button.jsx
│ │ │ │ ├── computed-well.jsx
│ │ │ │ ├── hover.jsx
│ │ │ │ └── radium.page.jsx
│ │ ├── css
│ │ │ └── index.css
│ │ ├── img
│ │ │ └── favicon.ico
│ │ ├── index.html
│ │ ├── lib
│ │ │ └── cache.js
│ │ └── store
│ │ │ ├── App.Store.js
│ │ │ └── app
│ │ │ ├── app.actions.js
│ │ │ └── app.reducer.js
│ ├── webpack.config.js
│ ├── webpack.config.json
│ └── yarn.lock
└── ReduxSocketIO
│ ├── README.md
│ ├── data
│ └── basic.json
│ ├── js
│ ├── mainsocket.js
│ ├── server.js
│ └── socket
│ │ └── GetSetData.js
│ ├── package.json
│ ├── ui-src
│ ├── app.jsx
│ ├── components
│ │ ├── app.ctrl.jsx
│ │ └── app.notes.jsx
│ ├── css
│ │ └── index.css
│ ├── img
│ │ └── favicon.ico
│ ├── index.html
│ └── store
│ │ ├── Actions.js
│ │ ├── App.Store.js
│ │ └── ws.api.js
│ ├── webpack.config.js
│ ├── webpack.config.json
│ └── yarn.lock
├── React.Common
├── README.md
├── data
│ ├── AppData.json
│ ├── ImageList.json
│ ├── TreeView.json
│ └── inputs.json
├── js
│ ├── routes.js
│ ├── routes
│ │ ├── GetPicList.js
│ │ └── GetSetData.js
│ └── server.js
├── package.json
├── ui-src
│ ├── app.jsx
│ ├── components
│ │ ├── Button
│ │ │ ├── app.text.js
│ │ │ └── button.page.jsx
│ │ ├── DropDowns
│ │ │ ├── app.text.js
│ │ │ ├── dropdown.menu.jsx
│ │ │ ├── dropdown.page.jsx
│ │ │ ├── dropdown.select.jsx
│ │ │ └── multi.select.jsx
│ │ ├── FormInput
│ │ │ ├── app.text.js
│ │ │ └── input.page.jsx
│ │ ├── Gallery
│ │ │ ├── app.text.js
│ │ │ └── gallery.page.jsx
│ │ ├── List
│ │ │ ├── app.text.js
│ │ │ └── list.page.jsx
│ │ ├── PageIndicator
│ │ │ ├── indicator.page.jsx
│ │ │ ├── indicator.pop.jsx
│ │ │ ├── indicator.style.js
│ │ │ └── indicator.text.js
│ │ ├── ProgressBar
│ │ │ ├── app.text.js
│ │ │ └── progress.page.jsx
│ │ ├── Sliders
│ │ │ ├── app.text.js
│ │ │ └── sliders.page.jsx
│ │ ├── Tooltip
│ │ │ ├── app.text.js
│ │ │ └── tooltip.page.jsx
│ │ ├── TreeViews
│ │ │ ├── app.text.js
│ │ │ ├── jumplist
│ │ │ │ └── jump.ctrl.jsx
│ │ │ ├── treeview.page.jsx
│ │ │ └── treeview
│ │ │ │ ├── tree.ctrl.jsx
│ │ │ │ ├── tree.detail.jsx
│ │ │ │ ├── tree.edit.jsx
│ │ │ │ ├── tree.list.jsx
│ │ │ │ ├── tree.menu.jsx
│ │ │ │ └── tree.new.jsx
│ │ ├── app.ctrl.jsx
│ │ └── common
│ │ │ ├── Button
│ │ │ └── jButton.jsx
│ │ │ ├── DropDowns
│ │ │ ├── Icon.jsx
│ │ │ ├── jDropMenu.jsx
│ │ │ ├── jDropSelect.jsx
│ │ │ └── jMultiSelect.jsx
│ │ │ ├── FormInput
│ │ │ └── jInput.jsx
│ │ │ ├── Gallery
│ │ │ ├── gallery.style.js
│ │ │ ├── jGallery.jsx
│ │ │ ├── jThumbs.jsx
│ │ │ ├── listitem.jsx
│ │ │ └── shortcuts.jsx
│ │ │ ├── List
│ │ │ └── jList.jsx
│ │ │ ├── PageIndicator
│ │ │ └── jPageIndicator.jsx
│ │ │ ├── ProgressBar
│ │ │ └── jProgressBar.jsx
│ │ │ ├── Sliders
│ │ │ ├── jRangeSelector.jsx
│ │ │ └── jSlider.jsx
│ │ │ ├── Tooltip
│ │ │ └── jTooltip.jsx
│ │ │ ├── TreeViews
│ │ │ ├── jTreeView.jsx
│ │ │ └── jTreeViewB.jsx
│ │ │ ├── app.colors.js
│ │ │ ├── app.notes.jsx
│ │ │ ├── app.style.jsx
│ │ │ └── nav.bar.jsx
│ ├── css
│ │ ├── index.css
│ │ └── rangeInput.css
│ ├── img
│ │ ├── 1x1TransShim.gif
│ │ ├── SLogoS5-48_C.png
│ │ ├── favicon.ico
│ │ ├── flow.png
│ │ ├── leaf.ico
│ │ ├── snow.ico
│ │ └── sun.ico
│ ├── index.html
│ └── store
│ │ ├── App.Store.js
│ │ ├── api
│ │ └── api.Actions.js
│ │ ├── app
│ │ ├── app.actions.js
│ │ └── app.reducer.js
│ │ ├── gallery
│ │ └── gallery.Reducer.js
│ │ ├── input
│ │ ├── input.Actions.js
│ │ └── input.Reducer.js
│ │ └── treeview
│ │ ├── tree.Actions.js
│ │ └── tree.Reducer.js
├── webpack.config.js
├── webpack.config.json
└── yarn.lock
└── package.json
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Janaka Stevens
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | 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, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ReactPatterns
2 |
3 | A collection of simple react projects providing reusable components, startup and test examples. Its my react playground.
4 | I am using webpack 2 and babel for the build tool chain.
5 | I have added linting with eslint. The linting rules are in .eslintrc.js.
6 |
7 | **React.15**
8 | * Basic
9 | * Basic Isometric/Universal
10 | * GoogleMaps
11 | * Redux Electron
12 | * Redux Fetch ajax
13 | * Redux Pages
14 | * Radium
15 | * Window Events
16 | * Window Object
17 | * Redux SocketIO
18 |
19 | **React.Common**
20 | * Button
21 | * DropDowns
22 | * Form Input
23 | * Gallery
24 | * List
25 | * PageIndicator
26 | * ProgressBar
27 | * Sliders
28 | * Tooltip
29 | * TreeViews
30 |
31 | # The basics
32 |
33 | Open two terminals at the desired project root. I use iTerm on Mac, ConEmu on Windows 10.
34 | First time do "npm install". On the React.15 projects in one terminal "npm run ww".
35 | In the other terminal "npm start".
36 | In your browser localhost:3500. All projects use the same port.
37 | If you want to do it with one terminal session you can run "npm run nw" for no watch.
38 |
39 |
40 | There is a code viewer running on page 2 of examples at http://jmarkstevens.com/.
41 |
--------------------------------------------------------------------------------
/React.15/Basic/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react", "stage-0"]
3 | }
--------------------------------------------------------------------------------
/React.15/Basic/README.md:
--------------------------------------------------------------------------------
1 | # ReactPatterns Basic
2 |
3 | Just the basics for react 15.
4 |
5 | # Getting started
6 |
7 | cd into the root directory of the project. If the first time "npm install". "npm run ww" for webpack with watch.
8 | "npm run nw" for webpack no watch. "npm start" to start the node server. "localhost:3500" in the browser.
9 | "npm test" for unit testing with Jest and Enzyme.
10 |
--------------------------------------------------------------------------------
/React.15/Basic/__tests__/.setup.js:
--------------------------------------------------------------------------------
1 | require('babel-register')();
2 |
3 | var jsdom = require('jsdom').jsdom;
4 |
5 | var exposedProperties = ['window', 'navigator', 'document'];
6 |
7 | global.document = jsdom('');
8 | global.window = document.defaultView;
9 | Object.keys(document.defaultView).forEach((property) => {
10 | if (typeof global[property] === 'undefined') {
11 | exposedProperties.push(property);
12 | global[property] = document.defaultView[property];
13 | }
14 | });
15 |
16 | global.navigator = {
17 | userAgent: 'node.js'
18 | };
19 |
20 | documentRef = document;
21 |
--------------------------------------------------------------------------------
/React.15/Basic/__tests__/app.ctrl.test.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import {shallow, mount} from 'enzyme';
5 | import {expect} from 'chai';
6 |
7 | import AppCtrl from '../ui-src/components/app.ctrl';
8 |
9 | describe('shallow() ', () => {
10 | const wrapper = shallow();
11 | it('checks div count', () => {
12 | expect(wrapper.find('div').length).to.equal(1);
13 | });
14 | it('checks br count', () => {
15 | expect(wrapper.find('br').length).to.equal(0);
16 | });
17 | it('checks text', () => {
18 | expect(wrapper.text()).to.equal('Hello World');
19 | });
20 | it('checks state world', () => {
21 | expect(wrapper.state('world')).to.equal('Hello World');
22 | });
23 | });
24 |
25 | describe('mount() ', () => {
26 | const wrapper = mount();
27 | it('checks text', () => {
28 | expect(wrapper.text()).to.equal('Hello WorldHide notesThis is a minimal starter project when not using flux.\n The only thing added is the hello world which demonstrates the use of state.');
29 | });
30 | it('checks state world', () => {
31 | expect(wrapper.state('world')).to.equal('Hello World');
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/React.15/Basic/js/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const express = require('express');
4 | const favicon = require('serve-favicon');
5 | const path = require('path');
6 | const port = Number(process.env.BASICPORT || 3500);
7 |
8 | const app = express();
9 | app.listen(port);
10 |
11 | app.use('/', express.static('ui-dist'));
12 | app.use(favicon(path.join(__dirname, '..', 'ui-dist', 'img', 'favicon.ico')));
13 | app.get('/', function(req, res){ res.sendfile(__dirname + '/index.html', [], null); });
14 |
--------------------------------------------------------------------------------
/React.15/Basic/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ReactPatterns.15-Basic",
3 | "version": "1.0.0",
4 | "description": "A collection of simple react projects providing reusable components, startup and test examples.",
5 | "license": "MIT",
6 | "author": {
7 | "name": "Janaka Stevens",
8 | "email": "jmstevens@calitek.com"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/calitek/ReactPatterns.git"
13 | },
14 | "scripts": {
15 | "start": "node js/server.js",
16 | "test": "mocha __tests__/.setup.js __tests__/**/*.test.js?",
17 | "testw": "npm test -- --watch",
18 | "ww": "webpack --progress --profile --colors --env.noMinimize --watch",
19 | "nw": "webpack --progress --profile --colors --env.noMinimize"
20 | },
21 | "dependencies": {
22 | "express": "latest",
23 | "serve-favicon": "latest"
24 | },
25 | "devDependencies": {
26 | "react": "^15.4.0",
27 | "react-dom": "^15.4.0",
28 |
29 | "babel-core": "latest",
30 | "babel-loader": "^6.1.0",
31 | "babel-preset-es2015": "latest",
32 | "babel-preset-react": "latest",
33 | "babel-preset-stage-0": "latest",
34 | "css-loader": "latest",
35 | "extract-text-webpack-plugin": "^2.0.0-rc.3",
36 | "file-loader": "latest",
37 | "loader-utils": "latest",
38 | "style-loader": "^0.13.1",
39 | "webpack": "latest",
40 |
41 | "babel-register": "latest",
42 | "chai": "latest",
43 | "chai-http": "latest",
44 | "enzyme": "latest",
45 | "jsdom": "latest",
46 | "mocha": "latest",
47 | "react-addons-test-utils": "^15.4.0",
48 | "sinon": "latest"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/React.15/Basic/ui-src/app.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import './index.html';
4 | import './css/index.css';
5 | import './img/favicon.ico';
6 |
7 | import React from 'react';
8 | import ReactDom from 'react-dom';
9 |
10 | import AppCtrl from './components/app.ctrl';
11 |
12 | window.ReactDom = ReactDom;
13 |
14 | ReactDom.render( , document.getElementById('react') );
15 |
--------------------------------------------------------------------------------
/React.15/Basic/ui-src/components/app.ctrl.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import AppNotes from './app.notes';
4 |
5 | let AppCtrlSty = {
6 | height: '100%',
7 | padding: '0 10px 0 0'
8 | };
9 |
10 | export default class AppCtrl extends React.Component {
11 | state = {world: ''};
12 | componentWillMount = () => { this.sayHello(); };
13 | sayHello = () => { this.setState({world: 'Hello World'}); };
14 | render() {
15 | return (
16 |
89 |
this.setMapRef(ref)} style={this.state.mapStyle} />
90 |
91 | );
92 | }
93 | }
94 |
95 | function mapStateToProps(store) {
96 | return {mapState: store.mapState};
97 | }
98 |
99 | function mapDispatchToProps(dispatch) {
100 | return bindActionCreators({mapChangeCenterAction, mapChangeZoomAction, mapInitializedAction}, dispatch);
101 | }
102 |
103 | export default connect(mapStateToProps, mapDispatchToProps)(GoogleMapsPage);
104 |
--------------------------------------------------------------------------------
/React.15/GoogleMaps/ui-src/components/dashboard/mapStyle.js:
--------------------------------------------------------------------------------
1 | export const mapStyle = [
2 | {elementType: 'geometry', stylers: [{color: '#eeffee'}]},
3 | {elementType: 'labels.text.stroke', stylers: [{color: '#242f3e'}]},
4 | {elementType: 'labels.text.fill', stylers: [{color: '#746855'}]},
5 | {
6 | featureType: 'administrative.locality',
7 | elementType: 'labels.text.fill',
8 | stylers: [{color: '#d59563'}]
9 | },
10 | {
11 | featureType: 'poi',
12 | elementType: 'labels.text.fill',
13 | stylers: [{color: '#d59563'}]
14 | },
15 | {
16 | featureType: 'poi.park',
17 | elementType: 'geometry',
18 | stylers: [{color: '#263c3f'}]
19 | },
20 | {
21 | featureType: 'poi.park',
22 | elementType: 'labels.text.fill',
23 | stylers: [{color: '#6b9a76'}]
24 | },
25 | {
26 | featureType: 'road',
27 | elementType: 'geometry',
28 | stylers: [{color: '#38414e'}]
29 | },
30 | {
31 | featureType: 'road',
32 | elementType: 'geometry.stroke',
33 | stylers: [{color: '#212a37'}]
34 | },
35 | {
36 | featureType: 'road',
37 | elementType: 'labels.text.fill',
38 | stylers: [{color: '#9ca5b3'}]
39 | },
40 | {
41 | featureType: 'road.highway',
42 | elementType: 'geometry',
43 | stylers: [{color: '#746855'}]
44 | },
45 | {
46 | featureType: 'road.highway',
47 | elementType: 'geometry.stroke',
48 | stylers: [{color: '#1f2835'}]
49 | },
50 | {
51 | featureType: 'road.highway',
52 | elementType: 'labels.text.fill',
53 | stylers: [{color: '#f3d19c'}]
54 | },
55 | {
56 | featureType: 'transit',
57 | elementType: 'geometry',
58 | stylers: [{color: '#2f3948'}]
59 | },
60 | {
61 | featureType: 'transit.station',
62 | elementType: 'labels.text.fill',
63 | stylers: [{color: '#d59563'}]
64 | },
65 | {
66 | featureType: 'water',
67 | elementType: 'geometry',
68 | stylers: [{color: '#17263c'}]
69 | },
70 | {
71 | featureType: 'water',
72 | elementType: 'labels.text.fill',
73 | stylers: [{color: '#515c6d'}]
74 | },
75 | {
76 | featureType: 'water',
77 | elementType: 'labels.text.stroke',
78 | stylers: [{color: '#17263c'}]
79 | }
80 | ];
81 |
--------------------------------------------------------------------------------
/React.15/GoogleMaps/ui-src/css/index.css:
--------------------------------------------------------------------------------
1 | .editor :global(.public-DraftEditor-content) {
2 | max-height: 8em;
3 | overflow: auto;
4 | }
5 |
6 | .bodyStyle {
7 | background-color: ##fefefe;
8 | color: #363636;
9 | display: block;
10 | height: 100vh;
11 | overflow-x: hidden;
12 | overflow-y: hidden;
13 | width: 100%;
14 | }
15 |
16 | .Title {font-size: 1.3em;}
17 |
18 | .content {
19 | height: 100%;
20 | overflow: hidden;
21 | padding: 0;
22 | }
23 |
24 | * { outline: none; }
25 |
26 | .a{display:block}
27 | iframe{border-width:0}
28 |
29 | .FlexBox {
30 | display: -webkit-box;
31 | display: -moz-box;
32 | display: -ms-flexbox;
33 | display: flex;
34 | }
35 |
36 | .FlexBoxJustAround {
37 | display: -webkit-box;
38 | display: -moz-box;
39 | display: -ms-flexbox;
40 | display: flex;
41 | justify-content: space-around;
42 | }
43 |
44 | .FlexBoxJustAroundWrap {
45 | display: -webkit-box;
46 | display: -moz-box;
47 | display: -ms-flexbox;
48 | display: flex;
49 | justify-content: space-around;
50 | flex-wrap: wrap;
51 | }
52 |
53 | .FlexBoxJustBetween {
54 | display: -webkit-box;
55 | display: -moz-box;
56 | display: -ms-flexbox;
57 | display: flex;
58 | justify-content: space-between;
59 | }
60 |
61 | .FlexBoxWrap {
62 | display: -webkit-box;
63 | display: -moz-box;
64 | display: -ms-flexbox;
65 | display: flex;
66 | flex-wrap: wrap;
67 | }
68 |
69 | .FlexJustify {
70 | -webkit-box-pack: justify;
71 | -moz-box-pack: justify;
72 | -ms-box-pack: justify;
73 | justify-content: space-between;
74 | }
75 |
76 | .FlexBoxStretch {
77 | display: -webkit-box;
78 | display: -moz-box;
79 | display: -ms-flexbox;
80 | display: flex;
81 | align-content: stretch;
82 | }
83 |
84 | .FlexItem {
85 | flex-grow: 1;
86 | }
87 |
88 | .HighZ {z-index: 200;}
89 |
--------------------------------------------------------------------------------
/React.15/GoogleMaps/ui-src/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.15/GoogleMaps/ui-src/img/favicon.ico
--------------------------------------------------------------------------------
/React.15/GoogleMaps/ui-src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
GoogleMaps
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/React.15/GoogleMaps/ui-src/store/App.Store.js:
--------------------------------------------------------------------------------
1 | import {createStore, combineReducers, applyMiddleware} from 'redux';
2 | import logger from 'redux-logger';
3 |
4 | import appState from './app/app.Reducer';
5 | import mapState from './map/map.Reducer';
6 |
7 | const reducer = combineReducers({appState, mapState});
8 | let middleware = [];
9 |
10 | const useLogger = 0;
11 | if (useLogger) middleware.push(logger);
12 |
13 | const store = createStore(reducer, applyMiddleware(...middleware));
14 |
15 | export default store;
16 |
--------------------------------------------------------------------------------
/React.15/GoogleMaps/ui-src/store/app/app.actions.js:
--------------------------------------------------------------------------------
1 |
2 | export function appNavMenuAction(newPage) {
3 | return {type: 'AppNavMenuAction', newPage};
4 | }
5 |
--------------------------------------------------------------------------------
/React.15/GoogleMaps/ui-src/store/app/app.reducer.js:
--------------------------------------------------------------------------------
1 | const pages = ['dashboard'];
2 | const initialAppState = {
3 | currentPage: pages[0],
4 | };
5 |
6 | export default function handleActions(state = initialAppState, action) {
7 | let _appState = Object.assign({}, state);
8 | switch (action.type) {
9 | case 'AppNavMenuAction':
10 | _appState.currentPage = action.newPage;
11 | return _appState;
12 | default:
13 | return state;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/React.15/GoogleMaps/ui-src/store/map/map.actions.js:
--------------------------------------------------------------------------------
1 |
2 | export function mapChangeZoomAction(newZoom) {
3 | return {type: 'MapChangeZoomAction', newZoom};
4 | }
5 |
6 | export function mapChangeCenterAction(newCenter) {
7 | return {type: 'MapChangeCenterAction', newCenter};
8 | }
9 |
10 | export function mapInitializedAction() {
11 | return {type: 'MapInitializedAction'};
12 | }
13 |
--------------------------------------------------------------------------------
/React.15/GoogleMaps/ui-src/store/map/map.reducer.js:
--------------------------------------------------------------------------------
1 | const initialMapState = {
2 | mapZoom: 3,
3 | mapCenter: {lat: 38.0000, lng: -97.0000},
4 | mapInitialized: false
5 | };
6 |
7 | export default function handleActions(state = initialMapState, action) {
8 | let _mapState = Object.assign({}, state);
9 | switch (action.type) {
10 | case 'MapChangeZoomAction':
11 | _mapState.mapZoom = action.newZoom;
12 | return _mapState;
13 | case 'MapChangeCenterAction':
14 | _mapState.mapCenter = action.newCenter;
15 | return _mapState;
16 | case 'MapInitializedAction':
17 | _mapState.mapInitialized = true;
18 | return _mapState;
19 | default:
20 | return state;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/React.15/GoogleMaps/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
3 | const webpack = require('webpack');
4 | const configJson = require('./webpack.config.json');
5 |
6 | module.exports = (env) => {
7 |
8 | const noMinimize = env.noMinimize;
9 | var plugins = [];
10 |
11 | plugins.push(new ExtractTextPlugin({filename: 'app.css', allChunks: true}));
12 | plugins.push(new webpack.optimize.CommonsChunkPlugin({name: 'lib'}));
13 | if (noMinimize) {
14 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('development')}}));
15 | } else {
16 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('production')}}));
17 | plugins.push(new webpack.optimize.UglifyJsPlugin({compress: {warnings: false, pure_funcs: ['console.log']},}));
18 | }
19 |
20 | const ROOT_PATH = path.resolve(__dirname);
21 | const SRC_PATH = path.resolve(ROOT_PATH, './ui-src');
22 | const DIST_PATH = path.resolve(ROOT_PATH, './ui-dist');
23 |
24 |
25 | return {
26 | context: SRC_PATH,
27 | entry: {
28 | app: './app.jsx',
29 | lib: configJson.lib
30 | },
31 |
32 | output: {
33 | path: DIST_PATH,
34 | filename: '[name].js'
35 | },
36 |
37 | module: {
38 | rules: [
39 | {
40 | test: /\.jsx?$/,
41 | loader: 'babel-loader',
42 | query: {presets:['es2015', 'react', 'stage-0']},
43 | exclude: /(node_modules)/,
44 | },
45 | {
46 | test: /\.css$/,
47 | use: ExtractTextPlugin.extract({
48 | fallback: 'style-loader',
49 | use: 'css-loader'
50 | })
51 | },
52 | {
53 | test: /\.(png|jpg|ico|gif)$/,
54 | loader: 'file-loader?name=img/[name].[ext]'
55 | },
56 | {
57 | test: /\.(html|pdf)$/,
58 | loader: 'file-loader?name=[name].[ext]'
59 | }
60 | ]
61 | },
62 | plugins,
63 | resolve: {
64 | extensions: ['.js', '.jsx'],
65 | modules: ['node_modules']
66 | }
67 | };
68 | };
69 |
--------------------------------------------------------------------------------
/React.15/GoogleMaps/webpack.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "lib": [
3 | "react",
4 | "react-dom",
5 | "react-redux",
6 | "redux",
7 | "redux-logger"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/README.md:
--------------------------------------------------------------------------------
1 | # ReactPatterns ReduxElectron
2 |
3 | A basic demonstration of redux with Electron. This would be the starting point for a simple data handling app.
4 | The 15 version uses more es6 and refines the reflux usage a bit.
5 |
6 | # Getting started
7 |
8 | cd into the root directory of the project. If the first time "npm install". "npm run ww" for webpack with watch.
9 | "npm run nw" for webpack no watch. "npm start" to start the node server. "localhost:3500" in the browser.
10 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "winProjectRoot": "K:/Projects/ReactPatterns/React.15.Webpack/ReduxElectron"
3 | }
4 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/data/basic.json:
--------------------------------------------------------------------------------
1 | {
2 | "Project": "Redux with Electron",
3 | "React version": "15",
4 | "currentDateTime": "2/20/2017, 1:10:55 PM"
5 | }
--------------------------------------------------------------------------------
/React.15/ReduxElectron/js/mainipc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 |
5 | const rootDataPath = './data';
6 |
7 | const getData = function(event, doneCallBack) {
8 | const filePath = rootDataPath + '/basic.json';
9 | const jsonReadCallBack = function(err, data){
10 | if (err) doneCallBack('Data readFile error ' + filePath);
11 | else {
12 | const jsonData = JSON.parse(data.toString());
13 | doneCallBack(event, jsonData);
14 | }
15 | };
16 | fs.readFile(filePath, jsonReadCallBack);
17 | };
18 |
19 | const setData = function(data, event, doneCallBack) {
20 | const filePath = rootDataPath + '/basic.json';
21 | const writeFileCallBack = function (err) {
22 | if (err) console.log('error saving Data.json file ');
23 | else doneCallBack(event);
24 | };
25 | fs.writeFile(filePath, JSON.stringify(data, null, 2), writeFileCallBack);
26 | };
27 |
28 | module.exports = function(socket) {
29 | console.log('mainipc called.');
30 |
31 | const getDataDone = function(event, data){ event.sender.send('server:GotData', data); };
32 | const onGetData = function(event){ getData(event, getDataDone); };
33 | socket.on('client:GetData', onGetData);
34 |
35 | const setDataDone = function(event){ event.sender.send('server:SetDataDone'); };
36 | const onSetData = function(event, data){ setData(data, event, setDataDone); };
37 | socket.on('client:SetData', onSetData);
38 | };
39 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const electron = require('electron');
4 | const {app} = electron;
5 | const {BrowserWindow} = electron;
6 | var fs = require('fs');
7 |
8 | const useDevTools = 0;
9 |
10 | const {ipcMain} = electron;
11 | require('./js/mainipc')(ipcMain);
12 |
13 | var mainWindow = null;
14 |
15 | app.on('window-all-closed', function() { app.quit(); });
16 |
17 | app.on('ready', function() {
18 | mainWindow = new BrowserWindow({width: 800, height: 600});
19 |
20 | var windowStatePath = './windowstate.json';
21 | var windowState = {};
22 | if (useDevTools) mainWindow.openDevTools();
23 | var jsonReadCallBack = function(err, data){
24 | if (err) console.log('error opening windowstate');
25 | else {
26 | windowState = JSON.parse(data.toString());
27 | mainWindow.setSize(windowState.size[0], windowState.size[1]);
28 | mainWindow.setPosition(windowState.position[0], windowState.position[1]);
29 | }
30 | };
31 | fs.readFile(windowStatePath, jsonReadCallBack);
32 |
33 | mainWindow.loadURL('file://' + __dirname + '/ui-dist/index.html');
34 | mainWindow.on('close', function() {
35 | windowState.size = mainWindow.getSize();
36 | windowState.position = mainWindow.getPosition();
37 | var writeFileCallBack = function (err) {
38 | if (err) console.log('error saving windowstate.json file ');
39 | mainWindow = null;
40 | };
41 | fs.writeFile(windowStatePath, JSON.stringify(windowState, null, 2), writeFileCallBack);
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ReactPatterns.15-ReduxElectron",
3 | "version": "1.0.0",
4 | "main": "main.js",
5 | "description": "A collection of simple react projects providing reusable components, startup and test examples.",
6 | "license": "MIT",
7 | "author": {
8 | "name": "Janaka Stevens",
9 | "email": "jmstevens@calitek.com"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/calitek/ReactPatterns.git"
14 | },
15 | "scripts": {
16 | "start": "electron .",
17 | "ww": "webpack --progress --profile --colors --env.noMinimize --watch",
18 | "nw": "webpack --progress --profile --colors --env.noMinimize"
19 | },
20 | "dependencies": {
21 | "electron": "*"
22 | },
23 | "devDependencies": {
24 | "react": "^15.4.0",
25 | "react-dom": "^15.4.0",
26 | "react-redux": "latest",
27 | "redux": "latest",
28 |
29 | "babel-core": "latest",
30 | "babel-loader": "^6.1.0",
31 | "babel-preset-es2015": "latest",
32 | "babel-preset-react": "latest",
33 | "babel-preset-stage-0": "latest",
34 | "css-loader": "latest",
35 | "extract-text-webpack-plugin": "^2.0.0-rc.3",
36 | "file-loader": "latest",
37 | "style-loader": "^0.13.1",
38 | "webpack": "latest"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/ui-src/app.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import './index.html';
4 | import './css/index.css';
5 | import './img/favicon.ico';
6 |
7 | import React from 'react';
8 | import ReactDom from 'react-dom';
9 | import {Provider} from 'react-redux';
10 |
11 | import AppCtrl from './components/app.ctrl';
12 | import AppStore from './store/App.Store';
13 |
14 | window.ReactDom = ReactDom;
15 |
16 | ReactDom.render(
17 |
,
18 | document.getElementById('react')
19 | );
20 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/ui-src/components/app.ctrl.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 |
4 | import AppNotes from './app.notes';
5 |
6 | let AppCtrlSty = {
7 | height: '100%',
8 | padding: '0 10px 0 0'
9 | };
10 |
11 | const AppCtrl = (props) => {
12 | let data1 = props.Data1;
13 | return (
14 |
15 | React Version: {data1['React version']}
16 | Project: {data1.Project}
17 | Current date/time: {data1.currentDateTime}
18 |
19 |
20 | );
21 | };
22 |
23 | function mapStateToProps(store) {
24 | return {Data1: store.data1};
25 | }
26 |
27 | export default connect(mapStateToProps, null)(AppCtrl);
28 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/ui-src/components/app.notes.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | let AppNotesSty = {
4 | marginLeft: 'auto',
5 | marginRight: 'auto',
6 | marginTop: '30px',
7 | maxWidth: '500px',
8 | textIndent: '20px'
9 | };
10 |
11 | let textSty = {
12 | color: '#000',
13 | fontSize: '1.0em',
14 | textAlign: 'left'
15 | };
16 |
17 | let btnDivSty = {textAlign: 'center'};
18 |
19 | let standardBtnSty = {
20 | backgroundColor: '#9a6',
21 | borderBottomColor: '#cea',
22 | borderLeftColor: '#93a363',
23 | borderRightColor: '#cea',
24 | borderTopColor: '#93a363',
25 | borderRadius: '6px',
26 | color: '#eeffee',
27 | cursor: 'pointer',
28 | lineHeight: '100%',
29 | outline: 'none',
30 | verticalAlign: 'middle',
31 | whiteSpace: 'nowrap'
32 | };
33 |
34 | let p1Text = `
35 | `;
36 |
37 | export default class AppNotes extends React.Component {
38 | state = {show: true};
39 | onClick = () => { this.setState({show: !this.state.show}); };
40 | render() {
41 | let showNotes = this.state.show;
42 | let btnText = showNotes ? 'Hide notes' : 'Show notes';
43 | let notesDivSty = showNotes ? {display: 'block'} : {display: 'none'};
44 | return (
45 |
46 |
47 |
48 |
49 |
52 |
53 | );
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/ui-src/css/index.css:
--------------------------------------------------------------------------------
1 | .bodyStyle {
2 | background-color: #00303f;
3 | color: #eae3ea;
4 | display: block;
5 | overflow: hidden;
6 | width: 100%;
7 | }
8 |
9 | .header {
10 | height: 30px;
11 | margin: 0;
12 | padding: 10px 0;
13 | text-align: center;
14 | }
15 |
16 | .Title {font-size: 1.3em;}
17 |
18 | .content {
19 | height: calc(100% - 52px);
20 | max-width: 1366px;
21 | margin-left: auto;
22 | margin-right: auto;
23 | padding: 0 5px;
24 | }
25 |
26 | * { outline: none; }
27 |
28 | .a{display:block}
29 |
30 | .FlexBox {
31 | display: -webkit-box;
32 | display: -moz-box;
33 | display: -ms-flexbox;
34 | display: flex;
35 | }
36 |
37 | .FlexBoxJustAround {
38 | display: -webkit-box;
39 | display: -moz-box;
40 | display: -ms-flexbox;
41 | display: flex;
42 | justify-content: space-around;
43 | }
44 |
45 | .FlexBoxJustBetween {
46 | display: -webkit-box;
47 | display: -moz-box;
48 | display: -ms-flexbox;
49 | display: flex;
50 | justify-content: space-between;
51 | }
52 |
53 | .FlexBoxWrap {
54 | display: -webkit-box;
55 | display: -moz-box;
56 | display: -ms-flexbox;
57 | display: flex;
58 | flex-wrap: wrap;
59 | }
60 |
61 | .FlexJustify {
62 | -webkit-box-pack: justify;
63 | justify-content: space-between;
64 | }
65 |
66 | .FlexBoxStretch {
67 | display: -webkit-box;
68 | display: -moz-box;
69 | display: -ms-flexbox;
70 | display: flex;
71 | align-content: stretch;
72 | }
73 |
74 | .FlexItem {
75 | flex-grow: 1;
76 | }
77 |
78 | .HighZ {z-index: 200;}
79 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/ui-src/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.15/ReduxElectron/ui-src/img/favicon.ico
--------------------------------------------------------------------------------
/React.15/ReduxElectron/ui-src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
ReactPatterns-ReduxElectron
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/ui-src/store/Actions.js:
--------------------------------------------------------------------------------
1 | export function apiGetData() { return {type: 'ApiGetData'}; }
2 |
3 | export function apiGotData(data) { return {type: 'ApiGotData', data}; }
4 |
5 | export function apiSetData(data) { return {type: 'ApiSetData', data}; }
6 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/ui-src/store/App.Store.js:
--------------------------------------------------------------------------------
1 | import {createStore, applyMiddleware} from 'redux';
2 | import {apiSetData} from './Actions';
3 | import startWs, {wsMiddleware} from './ipc.api';
4 |
5 | function handleData(state = {data1: {}}, action) {
6 | switch (action.type) {
7 | case 'ApiGotData': return Object.assign({}, state, {data1: action.data});
8 | default: return state;
9 | }
10 | }
11 |
12 | const store = createStore(handleData, applyMiddleware(wsMiddleware));
13 |
14 | startWs(store);
15 |
16 | const newData = {
17 | 'React version': '15',
18 | 'Project': 'Redux with Electron',
19 | 'currentDateTime': new Date().toLocaleString()
20 | };
21 |
22 | store.dispatch(apiSetData(newData));
23 |
24 | export default store;
25 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/ui-src/store/ipc.api.js:
--------------------------------------------------------------------------------
1 | import * as Actions from './Actions';
2 |
3 | export function wsMiddleware() {
4 | return (next) => (action) => {
5 | if (ipc && action.type === 'ApiGetData') {
6 | ipc.send('client:GetData', {});
7 | } else if (ipc && action.type === 'ApiSetData') {
8 | ipc.send('client:SetData', action.data);
9 | }
10 |
11 | return next(action);
12 | };
13 | }
14 |
15 | export default function (store) {
16 |
17 | ipc.on('server:GotData', (event, data) => {
18 | store.dispatch(Actions.apiGotData(data));
19 | });
20 |
21 | ipc.on('server:SetDataDone', () => {
22 | store.dispatch(Actions.apiGetData());
23 | });
24 | }
25 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
3 | const webpack = require('webpack');
4 | const configJson = require('./webpack.config.json');
5 |
6 | module.exports = (env) => {
7 |
8 | const noMinimize = env.noMinimize;
9 | var plugins = [];
10 |
11 | plugins.push(new ExtractTextPlugin({filename: 'app.css', allChunks: true}));
12 | plugins.push(new webpack.optimize.CommonsChunkPlugin({name: 'lib'}));
13 | if (noMinimize) {
14 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('development')}}));
15 | } else {
16 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('production')}}));
17 | plugins.push(new webpack.optimize.UglifyJsPlugin({include: /lib\.js/, minimize: true}));
18 | }
19 |
20 | const ROOT_PATH = path.resolve(__dirname);
21 | const SRC_PATH = path.resolve(ROOT_PATH, './ui-src');
22 | const DIST_PATH = path.resolve(ROOT_PATH, './ui-dist');
23 |
24 |
25 | return {
26 | context: SRC_PATH,
27 | entry: {
28 | app: './app.jsx',
29 | lib: configJson.lib
30 | },
31 |
32 | output: {
33 | path: DIST_PATH,
34 | filename: '[name].js'
35 | },
36 |
37 | module: {
38 | rules: [
39 | {
40 | test: /\.jsx?$/,
41 | loader: 'babel-loader',
42 | query: {presets:['es2015', 'react', 'stage-0']},
43 | exclude: /(node_modules)/,
44 | },
45 | {
46 | test: /\.css$/,
47 | use: ExtractTextPlugin.extract({
48 | fallback: 'style-loader',
49 | use: 'css-loader'
50 | })
51 | },
52 | {
53 | test: /\.(png|jpg|ico|gif)$/,
54 | loader: 'file-loader?name=img/[name].[ext]'
55 | },
56 | {
57 | test: /\.(html)$/,
58 | loader: 'file-loader?name=[name].[ext]'
59 | }
60 | ]
61 | },
62 | plugins,
63 | resolve: {
64 | extensions: ['.js', '.jsx'],
65 | modules: ['node_modules']
66 | }
67 | };
68 | };
69 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/webpack.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "lib": [
3 | "react",
4 | "react-dom",
5 | "react-redux",
6 | "redux"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/React.15/ReduxElectron/windowstate.json:
--------------------------------------------------------------------------------
1 | {
2 | "size": [
3 | 1365,
4 | 1335
5 | ],
6 | "position": [
7 | 1943,
8 | 23
9 | ]
10 | }
--------------------------------------------------------------------------------
/React.15/ReduxFetch/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react", "stage-0"]
3 | }
--------------------------------------------------------------------------------
/React.15/ReduxFetch/README.md:
--------------------------------------------------------------------------------
1 | # ReactPatterns ReduxFetch
2 |
3 | A basic demonstration of Redux with fetch polyfill. This would be the starting point for a simple data handling app.
4 | The 15 version uses more es6 and refines the reflux usage a bit.
5 |
6 | # Getting started
7 |
8 | cd into the root directory of the project. If the first time "npm install". "npm run ww" for webpack with watch.
9 | "npm run nw" for webpack no watch. "npm start" to start the node server. "localhost:3500" in the browser.
10 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/__tests__/.setup.js:
--------------------------------------------------------------------------------
1 | require('babel-register')();
2 |
3 | var jsdom = require('jsdom').jsdom;
4 |
5 | var exposedProperties = ['window', 'navigator', 'document'];
6 |
7 | global.document = jsdom('');
8 | global.window = document.defaultView;
9 | Object.keys(document.defaultView).forEach((property) => {
10 | if (typeof global[property] === 'undefined') {
11 | exposedProperties.push(property);
12 | global[property] = document.defaultView[property];
13 | }
14 | });
15 |
16 | global.navigator = {
17 | userAgent: 'node.js'
18 | };
19 |
20 | documentRef = document;
21 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/__tests__/app.ctrl.test.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import {Provider} from 'react-redux';
5 | import {mount} from 'enzyme';
6 | import {expect} from 'chai';
7 | import configureMockStore from 'redux-mock-store';
8 |
9 | import AppCtrl from '../ui-src/components/app.ctrl';
10 |
11 | const mockStore = configureMockStore();
12 |
13 | describe('mount(
)', () => {
14 | let store = mockStore({data1: {}});
15 | const wrapper = mount(
16 |
17 |
18 |
19 | );
20 | expect(wrapper.find(AppCtrl).length).to.equal(1);
21 | const container = wrapper.find(AppCtrl);
22 | it('checks div count', () => {
23 | expect(container.find('div').length).to.equal(4);
24 | });
25 | it('checks br count', () => {
26 | expect(container.find('br').length).to.equal(6);
27 | });
28 | it('checks props.Data1', () => {
29 | expect(container.props('Data1')).to.be.empty;
30 | });
31 | it('checks text contains', () => {
32 | expect(container.text()).to.contain('React Version');
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/__tests__/server.test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import chai, {expect} from 'chai';
4 | import chaiHttp from 'chai-http';
5 | // import sinon from 'sinon';
6 |
7 | chai.use(chaiHttp);
8 |
9 | describe('server test with chai-http', () => {
10 | it('checks get /', () => {
11 | chai.request('../js/server').get('/')
12 | .end(function (err, res) {
13 | expect(err).to.be.null;
14 | expect(res).to.have.status(200);
15 | });
16 | });
17 | it('checks get /routes/getData', () => {
18 | chai.request('../js/server').get('/routes/getData')
19 | .end(function (err, res) {
20 | expect(err).to.be.null;
21 | expect(res).to.have.status(200);
22 | expect(res).to.have.header('content-type', 'application/json; charset=utf-8');
23 | expect(res).to.have.header('content-length', '93');
24 | expect(res).to.be.json;
25 | console.log('res: ', res.headers);
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/cert.csr:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE REQUEST-----
2 | MIIB0TCCAToCAQAwejETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNVmFs
3 | bGV5IENlbnRlcjEQMA4GA1UEChMHQ2FsaXRlazEVMBMGA1UEAxMMSk1hcmtTdGV2
4 | ZW5zMSIwIAYJKoZIhvcNAQkBFhNvcGVuc3NsQGNhbGl0ZWsuY29tMIGfMA0GCSqG
5 | SIb3DQEBAQUAA4GNADCBiQKBgQCmxGXgGN9A+Op0AvzWFr8vWcGaXlRR5bA2Z6GU
6 | 0baHJoKRjaSX6vCxuiI+OoFk9R1yXIuFtuPGb+0Vi36hVabkn4yR9SfagueTdN+r
7 | KIi28q5bDV9ZF+D/nTsXKctDnmbMAtuLA4xe91RBLa7zSk5FA3Kq1a1OWjhUKmFB
8 | /dDOBQIDAQABoBcwFQYJKoZIhvcNAQkHMQgTBmZyaXNjbzANBgkqhkiG9w0BAQUF
9 | AAOBgQA8xSFREgQtMtLOlIdSCjbPuEzxQMJsPLNcKQq4Uov446VWA3x3mDt7KKKT
10 | MSs1a6zyzj3N1Rjz6+nG/9tHHpeZCD/bPUwg1q2E7MFtOgFW/v2h/ItIzfF5Ovrb
11 | Jmhxalt1Xn1vMRYRIMJ0aqlIKYRZLerUttxTlECDzbWsEBY+Jw==
12 | -----END CERTIFICATE REQUEST-----
13 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/certificate.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICazCCAdQCCQCvtmRxHlk/FTANBgkqhkiG9w0BAQUFADB6MRMwEQYDVQQIEwpD
3 | YWxpZm9ybmlhMRYwFAYDVQQHEw1WYWxsZXkgQ2VudGVyMRAwDgYDVQQKEwdDYWxp
4 | dGVrMRUwEwYDVQQDEwxKTWFya1N0ZXZlbnMxIjAgBgkqhkiG9w0BCQEWE29wZW5z
5 | c2xAY2FsaXRlay5jb20wHhcNMTYxMjI3MjI1NjU3WhcNMTcwMTI2MjI1NjU3WjB6
6 | MRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1WYWxsZXkgQ2VudGVyMRAw
7 | DgYDVQQKEwdDYWxpdGVrMRUwEwYDVQQDEwxKTWFya1N0ZXZlbnMxIjAgBgkqhkiG
8 | 9w0BCQEWE29wZW5zc2xAY2FsaXRlay5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0A
9 | MIGJAoGBAKbEZeAY30D46nQC/NYWvy9ZwZpeVFHlsDZnoZTRtocmgpGNpJfq8LG6
10 | Ij46gWT1HXJci4W248Zv7RWLfqFVpuSfjJH1J9qC55N036soiLbyrlsNX1kX4P+d
11 | Oxcpy0OeZswC24sDjF73VEEtrvNKTkUDcqrVrU5aOFQqYUH90M4FAgMBAAEwDQYJ
12 | KoZIhvcNAQEFBQADgYEAOzaxEZFj74h1gaSFQXUHAwkFXcZSRy+9uES7a2csnKe4
13 | xn9s6Ym8HadPt0ANGFifNemcuPWQlxir1LG/Pb8ZTCiqbqobVK48J1n5+b4C6T8Q
14 | /H7WGb70AAcMUXa1H1H5HsDa96G6k31bGOHlkCjKdrVjwq//NDdB7thFrAkVNhk=
15 | -----END CERTIFICATE-----
16 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/data/basic.json:
--------------------------------------------------------------------------------
1 | {
2 | "React version": "15",
3 | "Project": "Redux with fetch polyfill",
4 | "currentDateTime": "2/17/2017, 11:40:41 AM"
5 | }
--------------------------------------------------------------------------------
/React.15/ReduxFetch/js/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const express = require('express');
4 | const router = express.Router();
5 |
6 | const getSetData = require('./routes/GetSetData');
7 |
8 | router.get('/getData', function(req, res) {
9 | const getDataDone = function(data){ res.send(data); };
10 | getSetData.getData(getDataDone);
11 | });
12 |
13 | router.post('/setData', function(req, res) {
14 | const setDataDone = function(data){ res.send(data); };
15 | getSetData.setData(req.body, setDataDone);
16 | });
17 |
18 | module.exports = router;
19 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/js/routes/GetSetData.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 |
5 | const rootDataPath = './data';
6 |
7 | module.exports.getData = function(doneCallBack) {
8 | const filePath = rootDataPath + '/basic.json';
9 | const jsonReadCallBack = function(err, data){
10 | if (err) doneCallBack('Data readFile error ' + filePath);
11 | else {
12 | const jsonData = JSON.parse(data.toString());
13 | doneCallBack(jsonData);
14 | }
15 | };
16 | fs.readFile(filePath, jsonReadCallBack);
17 | };
18 |
19 | module.exports.setData = function(data, doneCallBack) {
20 | const filePath = rootDataPath + '/basic.json';
21 | const writeFileCallBack = function (err) {
22 | if (err) console.log('error saving Data.json file ');
23 | doneCallBack({setResponse: 'ok'});
24 | };
25 | fs.writeFile(filePath, JSON.stringify(data, null, 2), writeFileCallBack);
26 | };
27 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/js/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const bodyParser = require('body-parser');
4 | const express = require('express');
5 | const favicon = require('serve-favicon');
6 | const https = require('https');
7 | const http = require('http');
8 | const fs = require('fs');
9 |
10 | const path = require('path');
11 | const port = Number(process.env.REDUXFETCHPORT || 3500);
12 |
13 | var options = {
14 | key: fs.readFileSync('./private.key'),
15 | cert: fs.readFileSync('./certificate.pem')
16 | };
17 | const routes = require('./routes');
18 |
19 | const app = express();
20 | http.createServer(app).listen(port);
21 | https.createServer(options, app).listen(3600);
22 |
23 | app.use(bodyParser.json());
24 | app.use(bodyParser.urlencoded({extended: false}));
25 |
26 | app.use('/', express.static('ui-dist'));
27 | app.use('/routes', routes);
28 |
29 | app.use(favicon(path.join(__dirname, '..', 'ui-dist', 'img', 'favicon.ico')));
30 | app.get('/', function(req, res){ res.sendfile(__dirname + '/index.html', [], null); });
31 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ReactPatterns.15-ReduxFetch",
3 | "version": "1.0.0",
4 | "description": "A collection of simple react projects providing reusable components, startup and test examples.",
5 | "license": "MIT",
6 | "author": {
7 | "name": "Janaka Stevens",
8 | "email": "jmstevens@calitek.com"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/calitek/ReactPatterns.git"
13 | },
14 | "scripts": {
15 | "start": "node js/server.js",
16 | "test": "mocha __tests__/.setup.js __tests__/**/*.test.js?",
17 | "testw": "npm test -- --watch",
18 | "ww": "webpack --progress --profile --colors --env.noMinimize --watch",
19 | "nw": "webpack --progress --profile --colors --env.noMinimize"
20 | },
21 | "dependencies": {
22 | "body-parser": "latest",
23 | "express": "latest",
24 | "serve-favicon": "latest"
25 | },
26 | "devDependencies": {
27 | "react": "^15.4.0",
28 | "react-dom": "^15.4.0",
29 | "react-redux": "latest",
30 | "redux": "latest",
31 | "redux-thunk": "latest",
32 | "whatwg-fetch": "latest",
33 |
34 | "babel-core": "latest",
35 | "babel-loader": "^6.1.0",
36 | "babel-preset-es2015": "latest",
37 | "babel-preset-react": "latest",
38 | "babel-preset-stage-0": "latest",
39 | "css-loader": "latest",
40 | "extract-text-webpack-plugin": "^2.0.0-rc.3",
41 | "file-loader": "latest",
42 | "style-loader": "^0.13.1",
43 | "webpack": "latest",
44 |
45 | "babel-register": "latest",
46 | "chai": "latest",
47 | "chai-http": "latest",
48 | "enzyme": "latest",
49 | "jsdom": "latest",
50 | "mocha": "latest",
51 | "react-addons-test-utils": "^15.4.0",
52 | "redux-mock-store": "latest",
53 | "sinon": "latest"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/private.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICWwIBAAKBgQCmxGXgGN9A+Op0AvzWFr8vWcGaXlRR5bA2Z6GU0baHJoKRjaSX
3 | 6vCxuiI+OoFk9R1yXIuFtuPGb+0Vi36hVabkn4yR9SfagueTdN+rKIi28q5bDV9Z
4 | F+D/nTsXKctDnmbMAtuLA4xe91RBLa7zSk5FA3Kq1a1OWjhUKmFB/dDOBQIDAQAB
5 | AoGAG22z/863cX0/OoN/SEsHeOc/U39uSOYJPHmA9vQjHEl2MjBkwOPQYLrnhOqk
6 | e5FhHX0hKYXyIqIoEWIXGrv2reGAqD0telMwpueCKYx+HfnwYELGookfCP4yjcYv
7 | rZEmvQ79/JVWhc4Sg1dHciEyIEI600bYLnl7l1RdFzVmLcECQQDcQzBXRO0/Iz65
8 | K6XfCT3qNV2SdDuzR9+G1hRRu2/uauO3PnzNfJwG48JXTYzyuSrRM6c/Er9uFht5
9 | UKK3CsY1AkEAwdM7Vfp/npAyn+P4ZiwHPv51ss3rNxqDEkvukVkBk4Y+2Km5apgC
10 | 3BobeQxpuR38YbhdKC39cEbG6DPCJ0WikQJAdrrlEPW/qVwXUHt9wxdZP6makfqD
11 | v+VLUYSOmWwfLvaBX2KYpa+472HQfXz5MFGuCez9B1vUwsO59ZAI1gBBzQJAaFff
12 | 3JRjOahlKIBgjBhtujLgh+alFuAV6bao8uRYneOqV5dfMwwslfMUESFmlPqYkL7g
13 | n63KfzQLBpw+jEfHkQJAItc+cyf7Xn2MyYT5kOoFVS94miUqCo/hRVrAB6acReHA
14 | CdycidnkJYkOlwRCl0D9ur1gBmYvuO+buTojI+Cb3g==
15 | -----END RSA PRIVATE KEY-----
16 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/ui-src/app.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import './index.html';
4 | import './css/index.css';
5 | import './img/favicon.ico';
6 |
7 | import React from 'react';
8 | import ReactDom from 'react-dom';
9 | import {Provider} from 'react-redux';
10 |
11 | import AppCtrl from './components/app.ctrl';
12 | import AppStore from './store/App.Store';
13 |
14 | window.ReactDom = ReactDom;
15 |
16 | ReactDom.render(
17 |
,
18 | document.getElementById('react')
19 | );
20 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/ui-src/components/app.ctrl.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 |
4 | import AppNotes from './app.notes';
5 |
6 | let AppCtrlSty = {
7 | height: '100%',
8 | padding: '0 10px 0 0'
9 | };
10 |
11 | function AppCtrl({Data1}) {
12 | let data1 = Data1;
13 | return (
14 |
15 | React Version: {data1['React version']}
16 | Project: {data1.Project}
17 | Current date/time: {data1.currentDateTime}
18 |
19 |
20 | );
21 | }
22 |
23 | function mapStateToProps(store) {
24 | return {Data1: store.data1};
25 | }
26 |
27 | export default connect(mapStateToProps)(AppCtrl);
28 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/ui-src/components/app.notes.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import AppText from './app.text';
4 |
5 | const AppNotesSty = {
6 | marginLeft: 'auto',
7 | marginRight: 'auto',
8 | marginTop: '30px',
9 | maxWidth: '500px',
10 | textIndent: '20px'
11 | };
12 |
13 | const textSty = {
14 | color: '#FFF',
15 | fontSize: '1.0em',
16 | textAlign: 'left'
17 | };
18 |
19 | const btnDivSty = {textAlign: 'center'};
20 |
21 | const standardBtnSty = {
22 | backgroundColor: '#9a6',
23 | borderBottomColor: '#cea',
24 | borderLeftColor: '#93a363',
25 | borderRightColor: '#cea',
26 | borderTopColor: '#93a363',
27 | borderRadius: '6px',
28 | color: '#eeffee',
29 | cursor: 'pointer',
30 | lineHeight: '100%',
31 | outline: 'none',
32 | verticalAlign: 'middle',
33 | whiteSpace: 'nowrap'
34 | };
35 |
36 | export default class AppNotes extends React.Component {
37 | state = {show: true};
38 | onClick = () => { this.setState({show: !this.state.show}); };
39 | render() {
40 | if (AppText.p1Text.trim().length === 0) return null;
41 | let showNotes = this.state.show;
42 | let btnText = showNotes ? 'Hide notes' : 'Show notes';
43 | let notesDivSty = showNotes ? {display: 'block'} : {display: 'none'};
44 | return (
45 |
46 |
47 |
48 |
49 |
50 |
{AppText.p1Text}
51 |
52 |
53 | );
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/ui-src/components/app.text.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | p1Text: `
3 |
4 | `
5 | };
6 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/ui-src/css/index.css:
--------------------------------------------------------------------------------
1 | .bodyStyle {
2 | background-color: #00303f;
3 | color: #eae3ea;
4 | display: block;
5 | overflow: hidden;
6 | width: 100%;
7 | }
8 |
9 | .header {
10 | height: 30px;
11 | margin: 0;
12 | padding: 10px 0;
13 | text-align: center;
14 | }
15 |
16 | .Title {font-size: 1.3em;}
17 |
18 | .content {
19 | height: calc(100% - 52px);
20 | max-width: 1366px;
21 | margin-left: auto;
22 | margin-right: auto;
23 | padding: 0 5px;
24 | }
25 |
26 | * { outline: none; }
27 |
28 | .a{display:block}
29 |
30 | .FlexBox {
31 | display: -webkit-box;
32 | display: -moz-box;
33 | display: -ms-flexbox;
34 | display: flex;
35 | }
36 |
37 | .FlexBoxJustAround {
38 | display: -webkit-box;
39 | display: -moz-box;
40 | display: -ms-flexbox;
41 | display: flex;
42 | justify-content: space-around;
43 | }
44 |
45 | .FlexBoxJustBetween {
46 | display: -webkit-box;
47 | display: -moz-box;
48 | display: -ms-flexbox;
49 | display: flex;
50 | justify-content: space-between;
51 | }
52 |
53 | .FlexBoxWrap {
54 | display: -webkit-box;
55 | display: -moz-box;
56 | display: -ms-flexbox;
57 | display: flex;
58 | flex-wrap: wrap;
59 | }
60 |
61 | .FlexJustify {
62 | -webkit-box-pack: justify;
63 | justify-content: space-between;
64 | }
65 |
66 | .FlexBoxStretch {
67 | display: -webkit-box;
68 | display: -moz-box;
69 | display: -ms-flexbox;
70 | display: flex;
71 | align-content: stretch;
72 | }
73 |
74 | .FlexItem {
75 | flex-grow: 1;
76 | }
77 |
78 | .HighZ {z-index: 200;}
79 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/ui-src/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.15/ReduxFetch/ui-src/img/favicon.ico
--------------------------------------------------------------------------------
/React.15/ReduxFetch/ui-src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
ReactPatterns-ReduxFetch
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/ui-src/store/App.Store.js:
--------------------------------------------------------------------------------
1 | import {createStore, applyMiddleware} from 'redux';
2 | import thunkMiddleware from 'redux-thunk';
3 | import {apiSetData} from './api.Actions';
4 |
5 | function handleData(state = {data1: {}}, action) {
6 | switch (action.type) {
7 | case 'GOT_DATA': return Object.assign({}, state, {data1: action.payload});
8 | default: return state;
9 | }
10 | }
11 |
12 | const store = createStore(handleData, applyMiddleware(thunkMiddleware));
13 |
14 | const newData = {
15 | 'React version': '15',
16 | 'Project': 'Redux with fetch polyfill',
17 | 'currentDateTime': new Date().toLocaleString()
18 | };
19 |
20 | store.dispatch(apiSetData(newData));
21 |
22 | export default store;
23 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/ui-src/store/api.Actions.js:
--------------------------------------------------------------------------------
1 | import 'whatwg-fetch';
2 |
3 | let jsonHeader = {'Accept': 'application/json', 'Content-Type': 'application/json'};
4 |
5 | export function apiSetData(data) {
6 | return (dispatch) => {
7 | fetch('/routes/setData', {method: 'POST', headers: jsonHeader, body: JSON.stringify(data)})
8 | .then(() => {
9 | fetch('/routes/getData')
10 | .then((response) => response.json())
11 | .then((json) => dispatch({type: 'GOT_DATA', payload: json}));
12 | });
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
3 | const webpack = require('webpack');
4 | const configJson = require('./webpack.config.json');
5 |
6 | module.exports = (env) => {
7 |
8 | const noMinimize = env.noMinimize;
9 | var plugins = [];
10 |
11 | plugins.push(new ExtractTextPlugin({filename: 'app.css', allChunks: true}));
12 | plugins.push(new webpack.optimize.CommonsChunkPlugin({name: 'lib'}));
13 | if (noMinimize) {
14 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('development')}}));
15 | } else {
16 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('production')}}));
17 | plugins.push(new webpack.optimize.UglifyJsPlugin({include: /lib\.js/, minimize: true}));
18 | }
19 |
20 | const ROOT_PATH = path.resolve(__dirname);
21 | const SRC_PATH = path.resolve(ROOT_PATH, './ui-src');
22 | const DIST_PATH = path.resolve(ROOT_PATH, './ui-dist');
23 |
24 |
25 | return {
26 | context: SRC_PATH,
27 | entry: {
28 | app: './app.jsx',
29 | lib: configJson.lib
30 | },
31 |
32 | output: {
33 | path: DIST_PATH,
34 | filename: '[name].js'
35 | },
36 |
37 | module: {
38 | rules: [
39 | {
40 | test: /\.jsx?$/,
41 | loader: 'babel-loader',
42 | query: {presets:['es2015', 'react', 'stage-0']},
43 | exclude: /(node_modules)/,
44 | },
45 | {
46 | test: /\.css$/,
47 | use: ExtractTextPlugin.extract({
48 | fallback: 'style-loader',
49 | use: 'css-loader'
50 | })
51 | },
52 | {
53 | test: /\.(png|jpg|ico|gif)$/,
54 | loader: 'file-loader?name=img/[name].[ext]'
55 | },
56 | {
57 | test: /\.(html)$/,
58 | loader: 'file-loader?name=[name].[ext]'
59 | }
60 | ]
61 | },
62 | plugins,
63 | resolve: {
64 | extensions: ['.js', '.jsx'],
65 | modules: ['node_modules']
66 | }
67 | };
68 | };
69 |
--------------------------------------------------------------------------------
/React.15/ReduxFetch/webpack.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "lib": [
3 | "react",
4 | "react-dom",
5 | "react-redux",
6 | "redux",
7 | "redux-thunk",
8 | "whatwg-fetch"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/README.md:
--------------------------------------------------------------------------------
1 | # ReactPatterns ReduxPages
2 |
3 | This demonstrates using Redux to handle app state.
4 |
5 | Pages with;
6 |
7 | * Radium
8 | * Window Events
9 | * Window Object
10 |
11 | The singleton test is from (http://amanvirk.me/singleton-classes-in-es6/)
12 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/js/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const express = require('express');
4 | const favicon = require('serve-favicon');
5 | const path = require('path');
6 | const port = Number(3500);
7 |
8 | const app = express();
9 | app.listen(port);
10 |
11 | app.use('/', express.static('ui-dist'));
12 | app.use(favicon(path.join(__dirname, '..', 'ui-dist', 'img', 'favicon.ico')));
13 | app.get('/', function(req, res){ res.sendfile(__dirname + '/index.html', [], null); });
14 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ReactPatterns.15-ReduxPages",
3 | "version": "1.0.0",
4 | "description": "A collection of simple react projects providing reusable components, startup and test examples.",
5 | "license": "MIT",
6 | "author": {
7 | "name": "Janaka Stevens",
8 | "email": "jmstevens@calitek.com"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/calitek/ReactPatterns.git"
13 | },
14 | "scripts": {
15 | "start": "node js/server.js",
16 | "ww": "webpack --progress --profile --colors --env.noMinimize --watch",
17 | "nw": "webpack --progress --profile --colors --env.noMinimize"
18 | },
19 | "dependencies": {
20 | "express": "latest",
21 | "serve-favicon": "latest"
22 | },
23 | "devDependencies": {
24 | "radium": "latest",
25 | "react": "^15.4.0",
26 | "react-dom": "^15.4.0",
27 | "react-redux": "latest",
28 | "redux": "latest",
29 | "redux-logger": "latest",
30 |
31 | "babel-core": "latest",
32 | "babel-loader": "^6.1.0",
33 | "babel-preset-es2015": "latest",
34 | "babel-preset-react": "latest",
35 | "babel-preset-stage-0": "latest",
36 | "css-loader": "latest",
37 | "extract-text-webpack-plugin": "^2.0.0-rc.3",
38 | "file-loader": "latest",
39 | "loader-utils": "latest",
40 | "style-loader": "^0.13.1",
41 | "webpack": "latest"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/app.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import './index.html';
4 | import './css/index.css';
5 | import './img/favicon.ico';
6 |
7 | import React from 'react';
8 | import ReactDom from 'react-dom';
9 | import {Provider} from 'react-redux';
10 |
11 | import AppCtrl from './components/app.ctrl';
12 | import AppStore from './store/App.Store';
13 |
14 | window.ReactDom = ReactDom;
15 |
16 | ReactDom.render(
, document.getElementById('react'));
17 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/components/app.ctrl.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 |
4 | import NavBar from './common/nav.bar';
5 |
6 | import CachePage from './cache/cache.page';
7 | import EventPage from './event/event.page';
8 | import HomePage from './home/home.page';
9 | import ObjectPage from './object/object.page';
10 | import RadiumPage from './radium/radium.page';
11 |
12 | let AppCtrlSty = {
13 | height: '100%',
14 | overflow: 'hidden',
15 | padding: '0px',
16 | width: '100%'
17 | };
18 |
19 | function AppCtrl({appState}) {
20 | let page = appState.currentPage;
21 | let hideCache = (page != 'cache');
22 | let hideEvent = (page != 'event');
23 | let hideHome = (page != 'home');
24 | let hideObject = (page != 'object');
25 | let hideRadium = (page != 'radium');
26 | return (
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | );
36 | }
37 |
38 | function mapStateToProps(store) { return {appState: store.appState}; }
39 |
40 | export default connect(mapStateToProps)(AppCtrl);
41 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/components/cache/cache.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import Cache from '../../lib/cache';
4 |
5 | let AboutPageSty = {
6 | border: 'solid 1px darkslategrey',
7 | height: 'calc(100% - 2px)',
8 | overflow: 'hidden',
9 | padding: '0px',
10 | width: '100%'
11 | };
12 |
13 | export default class CachePage extends React.Component {
14 | state = {constructorTime: new Date().toLocaleString(), componentDidMountTime: ''};
15 | componentDidMount = () => { this.setState({componentDidMountTime: new Date().toLocaleString()}); };
16 | render() {
17 | if (this.props.hide) return null;
18 | let aTime = (new Cache()).time.toString();
19 | let renderTime = new Date().toLocaleString();
20 | return (
21 |
22 | singleton object time: {aTime}
23 |
24 | constructorTime: {this.state.constructorTime}
25 |
26 | componentDidMountTime: {this.state.componentDidMountTime}
27 |
28 | renderTime: {renderTime}
29 |
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/components/common/app.colors.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | morning_sky: '#cae4db',
3 | honey: '#dcae1d',
4 | cerulean: '#00303f',
5 | mist: '#7a9d96',
6 |
7 | bluebell: '#155765',
8 | olive: '#57652a',
9 | ornate: '#ab9353',
10 | plum: '#4d2c3d',
11 |
12 | gold: '#cda34f',
13 | daisy: '#e9e7da',
14 | stem: '#636b46',
15 | greenery: '#373f27',
16 |
17 | aqua: '#6bbaa7',
18 | sunshine: '#fba100',
19 | lavender: '#6c648b',
20 | dusty_rose: '#b6a19e',
21 |
22 | rust: '#b56357',
23 | mint: '#b4dbc0',
24 | slate: '#eae3ea',
25 | sea_foam: '#a7b3a5',
26 |
27 | white: '#fff',
28 | black: '#000'
29 | };
30 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/components/common/nav.bar.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 | import {bindActionCreators} from 'redux';
4 |
5 | import {appNavMenuAction} from '../../store/app/app.Actions';
6 | import AppColors from './app.colors';
7 |
8 | let NavBarSty = {
9 | background: AppColors.greenery,
10 | lineHeight: '3em',
11 | overflow: 'hidden',
12 | padding: '0px',
13 | };
14 |
15 | let spanSty = {
16 | color: AppColors.white,
17 | cursor: 'pointer',
18 | fontFamily: '\'Trebuchet MS\', \'Lucida Grande\', \'Lucida Sans Unicode\', \'Lucida Sans\', \'sans-serif\'',
19 | fontSize: '1.5em',
20 | fontWeight: '500',
21 | };
22 |
23 | let spanSpacerSty = {padding: '0 2em'};
24 |
25 | const NavBar = (props) => {
26 | const onMouseEnter = (event) => { if (props.navEnter) props.navEnter(event.target.id); };
27 | const onMouseLeave = (event) => { if (props.navLeave) props.navLeave(event.target.id); };
28 | const navClick = (event) => {
29 | props.appNavMenuAction(event.target.id);
30 | if (props.navEnter) props.navEnter('');
31 | };
32 | let SpanSty = Object.assign({}, spanSty);
33 | let SelectedSty = Object.assign({}, SpanSty);
34 | SelectedSty.color = AppColors.mint;
35 |
36 | let cacheSty = props.fromPage === 'cache' ? SelectedSty : SpanSty;
37 | let eventSty = props.fromPage === 'event' ? SelectedSty : SpanSty;
38 | let homeSty = props.fromPage === 'home' ? SelectedSty : SpanSty;
39 | let objectSty = props.fromPage === 'object' ? SelectedSty : SpanSty;
40 | let radiumSty = props.fromPage === 'radium' ? SelectedSty : SpanSty;
41 |
42 | return (
43 |
44 |
45 | Home
46 |
47 | Window Event
48 |
49 | Window Object
50 |
51 | Radium
52 |
53 | Cache
54 |
55 |
56 | );
57 | };
58 |
59 | function mapDispatchToProps(dispatch) {
60 | return bindActionCreators({appNavMenuAction}, dispatch);
61 | }
62 |
63 | export default connect(null, mapDispatchToProps)(NavBar);
64 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/components/event/event.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | let EventPageSty = {
4 | height: '100%',
5 | padding: '0 10px 0 0'
6 | };
7 |
8 | export default class EventPage extends React.Component {
9 | state = {keyCode: 0};
10 | componentDidMount = () => {
11 | window.addEventListener('keydown', this.keyDownListener);
12 | };
13 | componentWillUnmount = () => {
14 | window.removeEventListener('keydown', this.keyDownListener);
15 | };
16 | keyDownListener = (event) => {
17 | let intKey = (window.Event) ? event.which : event.keyCode;
18 | this.setState({keyCode: intKey});
19 | };
20 | render() {
21 | if (this.props.hide) return null;
22 | let keycode = this.state.keyCode;
23 | return (
24 |
25 | React 15 Window events
26 |
27 | Press any key to see the key code.
28 |
29 | Key code: {keycode}
30 |
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/components/home/home.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import Cache from '../../lib/cache';
4 |
5 | let HomePageSty = {
6 | border: 'solid 1px darkslategrey',
7 | height: 'calc(100% - 2px)',
8 | overflow: 'hidden',
9 | padding: '0px',
10 | width: '100%'
11 | };
12 |
13 | export default class HomePage extends React.Component {
14 | state = {constructorTime: new Date().toLocaleString(), componentDidMountTime: ''};
15 | componentDidMount = () => { this.setState({componentDidMountTime: new Date().toLocaleString()}); };
16 | render() {
17 | if (this.props.hide) return null;
18 | let aTime = (new Cache()).time.toString();
19 | let renderTime = new Date().toLocaleString();
20 | let platform = window.navigator.platform;
21 | let innerWidth = Math.floor(window.innerWidth);
22 | let innerHeight = Math.floor(window.innerHeight);
23 | let screenwidth = Math.floor(window.screen.width);
24 | let screenheight = Math.floor(window.screen.height);
25 | let devicePixelRatio = Math.floor(window.devicePixelRatio);
26 | let navigatorproduct = window.navigator.product;
27 | let navigatoruserAgent = window.navigator.userAgent;
28 | return (
29 |
30 | Platform: {platform}
31 | Inner Width: {innerWidth}
32 | Inner Height: {innerHeight}
33 | Screen Width: {screenwidth}
34 | Screen Height: {screenheight}
35 | Device Pixel Ratio: {devicePixelRatio}
36 | Navigator Product: {navigatorproduct}
37 | Navigator User Agent: {navigatoruserAgent}
38 | singleton object time: {aTime}
39 |
40 | constructorTime: {this.state.constructorTime}
41 |
42 | componentDidMountTime: {this.state.componentDidMountTime}
43 |
44 | renderTime: {renderTime}
45 |
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/components/radium/button.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Radium from 'radium';
3 |
4 | let styles = {
5 | base: {
6 | fontSize: 16,
7 | backgroundColor: '#0074d9',
8 | color: '#fff',
9 | border: 0,
10 | borderRadius: '0.3em',
11 | padding: '0.4em 1em',
12 | cursor: 'pointer',
13 | outline: 'none',
14 |
15 | '@media (min-width: 992px)': {
16 | padding: '0.6em 1.2em'
17 | },
18 |
19 | '@media (min-width: 1200px)': {
20 | padding: '0.8em 1.5em'
21 | },
22 |
23 | ':hover': {
24 | backgroundColor: '#0088FF'
25 | },
26 |
27 | ':focus': {
28 | backgroundColor: '#0088FF'
29 | },
30 |
31 | ':active': {
32 | backgroundColor: '#005299',
33 | transform: 'translateY(2px)',
34 | }
35 | },
36 |
37 | red: {
38 | backgroundColor: '#d90000',
39 |
40 | ':hover': {
41 | backgroundColor: '#FF0000'
42 | },
43 | ':focus': {
44 | backgroundColor: '#FF0000'
45 | },
46 | ':active': {
47 | backgroundColor: '#990000'
48 | }
49 | }
50 | };
51 |
52 | export default class Button extends React.Component {
53 | render() {
54 | return (
55 |
61 | );
62 | }
63 | }
64 |
65 | Button = Radium(Button);
66 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/components/radium/computed-well.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Radium from 'radium';
3 |
4 | export default class ComputedWell extends React.Component {
5 | constructor() {
6 | super();
7 | this.state = {dynamicBg: '#000'};
8 | }
9 | getStyles = () => {
10 | return {
11 | padding: '1em',
12 | borderRadius: 5,
13 | background: this.state.dynamicBg
14 | };
15 | };
16 | handleSubmit = (ev) => {
17 | ev.preventDefault();
18 | this.setState({dynamicBg: this.inputRef.value});
19 | };
20 | render() {
21 | return (
22 |
27 | );
28 | }
29 | }
30 |
31 | ComputedWell = Radium(ComputedWell);
32 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/components/radium/hover.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Radium from 'radium';
3 |
4 | class HoverMessage extends React.Component {
5 | render() {
6 | let buttonHover = Radium.getState(this.state, 'button', ':hover') ? (
{' '}Hovering yes!) : null;
7 | return (
8 |
9 |
10 | {buttonHover}
11 |
12 | );
13 | }
14 | }
15 |
16 | module.exports = Radium(HoverMessage);
17 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/css/index.css:
--------------------------------------------------------------------------------
1 | .bodyStyle {
2 | background-color: #00303f;
3 | color: #eae3ea;
4 | display: block;
5 | height: 100%;
6 | overflow: hidden;
7 | width: 100%;
8 | }
9 |
10 | .header {
11 | height: 30px;
12 | margin: 0;
13 | padding: 10px 0;
14 | text-align: center;
15 | }
16 |
17 | .Title {font-size: 1.3em;}
18 |
19 | .content {
20 | height: 100%;
21 | padding: 0 5px;
22 | }
23 |
24 | .contentPage {
25 | margin: 5px auto;
26 | max-width: 1366px;
27 | }
28 |
29 | * { outline: none; }
30 |
31 | .a{display:block}
32 |
33 | .FlexBox {
34 | display: -webkit-box;
35 | display: -moz-box;
36 | display: -ms-flexbox;
37 | display: flex;
38 | }
39 |
40 | .FlexBoxCenter {
41 | display: -webkit-box;
42 | display: -moz-box;
43 | display: -ms-flexbox;
44 | display: flex;
45 | justify-content: center;
46 | }
47 |
48 | .FlexBoxJustAround {
49 | display: -webkit-box;
50 | display: -moz-box;
51 | display: -ms-flexbox;
52 | display: flex;
53 | justify-content: space-around;
54 | }
55 |
56 | .FlexBoxJustBetween {
57 | display: -webkit-box;
58 | display: -moz-box;
59 | display: -ms-flexbox;
60 | display: flex;
61 | justify-content: space-between;
62 | }
63 |
64 | .FlexBoxWrap {
65 | display: -webkit-box;
66 | display: -moz-box;
67 | display: -ms-flexbox;
68 | display: flex;
69 | flex-wrap: wrap;
70 | }
71 |
72 | .FlexJustify {
73 | -webkit-box-pack: justify;
74 | justify-content: space-between;
75 | }
76 |
77 | .FlexBoxStretch {
78 | display: -webkit-box;
79 | display: -moz-box;
80 | display: -ms-flexbox;
81 | display: flex;
82 | align-content: stretch;
83 | }
84 |
85 | .FlexItem {
86 | flex-grow: 1;
87 | }
88 |
89 | .HighZ {z-index: 200;}
90 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.15/ReduxPages/ui-src/img/favicon.ico
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
ReactPatterns-ReduxPages
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/lib/cache.js:
--------------------------------------------------------------------------------
1 | //Singleton test
2 |
3 | let instance = null;
4 | export default class Cache{
5 | constructor() {
6 | if (!instance) instance = this;
7 | this.time = new Date();
8 | return instance;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/store/App.Store.js:
--------------------------------------------------------------------------------
1 | import {createStore, combineReducers, applyMiddleware} from 'redux';
2 | import createLogger from 'redux-logger';
3 |
4 | import appState from './app/app.Reducer';
5 |
6 | const reducer = combineReducers({appState});
7 | let middleware = [];
8 |
9 | const useLogger = 1;
10 | const loggerMiddleware = createLogger();
11 | if (useLogger) middleware.push(loggerMiddleware);
12 |
13 | const store = createStore(reducer, applyMiddleware(...middleware));
14 |
15 | export default store;
16 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/store/app/app.actions.js:
--------------------------------------------------------------------------------
1 | export function appNavMenuAction(newPage) { return {type: 'AppNavMenuAction', newPage}; }
2 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/ui-src/store/app/app.reducer.js:
--------------------------------------------------------------------------------
1 |
2 | const initialAppState = {
3 | currentPage: 'home',
4 | currentExample: '',
5 | srcUrl: ''
6 | };
7 |
8 | export default function handleActions(state = initialAppState, action) {
9 | let _appState = Object.assign({}, state);
10 | switch (action.type) {
11 | case 'AppNavMenuAction': _appState.currentPage = action.newPage; return _appState;
12 | default: return state;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
3 | const webpack = require('webpack');
4 | const configJson = require('./webpack.config.json');
5 |
6 | module.exports = (env) => {
7 |
8 | const noMinimize = env.noMinimize;
9 | var plugins = [];
10 |
11 | plugins.push(new ExtractTextPlugin({filename: 'app.css', allChunks: true}));
12 | plugins.push(new webpack.optimize.CommonsChunkPlugin({name: 'lib'}));
13 | if (noMinimize) {
14 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('development')}}));
15 | } else {
16 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('production')}}));
17 | plugins.push(new webpack.optimize.UglifyJsPlugin({include: /lib\.js/, minimize: true}));
18 | }
19 |
20 | const ROOT_PATH = path.resolve(__dirname);
21 | const SRC_PATH = path.resolve(ROOT_PATH, './ui-src');
22 | const DIST_PATH = path.resolve(ROOT_PATH, './ui-dist');
23 |
24 |
25 | return {
26 | context: SRC_PATH,
27 | entry: {
28 | app: './app.jsx',
29 | lib: configJson.lib
30 | },
31 |
32 | output: {
33 | path: DIST_PATH,
34 | filename: '[name].js'
35 | },
36 |
37 | module: {
38 | rules: [
39 | {
40 | test: /\.jsx?$/,
41 | loader: 'babel-loader',
42 | query: {presets:['es2015', 'react', 'stage-0']},
43 | exclude: /(node_modules)/,
44 | },
45 | {
46 | test: /\.css$/,
47 | use: ExtractTextPlugin.extract({
48 | fallback: 'style-loader',
49 | use: 'css-loader'
50 | })
51 | },
52 | {
53 | test: /\.(png|jpg|ico|gif)$/,
54 | loader: 'file-loader?name=img/[name].[ext]'
55 | },
56 | {
57 | test: /\.(html)$/,
58 | loader: 'file-loader?name=[name].[ext]'
59 | }
60 | ]
61 | },
62 | plugins,
63 | resolve: {
64 | extensions: ['.js', '.jsx'],
65 | modules: ['node_modules']
66 | }
67 | };
68 | };
69 |
--------------------------------------------------------------------------------
/React.15/ReduxPages/webpack.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "lib": [
3 | "radium",
4 | "react",
5 | "react-dom",
6 | "react-redux",
7 | "redux",
8 | "redux-logger"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/README.md:
--------------------------------------------------------------------------------
1 | # ReactPatterns ReduxSocketIO
2 |
3 | A basic demonstration of redux with websocket. This would be the starting point for a simple data handling app.
4 | The 15 version uses more es6 and refines the reflux usage a bit.
5 |
6 | # Getting started
7 |
8 | cd into the root directory of the project. If the first time "npm install". "npm run ww" for webpack with watch.
9 | "npm run nw" for webpack no watch. "npm start" to start the node server. "localhost:3500" in the browser.
10 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/data/basic.json:
--------------------------------------------------------------------------------
1 | {
2 | "React version": "15",
3 | "Project": "Redux with socket.io",
4 | "currentDateTime": "2/20/2017, 1:40:50 PM"
5 | }
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/js/mainsocket.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const getSetData = require('./socket/GetSetData');
4 |
5 | module.exports = function(socket) {
6 | console.log('Socket.io connection made.');
7 |
8 | const getDataDone = function(data){
9 | console.log('getDataDone');
10 | socket.emit('server:GetDataDone', data);
11 | };
12 | const onGetData = function() {
13 | console.log('onGetData');
14 | getSetData.getData(getDataDone);
15 | };
16 | socket.on('client:GetData', onGetData);
17 |
18 | const setDataDone = function(){ socket.emit('server:SetDataDone'); };
19 | const onSetData = function(data) {
20 | getSetData.setData(data, setDataDone);
21 | };
22 | socket.on('client:SetData', onSetData);
23 | };
24 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/js/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const express = require('express');
4 | const app = express();
5 | const server = require('http').Server(app);
6 | const ioServer = require('socket.io')(server);
7 | const favicon = require('serve-favicon');
8 |
9 | const path = require('path');
10 | const port = Number(3500);
11 |
12 | server.listen(port);
13 |
14 | const socketCallBack = function(socket){ require('./mainsocket')(socket); };
15 |
16 | ioServer.on('connection', socketCallBack);
17 |
18 | app.use('/', express.static('ui-dist'));
19 | app.use(favicon(path.join(__dirname, '..', 'ui-dist', 'img', 'favicon.ico')));
20 | app.get('/', function(req, res){ res.sendfile(__dirname + '/index.html', [], null); });
21 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/js/socket/GetSetData.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 |
5 | const rootDataPath = './data';
6 |
7 | module.exports.getData = function(doneCallBack) {
8 | const filePath = rootDataPath + '/basic.json';
9 | const jsonReadCallBack = function(err, data){
10 | if (err) doneCallBack('Data readFile error ' + filePath);
11 | else {
12 | const jsonData = JSON.parse(data.toString());
13 | doneCallBack(jsonData);
14 | }
15 | };
16 | fs.readFile(filePath, jsonReadCallBack);
17 | };
18 |
19 | module.exports.setData = function(data, doneCallBack) {
20 | const filePath = rootDataPath + '/basic.json';
21 | const writeFileCallBack = function (err) {
22 | if (err) console.log('error saving Data.json file ');
23 | else doneCallBack();
24 | };
25 | fs.writeFile(filePath, JSON.stringify(data, null, 2), writeFileCallBack);
26 | };
27 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ReactPatterns.15-ReduxSocketIO",
3 | "version": "1.0.0",
4 | "description": "A collection of simple react projects providing reusable components, startup and test examples.",
5 | "license": "MIT",
6 | "author": {
7 | "name": "Janaka Stevens",
8 | "email": "jmstevens@calitek.com"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/calitek/ReactPatterns.git"
13 | },
14 | "scripts": {
15 | "start": "nodemon --watch js js/server.js",
16 | "ww": "webpack --progress --profile --colors --env.noMinimize --watch",
17 | "nw": "webpack --progress --profile --colors --env.noMinimize"
18 | },
19 | "dependencies": {
20 | "express": "latest",
21 | "nodemon": "latest",
22 | "serve-favicon": "latest",
23 | "socket.io": "latest"
24 | },
25 | "devDependencies": {
26 | "react": "^15.4.0",
27 | "react-dom": "^15.4.0",
28 | "react-redux": "latest",
29 | "redux": "latest",
30 |
31 | "babel-core": "latest",
32 | "babel-loader": "^6.1.0",
33 | "babel-preset-es2015": "latest",
34 | "babel-preset-react": "latest",
35 | "babel-preset-stage-0": "latest",
36 | "css-loader": "latest",
37 | "extract-text-webpack-plugin": "^2.0.0-rc.3",
38 | "file-loader": "latest",
39 | "style-loader": "^0.13.1",
40 | "webpack": "latest"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/ui-src/app.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import './index.html';
4 | import './css/index.css';
5 | import './img/favicon.ico';
6 |
7 | import React from 'react';
8 | import ReactDom from 'react-dom';
9 | import {Provider} from 'react-redux';
10 |
11 | import AppCtrl from './components/app.ctrl';
12 | import AppStore from './store/App.Store';
13 |
14 | window.ReactDom = ReactDom;
15 |
16 | ReactDom.render(
17 |
,
18 | document.getElementById('react')
19 | );
20 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/ui-src/components/app.ctrl.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 |
4 | import AppNotes from './app.notes';
5 |
6 | let AppCtrlSty = {
7 | height: '100%',
8 | padding: '0 10px 0 0'
9 | };
10 |
11 | function AppCtrl({Data1}) {
12 | let data1 = Data1;
13 | return (
14 |
15 | React Version: {data1['React version']}
16 | Project: {data1.Project}
17 | Current date/time: {data1.currentDateTime}
18 |
19 |
20 | );
21 | }
22 |
23 | function mapStateToProps(store) {
24 | return {Data1: store.data1};
25 | }
26 |
27 | export default connect(mapStateToProps)(AppCtrl);
28 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/ui-src/components/app.notes.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | let AppNotesSty = {
4 | marginLeft: 'auto',
5 | marginRight: 'auto',
6 | marginTop: '30px',
7 | maxWidth: '500px',
8 | textIndent: '20px'
9 | };
10 |
11 | let textSty = {
12 | color: '#000',
13 | fontSize: '1.0em',
14 | textAlign: 'left'
15 | };
16 |
17 | let btnDivSty = {textAlign: 'center'};
18 |
19 | let standardBtnSty = {
20 | backgroundColor: '#9a6',
21 | borderBottomColor: '#cea',
22 | borderLeftColor: '#93a363',
23 | borderRightColor: '#cea',
24 | borderTopColor: '#93a363',
25 | borderRadius: '6px',
26 | color: '#eeffee',
27 | cursor: 'pointer',
28 | lineHeight: '100%',
29 | outline: 'none',
30 | verticalAlign: 'middle',
31 | whiteSpace: 'nowrap'
32 | };
33 |
34 | let p1Text = `
35 | `;
36 |
37 | export default class AppNotes extends React.Component {
38 | state = {show: true};
39 | onClick = () => { this.setState({show: !this.state.show}); };
40 | render() {
41 | let showNotes = this.state.show;
42 | let btnText = showNotes ? 'Hide notes' : 'Show notes';
43 | let notesDivSty = showNotes ? {display: 'block'} : {display: 'none'};
44 | return (
45 |
46 |
47 |
48 |
49 |
52 |
53 | );
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/ui-src/css/index.css:
--------------------------------------------------------------------------------
1 | .bodyStyle {
2 | background-color: #00303f;
3 | color: #eae3ea;
4 | display: block;
5 | overflow: hidden;
6 | width: 100%;
7 | }
8 |
9 | .header {
10 | height: 30px;
11 | margin: 0;
12 | padding: 10px 0;
13 | text-align: center;
14 | }
15 |
16 | .Title {font-size: 1.3em;}
17 |
18 | .content {
19 | height: calc(100% - 52px);
20 | max-width: 1366px;
21 | margin-left: auto;
22 | margin-right: auto;
23 | padding: 0 5px;
24 | }
25 |
26 | * { outline: none; }
27 |
28 | .a{display:block}
29 |
30 | .FlexBox {
31 | display: -webkit-box;
32 | display: -moz-box;
33 | display: -ms-flexbox;
34 | display: flex;
35 | }
36 |
37 | .FlexBoxJustAround {
38 | display: -webkit-box;
39 | display: -moz-box;
40 | display: -ms-flexbox;
41 | display: flex;
42 | justify-content: space-around;
43 | }
44 |
45 | .FlexBoxJustBetween {
46 | display: -webkit-box;
47 | display: -moz-box;
48 | display: -ms-flexbox;
49 | display: flex;
50 | justify-content: space-between;
51 | }
52 |
53 | .FlexBoxWrap {
54 | display: -webkit-box;
55 | display: -moz-box;
56 | display: -ms-flexbox;
57 | display: flex;
58 | flex-wrap: wrap;
59 | }
60 |
61 | .FlexJustify {
62 | -webkit-box-pack: justify;
63 | justify-content: space-between;
64 | }
65 |
66 | .FlexBoxStretch {
67 | display: -webkit-box;
68 | display: -moz-box;
69 | display: -ms-flexbox;
70 | display: flex;
71 | align-content: stretch;
72 | }
73 |
74 | .FlexItem {
75 | flex-grow: 1;
76 | }
77 |
78 | .HighZ {z-index: 200;}
79 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/ui-src/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.15/ReduxSocketIO/ui-src/img/favicon.ico
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/ui-src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
ReactPatterns-ReduxWebSocket
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/ui-src/store/Actions.js:
--------------------------------------------------------------------------------
1 | export function apiGetData() { return {type: 'ApiGetData'}; }
2 |
3 | export function apiGotData(data) { return {type: 'ApiGotData', data}; }
4 |
5 | export function apiSetData(data) { return {type: 'ApiSetData', data}; }
6 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/ui-src/store/App.Store.js:
--------------------------------------------------------------------------------
1 | import {createStore, applyMiddleware} from 'redux';
2 | import startWs, {wsMiddleware} from './ws.api';
3 | import {apiSetData} from './Actions';
4 |
5 | function handleData(state = {data1: {}}, action) {
6 | switch (action.type) {
7 | case 'ApiGotData': return Object.assign({}, state, {data1: action.data});
8 | default: return state;
9 | }
10 | }
11 |
12 | const store = createStore(handleData, applyMiddleware(wsMiddleware));
13 |
14 | startWs(store);
15 |
16 | const newData = {
17 | 'React version': '15',
18 | 'Project': 'Redux with socket.io',
19 | 'currentDateTime': new Date().toLocaleString()
20 | };
21 |
22 | store.dispatch(apiSetData(newData));
23 |
24 | export default store;
25 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/ui-src/store/ws.api.js:
--------------------------------------------------------------------------------
1 | import * as Actions from './Actions';
2 |
3 | var socket = null;
4 |
5 | export function wsMiddleware() {
6 | return (next) => (action) => {
7 | if (socket && action.type === 'ApiGetData') {
8 | console.log('ApiGetData');
9 | socket.emit('client:GetData', {});
10 | } else if (socket && action.type === 'ApiSetData') {
11 | console.log('ApiSetData');
12 | socket.emit('client:SetData', action.data);
13 | }
14 |
15 | return next(action);
16 | };
17 | }
18 |
19 | export default function (store) {
20 | /* eslint-disable */
21 | socket = new io();
22 | /* eslint-enable */
23 |
24 | socket.on('server:GetDataDone', (data) => {
25 | console.log('GetDataDone');
26 | store.dispatch(Actions.apiGotData(data));
27 | });
28 |
29 | socket.on('server:SetDataDone', () => {
30 | console.log('SetDataDone');
31 | store.dispatch(Actions.apiGetData());
32 | });
33 | }
34 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
3 | const webpack = require('webpack');
4 | const configJson = require('./webpack.config.json');
5 |
6 | module.exports = (env) => {
7 |
8 | const noMinimize = env.noMinimize;
9 | var plugins = [];
10 |
11 | plugins.push(new ExtractTextPlugin({filename: 'app.css', allChunks: true}));
12 | plugins.push(new webpack.optimize.CommonsChunkPlugin({name: 'lib'}));
13 | if (noMinimize) {
14 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('development')}}));
15 | } else {
16 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('production')}}));
17 | plugins.push(new webpack.optimize.UglifyJsPlugin({include: /lib\.js/, minimize: true}));
18 | }
19 |
20 | const ROOT_PATH = path.resolve(__dirname);
21 | const SRC_PATH = path.resolve(ROOT_PATH, './ui-src');
22 | const DIST_PATH = path.resolve(ROOT_PATH, './ui-dist');
23 |
24 |
25 | return {
26 | context: SRC_PATH,
27 | entry: {
28 | app: './app.jsx',
29 | lib: configJson.lib
30 | },
31 |
32 | output: {
33 | path: DIST_PATH,
34 | filename: '[name].js'
35 | },
36 |
37 | module: {
38 | rules: [
39 | {
40 | test: /\.jsx?$/,
41 | loader: 'babel-loader',
42 | query: {presets:['es2015', 'react', 'stage-0']},
43 | exclude: /(node_modules)/,
44 | },
45 | {
46 | test: /\.css$/,
47 | use: ExtractTextPlugin.extract({
48 | fallback: 'style-loader',
49 | use: 'css-loader'
50 | })
51 | },
52 | {
53 | test: /\.(png|jpg|ico|gif)$/,
54 | loader: 'file-loader?name=img/[name].[ext]'
55 | },
56 | {
57 | test: /\.(html)$/,
58 | loader: 'file-loader?name=[name].[ext]'
59 | }
60 | ]
61 | },
62 | plugins,
63 | resolve: {
64 | extensions: ['.js', '.jsx'],
65 | modules: ['node_modules']
66 | }
67 | };
68 | };
69 |
--------------------------------------------------------------------------------
/React.15/ReduxSocketIO/webpack.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "lib": [
3 | "react",
4 | "react-dom",
5 | "react-redux",
6 | "redux"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/React.Common/README.md:
--------------------------------------------------------------------------------
1 | # ReactPatterns Common Pages
2 |
3 | * Button
4 | * DropDowns
5 | * Form Input
6 | * Gallery
7 | * List
8 | * PageIndicator
9 | * ProgressBar
10 | * Sliders
11 | * Tooltip
12 | * TreeViews
13 |
--------------------------------------------------------------------------------
/React.Common/data/AppData.json:
--------------------------------------------------------------------------------
1 | {
2 | "nextid": "[object Object]1"
3 | }
--------------------------------------------------------------------------------
/React.Common/data/inputs.json:
--------------------------------------------------------------------------------
1 | {
2 | "text": "this is a text input",
3 | "checkbox": true,
4 | "radioGroup": "setkey",
5 | "color": "#546d53",
6 | "number": "20",
7 | "range": "70",
8 | "folder": "C:\\fakepath\\_1020715.JPG"
9 | }
--------------------------------------------------------------------------------
/React.Common/js/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const express = require('express');
4 | const router = express.Router();
5 |
6 | const getSetData = require('./routes/GetSetData');
7 | const getPicList = require('./routes/GetPicList');
8 |
9 | router.get('/getPicList', function(req, res) {
10 | const gotPicList = function(data){ res.send(data); };
11 | getPicList.getPicList(gotPicList);
12 | });
13 |
14 | router.get('/getAppData', function(req, res) {
15 | const getDataDone = function(data){ res.send(data); };
16 | getSetData.getAppData(getDataDone);
17 | });
18 |
19 | router.get('/getImageList', function(req, res) {
20 | const getDataDone = function(data){ res.send(data); };
21 | getSetData.getImageList(getDataDone);
22 | });
23 |
24 | router.get('/getTreeView', function(req, res) {
25 | const getDataDone = function(data){ res.send(data); };
26 | getSetData.getTreeView(getDataDone);
27 | });
28 |
29 | router.post('/setAppData', function(req) { getSetData.setAppData(req.body); });
30 | router.post('/setTreeView', function(req) { getSetData.setTreeView(req.body); });
31 |
32 | router.get('/getInputData', function(req, res) {
33 | const getDataDone = function(data){ res.send(data); };
34 | getSetData.getInputData(getDataDone);
35 | });
36 |
37 | router.post('/setInputData', function(req) {
38 | getSetData.setInputData(req.body);
39 | });
40 |
41 | module.exports = router;
42 |
--------------------------------------------------------------------------------
/React.Common/js/routes/GetPicList.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const exiftool = require('node-exiftool');
4 |
5 | const fieldList = [
6 | 'FileName',
7 | 'Description',
8 | 'Copyright',
9 | ];
10 |
11 | module.exports.getPicList = function(doneCallBack) {
12 | const ep = new exiftool.ExiftoolProcess();
13 | const picFolder = './ui-dist/data/_sm';
14 |
15 | const getFileListCallBack = function(fileList) {
16 | const lgPicFolder = '../data/_lg/';
17 | const smPicFolder = '../data/_sm/';
18 | let picList = [];
19 | const addObject = {lgFolder: lgPicFolder, smFolder: smPicFolder};
20 | fileList.forEach(function(value){ picList.push(Object.assign(value, addObject)); });
21 | doneCallBack({picList});
22 | };
23 | ep.open().then(() => ep.readMetadata(picFolder, fieldList))
24 | .then((outout) => { getFileListCallBack(outout.data); ep.close(); });
25 | };
26 |
--------------------------------------------------------------------------------
/React.Common/js/routes/GetSetData.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 |
5 | const rootDataPath = './data';
6 |
7 | module.exports.getAppData = function(doneCallBack) {
8 | const filePath = rootDataPath + '/AppData.json';
9 | const jsonReadCallBack = function(err, data){
10 | if (err) console.log('AppData readFile error ' + filePath);
11 | else {
12 | const jsonData = JSON.parse(data.toString());
13 | doneCallBack(jsonData);
14 | }
15 | };
16 | fs.readFile(filePath, jsonReadCallBack);
17 | };
18 |
19 | module.exports.setAppData = function(data) {
20 | const filePath = rootDataPath + '/AppData.json';
21 | const writeFileCallBack = function (err) {
22 | if (err) console.log('error saving AppData.json file ');
23 | };
24 | fs.writeFile(filePath, JSON.stringify(data, null, 2), writeFileCallBack);
25 | };
26 |
27 | module.exports.getImageList = function(doneCallBack) {
28 | const filePath = rootDataPath + '/ImageList.json';
29 | const jsonReadCallBack = function(err, data){
30 | if (err) console.log('ImageList readFile error ' + filePath);
31 | else {
32 | const jsonData = JSON.parse(data.toString());
33 | doneCallBack(jsonData);
34 | }
35 | };
36 | fs.readFile(filePath, jsonReadCallBack);
37 | };
38 |
39 | module.exports.getTreeView = function(doneCallBack) {
40 | const filePath = rootDataPath + '/TreeView.json';
41 | const jsonReadCallBack = function(err, data){
42 | if (err) console.log('TreeView readFile error ' + filePath);
43 | else {
44 | const jsonData = JSON.parse(data.toString());
45 | doneCallBack(jsonData);
46 | }
47 | };
48 | fs.readFile(filePath, jsonReadCallBack);
49 | };
50 |
51 | module.exports.setTreeView = function(data) {
52 | const filePath = rootDataPath + '/TreeView.json';
53 | const writeFileCallBack = function (err) {
54 | if (err) console.log('error saving TreeView.json file ');
55 | };
56 | fs.writeFile(filePath, JSON.stringify(data.data, null, 2), writeFileCallBack);
57 | };
58 |
59 | module.exports.getInputData = function(doneCallBack) {
60 | const filePath = rootDataPath + '/inputs.json';
61 | const jsonReadCallBack = function(err, data){
62 | if (err) doneCallBack('Data readFile error ' + filePath);
63 | else {
64 | const jsonData = JSON.parse(data.toString());
65 | doneCallBack(jsonData);
66 | }
67 | };
68 | fs.readFile(filePath, jsonReadCallBack);
69 | };
70 |
71 | module.exports.setInputData = function(data) {
72 | const filePath = rootDataPath + '/inputs.json';
73 | const writeFileCallBack = function (err) {
74 | if (err) console.log('error saving Data.json file ');
75 | };
76 | fs.writeFile(filePath, JSON.stringify(data, null, 2), writeFileCallBack);
77 | };
78 |
--------------------------------------------------------------------------------
/React.Common/js/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const bodyParser = require('body-parser');
4 | const express = require('express');
5 | const favicon = require('serve-favicon');
6 |
7 | const path = require('path');
8 | const port = Number(process.env.COMMONPORT || 3500);
9 |
10 | const routes = require('./routes');
11 |
12 | const app = express();
13 | app.listen(port);
14 |
15 | app.use(bodyParser.json());
16 | app.use(bodyParser.urlencoded({extended: false}));
17 |
18 | app.use('/', express.static('ui-dist'));
19 | app.use('/routes', routes);
20 |
21 | app.use(favicon(path.join(__dirname, '..', 'ui-dist', 'img', 'favicon.ico')));
22 | app.get('/', function(req, res){ res.sendfile(__dirname + '/index.html', [], null); });
23 |
--------------------------------------------------------------------------------
/React.Common/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ReactPatterns.Common",
3 | "version": "1.0.0",
4 | "description": "A simple react project providing reusable components.",
5 | "license": "MIT",
6 | "author": {
7 | "name": "J Mark Stevens",
8 | "email": "jms@jmarkstevens.com"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/calitek/ReactPatterns.git"
13 | },
14 | "scripts": {
15 | "start": "nodemon --watch js js/server.js",
16 | "ww": "webpack --progress --profile --colors --env.noMinimize --watch",
17 | "nw": "webpack --progress --profile --colors --env.noMinimize"
18 | },
19 | "dependencies": {
20 | "body-parser": "latest",
21 | "express": "latest",
22 | "node-exiftool": "latest",
23 | "nodemon": "latest",
24 | "serve-favicon": "latest"
25 | },
26 | "devDependencies": {
27 | "babel-core": "latest",
28 | "babel-loader": "^6.1.0",
29 | "babel-preset-es2015": "latest",
30 | "babel-preset-react": "latest",
31 | "babel-preset-stage-0": "latest",
32 | "css-loader": "latest",
33 | "extract-text-webpack-plugin": "^2.0.0-rc.3",
34 | "file-loader": "latest",
35 | "loader-utils": "latest",
36 | "lodash": "latest",
37 | "radium": "latest",
38 | "react": "^15.4.0",
39 | "react-dom": "^15.4.0",
40 | "react-mixin": "^1.2.2",
41 | "react-redux": "latest",
42 | "redux": "latest",
43 | "redux-logger": "latest",
44 | "redux-thunk": "latest",
45 | "screenfull": "latest",
46 | "style-loader": "^0.13.1",
47 | "traverse": "latest",
48 | "webpack": "latest",
49 | "whatwg-fetch": "latest"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/React.Common/ui-src/app.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import './index.html';
4 | import './css/index.css';
5 | import './css/rangeInput.css';
6 |
7 | import './img/favicon.ico';
8 | import './img/sun.ico';
9 | import './img/leaf.ico';
10 | import './img/snow.ico';
11 | import './img/flow.png';
12 | import './img/1x1TransShim.gif';
13 | import './img/SLogoS5-48_C.png';
14 |
15 | import React from 'react';
16 | import ReactDom from 'react-dom';
17 | import {Provider} from 'react-redux';
18 |
19 | import AppCtrl from './components/app.ctrl';
20 | import AppStore from './store/App.Store';
21 |
22 | window.ReactDom = ReactDom;
23 |
24 | ReactDom.render(
, document.getElementById('react'));
25 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/Button/app.text.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | p1Text: `
3 |
4 | `
5 | };
6 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/DropDowns/app.text.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | p1Text: `
3 |
4 | `
5 | };
6 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/DropDowns/dropdown.menu.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import JDropMenu from '../common/DropDowns/jDropMenu';
4 |
5 | let DropDownMenuSty = {
6 | fontSize: '1.2em',
7 | padding: '2px 2px 0 0',
8 | position: 'relative',
9 | right: '0px',
10 | top: '0px'
11 | };
12 |
13 | let options = [
14 | {value: 'new', label: 'New'},
15 | {value: 'edit', label: 'Edit'},
16 | {type: 'seperator', key: '100'},
17 | {value: 'moveUp', label: 'Move up'},
18 | {value: 'moveDown', label: 'Move down'},
19 | {type: 'seperator', key: '101'},
20 | {value: 'rename', label: 'Rename'},
21 | {type: 'seperator', key: '102'},
22 | {value: 'remove', label: 'Remove'}
23 | ];
24 |
25 | export default class DropDownMenu extends React.Component {
26 | state = {option: {}};
27 | onSelect = (option) => { this.setState({option}); };
28 | render() {
29 | let optionLabel = this.state.option.label;
30 | let optionValue = this.state.option.value;
31 | return (
32 |
33 |
36 | Label: {optionLabel}
37 | Value: {optionValue}
38 |
39 |
40 | );
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/DropDowns/dropdown.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import AppNotes from '../common/app.notes';
4 | import AppText from './app.text';
5 |
6 | import DropDownMenu from './dropdown.menu';
7 | import DropDownSelect from './dropdown.select';
8 | import JMultiSelect from './multi.select';
9 |
10 | let DropDownsSty = {
11 | borderBottom: '3px solid #636b46',
12 | padding: '0 10px 0 0'
13 | };
14 |
15 | let DropDownSty = {
16 | border: 'solid 1px darkslategrey',
17 | height: 'calc(100% - 10px)',
18 | overflow: 'auto',
19 | padding: '10px',
20 | width: '33%'
21 | };
22 |
23 | const ColumnsSty = {
24 | height: '100%',
25 | };
26 |
27 | export default function DropDowns(props) {
28 | if (props.hide) return null;
29 | return (
30 |
31 |
32 |
33 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | );
46 | }
47 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/DropDowns/dropdown.select.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import JDropSelect from '../common/DropDowns/jDropSelect';
4 |
5 | let DropDownSelectSty = {
6 | fontSize: '1.2em',
7 | padding: '2px 2px 0 0',
8 | textAlign: 'right'
9 | };
10 |
11 | let options = [
12 | {label: 'Any', value: 'Any'},
13 | {label: 'Extremely slow', value: 'slow3'},
14 | {label: 'Very slow', value: 'slow2'},
15 | {label: 'Slow', value: 'slow1'},
16 | {label: 'Moderate', value: 'mod'},
17 | {label: 'Fast', value: 'fast1'},
18 | {label: 'Very fast', value: 'fast2'},
19 | {label: 'Extremely fast', value: 'fast3'}
20 | ];
21 |
22 | export default class DropDownSelect extends React.Component {
23 | state = {name: 'growthspeed', option: {}};
24 | onDropSelect = (name, option) => { this.setState({name, option}); };
25 | render() {
26 | let name = 'growthspeed';
27 | // let defaultOption = this.state.option.value ? this.state.option : lodash.findWhere(options, {value: 'Any'});
28 | let defaultOption = this.state.option.value ? this.state.option : options[0];
29 | let selectedName = this.state.name;
30 | let selectedLabel = this.state.option.label;
31 | let selectedValue = this.state.option.value;
32 | return (
33 |
34 |
35 |
36 |
37 | Item name: {selectedName}
38 | Selected label: {selectedLabel}
39 | Selected value: {selectedValue}
40 |
41 |
42 | );
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/DropDowns/multi.select.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import JMultiSelect from '../common/DropDowns/jMultiSelect';
4 |
5 | const MultiSelectSty = {
6 | height: '100%',
7 | maxWidth: '300px',
8 | minHeight: '300px',
9 | };
10 |
11 | const leafcolor = {
12 | 'value': [],
13 | 'key': 'leaf color',
14 | 'options': [
15 | {
16 | 'count': 59,
17 | 'label': 'Green on both sides',
18 | 'value': 'allgrn'
19 | },
20 | {
21 | 'count': 13,
22 | 'label': 'Whitish bottom side',
23 | 'value': 'whtbot'
24 | },
25 | {
26 | 'count': 25,
27 | 'label': 'Moderately pale bottom side',
28 | 'value': 'mpbot'
29 | },
30 | {
31 | 'count': 19,
32 | 'label': 'Both sides blue-gray to silver',
33 | 'value': 'allbs'
34 | },
35 | {
36 | 'count': 3,
37 | 'label': 'Red, reddish to bronze when new',
38 | 'value': 'newred'
39 | }
40 | ]
41 | };
42 |
43 | const isDesktop = 1;
44 |
45 | export default class MultiSelect extends React.Component {
46 | state = {currentValue: leafcolor.value}
47 | onJSelect = (itemName, selectedItems) => {
48 | let newValue = [];
49 | selectedItems.forEach(item => newValue.push(item.value));
50 | console.log('itemName: ', itemName);
51 | console.log('newValue: ', newValue);
52 | this.setState({currentValue: newValue});
53 | }
54 | clickHandler = () => {
55 | this.setState({currentValue: []});
56 | }
57 | render() {
58 | return (
59 |
60 |
61 |
62 |
70 |
71 | );
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/FormInput/app.text.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | p1Text: `
3 |
4 | `
5 | };
6 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/Gallery/app.text.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | p1Text: `
3 |
4 | `
5 | };
6 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/Gallery/gallery.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 |
4 | import AppNotes from '../common/app.notes';
5 | import AppText from './app.text';
6 |
7 | import JButton from '../common/Button/jButton';
8 | import JGallery from '../common/Gallery/jGallery';
9 |
10 | let GallerySty = {
11 | borderBottom: '3px solid #636b46',
12 | padding: '0 10px 0 0'
13 | };
14 |
15 | let basicBtn = {buttonid: 'galleryHide', text: 'Open Gallery'};
16 |
17 | class Gallery extends React.Component {
18 | state = {hideGallery: false};
19 | galleryHideHandler = () => { this.setState({hideGallery: !this.state.hideGallery}); };
20 | render() {
21 | if (this.props.hide) return null;
22 | let data = this.props.picList;
23 | let hideGallery = this.state.hideGallery;
24 | return (
25 |
31 | );
32 | }
33 | }
34 |
35 | function mapStateToProps(store) { return {picList: store.galleryState.picList}; }
36 |
37 | export default connect(mapStateToProps, null)(Gallery);
38 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/List/app.text.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | p1Text: `
3 |
4 | `
5 | };
6 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/List/list.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import AppNotes from '../common/app.notes';
4 | import AppText from './app.text';
5 |
6 | import JList from '../common/List/jList';
7 |
8 | let ListSty = {
9 | borderBottom: '3px solid #cae4db',
10 | padding: '0 10px 0 0'
11 | };
12 |
13 | let list = [
14 | 'line one of list',
15 | 'another line of list',
16 | 'third line of list',
17 | 'fourth line of list',
18 | 'fifth line of list',
19 | 'sixth line of list'
20 | ];
21 |
22 | let listSty = {
23 | border: '1px solid #e9e7da',
24 | margin: '10px 10px'
25 | };
26 |
27 | let lineSty = {
28 | color: '#b4dbc0',
29 | marginLeft: '5px'
30 | };
31 |
32 | export default function List(props) {
33 | if (props.hide) return null;
34 | return (
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | );
46 | }
47 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/PageIndicator/indicator.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import JPageIndicator from '../common/PageIndicator/jPageIndicator';
4 |
5 | import AppStyle from '../common/app.style';
6 | import IndicatorPop from './indicator.pop';
7 |
8 | import IndicatorStyle from './indicator.style';
9 | import IndicatorText from './indicator.text';
10 |
11 | const pageNumber = 4;
12 |
13 | export default class IndicatorPage extends React.Component {
14 | state = {page: 1, hideNote: false};
15 | _handlePageIndicatorClick = (index) => {
16 | if (this.state.page !== (index + 1)) this.setState({page: index + 1});
17 | }
18 | showNoteHandler = () => { this.setState({hideNote: !this.state.hideNote}); }
19 | render() {
20 |
21 | if (this.props.hide) return null;
22 | let currentPage = this.state.page;
23 | let noteText;
24 | switch (currentPage) {
25 | case 1: noteText = IndicatorText.note1; break;
26 | case 2: noteText = IndicatorText.note2; break;
27 | case 3: noteText = IndicatorText.note3; break;
28 | case 4: noteText = IndicatorText.note4; break;
29 | }
30 |
31 |
32 | let bottomBtnDivSty = Object.assign({}, AppStyle.bottomBtnDivSty);
33 | bottomBtnDivSty.display = currentPage < pageNumber ? 'block' : 'none';
34 | let topBtnDivSty = Object.assign({}, AppStyle.topBtnDivSty);
35 | topBtnDivSty.top = '50px';
36 |
37 | let pageDesc = `Page ${currentPage} of ${pageNumber}`;
38 | return (
39 |
40 |
41 |
42 | {pageDesc}
43 |
44 |
45 |
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/PageIndicator/indicator.pop.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const popupSty = {
4 | background: 'rgba(28, 34, 24, .6)',
5 | color: '#e4eae0',
6 | fontFamily: 'Georgia, serif',
7 | fontSize: '1.3vmax',
8 | left: '50%',
9 | padding: '30px',
10 | position: 'absolute',
11 | textAlign: 'center',
12 | top: '33%',
13 | transform: 'translate(-50%, -50%)',
14 | zIndex: '5'
15 | };
16 |
17 | export default function IndicatorPopup({hide, subText}) {
18 | if (hide) return null;
19 | return (
20 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/PageIndicator/indicator.style.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | IndicatorPageSty: {
4 | height: 'calc(100% - 50px)',
5 | marginTop: '50px',
6 | overflow: 'hidden',
7 | padding: '0px',
8 | width: '100%'
9 | },
10 |
11 | iFrameSty: {
12 | overflow: 'hidden',
13 | width: '100%'
14 | },
15 |
16 | iframeDivSty: {
17 | overflowX: 'hidden',
18 | overflowY: 'hidden'
19 | },
20 |
21 | standardBtnImg: {
22 | backgroundColor: 'transparent',
23 | backgroundImg: 'none',
24 | backgroundSize: 'contain',
25 | border: '0px',
26 | color: '#9fd8de',
27 | cursor: 'pointer',
28 | height: 'inherit',
29 | margin: '0 3px',
30 | outline: 'none',
31 | padding: '0px',
32 | verticalAlign: 'middle',
33 | width: 'inherit'
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/PageIndicator/indicator.text.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | note1: `
3 | BergstromGardens.com is a current project written in javascript with react and redux libraries.
4 | The Palms page includes a filter that limits the data shown.
5 | `,
6 | note2: `
7 | CodeViewer is an app to view highlighted code for projects in a given root folder.
8 | This is actual project code for active projects.
9 | `,
10 | note3: `
11 | Gallery notes
12 | `,
13 | note4: `
14 | Clippets is what I use to store snippets of text. It is mostly used for things I don't do every day.
15 | For instance setting up a DigitalOcean server.
16 | `
17 | };
18 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/ProgressBar/app.text.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | p1Text: `
3 |
4 | `
5 | };
6 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/ProgressBar/progress.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import AppNotes from '../common/app.notes';
4 | import AppText from './app.text';
5 |
6 | import JButton from '../common/Button/jButton';
7 | import JProgressBar from '../common/ProgressBar/jProgressBar';
8 |
9 | let ProgressBarSty = {
10 | borderBottom: '3px solid #636b46',
11 | padding: '0 10px 0 0'
12 | };
13 |
14 | let customCountSty = {
15 | backgroundColor: '#33045B',
16 | height: '5px',
17 | marginRight: '5px',
18 | marginTop: '6px',
19 | width: '100%'
20 | };
21 |
22 | let customIndexSty = {backgroundColor: '#874C08', height: '5px', width: '1%'};
23 | let assignSty = {color: '#4d2c3d'};
24 |
25 | let firstItemBtn = {buttonid: 'first', icon: 'fa fa-fast-backward fa-lg', style: 'BtnImg', assignStyle: assignSty};
26 | let previousItemBtn = {buttonid: 'previous', icon: 'fa fa-backward fa-lg', style: 'BtnImg', assignStyle: assignSty};
27 |
28 | let nextItemBtn = {buttonid: 'next', icon: 'fa fa-forward fa-lg', style: 'BtnImg', assignStyle: assignSty};
29 | let lastItemBtn = {buttonid: 'last', icon: 'fa fa-fast-forward fa-lg', style: 'BtnImg', assignStyle: assignSty};
30 |
31 | let ButtonAreaSty = {
32 | fontSize: '.9em',
33 | height: '24px',
34 | marginBottom: '10px',
35 | marginTop: '10px',
36 | verticalAlign: 'middle'
37 | };
38 |
39 | let progressData = {count: 120};
40 |
41 | export default class ProgressBar extends React.Component {
42 | state = {progressIndex: 10};
43 | clickHandler = (buttonid) => {
44 | let oldIndex = this.state.progressIndex;
45 | let newIndex = oldIndex;
46 | switch (buttonid) {
47 | case 'first': newIndex = 1; break;
48 | case 'previous': newIndex -= oldIndex > 1 ? 1 : 0; break;
49 | case 'next': newIndex += oldIndex < progressData.count ? 1 : 0; break;
50 | case 'last': newIndex = progressData.count; break;
51 | }
52 | this.setState({progressIndex: newIndex});
53 | };
54 | render() {
55 | if (this.props.hide) return null;
56 | progressData.index = this.state.progressIndex;
57 | return (
58 |
59 |
60 |
default
61 |
62 |
center
63 |
64 |
after
65 |
66 |
before
67 |
68 |
beforenafter
69 |
70 |
none
71 |
72 |
indexColor
73 |
74 |
countColor
75 |
76 |
customStyle
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | );
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/Sliders/app.text.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | p1Text: `
3 |
4 | `
5 | };
6 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/Sliders/sliders.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import AppNotes from '../common/app.notes';
4 | import AppText from './app.text';
5 |
6 | import RangeSelector from '../common/Sliders/jRangeSelector';
7 | import SimpleSlider from '../common/Sliders/jSlider';
8 |
9 | let slidersSty = {
10 | backgroundColor: '#e1ded5',
11 | borderBottom: '3px solid #636b46',
12 | margin: '5px auto',
13 | maxWidth: '900px',
14 | padding: '10px'
15 | };
16 |
17 | let innerSty = {
18 | width: '100%'
19 | };
20 |
21 | const formatter = value => Math.ceil((value * 39) - 5);
22 | const unformatter = value => Math.ceil(((value + 4) / 39) * 100) / 100;
23 |
24 | let getInitialAppState = function() {
25 | return {
26 | formattedValue: 34,
27 | lowerValue: 1,
28 | upperValue: 85
29 | };
30 | };
31 |
32 | export default class Sliders extends React.Component {
33 | state = getInitialAppState();
34 | _handleSliderChange = (formattedValue) => { this.setState({formattedValue}); }
35 | _handleLowerChange = (lowerValue) => { this.setState({lowerValue}); }
36 | _handleUpperChange = (upperValue) => { this.setState({upperValue}); }
37 | _resetState = () => { this.setState(getInitialAppState()); }
38 | render() {
39 | if (this.props.hide) return null;
40 | let formattedValue = this.state.formattedValue;
41 | let percentValue = unformatter(formattedValue);
42 | let lowerValue = this.state.lowerValue;
43 | let upperValue = this.state.upperValue;
44 | return (
45 |
46 |
47 |
48 |
Lower Value: {lowerValue}
49 |
Upper Value: {upperValue}
50 |
62 |
63 |
64 |
Value -5 - 34: {formattedValue}
65 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | );
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/Tooltip/app.text.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | p1Text: `
3 |
4 | `
5 | };
6 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/Tooltip/tooltip.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import AppNotes from '../common/app.notes';
4 | import AppText from './app.text';
5 |
6 | import JTooltip from '../common/Tooltip/jTooltip';
7 |
8 | let TooltipSty = {
9 | borderBottom: '3px solid #636b46',
10 | padding: '0 10px'
11 | };
12 |
13 | let columnSty = {
14 | height: 'calc(100% - 10px)',
15 | overflow: 'auto',
16 | paddingLeft: '0px',
17 | width: '330px'
18 | };
19 |
20 | let titleSty = {
21 | background: 'transparent',
22 | boxSizing: 'border-box',
23 | cursor: 'default',
24 | height: '18px',
25 | lineHeight: '18px',
26 | overflow: 'hidden',
27 | outline: 'none',
28 | position: 'relative',
29 | textAlign: 'left',
30 | transition: 'all 200ms ease',
31 | width: '100%'
32 | };
33 |
34 | let toolTipSty = {display: 'inline-block', zIndex: '100'};
35 | let titleDivSty = {display: 'inline-block', lineHeight: '18px', position: 'relative'};
36 |
37 | let fillText = `
38 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
39 | `;
40 |
41 | let hoverValues = [
42 | {title: 'LowTemp', text: fillText.repeat(Math.ceil(Math.random() * 2)), place: 'bottom'},
43 | {title: 'LeafType', text: fillText.repeat(Math.ceil(Math.random() * 2)), place: 'bottom'},
44 | {title: 'Height', text: fillText.repeat(Math.ceil(Math.random() * 2)), place: 'bottom'},
45 | {title: 'Width', text: fillText.repeat(Math.ceil(Math.random() * 2)), place: 'bottom'},
46 | {title: 'TrunkType', text: fillText.repeat(Math.ceil(Math.random() * 2)), place: 'right'},
47 | {title: 'SunExposure', text: fillText.repeat(Math.ceil(Math.random() * 2)), place: 'right'},
48 | {title: 'WaterTolerance', text: fillText.repeat(Math.ceil(Math.random() * 2)), place: 'right'},
49 | {title: 'BogTolerant', text: fillText.repeat(Math.ceil(Math.random() * 2)), place: 'top'},
50 | {title: 'DraughtTolerant', text: fillText.repeat(Math.ceil(Math.random() * 2)), place: 'top'},
51 | {title: 'GrowthSpeed', text: fillText.repeat(Math.ceil(Math.random() * 2)), place: 'top'},
52 | {title: 'DryAirTolerance', text: fillText.repeat(Math.ceil(Math.random() * 2)), place: 'top'}
53 | ];
54 |
55 | function hoverMap(item) {
56 | let adjust = {left: 0, top: 0};
57 |
58 | let tooltip =
;
59 | return (
60 |
61 | {tooltip}
62 |
63 |
64 | {item.title}:
65 |
66 |
67 |
68 | );
69 | }
70 |
71 | export default function Tooltip(props) {
72 | let hoverList = hoverValues.map(hoverMap);
73 | if (props.hide) return null;
74 | return (
75 |
82 | );
83 | }
84 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/TreeViews/app.text.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | p1Text: `
3 |
4 | `
5 | };
6 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/TreeViews/jumplist/jump.ctrl.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import JTreeViewB from '../../common/TreeViews/jTreeViewB';
4 |
5 | const options = {
6 | icon: {sun: 1, leaf: 2, snow: 3},
7 | typeName: ['node', 'nodeLevel']
8 | };
9 |
10 | export default function JumpCtrl({imageList, clickHandler}) {
11 | return (
12 |
13 |
14 |
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/TreeViews/treeview.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 |
4 | import AppNotes from '../common/app.notes';
5 | import AppText from './app.text';
6 |
7 | import JumpCtrl from './jumplist/jump.ctrl';
8 | import TreeCtrl from './treeview/tree.ctrl';
9 |
10 |
11 | let TreeViewsSty = {
12 | height: '100%',
13 | padding: '0 10px 0 0'
14 | };
15 |
16 | let TreeCtrlSty = {
17 | border: 'solid 1px darkslategrey',
18 | height: 'calc(100% - 10px)',
19 | overflow: 'auto',
20 | paddingLeft: '0px',
21 | width: '50%'
22 | };
23 |
24 | class TreeViews extends React.Component {
25 | state = {currentImageItem: {title: 'not selected'}};
26 | jumpclick = (node) => { this.setState({currentImageItem: node});};
27 | render() {
28 | if (this.props.hide) return null;
29 | let currentTreeNode = this.props.currentTreeNode.title;
30 | let currentImageItem = this.state.currentImageItem.title;
31 | return (
32 |
33 |
34 |
35 | current node: {currentTreeNode}
36 |
37 |
38 |
39 |
40 | current node: {currentImageItem}
41 |
42 |
43 |
44 |
45 |
46 |
47 | );
48 | }
49 | }
50 |
51 | function mapStateToProps(store) {
52 | return {
53 | imageList: store.treeState.jumpList,
54 | treeData: store.treeState.treeData,
55 | currentTreeNode: store.treeState.currentTreeNode,
56 | showTreeEdit: store.treeState.showTreeEdit,
57 | showTreeNew: store.treeState.showTreeNew
58 | };
59 | }
60 |
61 | export default connect(mapStateToProps)(TreeViews);
62 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/TreeViews/treeview/tree.ctrl.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 |
4 | import {apiSetTreeView} from '../../../store/api/api.Actions';
5 | import TreeList from './tree.list';
6 | import TreeMenu from './tree.menu';
7 | import TreeEdit from './tree.edit';
8 | import TreeNew from './tree.new';
9 |
10 | let TreeCtrlRenderSty = {height: 'calc(100% - 19px)'};
11 |
12 | class TreeCtrl extends React.Component {
13 | componentWillReceiveProps = (nextProps) => {
14 | if (nextProps.treeData && (nextProps.treeData !== this.props.treeData)) {
15 | apiSetTreeView({data: nextProps.treeData});
16 | }
17 | }
18 | render() {
19 | let hideTreeEdit = !this.props.showTreeEdit;
20 | let hideTreeNew = !this.props.showTreeNew;
21 | return (
22 |
23 |
24 |
25 |
26 |
27 |
28 | );
29 | }
30 | }
31 |
32 | function mapStateToProps(store) {
33 | return {
34 | treeData: store.treeState.treeData,
35 | currentTreeNode: store.treeState.currentTreeNode,
36 | showTreeEdit: store.treeState.showTreeEdit,
37 | showTreeNew: store.treeState.showTreeNew
38 | };
39 | }
40 |
41 | export default connect(mapStateToProps)(TreeCtrl);
42 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/TreeViews/treeview/tree.detail.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import JInput from '../../common/FormInput/jInput';
4 |
5 | let treeDetailSty = {margin: '10px 10px'};
6 | let inputTextSty = {color: 'black', margin: '0 5px', width: '100%'};
7 |
8 | let titleInput = {name: 'title', type: 'text', style: inputTextSty, focus: true};
9 |
10 | let radioInput1 = {name: 'radioGroup', type: 'radio', radioValue: 'dev'};
11 | let radioInput2 = {name: 'radioGroup', type: 'radio', radioValue: 'home'};
12 | let radioInput3 = {name: 'radioGroup', type: 'radio', radioValue: 'sys'};
13 |
14 | export default class TreeDetail extends React.Component {
15 | state = {title: 'Hello!'};
16 | componentWillReceiveProps = (nextProps) => {
17 | if (this.state.title != nextProps.treeNode.title) this.setState({title: nextProps.treeNode.title});
18 | };
19 | handleTitleChange = (name, value) => { this.props.handleChange(name, value); };
20 | handleValueChange = (name, value) => { this.props.handleChange('type', value); };
21 | render() {
22 | titleInput.textValue = this.props.treeNode.title;
23 |
24 | let currentRadioGroupValue = this.props.treeNode.type;
25 | radioInput1.radioChecked = (currentRadioGroupValue == radioInput1.radioValue);
26 | radioInput2.radioChecked = (currentRadioGroupValue == radioInput2.radioValue);
27 | radioInput3.radioChecked = (currentRadioGroupValue == radioInput3.radioValue);
28 | return (
29 |
30 | Dev
31 | Home
32 | System
33 |
34 |
35 |
36 | );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/TreeViews/treeview/tree.edit.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 | import {bindActionCreators} from 'redux';
4 |
5 | import TreeDetail from './tree.detail';
6 | import {treeActions, saveTreeEdit} from '../../../store/treeview/tree.Actions';
7 | import JButton from '../../common/Button/jButton';
8 |
9 | let saveEditBtn = {buttonid: 'save', text: 'Save'};
10 | let cancelEditBtn = {buttonid: 'cancel', text: 'Cancel'};
11 |
12 | class TreeEdit extends React.Component {
13 | state = {treeNode: {nodeid: '', children: [], title: '', type: ''}};
14 |
15 | componentWillReceiveProps = (nextProps) => { this.setState({treeNode: nextProps.treeNode}); };
16 | clickHandler = (buttonid) => {
17 | let node = this.state.treeNode;
18 | switch (buttonid) {
19 | case 'save': this.props.saveTreeEdit(node); break;
20 | case 'cancel': this.props.treeActions('cancelEdit'); break;
21 | }
22 | };
23 | handleChange = (field, value) => {
24 | let node = this.state.treeNode;
25 | if (field == 'title') node.title = value;
26 | if (field == 'type') node.type = value;
27 | this.setState({treeNode: node});
28 | };
29 | render() {
30 | if (this.props.hide) return null;
31 | return (
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | );
40 | }
41 | }
42 |
43 | function mapDispatchToProps(dispatch) {
44 | return bindActionCreators({treeActions, saveTreeEdit}, dispatch);
45 | }
46 |
47 | export default connect(null, mapDispatchToProps)(TreeEdit);
48 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/TreeViews/treeview/tree.list.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 | import {bindActionCreators} from 'redux';
4 |
5 | import {selectTreeNode, setTreeNodeClosed} from '../../../store/treeview/tree.Actions';
6 | import TreeView from '../../common/TreeViews/jTreeView';
7 |
8 | const options = {
9 | icon: {sun: 'dev', leaf: 'home', snow: 'sys'},
10 | typeName: ['node', 'type']
11 | };
12 |
13 | const TreeList = (props) => {
14 | const iconHandler = (node) => { props.setTreeNodeClosed(node); };
15 | const clickHandler = (node) => { props.selectTreeNode(node); };
16 | return (
17 |
18 |
24 |
25 | );
26 | };
27 |
28 | function mapDispatchToProps(dispatch) {
29 | return bindActionCreators({selectTreeNode, setTreeNodeClosed}, dispatch);
30 | }
31 |
32 | export default connect(null, mapDispatchToProps)(TreeList);
33 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/TreeViews/treeview/tree.menu.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 | import {bindActionCreators} from 'redux';
4 |
5 | import {treeActions} from '../../../store/treeview/tree.Actions';
6 | import JButton from '../../common/Button/jButton';
7 |
8 | const TreeMenuSty = {
9 | fontSize: '.9em',
10 | height: '40px',
11 | marginBottom: '10px',
12 | textAlign: 'center',
13 | verticalAlign: 'middle'
14 | };
15 |
16 | const newBtn = {buttonid: 'new', icon: 'fa fa-file-text-o fa-2x', style: 'BtnImg', assignStyle: {color: '#419079'}};
17 | const editBtn = {buttonid: 'edit', icon: 'fa fa-pencil fa-2x', style: 'BtnImg'};
18 | const moveUpBtn = {buttonid: 'moveUp', icon: 'fa fa-arrow-up fa-2x', style: 'BtnImg'};
19 | const moveDownBtn = {buttonid: 'moveDown', icon: 'fa fa-arrow-down fa-2x', style: 'BtnImg'};
20 | const removeBtn = {buttonid: 'remove', icon: 'fa fa-trash-o fa-2x', style: 'BtnImg'};
21 |
22 | class TreeMenu extends React.Component {
23 | onSelect = (btn) => { this.props.treeActions(btn); };
24 | render() {
25 | return (
26 |
37 | );
38 | }
39 | }
40 |
41 | function mapDispatchToProps(dispatch) {
42 | return bindActionCreators({treeActions}, dispatch);
43 | }
44 |
45 | export default connect(null, mapDispatchToProps)(TreeMenu);
46 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/TreeViews/treeview/tree.new.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 | import {bindActionCreators} from 'redux';
4 |
5 | import TreeDetail from './tree.detail';
6 | import {saveTreeNew, treeActions} from '../../../store/treeview/tree.Actions';
7 | import JButton from '../../common/Button/jButton';
8 |
9 | let newBeforeBtn = {buttonid: 'before', text: 'New Before', assignStyle: {width: '92px'}};
10 | let newAfterBtn = {buttonid: 'after', text: 'New After', assignStyle: {width: '92px'}};
11 | let newChildBtn = {buttonid: 'child', text: 'New Child', assignStyle: {width: '92px'}};
12 | let cancelNewBtn = {buttonid: 'cancel', text: 'Cancel', assignStyle: {width: '92px'}};
13 |
14 | class TreeNew extends React.Component {
15 | state = {treeNode: {nodeid: '', title: '', type: 'dev', selected: false, children: []}};
16 | clickHandler = (buttonid) => {
17 | switch (buttonid) {
18 | case 'before':
19 | case 'after':
20 | case 'child': this.props.saveTreeNew(this.state.treeNode, buttonid); break;
21 | case 'cancel': this.props.treeActions('cancelNew'); break;
22 | }
23 | };
24 | handleChange = (field, value) => {
25 | let node = this.state.treeNode;
26 | if (field == 'title') node.title = value;
27 | if (field == 'type') node.type = value;
28 | this.setState({treeNode: node});
29 | };
30 | render() {
31 | if (this.props.hide) return null;
32 | return (
33 |
48 | );
49 | }
50 | }
51 |
52 | function mapDispatchToProps(dispatch) {
53 | return bindActionCreators({saveTreeNew, treeActions}, dispatch);
54 | }
55 |
56 | export default connect(null, mapDispatchToProps)(TreeNew);
57 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/app.ctrl.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 |
4 | import NavBar from './common/nav.bar';
5 |
6 | import Button from './Button/button.page';
7 | import DropDowns from './DropDowns/dropdown.page';
8 | import FormInput from './FormInput/input.page';
9 | import Gallery from './Gallery/gallery.page';
10 | import List from './List/list.page';
11 | import PageIndicator from './PageIndicator/indicator.page';
12 | import ProgressBar from './ProgressBar/progress.page';
13 | import Sliders from './Sliders/sliders.page';
14 | import Tooltip from './Tooltip/tooltip.page';
15 | import TreeViews from './TreeViews/treeview.page';
16 |
17 | let AppCtrlSty = {
18 | height: '100%',
19 | margin: '0px',
20 | overflow: 'hidden',
21 | padding: '0px',
22 | width: '100%'
23 | };
24 |
25 | function AppCtrl({appState}) {
26 | let page = appState.currentPage;
27 |
28 | let hideButton = (page != 'Button');
29 | let hideDropDowns = (page != 'DropDowns');
30 | let hideFormInput = (page != 'FormInput');
31 | let hideGallery = (page != 'Gallery');
32 | let hideList = (page != 'List');
33 | let hidePageIndicator = (page != 'PageIndicator');
34 | let hideProgressBar = (page != 'ProgressBar');
35 | let hideSliders = (page != 'Sliders');
36 | let hideTooltip = (page != 'Tooltip');
37 | let hideTreeViews = (page != 'TreeViews');
38 |
39 | return (
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | );
54 | }
55 |
56 | function mapStateToProps(store) { return {appState: store.appState}; }
57 |
58 | export default connect(mapStateToProps)(AppCtrl);
59 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/DropDowns/Icon.jsx:
--------------------------------------------------------------------------------
1 | const React = require('react');
2 |
3 | class Icon extends React.Component {
4 |
5 | styles = () => {
6 | return {
7 | component: Object.assign({
8 | width: this.props.size,
9 | height: this.props.size,
10 | display: 'inline-block',
11 | verticalAlign: 'middle'
12 | }, this.props.style)
13 | };
14 | }
15 |
16 | render() {
17 | const {elementProps} = this.props;
18 | const styles = this.styles();
19 |
20 | return (
21 |
42 | );
43 | }
44 | }
45 |
46 | Icon.propTypes = {
47 | elementProps: React.PropTypes.object,
48 | size: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]),
49 | style: React.PropTypes.object,
50 | type: React.PropTypes.string
51 | };
52 |
53 | Icon.defaultProps = {
54 | elementProps: {},
55 | size: 24,
56 | type: 'accounts'
57 | };
58 |
59 | module.exports = Icon;
60 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/DropDowns/jDropMenu.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | let DropdownSty = {position: 'relative'};
4 |
5 | let DropdownControlSty = {
6 | position: 'relative',
7 | overflow: 'hidden',
8 | background: 'transparent',
9 | boxSizing: 'border-box',
10 | cursor: 'default',
11 | outline: 'none',
12 | padding: '5px 5px',
13 | textAlign: 'right',
14 | transition: 'all 200ms ease',
15 | width: '100%'
16 | };
17 |
18 | let DropdownMenuSty = {
19 | backgroundColor: '#261a3b',
20 | boxShadow: '0 1px 0 rgba(0, 0, 0, 0.06)',
21 | boxSizing: 'border-box',
22 | fontSize: '.9em',
23 | lineHeight: '150%',
24 | marginTop: '-1px',
25 | maxHeight: '300px',
26 | overflowY: 'auto',
27 | padding: '8px 12px',
28 | position: 'absolute',
29 | right: '0px',
30 | top: '100%',
31 | zIndex: '200'
32 | };
33 |
34 | let DropdownSeperatorSty = {
35 | backgroundColor: '#000000',
36 | height: '3px',
37 | margin: '3px 0',
38 | width: '100%'
39 | };
40 |
41 | let DropdownOptionSty = {
42 | boxSizing: 'border-box',
43 | color: '#EEFFEE',
44 | cursor: 'pointer',
45 | display: 'block'
46 | };
47 |
48 | class JDropMenu extends React.Component {
49 | state = {isOpen: false, selected: {}};
50 | setValue = (e) => {
51 | let selectedOption = this.props.options[parseInt(e.target.id)];
52 | this.props.onChange(selectedOption);
53 | this.setState({isOpen: false});
54 | };
55 | handleMouseDown = (event) => {
56 | if (event.type == 'mousedown' && event.button !== 0) return;
57 | event.stopPropagation();
58 | event.preventDefault();
59 | this.setState({isOpen: !this.state.isOpen});
60 | };
61 | render() {
62 | let items = this.props.options.map((option, index) => {
63 | if (option.type == 'seperator') {
64 | return (
);
65 | } else {
66 | return (
67 |
{option.label}
73 | );
74 | }
75 | });
76 |
77 | let value = (
);
78 | let menu = this.state.isOpen ?
{items}
: null;
79 |
80 | return (
81 |
82 |
83 | {value}
84 |
85 | {menu}
86 |
87 | );
88 | }
89 | }
90 |
91 | JDropMenu.propTypes = {
92 | options: React.PropTypes.array.isRequired,
93 | onChange: React.PropTypes.func.isRequired
94 | };
95 |
96 | module.exports = JDropMenu;
97 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/Gallery/gallery.style.js:
--------------------------------------------------------------------------------
1 | let backgroundSize = 'contain';
2 | let dropShadow = '0 1px 0px #333, 1px 0 0px #333, 1px 2px 1px #333, 2px 1px 1px #333, 2px 3px 2px #333';
3 |
4 | module.exports = {
5 | GallerySty: {
6 | backgroundColor: 'grey',
7 | color: 'white',
8 | height: '100vh',
9 | left: '0px',
10 | padding: '0 10px 0 0',
11 | position: 'absolute',
12 | top: '0px',
13 | width: '100vw'
14 | },
15 | imageDivSty: {
16 | backgroundPosition: 'center center',
17 | backgroundRepeat: 'no-repeat',
18 | backgroundSize,
19 | height: '100%',
20 | MozBackgroundSize: backgroundSize,
21 | OBackgroundSize: backgroundSize,
22 | overflow: 'hidden',
23 | padding: '0px',
24 | position: 'relative',
25 | WebkitBackgroundSize: backgroundSize,
26 | width: '100%'
27 | },
28 | imageThumbSty: {position: 'relative', height: '100%', width: '100%'},
29 | actionSty: {position: 'relative', height: '100%', width: '100%'},
30 | fullCloseSty: {position: 'absolute', left: '15px', top: '5px'},
31 | nextSty: {position: 'absolute', right: '25px', top: '50%'},
32 | prevSty: {position: 'absolute', left: '25px', top: '50%'},
33 | thumbsOpenSty: {position: 'absolute', right: '25px', top: '5px'},
34 | thumbsClosedSty: {color: '#afac87', position: 'absolute', right: '25px', top: '0px'},
35 | nextPanelSty: {height: '80vh', position: 'absolute', right: '0px', top: '10vh', width: '75%'},
36 | prevPanelSty: {height: '80vh', position: 'absolute', left: '0px', top: '10vh', width: '25%'},
37 | copyRightSty: {
38 | position: 'absolute', color: '#777', right: '5px', top: '75%', fontSize: '.8em',
39 | writingMode: 'vertical-rl', textShadow: dropShadow
40 | },
41 | statusSty: {color: 'black', fontSize: '1.5em', position: 'absolute', textAlign: 'center', top: '5px', width: '100%'}
42 | };
43 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/Gallery/jThumbs.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import ListItem from './listitem';
4 |
5 | let thumbColumnSty = {
6 | boxSizing: 'border-box',
7 | flexGrow: '1',
8 | height: '100%',
9 | margin: '0px',
10 | maxWidth: '10%',
11 | overflowY: 'auto',
12 | overflowX: 'hidden',
13 | padding: '0px 10px',
14 | textAlign: 'center'
15 | };
16 |
17 | let thumbRowSty = {
18 | maxHeight: '13vh',
19 | margin: '10px 0px 5px',
20 | overflowY: 'hidden',
21 | overflowX: 'auto',
22 | padding: '0px',
23 | width: '100%',
24 | whiteSpace: 'nowrap'
25 | };
26 |
27 | function listMap(item, index) {
28 | return (
29 |
36 | );
37 | }
38 |
39 | class ThumbColumn extends React.Component {
40 | componentWillReceiveProps = () => {
41 | if (!this.props.hide) this.thumbDiv.scrollTop = 0;
42 | };
43 | setThumbDivRef = (node) => this.thumbDiv = node;
44 | afterScroll = () => {
45 | let thisElement = this.thumbDiv;
46 | let thisElementScrollTop = thisElement.scrollTop;
47 | if (thisElement.scrollHeight - thisElementScrollTop != thisElement.clientHeight) {
48 | thisElement.scrollTop = thisElementScrollTop - 300;
49 | }
50 | };
51 | render() {
52 | if (this.props.hide) return null;
53 | let children = this.props.data.list.map(listMap, this);
54 | let ThumbColumnSty;
55 | if (this.props.thumbColumn) ThumbColumnSty = Object.assign({}, thumbColumnSty);
56 | else ThumbColumnSty = Object.assign({}, thumbRowSty);
57 | return (
58 |
59 | {children}
60 |
61 | );
62 | }
63 | }
64 |
65 | ThumbColumn.propTypes = {
66 | data: React.PropTypes.object.isRequired,
67 | hide: React.PropTypes.bool,
68 | close: React.PropTypes.func
69 | };
70 |
71 | module.exports = ThumbColumn;
72 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/Gallery/listitem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | let ThumbColumnItemSty = {
4 | background: 'transparent',
5 | backgroundPosition: 'center center',
6 | backgroundRepeat: 'no-repeat',
7 | backgroundSize: 'contain',
8 | marginBottom: '10px',
9 | marginRight: 'auto',
10 | marginLeft: 'auto',
11 | textAlign: 'center',
12 | width: 'calc(100% - 4px)'
13 | };
14 |
15 | let ThumbRowItemSty = {
16 | background: 'transparent',
17 | display: 'inline-block',
18 | verticalAlign: 'middle'
19 | };
20 |
21 | let thumbImageSty = {
22 | display: 'block',
23 | marginRight: 'auto',
24 | marginLeft: 'auto',
25 | maxWidth: 'calc(100% - 6px)',
26 | maxHeight: 'calc(13vh - 41px)',
27 | width: 'auto',
28 | height: 'auto'
29 | };
30 |
31 | class ListItem extends React.Component {
32 | componentDidUpdate = () => {
33 | if ((this.props.index == this.props.selected)) {
34 | this.refName.scrollIntoView({behavior: 'smooth'});
35 | this.props.afterScroll();
36 | }
37 | };
38 | clickHandler = () => { this.props.clickHandler(this.props.index); };
39 | render() {
40 | let thumbColumnImgBorder;
41 | if (this.props.index == this.props.selected) thumbColumnImgBorder = '3px solid rgb(220, 112, 24)';
42 | else thumbColumnImgBorder = '3px solid transparent';
43 |
44 | let ThumbDivSty;
45 | if (this.props.thumbColumn) ThumbDivSty = Object.assign({}, ThumbColumnItemSty);
46 | else ThumbDivSty = Object.assign({}, ThumbRowItemSty);
47 | // ThumbDivSty.backgroundImage = 'url(' + src + ')';
48 | let ThumbImgSty = Object.assign({}, thumbImageSty);
49 | ThumbImgSty.border = thumbColumnImgBorder;
50 | let src = this.props.item.smFolder + this.props.item.FileName;
51 | return (
52 |
this.refName = ref} style={ThumbDivSty} >
53 |

54 |
55 | );
56 | }
57 | }
58 |
59 | ListItem.propTypes = {
60 | item: React.PropTypes.object.isRequired,
61 | thumbColumn: React.PropTypes.bool,
62 | index: React.PropTypes.number,
63 | selected: React.PropTypes.number,
64 | afterScroll: React.PropTypes.func
65 | };
66 |
67 | module.exports = ListItem;
68 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/Gallery/shortcuts.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | let ShortcutsSty = {
4 | backgroundColor: '#333',
5 | border: '1px solid green',
6 | color: '#AAA',
7 | left: '10px',
8 | padding: '10px',
9 | position: 'absolute',
10 | top: '50px'
11 | };
12 |
13 | let headSty = {
14 | color: '#e2d290',
15 | fontSize: '1.2em',
16 | textAlign: 'center'
17 | };
18 |
19 | let keySty = {
20 | color: '#aaa',
21 | fontSize: '1em',
22 | textAlign: 'center',
23 | width: '30px'
24 | };
25 |
26 | let descSty = {
27 | color: '#aaa',
28 | fontSize: '1em',
29 | textAlign: 'left'
30 | };
31 |
32 | let okSty = {
33 | backgroundColor: '#222',
34 | cursor: 'pointer',
35 | padding: '5px 0px',
36 | textAlign: 'center',
37 | width: '100%'
38 | };
39 |
40 | export default class Shortcuts extends React.Component {
41 | closeHandler = () => { this.props.closeHandler(); };
42 | render() {
43 | if (this.props.hide) return null;
44 | return (
45 |
46 |
Keyboard Shortcuts
47 |
48 |
49 |
50 | →
51 | ←
52 | T
53 | B
54 | S
55 | X
56 |
57 |
58 | Next pic
59 | Previous pic
60 | Side Thumbs
61 | Bottom Thumbs
62 | Full screen
63 | Exit
64 |
65 |
66 |
67 |
Ok
68 |
69 | );
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/List/jList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | let listSty = {};
4 | let listStyleDefault = {};
5 |
6 | let lineSty = {};
7 | let lineStyleDefault = {
8 | color: '#a7b3a5',
9 | marginLeft: '7px'
10 | };
11 |
12 | function divMap(item, index) {
13 | return (
{item}
);
14 | }
15 |
16 | function spanMap(item, index) {
17 | return (
{item});
18 | }
19 |
20 | function JList({data, lineStyle, listStyle, spanLine}) {
21 | listSty = listStyle ? listStyle : listStyleDefault;
22 | lineSty = lineStyle ? lineStyle : lineStyleDefault;
23 | var list;
24 | if (spanLine) list = data.map(spanMap);
25 | else list = data.map(divMap);
26 | return (
27 |
28 | {list}
29 |
30 | );
31 | }
32 |
33 | module.exports = JList;
34 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/PageIndicator/jPageIndicator.jsx:
--------------------------------------------------------------------------------
1 | const React = require('react');
2 |
3 | const styles = {
4 | component: {
5 | textAlign: 'center',
6 | padding: '0',
7 | },
8 | dot: {
9 | width: 9,
10 | height: 9,
11 | margin: 7,
12 | padding: 0,
13 | borderRadius: '100%',
14 | display: 'inline-block',
15 | verticalAlign: 'middle',
16 | backgroundColor: '#fff',
17 | cursor: 'pointer'
18 | },
19 | dotActive: {
20 | backgroundColor: '#b4dbc0'
21 | }
22 | };
23 |
24 | const PageIndicator = (props) => {
25 |
26 | const _handleDotClick = (e) => { if (props.onClick) props.onClick(parseInt(e.target.id)); };
27 |
28 | const _renderDots = () => {
29 | const dots = [];
30 |
31 | for (let i = 0; i < props.count; i++) {
32 | const dotStyles = props.activeIndex === i ? Object.assign({}, styles.dot, styles.dotActive) : styles.dot;
33 | dots.push(
);
34 | }
35 | return dots;
36 | };
37 |
38 | let renderedDots = _renderDots();
39 |
40 | return (
41 |
42 | {renderedDots}
43 |
44 | );
45 | };
46 |
47 | PageIndicator.propTypes = {
48 | activeIndex: React.PropTypes.number,
49 | count: React.PropTypes.number.isRequired,
50 | onClick: React.PropTypes.func
51 | };
52 |
53 | module.exports = PageIndicator;
54 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/ProgressBar/jProgressBar.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | let defaultCountSty = {
4 | backgroundColor: '#4d2c3d',
5 | height: '12px',
6 | marginRight: '5px',
7 | marginTop: '4px',
8 | width: '100%'
9 | };
10 |
11 | let defaultIndexSty = {backgroundColor: '#ab9353', height: '6px', borderTop: '3px solid #4d2c3d', width: '1%'};
12 | let centerSty = {color: '#e9e7da', marginLeft: 'auto', marginRight: 'auto', marginTop: '-33px'};
13 | let numberSty = {color: '#e9e7da'};
14 |
15 | const JProgressBar = (props) => {
16 | if (!props.data) return null;
17 | let progressSty = {fontSize: '1em', width: '100%'};
18 | let count = props.data.count;
19 | let index = props.data.index;
20 | let perc = index/count * 100;
21 | let percentage = perc > 50 ? Math.floor(perc) : Math.ceil(perc);
22 |
23 | let countSty = props.countSty ? Object.assign({}, props.countSty) : Object.assign({}, defaultCountSty);
24 | let indexSty = props.indexSty ? Object.assign({}, props.indexSty) : Object.assign({}, defaultIndexSty);
25 | indexSty.width = percentage + '%';
26 | countSty.backgroundColor = props.countColor ? props.countColor : defaultCountSty.backgroundColor;
27 | indexSty.backgroundColor = props.indexColor ? props.indexColor : defaultIndexSty.backgroundColor;
28 | indexSty.borderTopColor = countSty.backgroundColor;
29 |
30 | let barRender = (
31 |
34 | );
35 |
36 | let progressRender = '';
37 | let position = props.position ? props.position : 'center';
38 | switch (position) {
39 | case 'center': progressRender = (
40 |
41 | {barRender}
42 |
43 |
{index} / {count}
44 |
45 |
46 | ); break;
47 | case 'after': progressRender = (
48 |
49 | {barRender}
50 | {index} / {count}
51 |
52 | ); break;
53 | case 'before': progressRender = (
54 |
55 | {index} / {count}
56 | {barRender}
57 |
58 | ); break;
59 | case 'beforenafter': progressRender = (
60 |
61 | {index}
62 | {barRender}
63 | {count}
64 |
65 | ); break;
66 | case 'none': progressRender = (
67 |
68 | {barRender}
69 |
70 | ); break;
71 | }
72 | return progressRender;
73 | };
74 |
75 | module.exports = JProgressBar;
76 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/Tooltip/jTooltip.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | let TooltipSty = {
4 | display: 'inline-block',
5 | lineHeight: '14px',
6 | marginRight: '5px',
7 | verticalAlign: 'top'
8 | };
9 |
10 | let helpTip = {
11 | background: '#5a5e5e',
12 | border: '1px solid #a3aaaa',
13 | borderRadius: '50%',
14 | boxShadow: '0 1px 2px rgba(0, 0, 0, 0.18)',
15 | boxSizing: 'border-box',
16 | color: '#fafafa',
17 | cursor: 'default',
18 | fontSize: '11px',
19 | height: '14px',
20 | lineHeight: '14px',
21 | marginTop: '1px',
22 | textAlign: 'center',
23 | width: '14px'
24 | };
25 |
26 | let contentSty = {
27 | background: 'rgb(28, 34, 24)',
28 | border: '1px solid rgba(0, 0, 0, 0.08)',
29 | borderRadius: '3px',
30 | boxShadow: '0 2px 6px rgba(0, 0, 0, 0.2)',
31 | color: '#e9e7da',
32 | fontSize: '0.9375em',
33 | lineHeight: '1.2em',
34 | maxWidth: '280px',
35 | minWidth: '200px',
36 | padding: '5px',
37 | textAlign: 'left',
38 | wordWrap: 'break-word',
39 | zIndex: '200'
40 | };
41 |
42 | let contentOuterSty = {height: '100%', width: '100%'};
43 |
44 | function Contents({tooltipActive, place, position, data}) {
45 | if (!data) return null;
46 | let contentHtml = data;
47 | let contentLength = contentHtml.length;
48 | let topNeg = (Math.ceil(contentLength/40) + 1) * 18;
49 | let rightNeg = contentLength * .25;
50 |
51 | let active = tooltipActive;
52 | let inPosition = position || null;
53 | let contentInnerSty = {position: 'absolute'};
54 | if (active) {
55 | switch (place) {
56 | case 'bottom': contentInnerSty.left = inPosition.right + 5; contentInnerSty.top = inPosition.top + 20; break;
57 | case 'right': contentInnerSty.left = inPosition.right + 5; contentInnerSty.top = inPosition.top - rightNeg; break;
58 | case 'top': contentInnerSty.left = inPosition.right + 5; contentInnerSty.top = inPosition.top - topNeg; break;
59 | }
60 | }
61 | else contentInnerSty.display = 'none';
62 | let displayContent = {__html: contentHtml};
63 | return (
64 |
71 | );
72 | }
73 |
74 | class JTooltip extends React.Component {
75 | state = {tooltipActive: false, position: {}};
76 | onMouseEnter = () => {
77 | let rect = this.TooltipRef.getBoundingClientRect();
78 | let position = {};
79 | position.left = rect.left - this.props.adjust.left;
80 | position.top = rect.top - this.props.adjust.top;
81 | position.right = rect.right - this.props.adjust.left;
82 | position.bottom = rect.bottom - this.props.adjust.top;
83 | this.setState({tooltipActive: true, position});
84 | };
85 | onMouseLeave = () => { this.setState({tooltipActive: false}); };
86 | render() {
87 | let help = '?';
88 | return(
89 |
100 | );
101 | }
102 | }
103 |
104 | module.exports = JTooltip;
105 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/TreeViews/jTreeView.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import lodashGet from 'lodash/get';
3 |
4 | let TreeRootSty = {lineHeight: '120%'};
5 | let liSty = {listStyleType: 'none'};
6 | let ulSty = {height: 'inherit', WebkitPaddingStart: '16px'};
7 | let ulStyle = {height: 'inherit', WebkitPaddingStart: '16px'};
8 | let iconSty = {marginRight: '10px', width: '16px'};
9 |
10 | let nottogglable = {
11 | color: '#FFF',
12 | cursor: 'pointer',
13 | margin: '0 0 0 .8em'
14 | };
15 |
16 | let inOptions = {};
17 | let inCustomColors = {};
18 |
19 | const defaultColors = {
20 | parent: '#AF90A5',
21 | parentSelected: '#7BB53B',
22 | endnode: '#afac87',
23 | endnodeSelected: '#b58900'
24 | };
25 |
26 | const JTreeViewNode = (props) => {
27 | const iconHandler = () => {
28 | if (props.node.children && props.node.children.length > 0) {
29 | props.iconClick(props.node);
30 | } else {
31 | clickHandler();
32 | }
33 | };
34 | const clickHandler = () => { props.titleClick(props.node); };
35 | let titleColors = inCustomColors ? inCustomColors : defaultColors;
36 | let titleSty = {marginTop: '2px'};
37 | let childNodes;
38 | let pSty = nottogglable;
39 |
40 | if (props.node.children && props.node.children.length > 0) {
41 | childNodes = props.node.children.map((child, index) => {
42 | return (
43 |
44 |
45 |
46 | );
47 | });
48 | titleSty.color = props.node.selected ? titleColors.parentSelected : titleColors.parent;
49 | } else {
50 | titleSty.color = props.node.selected ? titleColors.endnodeSelected : titleColors.endnode;
51 | }
52 |
53 | let isClosed = true;
54 | if (props.node.closed != null) isClosed = props.node.closed;
55 |
56 | let branch = (
57 |
60 | );
61 | if (isClosed) branch = null;
62 |
63 | let iconType = lodashGet(props, inOptions.typeName);
64 | if (iconType == inOptions.icon.sun) iconSty.background = 'url(\'./img/sun.ico\') 0/16px no-repeat';
65 | else if (iconType == inOptions.icon.leaf) iconSty.background = 'url(\'./img/leaf.ico\') 0/16px no-repeat';
66 | else if (iconType == inOptions.icon.snow) iconSty.background = 'url(\'./img/snow.ico\') 0/16px no-repeat';
67 | else iconSty.background = 'url(\'./img/sun.ico\') 0/16px no-repeat';
68 |
69 | return (
70 |
71 |
72 |
73 |
74 | {props.node.title}
75 |
76 |
77 | {branch}
78 |
79 | );
80 | };
81 |
82 | function JTreeView({data, options, iconClick, titleClick, customColors}) {
83 | inOptions = options;
84 | inCustomColors = customColors;
85 | let childNodes = data.map((child, index) => {
86 | return (
87 |
88 |
89 |
90 | );
91 | });
92 | return (
93 |
98 | );
99 | }
100 |
101 | module.exports = JTreeView;
102 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/app.colors.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | morning_sky: '#cae4db',
3 | honey: '#dcae1d',
4 | cerulean: '#00303f',
5 | mist: '#7a9d96',
6 |
7 | bluebell: '#155765',
8 | olive: '#57652a',
9 | ornate: '#ab9353',
10 | plum: '#4d2c3d',
11 |
12 | gold: '#cda34f',
13 | daisy: '#e9e7da',
14 | stem: '#636b46',
15 | greenery: '#373f27',
16 |
17 | aqua: '#6bbaa7',
18 | sunshine: '#fba100',
19 | lavender: '#6c648b',
20 | dusty_rose: '#b6a19e',
21 |
22 | rust: '#b56357',
23 | mint: '#b4dbc0',
24 | slate: '#eae3ea',
25 | sea_foam: '#a7b3a5',
26 |
27 | white: '#fff',
28 | black: '#000'
29 | };
30 |
--------------------------------------------------------------------------------
/React.Common/ui-src/components/common/app.notes.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const AppNotesSty = {
4 | marginLeft: 'auto',
5 | marginRight: 'auto',
6 | marginTop: '30px',
7 | maxWidth: '500px',
8 | textIndent: '20px'
9 | };
10 |
11 | const textSty = {
12 | color: '#FFF',
13 | fontSize: '1.0em',
14 | textAlign: 'left'
15 | };
16 |
17 | const btnDivSty = {textAlign: 'center'};
18 |
19 | const standardBtnSty = {
20 | backgroundColor: '#9a6',
21 | borderBottomColor: '#cea',
22 | borderLeftColor: '#93a363',
23 | borderRightColor: '#cea',
24 | borderTopColor: '#93a363',
25 | borderRadius: '6px',
26 | color: '#eeffee',
27 | cursor: 'pointer',
28 | lineHeight: '100%',
29 | outline: 'none',
30 | verticalAlign: 'middle',
31 | whiteSpace: 'nowrap'
32 | };
33 |
34 | export default class AppNotes extends React.Component {
35 | state = {show: true};
36 | onClick = () => { this.setState({show: !this.state.show}); };
37 | render() {
38 | if (this.props.AppText.trim().length === 0) return null;
39 | let showNotes = this.state.show;
40 | let btnText = showNotes ? 'Hide notes' : 'Show notes';
41 | let notesDivSty = showNotes ? {display: 'block'} : {display: 'none'};
42 | return (
43 |
44 |
45 |
46 |
47 |
48 |
{this.props.AppText}
49 |
50 |
51 | );
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/React.Common/ui-src/css/index.css:
--------------------------------------------------------------------------------
1 | .bodyStyle {
2 | background-color: #00303f;
3 | color: #eae3ea;
4 | display: block;
5 | height: 100%;
6 | overflow: hidden;
7 | width: 100%;
8 | }
9 |
10 | .header {
11 | height: 30px;
12 | margin: 0;
13 | padding: 10px 0;
14 | text-align: center;
15 | }
16 |
17 | .Title {font-size: 1.3em;}
18 |
19 | .content {
20 | height: 100%;
21 | padding: 0 5px;
22 | }
23 |
24 | .contentPage {
25 | margin: 5px auto;
26 | max-width: 1366px;
27 | }
28 |
29 | * { outline: none; }
30 |
31 | .a{display:block}
32 |
33 | .FlexBox {
34 | display: -webkit-box;
35 | display: -moz-box;
36 | display: -ms-flexbox;
37 | display: flex;
38 | }
39 |
40 | .FlexBoxC {
41 | display: -webkit-box;
42 | display: -moz-box;
43 | display: -ms-flexbox;
44 | display: flex;
45 | flex-direction: column;
46 | }
47 |
48 | .FlexBoxCenter {
49 | display: -webkit-box;
50 | display: -moz-box;
51 | display: -ms-flexbox;
52 | display: flex;
53 | justify-content: center;
54 | }
55 |
56 | .FlexBoxJustAround {
57 | display: -webkit-box;
58 | display: -moz-box;
59 | display: -ms-flexbox;
60 | display: flex;
61 | justify-content: space-around;
62 | }
63 |
64 | .FlexBoxJustBetween {
65 | display: -webkit-box;
66 | display: -moz-box;
67 | display: -ms-flexbox;
68 | display: flex;
69 | flex-wrap: wrap;
70 | justify-content: space-between;
71 | }
72 |
73 | .FlexBoxWrap {
74 | display: -webkit-box;
75 | display: -moz-box;
76 | display: -ms-flexbox;
77 | display: flex;
78 | flex-wrap: wrap;
79 | }
80 |
81 | .FlexJustify {
82 | -webkit-box-pack: justify;
83 | justify-content: space-between;
84 | }
85 |
86 | .FlexBoxStretch {
87 | display: -webkit-box;
88 | display: -moz-box;
89 | display: -ms-flexbox;
90 | display: flex;
91 | align-content: stretch;
92 | }
93 |
94 | .FlexItem {
95 | flex-grow: 1;
96 | }
97 |
98 | .HighZ {z-index: 200;}
99 |
--------------------------------------------------------------------------------
/React.Common/ui-src/css/rangeInput.css:
--------------------------------------------------------------------------------
1 | input[type=range] {
2 | -webkit-appearance: none;
3 | margin: 18px 0;
4 | width: 100%;
5 | }
6 | input[type=range]:focus {
7 | outline: none;
8 | }
9 | input[type=range]::-webkit-slider-runnable-track {
10 | width: 100%;
11 | height: 8.4px;
12 | cursor: pointer;
13 | animate: 0.2s;
14 | box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
15 | background: #4d2c3d;
16 | border-radius: 1.3px;
17 | border: 0.2px solid #010101;
18 | }
19 | input[type=range]::-webkit-slider-thumb {
20 | box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
21 | border: 1px solid #000000;
22 | height: 36px;
23 | width: 16px;
24 | border-radius: 3px;
25 | background: #ffffff;
26 | cursor: pointer;
27 | -webkit-appearance: none;
28 | margin-top: -14px;
29 | }
30 | input[type=range]:focus::-webkit-slider-runnable-track {
31 | background: #367ebd;
32 | }
33 | input[type=range]::-moz-range-track {
34 | width: 100%;
35 | height: 8.4px;
36 | cursor: pointer;
37 | animate: 0.2s;
38 | box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
39 | background: #3071a9;
40 | border-radius: 1.3px;
41 | border: 0.2px solid #010101;
42 | }
43 | input[type=range]::-moz-range-thumb {
44 | box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
45 | border: 1px solid #000000;
46 | height: 36px;
47 | width: 16px;
48 | border-radius: 3px;
49 | background: #ffffff;
50 | cursor: pointer;
51 | }
52 | input[type=range]::-ms-track {
53 | width: 100%;
54 | height: 8.4px;
55 | cursor: pointer;
56 | animate: 0.2s;
57 | background: transparent;
58 | border-color: transparent;
59 | border-width: 16px 0;
60 | color: transparent;
61 | }
62 | input[type=range]::-ms-fill-lower {
63 | background: #2a6495;
64 | border: 0.2px solid #010101;
65 | border-radius: 2.6px;
66 | box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
67 | }
68 | input[type=range]::-ms-fill-upper {
69 | background: #3071a9;
70 | border: 0.2px solid #010101;
71 | border-radius: 2.6px;
72 | box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
73 | }
74 | input[type=range]::-ms-thumb {
75 | box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
76 | border: 1px solid #000000;
77 | height: 36px;
78 | width: 16px;
79 | border-radius: 3px;
80 | background: #ffffff;
81 | cursor: pointer;
82 | }
83 | input[type=range]:focus::-ms-fill-lower {
84 | background: #3071a9;
85 | }
86 | input[type=range]:focus::-ms-fill-upper {
87 | background: #367ebd;
88 | }
89 |
--------------------------------------------------------------------------------
/React.Common/ui-src/img/1x1TransShim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.Common/ui-src/img/1x1TransShim.gif
--------------------------------------------------------------------------------
/React.Common/ui-src/img/SLogoS5-48_C.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.Common/ui-src/img/SLogoS5-48_C.png
--------------------------------------------------------------------------------
/React.Common/ui-src/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.Common/ui-src/img/favicon.ico
--------------------------------------------------------------------------------
/React.Common/ui-src/img/flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.Common/ui-src/img/flow.png
--------------------------------------------------------------------------------
/React.Common/ui-src/img/leaf.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.Common/ui-src/img/leaf.ico
--------------------------------------------------------------------------------
/React.Common/ui-src/img/snow.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.Common/ui-src/img/snow.ico
--------------------------------------------------------------------------------
/React.Common/ui-src/img/sun.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmarkstevens/ReactPatterns/3a0e40f4d562155163bcac98d9555c1f2bba8f1b/React.Common/ui-src/img/sun.ico
--------------------------------------------------------------------------------
/React.Common/ui-src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
ReactPatterns-ReduxPages
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/React.Common/ui-src/store/App.Store.js:
--------------------------------------------------------------------------------
1 | import {createStore, combineReducers, applyMiddleware} from 'redux';
2 | import logger from 'redux-logger';
3 | import thunkMiddleware from 'redux-thunk';
4 |
5 | import {apiGetAppData, apiGetImageList, apiGetTreeView, apiGetInputData, apiGetPicList} from './api/api.Actions';
6 |
7 | import appState from './app/app.Reducer';
8 | import galleryState from './gallery/gallery.Reducer';
9 | import inputState from './input/input.Reducer';
10 | import treeState from './treeview/tree.Reducer';
11 |
12 | const reducer = combineReducers({appState, galleryState, inputState, treeState});
13 | let middleware = [thunkMiddleware];
14 |
15 | const useLogger = 1;
16 | if (useLogger) middleware.push(logger);
17 |
18 | const store = createStore(reducer, applyMiddleware(...middleware));
19 |
20 | store.dispatch(apiGetAppData());
21 | store.dispatch(apiGetImageList());
22 | store.dispatch(apiGetTreeView());
23 | store.dispatch(apiGetInputData());
24 | store.dispatch(apiGetPicList());
25 |
26 | export default store;
27 |
--------------------------------------------------------------------------------
/React.Common/ui-src/store/api/api.Actions.js:
--------------------------------------------------------------------------------
1 | import 'whatwg-fetch';
2 |
3 | let jsonHeader = {'Accept': 'application/json', 'Content-Type': 'application/json'};
4 |
5 | export function apiGetAppData() {
6 | return (dispatch) => {
7 | fetch('/routes/getAppData')
8 | .then((response) => response.json())
9 | .then((json) => dispatch({type: 'GetAppDataDone', payload: json}));
10 | };
11 | }
12 |
13 | export function apiGetImageList() {
14 | return (dispatch) => {
15 | fetch('/routes/getImageList')
16 | .then((response) => response.json())
17 | .then((json) => dispatch({type: 'GetImageListDone', payload: json}));
18 | };
19 | }
20 |
21 | export function apiGetInputData() {
22 | return (dispatch) => {
23 | fetch('/routes/getInputData')
24 | .then((response) => response.json())
25 | .then((json) => dispatch({type: 'GetInputDataDone', payload: json}));
26 | };
27 | }
28 |
29 | export function apiGetPicList() {
30 | return (dispatch) => {
31 | fetch('/routes/getPicList')
32 | .then((response) => response.json())
33 | .then((json) => dispatch({type: 'GetPicListDone', payload: json}));
34 | };
35 | }
36 |
37 | export function apiGetTreeView() {
38 | return (dispatch) => {
39 | fetch('/routes/getTreeView')
40 | .then((response) => response.json())
41 | .then((json) => dispatch({type: 'GetTreeViewDone', payload: json}));
42 | };
43 | }
44 |
45 | export function apiSetAppData(data) {
46 | fetch('/routes/setAppData', {method: 'POST', headers: jsonHeader, body: JSON.stringify(data)});
47 | }
48 |
49 | export function apiSetInputData(data) {
50 | fetch('/routes/setInputData', {method: 'POST', headers: jsonHeader, body: JSON.stringify(data)});
51 | }
52 |
53 | export function apiSetTreeView(data) {
54 | fetch('/routes/setTreeView', {method: 'POST', headers: jsonHeader, body: JSON.stringify(data)});
55 | }
56 |
--------------------------------------------------------------------------------
/React.Common/ui-src/store/app/app.actions.js:
--------------------------------------------------------------------------------
1 | export function appNavMenuAction(newPage) { return {type: 'AppNavMenuAction', newPage}; }
2 |
--------------------------------------------------------------------------------
/React.Common/ui-src/store/app/app.reducer.js:
--------------------------------------------------------------------------------
1 |
2 | const initialAppState = {
3 | currentPage: 'Button'
4 | };
5 |
6 | export default function handleActions(state = initialAppState, action) {
7 | let _appState = Object.assign({}, state);
8 | switch (action.type) {
9 | case 'AppNavMenuAction': _appState.currentPage = action.newPage; return _appState;
10 | default: return state;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/React.Common/ui-src/store/gallery/gallery.Reducer.js:
--------------------------------------------------------------------------------
1 |
2 | const initialState = {
3 | picList: [],
4 | };
5 |
6 | export default function handleActions(state = initialState, action) {
7 | switch (action.type) {
8 | case 'GetPicListDone': return {...state, ...action.payload};
9 | default: return state;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/React.Common/ui-src/store/input/input.Actions.js:
--------------------------------------------------------------------------------
1 |
2 | export function editRecord(field, value) { return {type: 'EditRecord', field, value}; }
3 |
--------------------------------------------------------------------------------
/React.Common/ui-src/store/input/input.Reducer.js:
--------------------------------------------------------------------------------
1 |
2 | import {apiSetInputData} from '../api/api.Actions';
3 |
4 | const setData = (inputCopy) => { apiSetInputData(inputCopy); };
5 |
6 | const onEditRecord = (inputCopy, field, value) => {
7 | switch (field) {
8 | case 'text': inputCopy.text = value; break;
9 | case 'checkbox': inputCopy.checkbox = value; break;
10 | case 'radioGroup': inputCopy.radioGroup = value; break;
11 | case 'color': inputCopy.color = value; break;
12 | case 'number': inputCopy.number = value; break;
13 | case 'range': inputCopy.range = value; break;
14 | case 'folder': inputCopy.folder = value; break;
15 | }
16 | setData(inputCopy);
17 | return inputCopy;
18 | };
19 |
20 | const initialState = {
21 | 'text': '',
22 | 'checkbox': false,
23 | 'radioGroup': '',
24 | 'color': '#ffffff',
25 | 'number': '',
26 | 'range': '',
27 | 'folder': ''
28 | };
29 |
30 | export default function handleActions(state = initialState, action) {
31 | let inputCopy = Object.assign({}, state);
32 | switch (action.type) {
33 | case 'GetInputDataDone': return {...state, ...action.payload};
34 | case 'EditRecord': {
35 | let editRecordData = onEditRecord(inputCopy, action.field, action.value);
36 | return {...state, ...editRecordData};
37 | }
38 | default: return state;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/React.Common/ui-src/store/treeview/tree.Actions.js:
--------------------------------------------------------------------------------
1 |
2 | export function setClippetsTree() { return {type: 'SetClippetsTree'}; }
3 |
4 | export function selectTreeNode(node) { return {type: 'SelectTreeNode', node}; }
5 |
6 | export function setTreeNodeClosed(node) { return {type: 'SetTreeNodeClosed', node}; }
7 |
8 | export function saveTreeEdit(node) { return {type: 'SaveTreeEdit', node}; }
9 |
10 | export function saveTreeNew(node, location) { return {type: 'SaveTreeNew', node, location}; }
11 |
12 | export function treeActions(action) {
13 | switch (action) {
14 | case 'new': return {type: 'ShowNew'};
15 | case 'edit': return {type: 'ShowEdit'};
16 | case 'moveUp': return {type: 'MoveUp'};
17 | case 'moveDown': return {type: 'MoveDown'};
18 | case 'remove': return {type: 'Remove'};
19 | case 'cancelEdit': return {type: 'CancelEdit'};
20 | case 'cancelNew': return {type: 'CancelNew'};
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/React.Common/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
3 | const webpack = require('webpack');
4 | const configJson = require('./webpack.config.json');
5 |
6 | module.exports = (env) => {
7 |
8 | const noMinimize = env.noMinimize;
9 | var plugins = [];
10 |
11 | plugins.push(new ExtractTextPlugin({filename: 'app.css', allChunks: true}));
12 | plugins.push(new webpack.optimize.CommonsChunkPlugin({name: 'lib'}));
13 | if (noMinimize) {
14 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('development')}}));
15 | } else {
16 | plugins.push(new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('production')}}));
17 | plugins.push(new webpack.optimize.UglifyJsPlugin({include: /lib\.js/, minimize: true}));
18 | }
19 |
20 | const ROOT_PATH = path.resolve(__dirname);
21 | const SRC_PATH = path.resolve(ROOT_PATH, './ui-src');
22 | const DIST_PATH = path.resolve(ROOT_PATH, './ui-dist');
23 |
24 |
25 | return {
26 | context: SRC_PATH,
27 | entry: {
28 | app: './app.jsx',
29 | lib: configJson.lib
30 | },
31 |
32 | output: {
33 | path: DIST_PATH,
34 | filename: '[name].js'
35 | },
36 |
37 | module: {
38 | rules: [
39 | {
40 | test: /\.jsx?$/,
41 | loader: 'babel-loader',
42 | query: {presets:['es2015', 'react', 'stage-0']},
43 | exclude: /(node_modules)/,
44 | },
45 | {
46 | test: /\.css$/,
47 | use: ExtractTextPlugin.extract({
48 | fallback: 'style-loader',
49 | use: 'css-loader'
50 | })
51 | },
52 | {
53 | test: /\.(png|jpg|ico|gif)$/,
54 | loader: 'file-loader?name=img/[name].[ext]'
55 | },
56 | {
57 | test: /\.(html)$/,
58 | loader: 'file-loader?name=[name].[ext]'
59 | }
60 | ]
61 | },
62 | plugins,
63 | resolve: {
64 | extensions: ['.js', '.jsx'],
65 | modules: ['node_modules']
66 | }
67 | };
68 | };
69 |
--------------------------------------------------------------------------------
/React.Common/webpack.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "lib": [
3 | "lodash",
4 | "lodash/throttle",
5 | "radium",
6 | "react",
7 | "react-dom",
8 | "react-mixin",
9 | "react-redux",
10 | "redux",
11 | "redux-logger",
12 | "screenfull",
13 | "redux-thunk",
14 | "traverse",
15 | "whatwg-fetch"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ReactPatterns",
3 | "version": "4.0.1",
4 | "description": "A collection of simple react projects providing reusable components, startup and test examples.",
5 | "license": "MIT",
6 | "author": {
7 | "name": "J Mark Stevens",
8 | "email": "jmstevens@jmarkstevens.com"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/jmarkstevens/ReactPatterns.git"
13 | },
14 | "bugs": {
15 | "url": "https://github.com/jmarkstevens/ReactPatterns/issues"
16 | },
17 | "keywords": [
18 | "react",
19 | "patterns",
20 | "treeview",
21 | "dropdown",
22 | "buttons",
23 | "form",
24 | "list",
25 | "progressbar",
26 | "range slider",
27 | "slider",
28 | "tooltip",
29 | "reflux",
30 | "websocket",
31 | "electron",
32 | "keycapture",
33 | "drag and drop"
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------