├── .gitignore ├── Procfile ├── README.MD ├── build ├── asset-manifest.json ├── favicon.ico ├── font-awesome │ ├── HELP-US-OUT.txt │ ├── css │ │ ├── font-awesome.css │ │ └── font-awesome.min.css │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── less │ │ ├── animated.less │ │ ├── bordered-pulled.less │ │ ├── core.less │ │ ├── fixed-width.less │ │ ├── font-awesome.less │ │ ├── icons.less │ │ ├── larger.less │ │ ├── list.less │ │ ├── mixins.less │ │ ├── path.less │ │ ├── rotated-flipped.less │ │ ├── screen-reader.less │ │ ├── stacked.less │ │ └── variables.less │ └── scss │ │ ├── _animated.scss │ │ ├── _bordered-pulled.scss │ │ ├── _core.scss │ │ ├── _fixed-width.scss │ │ ├── _icons.scss │ │ ├── _larger.scss │ │ ├── _list.scss │ │ ├── _mixins.scss │ │ ├── _path.scss │ │ ├── _rotated-flipped.scss │ │ ├── _screen-reader.scss │ │ ├── _stacked.scss │ │ ├── _variables.scss │ │ └── font-awesome.scss ├── index.html └── static │ ├── css │ ├── main.048b16d4.css │ └── main.048b16d4.css.map │ ├── js │ ├── main.f685c311.js │ └── main.f685c311.js.map │ └── media │ ├── github-square.df8a65b0.svg │ ├── glyphicons-halflings-regular.448c34a5.woff2 │ ├── glyphicons-halflings-regular.89889688.svg │ ├── glyphicons-halflings-regular.e18bbf61.ttf │ ├── glyphicons-halflings-regular.f4769f9b.eot │ ├── glyphicons-halflings-regular.fa277232.woff │ ├── gridBlueIcon.426cc68f.svg │ ├── gridGrey.8ab09ac7.svg │ ├── gridPurpleIcon.b424db63.svg │ ├── react.5d5d9eef.svg │ ├── reactReduxGrid.fbd0480c.svg │ ├── redux.5ae1af16.svg │ ├── spinner.8c14c79f.gif │ └── tiny_grid.c704d76c.png ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── font-awesome │ ├── HELP-US-OUT.txt │ ├── css │ │ ├── font-awesome.css │ │ └── font-awesome.min.css │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── less │ │ ├── animated.less │ │ ├── bordered-pulled.less │ │ ├── core.less │ │ ├── fixed-width.less │ │ ├── font-awesome.less │ │ ├── icons.less │ │ ├── larger.less │ │ ├── list.less │ │ ├── mixins.less │ │ ├── path.less │ │ ├── rotated-flipped.less │ │ ├── screen-reader.less │ │ ├── stacked.less │ │ └── variables.less │ └── scss │ │ ├── _animated.scss │ │ ├── _bordered-pulled.scss │ │ ├── _core.scss │ │ ├── _fixed-width.scss │ │ ├── _icons.scss │ │ ├── _larger.scss │ │ ├── _list.scss │ │ ├── _mixins.scss │ │ ├── _path.scss │ │ ├── _rotated-flipped.scss │ │ ├── _screen-reader.scss │ │ ├── _stacked.scss │ │ ├── _variables.scss │ │ └── font-awesome.scss └── index.html ├── server ├── api │ ├── functions.js │ ├── routes.js │ └── services.js ├── config │ ├── fakedata.js │ ├── helpers.js │ └── init.js └── server.js └── src ├── App.css ├── App.js ├── App.test.js ├── components ├── examples │ ├── ColRenderer.js │ ├── Editable.js │ ├── ErrorMessage.js │ ├── ExampleGridContainer.css │ ├── ExampleGridContainer.js │ ├── Simple.js │ ├── Sticky.js │ ├── Stress.js │ ├── Tree.js │ ├── bootstrap │ │ ├── Bootstrap.js │ │ ├── README.md │ │ ├── css │ │ │ ├── bootstrap-theme.css │ │ │ ├── bootstrap-theme.css.map │ │ │ ├── bootstrap-theme.min.css │ │ │ ├── bootstrap-theme.min.css.map │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ │ ├── bootstrap.js │ │ │ ├── bootstrap.min.js │ │ │ └── npm.js │ ├── bulk-selection │ │ ├── BulkPager.js │ │ ├── BulkSelection.js │ │ ├── BulkSelection.test.js │ │ └── getBulkSelectionSelectedRows.js │ ├── complex │ │ ├── Complex.js │ │ └── Complex.test.js │ ├── custom-loader │ │ ├── CustomLoader.js │ │ ├── loader.css │ │ └── spinner.gif │ ├── custom-pager │ │ ├── Api.js │ │ ├── CustomPager.js │ │ ├── CustomPager.test.js │ │ └── Pager.js │ └── data │ │ ├── Api.js │ │ ├── demodata.js │ │ ├── provider.js │ │ ├── stressdata.js │ │ └── treedata.json ├── footer │ ├── Footer.css │ ├── Footer.js │ └── gridGrey.svg ├── header │ ├── Header.css │ ├── Header.js │ ├── github-square.svg │ ├── grid.svg │ ├── react.svg │ ├── reactReduxGrid.svg │ ├── redux.svg │ └── tiny_grid │ │ ├── readme.txt │ │ ├── tiny_grid.png │ │ └── tiny_grid_@2X.png ├── instructions │ ├── Instructions.css │ └── Instructions.js └── sidebar │ ├── ExamplesSidebar.js │ ├── FeaturesSidebar.js │ ├── Sidebar.css │ ├── gridBlueIcon.svg │ └── gridPurpleIcon.svg ├── index.css ├── index.js └── redux ├── actions ├── appActions.js └── bulkSelectionActions.js ├── configureStore.js ├── configureStoreForTests.js ├── reducers ├── appReducers.js ├── bulkSelectionReducers.js └── features.js └── types └── types.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | 6 | # testing 7 | coverage 8 | 9 | # misc 10 | .DS_Store 11 | .env 12 | npm-debug.log 13 | yarn.lock 14 | 15 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: npm run prod -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # React-Redux-Grid Examples 2 | 3 | A simple app displaying multiple grids with different features. 4 | 5 | [Examples Website](http://react-redux-grid.herokuapp.com/) 6 | 7 | The relevant (to grid) source code is located in: 8 | 9 | `/src/components/examples` 10 | 11 | ## Getting Started 12 | 13 | ``` 14 | npm install 15 | npm start 16 | ``` 17 | This will launch the examples website at http://localhost:3000 as well as a fake data API service on http://localhost:3001 18 | 19 | ## Contributing 20 | 21 | To begin creating an example, you can also simply copy an example folder and rename it. 22 | 23 | Feel free to install other libraries ( redux-sagas, etc) to demonstrate any new functionality in your example folder. 24 | 25 | When you add a new example, you will need to: 26 | 1. add a new example folder for your demo and provide at least one simple test that it renderers 27 | 2. add the new example data to features.js in redux/reducers 28 | 3. add the new route to index.js 29 | 30 | ## Tests 31 | 32 | We are using [jest](https://facebook.github.io/) & [enzyme](http://airbnb.io/enzyme) to manage our test suite with the goal of testing each example. We could use help here in testing the examples if you would like to contribute. Don't worry if you've never written tests before, this is good example site to learn. 33 | 34 | When you run the tests, they should all be passing. Please file a bug if you see any failing; better yet fix the fail and push an update! 35 | 36 | ``` 37 | npm test 38 | ``` 39 | 40 | ## Website 41 | 42 | We used create-react-app to build the website adding Redux & React-Redux-Grid. 43 | 44 | ``` 45 | create-react-app folderName 46 | cd folderName 47 | npm i redux react-redux react-redux-grid redux-logger --save 48 | ``` 49 | 50 | [shields.io](http://shields.io/) 51 | 52 | ## React-Redux-Grid 53 | 54 | This is examples site but the main library can be found here: 55 | 56 | 🍴[react-redux-grid on Github](https://github.com/bencripps/react-redux-grid) 57 | ⌛[react-redux-grid on NPM](https://www.npmjs.com/package/react-redux-grid) 58 | -------------------------------------------------------------------------------- /build/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "main.css": "static/css/main.048b16d4.css", 3 | "main.css.map": "static/css/main.048b16d4.css.map", 4 | "main.js": "static/js/main.f685c311.js", 5 | "main.js.map": "static/js/main.f685c311.js.map", 6 | "static/media/github-square.svg": "static/media/github-square.df8a65b0.svg", 7 | "static/media/glyphicons-halflings-regular.eot": "static/media/glyphicons-halflings-regular.f4769f9b.eot", 8 | "static/media/glyphicons-halflings-regular.svg": "static/media/glyphicons-halflings-regular.89889688.svg", 9 | "static/media/glyphicons-halflings-regular.ttf": "static/media/glyphicons-halflings-regular.e18bbf61.ttf", 10 | "static/media/glyphicons-halflings-regular.woff": "static/media/glyphicons-halflings-regular.fa277232.woff", 11 | "static/media/glyphicons-halflings-regular.woff2": "static/media/glyphicons-halflings-regular.448c34a5.woff2", 12 | "static/media/gridBlueIcon.svg": "static/media/gridBlueIcon.426cc68f.svg", 13 | "static/media/gridGrey.svg": "static/media/gridGrey.8ab09ac7.svg", 14 | "static/media/gridPurpleIcon.svg": "static/media/gridPurpleIcon.b424db63.svg", 15 | "static/media/react.svg": "static/media/react.5d5d9eef.svg", 16 | "static/media/reactReduxGrid.svg": "static/media/reactReduxGrid.fbd0480c.svg", 17 | "static/media/redux.svg": "static/media/redux.5ae1af16.svg", 18 | "static/media/spinner.gif": "static/media/spinner.8c14c79f.gif", 19 | "static/media/tiny_grid.png": "static/media/tiny_grid.c704d76c.png" 20 | } -------------------------------------------------------------------------------- /build/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/favicon.ico -------------------------------------------------------------------------------- /build/font-awesome/HELP-US-OUT.txt: -------------------------------------------------------------------------------- 1 | I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project, 2 | Fort Awesome (https://fortawesome.com). It makes it easy to put the perfect icons on your website. Choose from our awesome, 3 | comprehensive icon sets or copy and paste your own. 4 | 5 | Please. Check it out. 6 | 7 | -Dave Gandy 8 | -------------------------------------------------------------------------------- /build/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /build/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /build/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /build/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /build/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /build/font-awesome/less/animated.less: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .@{fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /build/font-awesome/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .@{fa-css-prefix}-pull-left { float: left; } 11 | .@{fa-css-prefix}-pull-right { float: right; } 12 | 13 | .@{fa-css-prefix} { 14 | &.@{fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.@{fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .@{fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /build/font-awesome/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /build/font-awesome/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /build/font-awesome/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "animated.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | @import "screen-reader.less"; 19 | -------------------------------------------------------------------------------- /build/font-awesome/less/larger.less: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .@{fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .@{fa-css-prefix}-2x { font-size: 2em; } 11 | .@{fa-css-prefix}-3x { font-size: 3em; } 12 | .@{fa-css-prefix}-4x { font-size: 4em; } 13 | .@{fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /build/font-awesome/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /build/font-awesome/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | .fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | .fa-icon-rotate(@degrees, @rotation) { 15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})"; 16 | -webkit-transform: rotate(@degrees); 17 | -ms-transform: rotate(@degrees); 18 | transform: rotate(@degrees); 19 | } 20 | 21 | .fa-icon-flip(@horiz, @vert, @rotation) { 22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation}, mirror=1)"; 23 | -webkit-transform: scale(@horiz, @vert); 24 | -ms-transform: scale(@horiz, @vert); 25 | transform: scale(@horiz, @vert); 26 | } 27 | 28 | 29 | // Only display content to screen readers. A la Bootstrap 4. 30 | // 31 | // See: http://a11yproject.com/posts/how-to-hide-content/ 32 | 33 | .sr-only() { 34 | position: absolute; 35 | width: 1px; 36 | height: 1px; 37 | padding: 0; 38 | margin: -1px; 39 | overflow: hidden; 40 | clip: rect(0,0,0,0); 41 | border: 0; 42 | } 43 | 44 | // Use in conjunction with .sr-only to only display content when it's focused. 45 | // 46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 47 | // 48 | // Credit: HTML5 Boilerplate 49 | 50 | .sr-only-focusable() { 51 | &:active, 52 | &:focus { 53 | position: static; 54 | width: auto; 55 | height: auto; 56 | margin: 0; 57 | overflow: visible; 58 | clip: auto; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /build/font-awesome/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /build/font-awesome/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /build/font-awesome/less/screen-reader.less: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { .sr-only(); } 5 | .sr-only-focusable { .sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /build/font-awesome/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /build/font-awesome/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /build/font-awesome/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .#{$fa-css-prefix}-pull-left { float: left; } 11 | .#{$fa-css-prefix}-pull-right { float: right; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .#{$fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /build/font-awesome/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /build/font-awesome/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /build/font-awesome/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /build/font-awesome/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /build/font-awesome/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | @mixin fa-icon-rotate($degrees, $rotation) { 15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})"; 16 | -webkit-transform: rotate($degrees); 17 | -ms-transform: rotate($degrees); 18 | transform: rotate($degrees); 19 | } 20 | 21 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)"; 23 | -webkit-transform: scale($horiz, $vert); 24 | -ms-transform: scale($horiz, $vert); 25 | transform: scale($horiz, $vert); 26 | } 27 | 28 | 29 | // Only display content to screen readers. A la Bootstrap 4. 30 | // 31 | // See: http://a11yproject.com/posts/how-to-hide-content/ 32 | 33 | @mixin sr-only { 34 | position: absolute; 35 | width: 1px; 36 | height: 1px; 37 | padding: 0; 38 | margin: -1px; 39 | overflow: hidden; 40 | clip: rect(0,0,0,0); 41 | border: 0; 42 | } 43 | 44 | // Use in conjunction with .sr-only to only display content when it's focused. 45 | // 46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 47 | // 48 | // Credit: HTML5 Boilerplate 49 | 50 | @mixin sr-only-focusable { 51 | &:active, 52 | &:focus { 53 | position: static; 54 | width: auto; 55 | height: auto; 56 | margin: 0; 57 | overflow: visible; 58 | clip: auto; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /build/font-awesome/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /build/font-awesome/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /build/font-awesome/scss/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { @include sr-only(); } 5 | .sr-only-focusable { @include sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /build/font-awesome/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /build/font-awesome/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | @import "screen-reader"; 19 | -------------------------------------------------------------------------------- /build/index.html: -------------------------------------------------------------------------------- 1 | React App
-------------------------------------------------------------------------------- /build/static/css/main.048b16d4.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"static/css/main.048b16d4.css","sourceRoot":""} -------------------------------------------------------------------------------- /build/static/media/github-square.df8a65b0.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /build/static/media/glyphicons-halflings-regular.448c34a5.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/static/media/glyphicons-halflings-regular.448c34a5.woff2 -------------------------------------------------------------------------------- /build/static/media/glyphicons-halflings-regular.e18bbf61.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/static/media/glyphicons-halflings-regular.e18bbf61.ttf -------------------------------------------------------------------------------- /build/static/media/glyphicons-halflings-regular.f4769f9b.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/static/media/glyphicons-halflings-regular.f4769f9b.eot -------------------------------------------------------------------------------- /build/static/media/glyphicons-halflings-regular.fa277232.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/static/media/glyphicons-halflings-regular.fa277232.woff -------------------------------------------------------------------------------- /build/static/media/gridBlueIcon.426cc68f.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /build/static/media/gridGrey.8ab09ac7.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /build/static/media/gridPurpleIcon.b424db63.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /build/static/media/react.5d5d9eef.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /build/static/media/reactReduxGrid.fbd0480c.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 37 | 38 | 39 | 40 | 50 | 51 | 52 | 53 | 56 | 57 | 62 | 63 | 66 | 67 | 68 | 69 | 72 | 73 | 74 | 75 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /build/static/media/redux.5ae1af16.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /build/static/media/spinner.8c14c79f.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/static/media/spinner.8c14c79f.gif -------------------------------------------------------------------------------- /build/static/media/tiny_grid.c704d76c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/build/static/media/tiny_grid.c704d76c.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "version": "0.1.0", 4 | "private": true, 5 | "devDependencies": { 6 | "enzyme": "^2.7.1", 7 | "faker": "^3.1.0", 8 | "gh-pages": "^0.12.0", 9 | "react-addons-test-utils": "^15.4.2", 10 | "react-scripts": "0.8.5", 11 | "redux-logger": "^2.7.4" 12 | }, 13 | "dependencies": { 14 | "body-parser": "^1.16.0", 15 | "concurrently": "^3.1.0", 16 | "express": "^4.14.0", 17 | "immutable": "^3.8.1", 18 | "isomorphic-fetch": "^2.2.1", 19 | "react": "^15.4.2", 20 | "react-dom": "^15.4.2", 21 | "react-redux": "^5.0.2", 22 | "react-redux-grid": "^5.5.2", 23 | "react-router": "^3.0.1", 24 | "react-router-redux": "^4.0.7", 25 | "redux": "^3.6.0", 26 | "redux-router": "^2.1.2", 27 | "redux-thunk": "^2.2.0", 28 | "serve-favicon": "^2.3.2" 29 | }, 30 | "scripts": { 31 | "start": "concurrently --kill-others \"npm run api\" \"react-scripts start\" ", 32 | "prod": "npm run api", 33 | "build": "react-scripts build", 34 | "test": "react-scripts test --env=jsdom", 35 | "eject": "react-scripts eject", 36 | "api": "node ./server/server", 37 | "deploy": "npm run build&&gh-pages -d build" 38 | }, 39 | "engines": { 40 | "node": "6.6.0", 41 | "npm": "3.10.8" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/public/favicon.ico -------------------------------------------------------------------------------- /public/font-awesome/HELP-US-OUT.txt: -------------------------------------------------------------------------------- 1 | I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project, 2 | Fort Awesome (https://fortawesome.com). It makes it easy to put the perfect icons on your website. Choose from our awesome, 3 | comprehensive icon sets or copy and paste your own. 4 | 5 | Please. Check it out. 6 | 7 | -Dave Gandy 8 | -------------------------------------------------------------------------------- /public/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/public/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /public/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/public/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /public/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/public/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /public/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/public/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /public/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/public/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /public/font-awesome/less/animated.less: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .@{fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /public/font-awesome/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .@{fa-css-prefix}-pull-left { float: left; } 11 | .@{fa-css-prefix}-pull-right { float: right; } 12 | 13 | .@{fa-css-prefix} { 14 | &.@{fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.@{fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .@{fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /public/font-awesome/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /public/font-awesome/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /public/font-awesome/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "animated.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | @import "screen-reader.less"; 19 | -------------------------------------------------------------------------------- /public/font-awesome/less/larger.less: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .@{fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .@{fa-css-prefix}-2x { font-size: 2em; } 11 | .@{fa-css-prefix}-3x { font-size: 3em; } 12 | .@{fa-css-prefix}-4x { font-size: 4em; } 13 | .@{fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /public/font-awesome/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /public/font-awesome/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | .fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | .fa-icon-rotate(@degrees, @rotation) { 15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})"; 16 | -webkit-transform: rotate(@degrees); 17 | -ms-transform: rotate(@degrees); 18 | transform: rotate(@degrees); 19 | } 20 | 21 | .fa-icon-flip(@horiz, @vert, @rotation) { 22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation}, mirror=1)"; 23 | -webkit-transform: scale(@horiz, @vert); 24 | -ms-transform: scale(@horiz, @vert); 25 | transform: scale(@horiz, @vert); 26 | } 27 | 28 | 29 | // Only display content to screen readers. A la Bootstrap 4. 30 | // 31 | // See: http://a11yproject.com/posts/how-to-hide-content/ 32 | 33 | .sr-only() { 34 | position: absolute; 35 | width: 1px; 36 | height: 1px; 37 | padding: 0; 38 | margin: -1px; 39 | overflow: hidden; 40 | clip: rect(0,0,0,0); 41 | border: 0; 42 | } 43 | 44 | // Use in conjunction with .sr-only to only display content when it's focused. 45 | // 46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 47 | // 48 | // Credit: HTML5 Boilerplate 49 | 50 | .sr-only-focusable() { 51 | &:active, 52 | &:focus { 53 | position: static; 54 | width: auto; 55 | height: auto; 56 | margin: 0; 57 | overflow: visible; 58 | clip: auto; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /public/font-awesome/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /public/font-awesome/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /public/font-awesome/less/screen-reader.less: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { .sr-only(); } 5 | .sr-only-focusable { .sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /public/font-awesome/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /public/font-awesome/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /public/font-awesome/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .#{$fa-css-prefix}-pull-left { float: left; } 11 | .#{$fa-css-prefix}-pull-right { float: right; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .#{$fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /public/font-awesome/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /public/font-awesome/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /public/font-awesome/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /public/font-awesome/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /public/font-awesome/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | @mixin fa-icon-rotate($degrees, $rotation) { 15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})"; 16 | -webkit-transform: rotate($degrees); 17 | -ms-transform: rotate($degrees); 18 | transform: rotate($degrees); 19 | } 20 | 21 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)"; 23 | -webkit-transform: scale($horiz, $vert); 24 | -ms-transform: scale($horiz, $vert); 25 | transform: scale($horiz, $vert); 26 | } 27 | 28 | 29 | // Only display content to screen readers. A la Bootstrap 4. 30 | // 31 | // See: http://a11yproject.com/posts/how-to-hide-content/ 32 | 33 | @mixin sr-only { 34 | position: absolute; 35 | width: 1px; 36 | height: 1px; 37 | padding: 0; 38 | margin: -1px; 39 | overflow: hidden; 40 | clip: rect(0,0,0,0); 41 | border: 0; 42 | } 43 | 44 | // Use in conjunction with .sr-only to only display content when it's focused. 45 | // 46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 47 | // 48 | // Credit: HTML5 Boilerplate 49 | 50 | @mixin sr-only-focusable { 51 | &:active, 52 | &:focus { 53 | position: static; 54 | width: auto; 55 | height: auto; 56 | margin: 0; 57 | overflow: visible; 58 | clip: auto; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /public/font-awesome/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /public/font-awesome/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /public/font-awesome/scss/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { @include sr-only(); } 5 | .sr-only-focusable { @include sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /public/font-awesome/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /public/font-awesome/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | @import "screen-reader"; 19 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 20 | React App 21 | 22 | 23 |
24 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /server/api/functions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const dataObj = require('../config/fakedata'); 4 | const url = require('url'); 5 | const path = require('path'); 6 | 7 | module.exports = class Functions { 8 | constructor() { 9 | 10 | } 11 | 12 | idx(vars, req, res) { 13 | res.render(vars.routeName, this.app.helper.template({env: this.env, vars: vars})); 14 | } 15 | 16 | main(vars, req, res) { 17 | res.sendFile(path.join(__dirname, './../../build', 'index.html')); 18 | } 19 | 20 | getFakeData(vars, req, res) { 21 | const reqURL = url.parse(req.url, true); 22 | const json = reqURL.query; 23 | 24 | res.setHeader('Access-Control-Allow-Origin', '*'); 25 | 26 | const pageIndex = Number(json.pageIndex !== undefined ? json.pageIndex : 0); 27 | const pageSize = Number(json.pageSize || 20); 28 | 29 | const total = dataObj.data.length; 30 | const pages = dataObj.data.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize); 31 | 32 | res.json({ 33 | data: pages, 34 | total: total 35 | }); 36 | } 37 | 38 | getFakedPagedDataForBootstrap(vars, req, res) { 39 | const reqURL = url.parse(req.url, true); 40 | const json = reqURL.query; 41 | 42 | res.setHeader('Access-Control-Allow-Origin', '*'); 43 | 44 | const pageIndex = Number(json.pageIndex !== undefined ? json.pageIndex : 0); 45 | const pageSize = Number(json.pageSize || 20); 46 | 47 | const rows = dataObj.data.slice(1); 48 | 49 | const total = rows.length; 50 | const pages = rows.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize); 51 | 52 | res.json({ 53 | data: pages, 54 | total: total 55 | }); 56 | } 57 | 58 | 59 | 60 | getPrefetchData(vars, req, res) { 61 | const reqURL = url.parse(req.url, true); 62 | const json = reqURL.query; 63 | 64 | const pageIndex = json.pageIndex !== undefined ? json.pageIndex : 0; 65 | const pageSize = json.pageSize || 25; 66 | const total = dataObj.data.length; 67 | const pages = dataObj.data.slice(pageIndex * (pageSize * 2), ((pageIndex) + 1) * (pageSize * 2)); 68 | 69 | res.setHeader('Access-Control-Allow-Origin', '*'); 70 | 71 | res.json({ 72 | data: pages, 73 | total: total 74 | }); 75 | } 76 | 77 | getTreeData(vars, req, res) { 78 | 79 | const reqURL = url.parse(req.url, true); 80 | const json = reqURL.query; 81 | 82 | res.setHeader('Access-Control-Allow-Origin', '*'); 83 | 84 | if (json && json.parentId) { 85 | res.json({ 86 | partial: true, 87 | data: [ 88 | { 89 | id: 211, 90 | parentId: 21, 91 | Name: 'Category 211', 92 | GUID: '8f7q2dc-facf-91865', 93 | Email: 'hehehe@ed.gov', 94 | Gender: 'Male', 95 | Address: '21112 Park', 96 | 'Phone Number': '31-(678)495-4134' 97 | }, 98 | { 99 | id: 212, 100 | parentId: 21, 101 | Name: 'Category 212', 102 | GUID: 'q2dc-facf-527fcsw-jdjd991865', 103 | Email: 'hehehe@ed.gov', 104 | Gender: 'Male', 105 | Address: '21112 Park', 106 | 'Phone Number': '31-(678)495-4134', 107 | children: [ 108 | { 109 | id: 2121, 110 | parentId: 212, 111 | Name: 'Category 2121', 112 | GUID: 'q2dc-facf-527fcsw-sss865', 113 | Email: 'hehehe@ed.gov', 114 | Gender: 'Male', 115 | Address: '21112 Park', 116 | 'Phone Number': '31-(678)495-4134' 117 | } 118 | ] 119 | } 120 | ] 121 | }); 122 | } 123 | 124 | else { 125 | res.json({ 126 | data: dataObj.treeData 127 | }); 128 | } 129 | 130 | } 131 | 132 | getFakeDataPaged(vars, req, res) { 133 | const json = JSON.parse(Object.keys(req.body)[0]); 134 | const pageIndex = json.pageIndex; 135 | const pageSize = json.pageSize; 136 | const total = dataObj.data.length; 137 | const pages = dataObj.data.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize); 138 | 139 | res.setHeader('Access-Control-Allow-Origin', '*'); 140 | res.json({ 141 | data: pages, 142 | total: total 143 | }); 144 | } 145 | 146 | }; -------------------------------------------------------------------------------- /server/api/routes.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: ben_cripps 3 | * @Date: 2015-05-18 20:58:33 4 | * @Last Modified by: ben_cripps 5 | * @Last Modified time: 2017-01-25 09:24:37 6 | */ 7 | 8 | const Functions = require('./functions'); 9 | 10 | const funcs = new Functions(); 11 | module.exports = [ 12 | { 13 | uri: '/getFakeData', 14 | method: 'get', 15 | func: funcs.getFakeData, 16 | vars: {} 17 | }, 18 | { 19 | uri: '/getFakedPagedDataForBootstrap', 20 | method: 'get', 21 | func: funcs.getFakedPagedDataForBootstrap, 22 | vars: {} 23 | }, 24 | { 25 | uri: '/getFakedPagedData', 26 | method: 'post', 27 | func: funcs.getFakeDataPaged, 28 | vars: {} 29 | }, 30 | { 31 | uri: '/getTreeData', 32 | method: 'get', 33 | func: funcs.getTreeData, 34 | vars: {} 35 | }, 36 | { 37 | uri: '/getPrefetchData', 38 | method: 'get', 39 | func: funcs.getPrefetchData, 40 | vars: {} 41 | }, 42 | { 43 | uri: '/', 44 | method: 'get', 45 | func: funcs.main, 46 | vars: {} 47 | }, 48 | { 49 | uri: '*', 50 | method: 'get', 51 | func: funcs.main, 52 | vars: {} 53 | } 54 | ]; -------------------------------------------------------------------------------- /server/api/services.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: ben_cripps 3 | * @Date: 2015-05-18 20:33:19 4 | * @Last Modified by: ben_cripps 5 | * @Last Modified time: 2016-05-31 20:42:41 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const routes = require('./routes'); 11 | 12 | module.exports = class Api { 13 | constructor(app) { 14 | this.app = app.server; 15 | this.env = app.env; 16 | this.initRoutes(); 17 | } 18 | initRoutes() { 19 | routes.forEach((route) => this.app[route.method](route.uri, route.func.bind(this, route.vars)), this); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /server/config/helpers.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: ben_cripps 3 | * @Date: 2015-05-22 14:29:47 4 | * @Last Modified by: ben_cripps 5 | * @Last Modified time: 2016-08-07 08:01:21 6 | */ 7 | 'use strict'; 8 | 9 | module.exports = class Helper { 10 | constructor() { 11 | this.template = this.templateFunc; 12 | } 13 | templateFunc(obj) { 14 | 15 | let base = { 16 | baseDir: '', 17 | routes: [ 18 | { 19 | name: 'home', 20 | uri: '/' 21 | }, 22 | { 23 | name: 'about', 24 | uri: '/about' 25 | }, 26 | { 27 | name: 'blogs', 28 | uri: '/blog' 29 | }, 30 | { 31 | name: 'projects', 32 | uri: '/projects' 33 | } 34 | ] 35 | }; 36 | 37 | Object.keys(obj).map((k) => { 38 | if (k === 'vars') { 39 | Object.keys(obj[k]).forEach((internalK) => { 40 | base[internalK] = obj[k][internalK]; 41 | }); 42 | } 43 | else { 44 | base[k] = obj[k]; 45 | } 46 | }); 47 | 48 | return base; 49 | 50 | } 51 | } -------------------------------------------------------------------------------- /server/config/init.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: ben_cripps 3 | * @Date: 2015-05-18 19:34:42 4 | * @Last Modified by: ben_cripps 5 | * @Last Modified time: 2017-01-25 09:39:34 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const path = require('path'); 11 | const Helper = require('./helpers.js'); 12 | 13 | module.exports = class App { 14 | 15 | constructor(args) { 16 | this.env = args.length === 3 && args[2] === 'dev' ? args[2] : 'min'; 17 | this.server = this.init( 18 | require('express'), 19 | require('body-parser'), 20 | require('serve-favicon') 21 | ); 22 | } 23 | 24 | init(express, bodyParser, favicon) { 25 | 26 | const app = express() 27 | .set('port', process.env.PORT || 3001) 28 | .set('views', path.join(__dirname, '/../views')) 29 | .set('view engine', 'jade') 30 | .use(express.static('build')) 31 | .use(bodyParser.json()) 32 | .use(bodyParser.urlencoded({extended: true})); 33 | 34 | app.helper = new Helper(); 35 | 36 | return app; 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /server/server.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: ben_cripps 3 | * @Date: 2014-12-01 10:10:44 4 | * @Last Modified by: ben_cripps 5 | * @Last Modified time: 2016-05-31 20:38:50 6 | */ 7 | 8 | const App = require('./config/init'); 9 | const Api = require('./api/services'); 10 | 11 | const app = new App(process.argv); 12 | const api = new Api(app); 13 | 14 | app.server.listen(app.server.get('port'), () => { 15 | console.log('The API is running in ' + 16 | (app.env === 'dev' ? app.env : 'prod') + 17 | ' mode, on port ' + app.server.get('port')); 18 | }); 19 | 20 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .app { 2 | display: block; 3 | position: relative; 4 | } 5 | 6 | .split { 7 | display: flex; 8 | flex-direction: row; 9 | justify-content: flex-start; 10 | margin-left: 10px; 11 | margin-right: 10px; 12 | } 13 | 14 | .purpleHilite { 15 | color: #663399; 16 | } 17 | 18 | .tableContainer { 19 | display: block; 20 | position: relative; 21 | } 22 | 23 | ul { 24 | list-style-type: none; 25 | margin: 0px; 26 | margin-left: 0px; 27 | padding: 0px; 28 | padding-left: 5px; 29 | } 30 | 31 | li { 32 | margin: 0px; 33 | padding: 0px; 34 | } 35 | 36 | .react-redux-grid-active, .react-redux-grid-inactive { 37 | margin: 5px; 38 | border-radius: 5px; 39 | background-color: #49b8dc; 40 | } 41 | 42 | .react-redux-grid-active { 43 | color: white; 44 | background-color: #644581; 45 | } 46 | 47 | .gridH2 { 48 | font-family: 'Bree Serif', serif; 49 | font-size: 18px; 50 | color: #49b8dc; 51 | font-weight: normal; 52 | margin: 0px; 53 | margin-bottom: 10px; 54 | padding: 0px; 55 | margin-top: 10px; 56 | } 57 | 58 | 59 | 60 | :focus { 61 | border: none; 62 | outline: none; 63 | }; 64 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Header from './components/header/Header'; 3 | import ExamplesSidebar from './components/sidebar/ExamplesSidebar'; 4 | import FeaturesSidebar from './components/sidebar/FeaturesSidebar'; 5 | import Footer from './components/footer/Footer'; 6 | import './App.css'; 7 | 8 | class App extends Component { 9 | 10 | render() { 11 | return ( 12 |
13 |
14 |
15 |
16 | 17 | 18 |
19 |
20 | {this.props.children} 21 |
22 | 23 |
24 |
26 | ); 27 | } 28 | 29 | componentDidMount() { 30 | document.title = 'React-Redux-Grid'; 31 | } 32 | } 33 | 34 | export default App; 35 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import { Provider } from 'react-redux'; 5 | import store from './redux/configureStoreForTests'; 6 | 7 | describe('', () => { 8 | it('renders without crashing', () => { 9 | const div = document.createElement('div'); 10 | 11 | ReactDOM.render( 12 | 13 | 14 | , 15 | div 16 | ); 17 | }) 18 | }); 19 | -------------------------------------------------------------------------------- /src/components/examples/ColRenderer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { PropTypes } from 'react'; 3 | import { Grid } from 'react-redux-grid'; 4 | 5 | import { 6 | data, 7 | pageSize, 8 | events, 9 | dataSource 10 | } from './data/demodata'; 11 | 12 | export const ColRenderer = ({ store }) => { 13 | 14 | const cols = [{ 15 | name: 'Phone', 16 | dataIndex: 'phone number', 17 | renderer: (ob) => { 18 | 19 | const imgProps = { 20 | src: '//icons.iconarchive.com/icons/icons8/windows-8/512/Mobile-Phone-icon.png', 21 | style: { 22 | height: '20px' 23 | } 24 | }; 25 | 26 | const spanProps = { 27 | style: { 28 | position: 'relative', 29 | top: '-5px', 30 | left: '10px' 31 | } 32 | }; 33 | 34 | return ( 35 | 36 | 37 | 38 | { ob.row['Phone Number'] } 39 | 40 | 41 | ); 42 | } 43 | }]; 44 | 45 | const colData = { 46 | columns: cols, 47 | data, 48 | pageSize, 49 | plugins: {}, 50 | events, 51 | dataSource, 52 | store, 53 | stateKey: 'colRenderer' 54 | }; 55 | 56 | return ( 57 | 58 | ); 59 | }; 60 | 61 | const { object } = PropTypes; 62 | 63 | ColRenderer.propTypes = { 64 | store: object.isRequired 65 | }; 66 | 67 | ColRenderer.defaultProps = {}; 68 | 69 | export default ColRenderer; -------------------------------------------------------------------------------- /src/components/examples/Editable.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { Component, PropTypes } from 'react'; 3 | import { Grid } from 'react-redux-grid'; 4 | 5 | import { 6 | columns, 7 | data, 8 | pageSize, 9 | events, 10 | dataSource 11 | } from './data/demodata'; 12 | 13 | export class Editable extends Component { 14 | 15 | render() { 16 | 17 | const { store } = this.props; 18 | const { on } = this.state; 19 | 20 | const editableProps = { 21 | columns, 22 | data: on ? [] : data, 23 | pageSize, 24 | plugins: { 25 | EDITOR: { 26 | enabled: true, 27 | type: 'grid' 28 | } 29 | }, 30 | events, 31 | store, 32 | stateKey: 'editable' 33 | }; 34 | 35 | return ; 36 | } 37 | 38 | constructor(props) { 39 | super(props); 40 | this.state = {}; 41 | } 42 | 43 | handleClick = () => { 44 | const { on } = this.state; 45 | this.setState({ on: !on }); 46 | } 47 | } 48 | 49 | const { object } = PropTypes; 50 | 51 | Editable.propTypes = { 52 | store: object.isRequired 53 | }; 54 | 55 | Editable.defaultProps = {}; 56 | 57 | export default Editable; -------------------------------------------------------------------------------- /src/components/examples/ErrorMessage.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { Component, PropTypes } from 'react'; 3 | import { Grid, Actions } from 'react-redux-grid'; 4 | 5 | import { 6 | columns, 7 | data, 8 | pageSize, 9 | events, 10 | dataSource 11 | } from './data/demodata'; 12 | 13 | export class ErrorMessage extends Component { 14 | componentDidMount() { 15 | const { store } = this.props; 16 | 17 | store.dispatch( 18 | Actions.ErrorHandlerActions.setError({ 19 | stateKey: 'error', 20 | error: 'An error occurred!' 21 | }) 22 | ); 23 | } 24 | 25 | render() { 26 | const errorData = { 27 | columns, 28 | data: [], 29 | pageSize, 30 | plugins: { 31 | ERROR_HANDLER: { 32 | defaultErrorMessage: 'AN ERROR OCURRED', 33 | enabled: true 34 | } 35 | }, 36 | events, 37 | store: this.props.store, 38 | stateKey: 'error' 39 | }; 40 | 41 | return ( 42 | 43 | ); 44 | } 45 | }; 46 | 47 | const { object } = PropTypes; 48 | 49 | ErrorMessage.propTypes = { 50 | store: object.isRequired 51 | }; 52 | 53 | ErrorMessage.defaultProps = {}; 54 | 55 | export default ErrorMessage; -------------------------------------------------------------------------------- /src/components/examples/ExampleGridContainer.css: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | .simpleContainer { 3 | display: block; 4 | position: relative; 5 | padding-left: 10px; 6 | padding-right: 10px; 7 | width: auto; 8 | } 9 | 10 | /* override React-Redux-Grid library */ 11 | .react-grid-pager-toolbar { 12 | height: 40px !important; 13 | padding: 5px !important; 14 | 15 | } 16 | 17 | .react-grid-header-fixed-container th { 18 | padding-left: 10px !important; 19 | background: transparent !important; 20 | overflow: visible !important; 21 | } 22 | 23 | .react-grid-pager-toolbar span { 24 | font-size: 12px !important; 25 | color: #666; 26 | } 27 | 28 | /* override Bootstrap library */ 29 | .bootstrap-description { 30 | height: 30px !important; 31 | margin: 5px !important; 32 | } 33 | 34 | .bootstrap-description span { 35 | font-size: 12px !important; 36 | color: #666; 37 | } 38 | 39 | .bootstrap-description button { 40 | margin-right: 10px; 41 | } 42 | 43 | .table-responsive thead { 44 | display: none !important; 45 | } 46 | 47 | input[type="text"] { 48 | color: #000; 49 | height: 20px; 50 | border-radius: 5px; 51 | border-width: 0px; 52 | width: 100%; 53 | padding-left: 5px; 54 | background-color: #f9f9f9; 55 | } 56 | 57 | .react-grid-edit { 58 | background-color: #e4e4e4 !important; 59 | } 60 | 61 | .react-grid-button-container { 62 | background-color: #e4e4e4 !important; 63 | padding: 5px !important; 64 | } 65 | 66 | .react-grid-cancel-button { 67 | margin-right: 5px; 68 | font-size: 12px; 69 | font-weight: bold; 70 | } 71 | 72 | .react-grid-save-button { 73 | font-size: 12px; 74 | font-weight: bold; 75 | background-color: #663399 !important; 76 | } 77 | 78 | .react-grid-sort-handle { 79 | cursor: pointer; 80 | width: 20px; 81 | height: 20px; 82 | padding-left: 5px; 83 | } 84 | 85 | th { 86 | cursor: pointer; 87 | font-size: 12px; 88 | font-weight: bold; 89 | font-family: 'Open Sans', sans-serif; 90 | } 91 | 92 | button.react-redux-grid-active, button.react-redux-grid-inactive { 93 | border: none !important; 94 | } 95 | -------------------------------------------------------------------------------- /src/components/examples/ExampleGridContainer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { Component } from 'react'; 3 | import './ExampleGridContainer.css'; 4 | import { connect } from 'react-redux'; 5 | import store from './../../redux/configureStore'; 6 | import Simple from './Simple'; 7 | import Complex from './complex/Complex'; 8 | import Sticky from './Sticky'; 9 | import Stress from './Stress'; 10 | import ColRenderer from './ColRenderer'; 11 | import Tree from './Tree'; 12 | import Bootstrap from './bootstrap/Bootstrap'; 13 | import Editable from './Editable'; 14 | import CustomPager from './custom-pager/CustomPager'; 15 | import ErrorMessage from './ErrorMessage'; 16 | import BulkSelection from './bulk-selection/BulkSelection'; 17 | import * as _ from "lodash"; 18 | import CustomLoader from './custom-loader/CustomLoader'; 19 | import getBulkSelectionSelectedRows from './bulk-selection/getBulkSelectionSelectedRows'; 20 | 21 | 22 | class ExampleGridContainer extends Component { 23 | 24 | componentWillReceiveProps(nextProps, nextState){ 25 | this.props = nextProps; 26 | } 27 | 28 | shouldComponentUpdate(){ 29 | return true; 30 | } 31 | 32 | render() { 33 | 34 | const title = this.props.app.featureTitle; 35 | 36 | const getGrid = (title) => { 37 | switch(title) { 38 | case "BulkSelection" : 39 | return (); 40 | case "Bootstrap" : 41 | return (); 42 | case "ColRenderer" : 43 | return (); 44 | case "Tree" : 45 | return (); 46 | case "Stress" : 47 | return (); 48 | case "Sticky" : 49 | return (); 50 | case "Editable" : 51 | return (); 52 | case "Complex" : 53 | return (); 54 | case "CustomPager" : 55 | return (); 56 | case "CustomLoader" : 57 | return (); 58 | case "ErrorMessage" : 59 | return (); 60 | case "Simple" : 61 | default : 62 | return (); 63 | } 64 | } 65 | 66 | return ( 67 |
68 |

{this.props.app.featureTitle}

69 | { getBulkSelectionSelectedRows(this.props) } 70 | { getGrid(title) } 71 |
72 | ); 73 | } 74 | } 75 | 76 | const mapStateToProps = (state) => ({ 77 | faker: state.faker, 78 | grid: state.grid, 79 | app: state.app, 80 | bulkSelection: state.bulkSelection, 81 | selection: state.selection 82 | }); 83 | 84 | const mapDispatchToProps = (dispatch) => { 85 | return { 86 | dispatch 87 | } 88 | }; 89 | export default connect(mapStateToProps, mapDispatchToProps)(ExampleGridContainer); -------------------------------------------------------------------------------- /src/components/examples/Simple.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { PropTypes } from 'react'; 3 | import { Grid } from 'react-redux-grid'; 4 | 5 | import { 6 | columns, 7 | data, 8 | pageSize, 9 | events, 10 | dataSource 11 | } from './data/demodata'; 12 | 13 | export const Simple = ({ store }) => { 14 | 15 | const simpleData = { 16 | columns, 17 | data, 18 | pageSize, 19 | plugins: {}, 20 | events, 21 | store, 22 | stateKey: 'simple' 23 | }; 24 | 25 | return ( 26 | 27 | ); 28 | }; 29 | 30 | const { object } = PropTypes; 31 | 32 | Simple.propTypes = { 33 | store: object.isRequired 34 | }; 35 | 36 | Simple.defaultProps = {}; 37 | 38 | export default Simple; -------------------------------------------------------------------------------- /src/components/examples/Sticky.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { PropTypes } from 'react'; 3 | import { Grid } from 'react-redux-grid'; 4 | 5 | import { 6 | columns, 7 | data, 8 | pageSize, 9 | events, 10 | plugins 11 | } from './data/demodata'; 12 | 13 | export const Sticky = ({ store }) => { 14 | 15 | const stickyData = { 16 | columns, 17 | data, 18 | pageSize, 19 | plugins: { 20 | ...plugins, 21 | STICKY_HEADER: { 22 | enabled: true 23 | }, 24 | STICKY_FOOTER: { 25 | enabled: true 26 | }, 27 | FILTER_CONTAINER: { 28 | enabled: false 29 | }, 30 | BULK_ACTIONS: { 31 | enabled: false 32 | } 33 | }, 34 | height: '', 35 | events, 36 | store, 37 | stateKey: 'sticky' 38 | }; 39 | 40 | return ( 41 | 42 | ); 43 | }; 44 | 45 | const { object } = PropTypes; 46 | 47 | Sticky.propTypes = { 48 | store: object.isRequired 49 | }; 50 | 51 | Sticky.defaultProps = {}; 52 | 53 | export default Sticky; -------------------------------------------------------------------------------- /src/components/examples/Stress.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { PropTypes } from 'react'; 3 | import { Grid } from 'react-redux-grid'; 4 | 5 | import { 6 | stressData 7 | } from './data/demodata'; 8 | 9 | export const Stress = ({ store }) => { 10 | 11 | const stateKey = 'stress'; 12 | 13 | const stressProps = { 14 | columns: [ 15 | { 16 | name: 'Name', 17 | width: '10%', 18 | className: 'additional-class', 19 | dataIndex: 'Name', 20 | sortable: false 21 | }, 22 | { 23 | name: 'Phone Number', 24 | width: '20%', 25 | dataIndex: 'Phone Number', 26 | sortable: false 27 | }, 28 | { 29 | name: 'Email', 30 | width: '25%', 31 | dataIndex: 'Email', 32 | sortable: false 33 | }, 34 | { 35 | name: 'Address', 36 | dataIndex: 'Address', 37 | sortable: false 38 | } 39 | ], 40 | data: stressData, 41 | pageSize: stressData.length, 42 | infinite: true, 43 | plugins: { 44 | PAGER: { 45 | enabled: false 46 | } 47 | }, 48 | events: {}, 49 | store, 50 | stateKey 51 | }; 52 | 53 | return ( 54 | 55 | ); 56 | }; 57 | 58 | const { object } = PropTypes; 59 | 60 | Stress.propTypes = { 61 | store: object.isRequired 62 | }; 63 | 64 | Stress.defaultProps = {}; 65 | 66 | export default Stress; -------------------------------------------------------------------------------- /src/components/examples/Tree.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { PropTypes } from 'react'; 3 | import { Grid, Actions } from 'react-redux-grid'; 4 | 5 | import { 6 | columns, 7 | data, 8 | pageSize, 9 | events, 10 | plugins, 11 | treeDataSource 12 | } from './data/demodata'; 13 | 14 | export const Tree = ({ store }) => { 15 | 16 | const stateKey = 'tree'; 17 | 18 | const complexData = { 19 | showTreeRootNode: false, 20 | dataSource: treeDataSource, 21 | gridType: 'tree', 22 | dragAndDrop: true, 23 | columns: [ 24 | { 25 | name: 'Name', 26 | width: '30%', 27 | className: 'additional-class', 28 | dataIndex: 'Name', 29 | sortable: false, 30 | expandable: true 31 | }, 32 | { 33 | name: 'Phone Number', 34 | dataIndex: 'Phone Number', 35 | sortable: false, 36 | className: 'additional-class' 37 | }, 38 | { 39 | name: 'Email', 40 | dataIndex: 'Email', 41 | sortable: false, 42 | className: 'additional-class', 43 | defaultSortDirection: 'descend' 44 | }, 45 | { 46 | name: 'Address', 47 | dataIndex: 'Address', 48 | sortable: false, 49 | className: 'additional-class' 50 | } 51 | ], 52 | data, 53 | plugins: { 54 | ...plugins, 55 | GRID_ACTIONS: null, 56 | SELECTION_MODEL: { 57 | mode: 'single' 58 | }, 59 | PAGER: { 60 | enabled: false 61 | }, 62 | BULK_ACTIONS: { 63 | enabled: false 64 | } 65 | }, 66 | events, 67 | store, 68 | stateKey 69 | }; 70 | 71 | return ( 72 | 73 | ); 74 | }; 75 | 76 | const { object } = PropTypes; 77 | 78 | Tree.propTypes = { 79 | store: object.isRequired 80 | }; 81 | 82 | Tree.defaultProps = {}; 83 | 84 | export default Tree; -------------------------------------------------------------------------------- /src/components/examples/bootstrap/Bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { Component, PropTypes } from 'react'; 3 | import { Grid, Actions, applyGridConfig } from 'react-redux-grid'; 4 | import './css/bootstrap.min.css'; 5 | 6 | import { 7 | columns, 8 | data, 9 | pageSize, 10 | events, 11 | plugins, 12 | dataSource 13 | } from '../data/demodata'; 14 | 15 | export class Bootstrap extends Component { 16 | 17 | componentWillUnmount() { 18 | applyGridConfig({ 19 | CLASS_NAMES: { 20 | ACTIVE_CLASS: 'active', 21 | INACTIVE_CLASS: 'inactive', 22 | DRAG_HANDLE: 'drag-handle', 23 | SORT_HANDLE: 'sort-handle', 24 | SECONDARY_CLASS: 'secondary', 25 | CONTAINER: 'container', 26 | TABLE: 'table', 27 | TABLE_CONTAINER: 'table-container', 28 | HEADER: 'header', 29 | THEADER: 't-head', 30 | HEADER_HIDDEN: 'header-hidden', 31 | HEADER_FIXED: 'header-fixed', 32 | HEADER_FIXED_CONTAINER: 'header-fixed-container', 33 | HEADER_STUCK: 'header-stuck', 34 | HEADER_STUCK_BOTTOM: 'header-stuck-bottom', 35 | ROW: 'row', 36 | ROW_IS_DRAGGING: 'row-is-dragging', 37 | CELL: 'cell', 38 | CELL_TREE_ARROW: 'cell-tree-arrow', 39 | CELL_HANDNLE_CONTAINER: 'cell-handle-container', 40 | ROW_DRAG_HANDLE: 'row-drag-handle', 41 | PAGERTOOLBAR: 'pager-toolbar', 42 | EMPTY_ROW: 'empty-row', 43 | EDITED_CELL: 'edit', 44 | LOADING_BAR: 'loading-bar', 45 | DRAGGABLE_COLUMN: 'draggable-column', 46 | COLUMN: 'column', 47 | SORT_HANDLE_VISIBLE: 'sort-handle-visible', 48 | BUTTONS: { 49 | PAGER: 'page-buttons' 50 | }, 51 | SELECTION_MODEL: { 52 | CHECKBOX: 'checkbox', 53 | CHECKBOX_CONTAINER: 'checkbox-container' 54 | }, 55 | ERROR_HANDLER: { 56 | CONTAINER: 'error-container', 57 | MESSAGE: 'error-message' 58 | }, 59 | EDITOR: { 60 | INLINE: { 61 | CONTAINER: 'inline-editor', 62 | SHOWN: 'shown', 63 | HIDDEN: 'hidden', 64 | SAVE_BUTTON: 'save-button', 65 | CANCEL_BUTTON: 'cancel-button', 66 | BUTTON_CONTAINER: 'button-container', 67 | INPUT_WRAPPER: 'editor-wrapper' 68 | } 69 | }, 70 | GRID_ACTIONS: { 71 | CONTAINER: 'action-container', 72 | SELECTED_CLASS: 'action-menu-selected', 73 | NO_ACTIONS: 'no-actions', 74 | DISABLED: 'disabled', 75 | ICON: 'action-icon', 76 | MENU: { 77 | CONTAINER: 'action-menu-container', 78 | ITEM: 'action-menu-item' 79 | } 80 | }, 81 | FILTER_CONTAINER: { 82 | CONTAINER: 'filter-container', 83 | INPUT: 'filter-input', 84 | SEARCH_BUTTON: 'filter-search-button', 85 | MENU_BUTTON: 'filter-menu-button', 86 | CLEAR_BUTTON: 'filter-clear-button', 87 | BUTTON_CONTAINER: 'filter-button-container', 88 | MENU: { 89 | CONTAINER: 'advanced-filter-menu-container', 90 | TITLE: 'advanced-filter-menu-title', 91 | BUTTON: 'advanced-filter-menu-button', 92 | BUTTON_CONTAINER: 'advanced-filter-menu-button-container', 93 | FIELD: { 94 | CONTAINER: 'advanced-filter-menu-field-container', 95 | LABEL: 'advanced-filter-menu-field-label', 96 | INPUT: 'advanced-filter-menu-field-input' 97 | } 98 | } 99 | }, 100 | BULK_ACTIONS: { 101 | CONTAINER: 'bulkaction-container', 102 | DESCRIPTION: 'bulkaction-description', 103 | SHOWN: 'shown', 104 | HIDDEN: 'hidden' 105 | } 106 | }, 107 | CSS_PREFIX: 'react-grid' 108 | }); 109 | } 110 | 111 | render() { 112 | const { store } = this.props; 113 | const stateKey = 'bootstrap'; 114 | 115 | applyGridConfig({ 116 | CLASS_NAMES: { 117 | TABLE: 'table table-striped', 118 | TABLE_CONTAINER: 'table-responsive', 119 | HEADER_FIXED_CONTAINER: 'header-fixed', 120 | HEADER: 'header-bs', 121 | HEADER_HIDDEN: 'hidden-override', 122 | ROW: 'row-bs', 123 | CELL: 'text-left', 124 | COLUMN: 'column-bs', 125 | PAGERTOOLBAR: 'text-right bootstrap-description', 126 | BUTTONS: { 127 | PAGER: 'btn pull-left negative-margin' 128 | }, 129 | ERROR_HANDLER: { 130 | CONTAINER: 'hidden' 131 | } 132 | }, 133 | CSS_PREFIX: '' 134 | }); 135 | 136 | const bootstrapData = { 137 | columns: [ 138 | { 139 | name: 'Name', 140 | width: '10%', 141 | className: 'additional-class', 142 | dataIndex: 'Name', 143 | sortable: true, 144 | HANDLE_CLICK: () => { console.log('Header Click'); } 145 | }, 146 | { 147 | name: 'Phone Number', 148 | width: '20%', 149 | dataIndex: 'Phone Number', 150 | sortable: true, 151 | className: 'additional-class' 152 | }, 153 | { 154 | name: 'Email', 155 | width: '25%', 156 | dataIndex: 'Email', 157 | sortable: true, 158 | className: 'additional-class', 159 | defaultSortDirection: 'descend' 160 | }, 161 | { 162 | name: 'Address', 163 | dataIndex: 'Address', 164 | sortable: true, 165 | width: '35%', 166 | className: 'additional-class' 167 | } 168 | ], 169 | data, 170 | pageSize, 171 | plugins: { 172 | ...plugins, 173 | BULK_ACTIONS: { 174 | enabled: false 175 | }, 176 | GRID_ACTIONS: { 177 | menu: [] 178 | } 179 | }, 180 | events, 181 | dataSource, 182 | store, 183 | stateKey 184 | }; 185 | 186 | return ; 187 | } 188 | 189 | } 190 | 191 | const { object } = PropTypes; 192 | 193 | Bootstrap.propTypes = { 194 | store: object.isRequired 195 | }; 196 | 197 | Bootstrap.defaultProps = {}; 198 | 199 | export default Bootstrap; -------------------------------------------------------------------------------- /src/components/examples/bootstrap/README.md: -------------------------------------------------------------------------------- 1 | ## Bootstrap 2 | 3 | This example uses Bootstrap 3.3.7 4 | 5 | If you would like to use a different version, please update the css, fonts, js folders with the version of your choice. We can only load 1 version of bootstrap at time on the examples website but it we'll try to keep it a recent, stable version. 6 | 7 | 8 | #### Jan 24/2017 9 | Currently, Bootstrap is about to release version 4.0.0 -------------------------------------------------------------------------------- /src/components/examples/bootstrap/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2016 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} 6 | /*# sourceMappingURL=bootstrap-theme.min.css.map */ -------------------------------------------------------------------------------- /src/components/examples/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/src/components/examples/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/components/examples/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/src/components/examples/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/components/examples/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/src/components/examples/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/components/examples/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/src/components/examples/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/components/examples/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /src/components/examples/bulk-selection/BulkPager.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { Component, PropTypes } from 'react'; 3 | import { connect } from 'react-redux'; 4 | import { Actions } from 'react-redux-grid'; 5 | import * as BulkSelectionActions from '../../../redux/actions/bulkSelectionActions'; 6 | import * as _ from 'lodash'; 7 | 8 | import { 9 | columns, 10 | data, 11 | pageSize, 12 | events, 13 | dataSource, 14 | pagingDataSource 15 | } from './..//data/demodata'; 16 | 17 | class BulkPager extends Component { 18 | 19 | constructor(props){ 20 | super(props); 21 | this.state = { 22 | currentPageLimit: 10 23 | }; 24 | this.handleBulkActionClick = this.handleBulkActionClick.bind(this); 25 | this.handleSelectChange = this.handleSelectChange.bind(this); 26 | this.handleNumberedPageButtonClick = this.handleNumberedPageButtonClick.bind(this); 27 | 28 | } 29 | 30 | getSelectedIds() { 31 | 32 | const bulkMap = this.props.selection.get("bulk"); 33 | const selectedIds = bulkMap.get("indexes"); 34 | 35 | if (undefined !== selectedIds) { 36 | return selectedIds; 37 | } else { 38 | // you could dispatch a notification... 39 | // this.props.displayWarningRequestMessage("No rows selected"); 40 | console.warn("BulkPage selectedIds were false! no rows selected"); 41 | console.log( bulkMap.toJSON() ); 42 | return []; 43 | } 44 | }; 45 | 46 | handleBulkActionClick(e) { 47 | e.preventDefault(); 48 | const selectedIds = this.getSelectedIds(); 49 | 50 | //const currentPageRecords = this.props.gridData.get("data").toJSON(); 51 | 52 | // credit: http://stackoverflow.com/questions/28357971/lodash-challenges-i-have-an-array-of-objects-i-need-to-filter-for-an-array-of 53 | const list = this.props.gridData.get("data"); 54 | 55 | console.warn("BulkPage selectedIds :", selectedIds); 56 | 57 | const remaining = list.toJSON().filter( obj => { return selectedIds.indexOf( obj._id ) > -1; }) 58 | const removed = list.toJSON().filter( obj => { return selectedIds.indexOf( obj._id ) === -1; }) 59 | 60 | this.props.bulkDisplay({removed, remaining}) 61 | 62 | }; 63 | 64 | handleSelectChange(e) { 65 | console.log("BulkPager handleSelectChange"); 66 | e.preventDefault(); 67 | const newPageLimit = Number(e.target.value); 68 | 69 | const currIndex = this.props.currentPager 70 | && this.props.currentPager.get !== undefined 71 | ? this.props.currentPager.get('pageIndex') 72 | : 0; 73 | 74 | this.setState({ 75 | currentPageLimit: newPageLimit 76 | }); 77 | 78 | Promise.all([ 79 | this.props.getAsyncData({ 80 | dataSource: this.props.api, 81 | stateKey: 'bulk', 82 | extraParams: { 83 | pageIndex: currIndex, 84 | pageSize: newPageLimit, 85 | } 86 | }), 87 | this.props.changePageLimit(newPageLimit) 88 | ]) 89 | 90 | }; 91 | 92 | handleNumberedPageButtonClick(e) { 93 | 94 | const newPageIndex = parseInt(e.target.innerHTML) - 1; 95 | 96 | 97 | this.props.getAsyncData({ 98 | dataSource: this.props.api, 99 | stateKey: 'bulk', 100 | extraParams: { 101 | pageIndex: newPageIndex, 102 | pageSize: this.state.currentPageLimit, 103 | } 104 | }) 105 | 106 | Promise.all([ 107 | this.props.getAsyncData({ 108 | dataSource: this.props.api, 109 | stateKey: 'bulk', 110 | extraParams: { 111 | pageIndex: newPageIndex, 112 | pageSize: this.state.currentPageLimit, 113 | } 114 | }), 115 | 116 | this.props.setPageIndexAsync({ 117 | pageIndex: newPageIndex, 118 | pageSize: this.state.currentPageLimit, 119 | dataSource: this.props.api, 120 | stateKey: 'bulk' 121 | }) 122 | ]); 123 | 124 | }; 125 | 126 | 127 | render(){ 128 | 129 | const total = this.props.gridData ? 130 | this.props.gridData.total 131 | : 0; 132 | 133 | const currIndex = this.props.currentPager 134 | && this.props.currentPager.get !== undefined 135 | ? this.props.currentPager.get('pageIndex') 136 | : 0; 137 | 138 | 139 | const totalButtons = total / this.props.bulkSelection.pageSize; 140 | const buttons = []; 141 | 142 | _.times(totalButtons, i => { 143 | buttons.push( 144 | 172 | 173 | ); 174 | } 175 | }; 176 | 177 | const { string, object } = PropTypes; 178 | 179 | BulkPager.propTypes = { 180 | pagingDataSource: string, 181 | store: object.isRequired 182 | }; 183 | 184 | BulkPager.defaultProps = {}; 185 | 186 | const mapStateToProps = (state, ownProps) => ({ 187 | grid: state.grid, 188 | selection: state.selection, 189 | currentPager: state.pager.get('bulk'), 190 | gridData: state.dataSource.get('bulk'), 191 | bulkSelection: state.bulkSelection 192 | }); 193 | 194 | const mapDispatchToProps = dispatch => { 195 | return { 196 | getAsyncData: config => { 197 | dispatch(Actions.GridActions.getAsyncData(config)) 198 | }, 199 | setPageIndexAsync: config => { 200 | dispatch(Actions.PagerActions.setPageIndexAsync(config)) 201 | }, 202 | bulkDisplay: newData => { 203 | dispatch(BulkSelectionActions.bulkDisplay(newData)) 204 | }, 205 | changePageLimit: newPageLimit => { 206 | dispatch(BulkSelectionActions.changePageLimit(newPageLimit)) 207 | }, 208 | dispatch 209 | } 210 | } 211 | 212 | export default connect(mapStateToProps, mapDispatchToProps)(BulkPager); -------------------------------------------------------------------------------- /src/components/examples/bulk-selection/BulkSelection.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { Component } from 'react'; 3 | import { Grid, Actions } from 'react-redux-grid'; 4 | import { connect } from 'react-redux'; 5 | import BulkPager from './BulkPager'; 6 | import store from '../../../redux/configureStore'; 7 | import Api from './..//data/Api'; 8 | 9 | import { 10 | columns, 11 | events, 12 | plugins, 13 | } from '../data/demodata'; 14 | 15 | class BulkSelection extends Component { 16 | 17 | constructor(props){ 18 | super(props); 19 | 20 | console.log("BulkSelection constructor: ", props); 21 | 22 | const pagerConfig = { 23 | pageSize: this.props.bulkSelection.pageSize 24 | } 25 | 26 | }; 27 | 28 | componentWillReceiveProps(nextProps, nextState) { 29 | this.props = nextProps; 30 | }; 31 | 32 | componentDidMount() { 33 | 34 | }; 35 | 36 | componentDidUpdate() { 37 | console.log("BulkSelection componentDidUpdate this.props: ", this.props); 38 | 39 | }; 40 | 41 | render(){ 42 | console.log("BulkSelection render this.props: ", this.props); 43 | 44 | let pagerConfig = { 45 | data: this.props.bulkSelection.data, 46 | pageSize: this.props.bulkSelection.pageSize 47 | } 48 | 49 | let config = { 50 | columns, 51 | dataSource: Api, 52 | pageSize: pagerConfig.pageSize, 53 | plugins: { 54 | ...plugins, 55 | STICKY_HEADER: { 56 | enabled: true 57 | }, 58 | STICKY_FOOTER: { 59 | enabled: true 60 | }, 61 | FILTER_CONTAINER: { 62 | enabled: true 63 | }, 64 | 65 | PAGER: { 66 | enabled: true, 67 | pagingType: 'remote', 68 | pagerComponent: ( 69 | 73 | ) 74 | }, 75 | BULK_ACTIONS: { 76 | enabled: true, 77 | actions: [ 78 | { 79 | text: 'Move', 80 | EVENT_HANDLER: () => { 81 | 82 | } 83 | }, 84 | { 85 | text: 'Add', 86 | EVENT_HANDLER: () => { 87 | 88 | } 89 | } 90 | ] 91 | }, 92 | GRID_ACTIONS: { 93 | iconCls: 'action-icon', 94 | menu: [ 95 | { 96 | text: 'Delete', 97 | EVENT_HANDLER: ({ metaData }) => { 98 | const rowIndex = metaData.rowIndex; 99 | 100 | store.dispatch( 101 | Actions.EditorActions.removeRow({ 102 | stateKey, 103 | rowIndex 104 | }) 105 | ); 106 | } 107 | } 108 | ] 109 | } 110 | }, 111 | height: '', 112 | events, 113 | store, 114 | stateKey: 'bulk' 115 | } 116 | 117 | 118 | return ( 119 | 120 | ); 121 | }; 122 | } 123 | 124 | 125 | 126 | const mapStateToProps = (state, ownProps) => ({ 127 | grid: state.grid, 128 | bulkSelection: state.bulkSelection, 129 | }); 130 | 131 | const mapDispatchToProps = dispatch => { 132 | return { 133 | dispatch 134 | } 135 | } 136 | 137 | export default connect(mapStateToProps, mapDispatchToProps)(BulkSelection); -------------------------------------------------------------------------------- /src/components/examples/bulk-selection/BulkSelection.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import store from '../../../redux/configureStoreForTests'; 3 | import { shallow, mount, render } from 'enzyme'; 4 | import BulkSelection from './BulkSelection'; 5 | import { Grid, Actions } from 'react-redux-grid'; 6 | 7 | jest.unmock() 8 | 9 | describe('', () => { 10 | 11 | it("should render swallowly without testing sub components", function() { 12 | const wrapper = shallow(); 13 | expect(wrapper).toBeDefined(); 14 | }); 15 | 16 | it("should render mounted with sub components affecting tests", function() { 17 | const wrapper = mount(); 18 | expect(wrapper).toBeDefined(); 19 | }); 20 | 21 | it("should have a Grid with data", function() { 22 | const wrapper = mount(); 23 | expect( wrapper.find('Grid') ).toBeDefined(); 24 | //expect(wrapper.prop('data')).to.have.length.toBeGreaterThan(1); 25 | }); 26 | 27 | it("should have a Grid with data with 1 on init", function() { 28 | const wrapper = mount(); 29 | const data = wrapper.find('Grid').prop('data'); 30 | 31 | expect(data).toBeDefined(); 32 | }); 33 | 34 | it("should have a Grid with data with greater than 1 after load", function() { 35 | const wrapper = mount(); 36 | const data = wrapper.find('Grid').prop('data'); 37 | 38 | expect(data.length).toBeGreaterThan(1); 39 | }); 40 | 41 | 42 | }); 43 | 44 | -------------------------------------------------------------------------------- /src/components/examples/bulk-selection/getBulkSelectionSelectedRows.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React from 'react'; 3 | import * as _ from "lodash"; 4 | import store from './../../../redux/configureStore'; 5 | import { events } from '../data/demodata'; 6 | import { Grid } from 'react-redux-grid'; 7 | 8 | // the BulkSelection example will display a message after you select several rows and click the Bulk Action button 9 | const getBulkSelectionSelectedRows = props => { 10 | 11 | console.log("getBulkSelectionSelectedRows props: ", props); 12 | 13 | const totalRowsSelected = ( undefined !== props.selection.get('bulk') && undefined !== props.selection.get('bulk').get("indexes") ) ? props.selection.get('bulk').get("indexes").length : 0; 14 | const rowsSelectedMessage = (totalRowsSelected > 0) ? totalRowsSelected + " Rows Selected" : "0 Rows Selected"; 15 | 16 | if ( props.app.featureTitle === "BulkSelection" && props.bulkSelection.recordsRemoved.length > 0 ) { 17 | 18 | const emails = _.map( props.bulkSelection.recordsRemoved, record => { 19 | console.log("record ", record); 20 | return (
  • {record.Email}
  • ) 21 | }); 22 | 23 | const discStyle = {listStyleType:"disc", marginLeft: "20px", color:"#644581"}; 24 | const selectedIndexes = props.selection.get('bulk').get("indexes"); 25 | 26 | return (
    You have selected { ( undefined !== selectedIndexes ) ? selectedIndexes.length : 0 } records with the following emails: 27 |
      28 | {emails} 29 |
    30 |
    ) 31 | } else if (props.app.featureTitle === "BulkSelection") { 32 | return (
    {rowsSelectedMessage}
    ) 33 | } else { 34 | return null; 35 | } 36 | } 37 | 38 | export default getBulkSelectionSelectedRows; 39 | -------------------------------------------------------------------------------- /src/components/examples/complex/Complex.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { PropTypes } from 'react'; 3 | import { Grid, Actions } from 'react-redux-grid'; 4 | 5 | import { 6 | columns, 7 | data, 8 | pageSize, 9 | events, 10 | plugins, 11 | dataSource 12 | } from '../data/demodata'; 13 | 14 | export const Complex = ({ store }) => { 15 | 16 | const stateKey = 'complex'; 17 | 18 | const complexData = { 19 | columns: [ 20 | { 21 | name: 'Name', 22 | width: '10%', 23 | className: 'additional-class', 24 | dataIndex: 'Name', 25 | sortable: true, 26 | HANDLE_CLICK: () => { console.log('Header Click'); } 27 | }, 28 | { 29 | name: 'Phone Number', 30 | width: '20%', 31 | dataIndex: 'Phone Number', 32 | sortable: true, 33 | className: 'additional-class' 34 | }, 35 | { 36 | name: 'Email', 37 | width: '25%', 38 | dataIndex: 'Email', 39 | sortable: true, 40 | className: 'additional-class', 41 | defaultSortDirection: 'descend' 42 | }, 43 | { 44 | name: 'Address', 45 | dataIndex: 'Address', 46 | sortable: true, 47 | width: '35%', 48 | className: 'additional-class' 49 | } 50 | ], 51 | data, 52 | pageSize, 53 | plugins: { 54 | ...plugins, 55 | BULK_ACTIONS: { 56 | enabled: true 57 | }, 58 | GRID_ACTIONS: { 59 | iconCls: 'action-icon', 60 | menu: [ 61 | { 62 | text: 'DeleteA', 63 | EVENT_HANDLER: ({ metaData }) => { 64 | const rowIndex = metaData.rowIndex; 65 | 66 | store.dispatch( 67 | Actions.EditorActions.removeRow({ 68 | stateKey, 69 | rowIndex 70 | }) 71 | ); 72 | } 73 | } 74 | ] 75 | } 76 | }, 77 | events, 78 | dataSource, 79 | store, 80 | stateKey 81 | }; 82 | 83 | return ( 84 | 85 | ); 86 | }; 87 | 88 | const { object } = PropTypes; 89 | 90 | Complex.propTypes = { 91 | store: object.isRequired 92 | }; 93 | 94 | Complex.defaultProps = {}; 95 | 96 | export default Complex; -------------------------------------------------------------------------------- /src/components/examples/complex/Complex.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import store from '../../../redux/configureStoreForTests'; 3 | import { shallow, mount, render } from 'enzyme'; 4 | import Complex from './Complex'; 5 | import { Grid, Actions } from 'react-redux-grid'; 6 | 7 | jest.unmock() 8 | 9 | describe('', () => { 10 | 11 | it("should render swallowly without testing sub components", function() { 12 | const wrapper = shallow(); 13 | expect(wrapper).toBeDefined(); 14 | }); 15 | 16 | it("should render mounted with sub components affecting tests", function() { 17 | const wrapper = mount(); 18 | expect(wrapper).toBeDefined(); 19 | }); 20 | 21 | it("should have a Grid with data", function() { 22 | const wrapper = mount(); 23 | expect( wrapper.find('Grid') ).toBeDefined(); 24 | //expect(wrapper.prop('data')).to.have.length.toBeGreaterThan(1); 25 | }); 26 | 27 | it("should have a Grid with data with 1 on init", function() { 28 | const wrapper = mount(); 29 | const data = wrapper.find('Grid').prop('data'); 30 | 31 | expect(data).toBeDefined(); 32 | }); 33 | 34 | it("should have a Grid with data with greater than 1 after load", function() { 35 | const wrapper = mount(); 36 | const data = wrapper.find('Grid').prop('data'); 37 | 38 | expect(data.length).toBeGreaterThan(1); 39 | }); 40 | 41 | describe('Phone Number column', () => { 42 | it("should have a drag handle", function() { 43 | const wrapper = mount(); 44 | expect(wrapper.find('./react-grid-resizable')).toBeDefined(); 45 | // react-grid-drag-handle 46 | }); 47 | }); 48 | 49 | }); 50 | 51 | -------------------------------------------------------------------------------- /src/components/examples/custom-loader/CustomLoader.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { Component, PropTypes } from 'react'; 3 | import { Actions, Grid } from 'react-redux-grid'; 4 | 5 | import { 6 | columns, 7 | data, 8 | pageSize, 9 | events, 10 | dataSource 11 | } from './../data/demodata'; 12 | 13 | import './loader.css'; 14 | 15 | export class CustomLoader extends Component { 16 | render() { 17 | 18 | const { store } = this.props; 19 | const loaderData = { 20 | columns, 21 | data, 22 | pageSize, 23 | plugins: { 24 | LOADER: { 25 | enabled: true 26 | } 27 | }, 28 | events, 29 | store, 30 | classNames: ['custom-loader'], 31 | stateKey: 'custom-loader', 32 | 33 | }; 34 | 35 | return ( 36 | 37 | ); 38 | } 39 | 40 | componentDidMount() { 41 | const { store } = this.props; 42 | 43 | store.dispatch( 44 | Actions.LoaderActions.setLoaderState({ 45 | state: true, 46 | stateKey: 'custom-loader' 47 | }) 48 | ) 49 | } 50 | }; 51 | 52 | const { object } = PropTypes; 53 | 54 | CustomLoader.propTypes = { 55 | store: object.isRequired 56 | }; 57 | 58 | CustomLoader.defaultProps = {}; 59 | 60 | export default CustomLoader; -------------------------------------------------------------------------------- /src/components/examples/custom-loader/loader.css: -------------------------------------------------------------------------------- 1 | .react-grid-custom-loader .react-grid-loading-bar { 2 | position: absolute; 3 | height: 100%; 4 | top: 0px; 5 | background-color: rgba(0,0,0,0.5); 6 | background-image: url('./spinner.gif'); 7 | background-repeat: no-repeat; 8 | background-position: 50% 50%; 9 | background-size: 15%; 10 | } -------------------------------------------------------------------------------- /src/components/examples/custom-loader/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencripps/react-redux-grid-demo/91776d836402efc0027821e95f6a62e23c5277d1/src/components/examples/custom-loader/spinner.gif -------------------------------------------------------------------------------- /src/components/examples/custom-pager/Api.js: -------------------------------------------------------------------------------- 1 | export const dataSource = function getData({ 2 | pageIndex 3 | }) { 4 | return new Promise((resolve) => { 5 | const request = new XMLHttpRequest(); 6 | 7 | const config = { 8 | method: 'GET', 9 | route: 'http://react-redux-grid.herokuapp.com/getfakeData' 10 | }; 11 | 12 | if (pageIndex) { 13 | config.route = `${config.route}?pageIndex=${pageIndex}&pageSize=10`; // eslint-disable-line max-len 14 | } 15 | 16 | else { 17 | config.route = `${config.route}?pageSize=10`; // eslint-disable-line max-len 18 | } 19 | 20 | request.open(config.method, config.route, true); 21 | 22 | request.addEventListener( 23 | 'load', (res) => { 24 | const response = JSON.parse(res.target.responseText); 25 | 26 | // if you have more data than is being shown 27 | // ensure you return a total, so the pager knows 28 | // what paging actions are possible 29 | 30 | resolve({ 31 | data: response.data, 32 | total: response.total 33 | }); 34 | } 35 | ); 36 | 37 | request.send(config.data || null); 38 | }); 39 | }; 40 | 41 | export default dataSource; -------------------------------------------------------------------------------- /src/components/examples/custom-pager/CustomPager.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { PropTypes } from 'react'; 3 | import { Grid } from 'react-redux-grid'; 4 | 5 | import Pager from './Pager'; 6 | import Api from './..//data/Api'; 7 | 8 | import { 9 | columns, 10 | data, 11 | events, 12 | dataSource 13 | } from './..//data/demodata'; 14 | 15 | export const CustomFooter = ({ store }) => { 16 | 17 | const customFooter = { 18 | columns, 19 | dataSource: Api, 20 | plugins: { 21 | PAGER: { 22 | enabled: true, 23 | pagingType: 'remote', 24 | pagerComponent: ( 25 | 29 | ) 30 | } 31 | }, 32 | events, 33 | store, 34 | stateKey: 'custom-pager' 35 | }; 36 | 37 | return ; 38 | }; 39 | 40 | const { object } = PropTypes; 41 | 42 | CustomFooter.propTypes = { 43 | store: object.isRequired 44 | }; 45 | 46 | CustomFooter.defaultProps = {}; 47 | 48 | export default CustomFooter; -------------------------------------------------------------------------------- /src/components/examples/custom-pager/CustomPager.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import store from '../../../redux/configureStoreForTests'; 3 | import { shallow, mount, render } from 'enzyme'; 4 | import CustomerPager from './CustomerPager'; 5 | import { Grid, Actions } from 'react-redux-grid'; 6 | 7 | jest.unmock() 8 | 9 | describe('', () => { 10 | 11 | it("should render swallowly without testing sub components", function() { 12 | const wrapper = shallow(); 13 | expect(wrapper).toBeDefined(); 14 | }); 15 | 16 | it("should render mounted with sub components affecting tests", function() { 17 | const wrapper = mount(); 18 | expect(wrapper).toBeDefined(); 19 | }); 20 | 21 | it("should have a Grid with data", function() { 22 | const wrapper = mount(); 23 | expect( wrapper.find('Grid') ).toBeDefined(); 24 | //expect(wrapper.prop('data')).to.have.length.toBeGreaterThan(1); 25 | }); 26 | 27 | it("should have a Grid with data with 1 on init", function() { 28 | const wrapper = mount(); 29 | const data = wrapper.find('Grid').prop('data'); 30 | 31 | expect(data).toBeDefined(); 32 | }); 33 | 34 | it("should have a Grid with data with greater than 1 after load", function() { 35 | const wrapper = mount(); 36 | const data = wrapper.find('Grid').prop('data'); 37 | 38 | expect(data.length).toBeGreaterThan(1); 39 | }); 40 | 41 | 42 | }); 43 | 44 | -------------------------------------------------------------------------------- /src/components/examples/custom-pager/Pager.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React, { PropTypes } from 'react'; 3 | import { connect } from 'react-redux'; 4 | import { Actions } from 'react-redux-grid'; 5 | 6 | import { 7 | columns, 8 | data, 9 | pageSize, 10 | events, 11 | dataSource, 12 | pagingDataSource 13 | } from './..//data/demodata'; 14 | 15 | export const Pager = ({ api, current, gridData, pagingDataSource, store }) => { 16 | 17 | const total = gridData ? 18 | gridData.total 19 | : 0; 20 | 21 | const currIndex = current 22 | && current.get !== undefined 23 | ? current.get('pageIndex') 24 | : 0; 25 | 26 | const buttons = []; 27 | 28 | const onClick = (e) => { 29 | const index = e.target.innerHTML 30 | store.dispatch( 31 | Actions.PagerActions 32 | .setPageIndexAsync({ 33 | pageIndex: parseInt(index) - 1, 34 | pageSize: 10, 35 | dataSource: api, 36 | stateKey: 'custom-pager' 37 | }) 38 | ); 39 | }; 40 | 41 | for (let i = 0; i < total / 10; i++) { 42 | buttons.push( 43 | ) 48 | else 49 | return (
  • ) 50 | }); 51 | return ( 52 |
    53 |

    Examples

    54 |
      55 | {listItems} 56 |
    57 |
    58 | ); 59 | } 60 | } 61 | 62 | const mapStateToProps = (state) => ({ 63 | app: state.app 64 | }); 65 | 66 | 67 | const mapDispatchToProps = (dispatch) => { 68 | return { 69 | changeRoute: (url) => dispatch(push(url)), 70 | switchFeature: (featureTitle) => dispatch(switchFeature(featureTitle)), 71 | dispatch, 72 | }; 73 | } 74 | 75 | export default connect(mapStateToProps, mapDispatchToProps)(ExamplesSidebar); -------------------------------------------------------------------------------- /src/components/sidebar/FeaturesSidebar.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import './Sidebar.css'; 4 | 5 | class FeaturesSidebar extends Component { 6 | 7 | constructor(props){ 8 | super(props); 9 | this.handleClickSimple = this.handleClickSimple.bind(this); 10 | this.handleClickAllFeatures = this.handleClickAllFeatures.bind(this); 11 | } 12 | 13 | handleClickSimple(event){ 14 | event.preventDefault(); 15 | 16 | } 17 | 18 | handleClickAllFeatures(event){ 19 | event.preventDefault(); 20 | 21 | } 22 | 23 | render() { 24 | const { features } = this.props.app; 25 | const listItems = features.map((feature) => 26 |
  • 27 | 28 | {feature} 29 |
  • 30 | ); 31 | 32 | return ( 33 |
    34 |

    Features

    35 |
      36 | {listItems} 37 |
    38 |
    39 | ); 40 | } 41 | } 42 | 43 | 44 | const mapStateToProps = (state) => ({ 45 | faker: state.faker, 46 | grid: state.grid, 47 | app: state.app 48 | }); 49 | 50 | const mapDispatchToProps = (dispatch) => { 51 | return { 52 | dispatch 53 | } 54 | }; 55 | export default connect(mapStateToProps, mapDispatchToProps)(FeaturesSidebar); -------------------------------------------------------------------------------- /src/components/sidebar/Sidebar.css: -------------------------------------------------------------------------------- 1 | .sidebarContainer { 2 | display: block; 3 | position: relative; 4 | width: 170px; 5 | height: auto; 6 | background-color:white; 7 | } 8 | 9 | .featuresContainer { 10 | width: 170px; 11 | } 12 | 13 | 14 | .sidebarsContainer li { 15 | display: flex; 16 | justify-content: flex-start; 17 | flex-direction: column; 18 | width: 170px; 19 | } 20 | 21 | .sidebarContainer li { 22 | font-size: 12px; 23 | color: #666; 24 | margin: 0px; 25 | padding: 0px; 26 | font-size: 12px; 27 | } 28 | 29 | .examplesContainer li button { 30 | font-size: 12px; 31 | } 32 | 33 | .sidebarContainer button { 34 | display: block; 35 | position: relative; 36 | } 37 | 38 | .gridIcon { 39 | display: inline-block; 40 | width: 30px; 41 | vertical-align: top; 42 | margin-top: 3px; 43 | } 44 | 45 | .gridLabelOff { 46 | display: inline-block; 47 | vertical-align: top; 48 | margin:0px; 49 | padding:0px; 50 | position: absolute; 51 | left: 30px; 52 | top: 6px; 53 | color: #176680; 54 | } 55 | 56 | .gridButtonOff { 57 | display: block; 58 | border: none; 59 | border-radius: 5px; 60 | margin: 5px; 61 | background-color: #49b8dc; 62 | color: #fff; 63 | cursor: pointer; 64 | height: 28px; 65 | width: 150px; 66 | text-align: left; 67 | } 68 | 69 | .gridLabelOn { 70 | display: inline-block; 71 | vertical-align: top; 72 | margin:0px; 73 | padding:0px; 74 | position: absolute; 75 | left: 30px; 76 | top: 6px; 77 | color: #f1f1f1; 78 | } 79 | 80 | .gridButtonOn { 81 | display: block; 82 | border: none; 83 | border-radius: 5px; 84 | margin: 5px; 85 | background-color: #644581; 86 | color: #fff; 87 | cursor: pointer; 88 | height: 28px; 89 | width: 150px; 90 | text-align: left; 91 | } 92 | 93 | img { 94 | cursor: pointer; 95 | } 96 | -------------------------------------------------------------------------------- /src/components/sidebar/gridBlueIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/sidebar/gridPurpleIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import store from './redux/configureStore'; 5 | import App from './App'; 6 | import ExampleGrid from './components/examples/ExampleGridContainer'; 7 | import { Router, Route, IndexRoute, browserHistory } from 'react-router'; 8 | import { syncHistoryWithStore } from 'react-router-redux'; 9 | import './index.css'; 10 | 11 | const history = syncHistoryWithStore(browserHistory, store) 12 | 13 | ReactDOM.render( 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | , 33 | document.getElementById('root') 34 | ); -------------------------------------------------------------------------------- /src/redux/actions/appActions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import fetch from 'isomorphic-fetch'; 3 | import * as types from '../types/types'; 4 | 5 | export const switchFeature = (featureTitle) => { 6 | return { 7 | type: types.FEATURE_SWITCH, 8 | featureTitle 9 | }; 10 | } 11 | 12 | export function ready() { 13 | return { 14 | type: types.APP_READY 15 | }; 16 | } -------------------------------------------------------------------------------- /src/redux/actions/bulkSelectionActions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import fetch from 'isomorphic-fetch'; 3 | import * as types from '../types/types'; 4 | 5 | export const bulkDisplay = newData => { 6 | return { 7 | type: types.BULK_DISPLAY, 8 | recordsRemaining: newData.removed, 9 | recordsRemoved: newData.remaining 10 | }; 11 | } 12 | 13 | export const changePageLimit = newPageLimit => { 14 | return { 15 | type: types.PAGING_CHANGE_LIMIT, 16 | newPageLimit 17 | }; 18 | } -------------------------------------------------------------------------------- /src/redux/configureStore.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { createStore, applyMiddleware, combineReducers } from 'redux' 3 | import createLogger from 'redux-logger' 4 | import { Reducers as gridReducers } from 'react-redux-grid'; 5 | import appReducers from './reducers/appReducers'; 6 | import bulkSelectionReducers from './reducers/bulkSelectionReducers'; 7 | import { routerReducer, routerMiddleware } from 'react-router-redux'; 8 | import { browserHistory } from 'react-router'; 9 | import thunk from 'redux-thunk'; 10 | 11 | const loggerMiddleware = createLogger(); 12 | 13 | const rootReducer = combineReducers({ 14 | ...gridReducers, 15 | app: appReducers, 16 | bulkSelection: bulkSelectionReducers, 17 | routing: routerReducer 18 | }); 19 | 20 | export function configureStore() { 21 | return createStore( 22 | rootReducer, 23 | applyMiddleware( 24 | loggerMiddleware, 25 | routerMiddleware(browserHistory), 26 | thunk 27 | ) 28 | ) 29 | } 30 | 31 | const store = configureStore(); 32 | 33 | export default store; 34 | -------------------------------------------------------------------------------- /src/redux/configureStoreForTests.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { createStore, applyMiddleware, combineReducers } from 'redux' 3 | import { Reducers as gridReducers } from 'react-redux-grid'; 4 | import appReducers from './reducers/appReducers'; 5 | import { routerReducer, routerMiddleware } from 'react-router-redux'; 6 | import { browserHistory } from 'react-router'; 7 | import thunk from 'redux-thunk'; 8 | 9 | const rootReducer = combineReducers({ 10 | ...gridReducers, 11 | app: appReducers, 12 | routing: routerReducer 13 | }); 14 | 15 | export function configureStore() { 16 | return createStore( 17 | rootReducer, 18 | applyMiddleware( 19 | routerMiddleware(browserHistory), 20 | thunk 21 | ) 22 | ) 23 | } 24 | 25 | const store = configureStore(); 26 | 27 | export default store; 28 | -------------------------------------------------------------------------------- /src/redux/reducers/appReducers.js: -------------------------------------------------------------------------------- 1 | import * as types from "../types/types"; 2 | import * as features from "./features"; 3 | import { LOCATION_CHANGE } from 'react-router-redux'; 4 | 5 | const getFeatures = (featureTitle) => { 6 | let key = featureTitle.toLowerCase() + "Features"; 7 | return features[key] 8 | } 9 | 10 | const initialState = { 11 | ready: false, 12 | name: "React Redux Grip Examples", 13 | features: getFeatures('Simple'), 14 | featureTitle: "Simple", 15 | featureTitles: features.featureTitles 16 | }; 17 | 18 | export default function reducer(state = initialState, action = {}) { 19 | switch (action.type) { 20 | case LOCATION_CHANGE: 21 | console.log("App heard the route change action: ", action); 22 | let featureTitle = action.payload.pathname.split("/")[1]; 23 | if (featureTitle === "") featureTitle = "Simple"; 24 | return { 25 | ...state, 26 | featureTitle, 27 | features: getFeatures(featureTitle), 28 | ready: true 29 | }; 30 | case types.APP_READY: 31 | return { 32 | ...state, 33 | ready: true 34 | }; 35 | case types.FEATURE_SWITCH: 36 | return { 37 | ...state, 38 | features: getFeatures(action.featureTitle), 39 | featureTitle: action.featureTitle 40 | }; 41 | default: 42 | return state; 43 | } 44 | } 45 | 46 | export function ready() { 47 | return { 48 | type: types.APP_READY 49 | }; 50 | } -------------------------------------------------------------------------------- /src/redux/reducers/bulkSelectionReducers.js: -------------------------------------------------------------------------------- 1 | import * as types from "../types/types"; 2 | import {data} from "../../components/examples/data/demodata"; 3 | // import {SET_DATA} from "react-redux-grid/src/constants/ActionTypes"; how can I get the types?! 4 | 5 | const initialState = { 6 | ready: false, 7 | pageSize: 10, 8 | data: data, 9 | recordsRemaining: [], 10 | recordsRemoved: [] 11 | }; 12 | 13 | export default function reducer(state = initialState, action = {}) { 14 | switch (action.type) { 15 | case types.APP_READY: 16 | return { 17 | ...state, 18 | ready: true 19 | }; 20 | case types.PAGING_CHANGE_LIMIT: 21 | return { 22 | ...state, 23 | pageSize: action.newPageLimit 24 | }; 25 | case types.GRID_ROWS_BULK_DELETE: 26 | return { 27 | ...state, 28 | data: action.newRows 29 | }; 30 | case types.BULK_DISPLAY: 31 | return { 32 | ...state, 33 | recordsRemaining: action.recordsRemaining, 34 | recordsRemoved: action.recordsRemoved 35 | }; 36 | case "@@react-redux-grid/SET_DATA": 37 | return { 38 | ...state, 39 | recordsRemaining: [], 40 | recordsRemoved: [] 41 | }; 42 | default: 43 | return state; 44 | } 45 | } 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/redux/reducers/features.js: -------------------------------------------------------------------------------- 1 | 2 | // all features 3 | export const featureTitles = [ 4 | "Simple", 5 | "Complex", 6 | "Sticky", 7 | "ColRenderer", 8 | "Stress", 9 | "Editable", 10 | "Bootstrap", 11 | "Tree", 12 | "CustomPager", 13 | "BulkSelection", 14 | "CustomLoader", 15 | "ErrorMessage" 16 | ]; 17 | 18 | export const errormessageFeatures = []; 19 | 20 | export const defaultFeatures = [ 21 | "No Features Found" 22 | ] 23 | 24 | export const simpleFeatures = [ 25 | "Flat List", 26 | "Local/Remote Data Source", 27 | "Sortable", 28 | "Selection Model" 29 | ] 30 | 31 | export const complexFeatures = [ 32 | "Flat List", 33 | "Sortable", 34 | "Draggable Columns", 35 | "Resizeable Columns", 36 | "Local/Remote Data Source", 37 | "Checkbox Selection", 38 | "Multi Select", 39 | "Pagination", 40 | "Row Actions and Menus", 41 | "Hideable Columns" 42 | ] 43 | 44 | export const colrendererFeatures = [ 45 | "Customizable Cell Components" 46 | ] 47 | 48 | export const stickyFeatures = [ 49 | "Sticky Footer", 50 | "Sticky Header", 51 | "Infinite Scroll" 52 | ] 53 | 54 | export const bulkselectionFeatures = [ 55 | "Sticky Footer", 56 | "Sticky Header", 57 | "Paging", 58 | "Change Row Limit", 59 | "Bulk Actions", 60 | "Checkbox Selection", 61 | "Multi Select" 62 | ] 63 | 64 | export const stressFeatures = [ 65 | "1000000+ Records" 66 | ] 67 | 68 | export const editableFeatures = [ 69 | "Edit Cells and Rows" 70 | ] 71 | 72 | export const bootstrapFeatures = [ 73 | "Styled by Bootstrap " 74 | ]; 75 | 76 | 77 | export const treeFeatures = [ 78 | "Tree Structure ", 79 | "Drag amd Drop Rows", 80 | "Show/Hide Actions" 81 | ] 82 | 83 | 84 | export const custompagerFeatures = [ 85 | "Tree Structure ", 86 | "Drag amd Drop Rows", 87 | "Show/Hide Actions" 88 | ] 89 | 90 | export const customloaderFeatures = [ 91 | "Custom Loading Mask" 92 | ] 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/redux/types/types.js: -------------------------------------------------------------------------------- 1 | // OVERALL APP 2 | export const APP_READY = "APP_READY"; 3 | export const APP_STATUS_CHANGE = "APP_STATUS_CHANGE"; 4 | export const FEATURE_SWITCH = "FEATURE_SWITCH"; 5 | // DATA 6 | export const REQUEST_DATA_FAKE = "REQUEST_DATA_FAKE"; 7 | export const RECEIVE_DATA_FAKE_SUCCESS = "RECEIVE_DATA_FAKE_SUCCESS"; 8 | export const RECEIVE_DATA_FAKE_FAIL = "RECEIVE_DATA_FAKE_FAIL"; 9 | // GRID 10 | export const GRID_STATUS_CHANGE = "GRID_STATUS_CHANGE"; 11 | export const GRID_SORT = "GRID_SORT"; 12 | export const GRID_FILTERS_CHANGE = "GRID_FILTERS_CHANGE"; 13 | export const GRID_FILTERS_CLEAR = "GRID_FILTERS_CLEAR"; 14 | export const GRID_REQUEST_SAVE = "GRID_REQUEST_SAVE"; 15 | export const GRID_RECEIVE_SAVE_SUCCESS = "GRID_RECEIVE_SAVE_SUCCESS"; 16 | export const GRID_RECEIVE_SAVE_FAIL = "GRID_RECEIVE_SAVE_FAIL"; 17 | export const GRID_ROWS_UPDATE = "GRID_ROWS_UPDATE"; 18 | // PAGING 19 | export const PAGING_CHANGE_LIMIT = "PAGING_CHANGE_LIMIT"; 20 | // BULK SELECTION 21 | export const BULK_DISPLAY = "BULK_DISPLAY"; --------------------------------------------------------------------------------