├── ReactWebPack.CoreRC2 ├── wwwroot │ ├── js │ │ ├── site.min.js │ │ └── site.js │ ├── favicon.ico │ ├── lib │ │ ├── bootstrap │ │ │ ├── dist │ │ │ │ ├── fonts │ │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ │ └── js │ │ │ │ │ └── npm.js │ │ │ ├── .bower.json │ │ │ └── LICENSE │ │ ├── jquery │ │ │ ├── .bower.json │ │ │ └── LICENSE.txt │ │ ├── jquery-validation │ │ │ ├── .bower.json │ │ │ └── LICENSE.md │ │ └── jquery-validation-unobtrusive │ │ │ └── .bower.json │ ├── css │ │ ├── site.min.css │ │ ├── site.css │ │ ├── kanban-styles.min.css │ │ └── kanban-styles.css │ └── _references.js ├── JsUnitTests │ ├── localSrc │ │ ├── InnerValue.js │ │ ├── InnerFunction.js │ │ ├── OuterFunction.js │ │ ├── InnerConnect.js │ │ ├── OuterConnect.js │ │ ├── CheckboxWithLabel.js │ │ └── Decoded CheckboxWithLabel.js │ ├── mocksEtc │ │ ├── MockInnerFunction.js │ │ ├── WrapTestDnD.js │ │ └── MockPromise.js │ ├── Tests │ │ ├── localTests │ │ │ ├── karam-setup.test.js │ │ │ ├── EnzymeSuimulate.test.js │ │ │ ├── CheckboxWithLabel.test.js │ │ │ └── TestMocking.test.js │ │ ├── kanbanUtils │ │ │ └── ReduxDispatcher.test.js │ │ ├── components │ │ │ ├── List.test.js │ │ │ ├── Card.test.js │ │ │ └── KanbanBoard.test.js │ │ └── reducers │ │ │ └── CardReducer.test.js │ └── TestUtils │ │ └── CardCreators.js ├── .bowerrc ├── Views │ ├── _ViewStart.cshtml │ ├── _ViewImports.cshtml │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ └── Index.cshtml │ └── Shared │ │ ├── Error.cshtml │ │ ├── _ReactLayout.cshtml │ │ └── _Layout.cshtml ├── tests.webpack.js ├── appsettings.json ├── bower.json ├── app │ ├── reducers │ │ ├── index.js │ │ └── draftCardReducer.js │ ├── cardUtils.js │ ├── store │ │ └── reduxStore.js │ ├── ReduxDispatcher.js │ ├── App.js │ ├── components │ │ ├── KanbanBoardContainer.js │ │ ├── KanbanBoard.js │ │ ├── List.js │ │ ├── NewCard.js │ │ ├── CheckList.js │ │ ├── EditCard.js │ │ ├── CardForm.js │ │ └── Card.js │ ├── actions │ │ ├── TaskActionCreators.js │ │ └── CardActionCreators.js │ ├── constants.js │ └── api │ │ └── KanbanApi.js ├── Program.cs ├── web.config ├── Models │ └── TaskData.cs ├── Properties │ └── launchSettings.json ├── Controllers │ └── HomeController.cs ├── bundleconfig.json ├── karma.conf.js ├── package.json ├── Startup.cs ├── ReactWebPack.CoreRC2.csproj └── webpack.config.js ├── ReactJsNet.MVC5 ├── Views │ ├── _ViewStart.cshtml │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ └── Web.config ├── favicon.ico ├── Global.asax ├── Scripts │ ├── _references.js │ └── respond.min.js ├── app │ ├── app.jsx │ ├── CommentList.jsx │ ├── Comment.jsx │ ├── CommentForm.jsx │ └── CommentBox.jsx ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff ├── App_Start │ ├── FilterConfig.cs │ ├── RouteConfig.cs │ ├── ReactConfig.cs │ ├── WebApiConfig.cs │ └── BundleConfig.cs ├── readme.txt ├── Content │ ├── Site.css │ └── base.css ├── Controllers │ ├── HomeController.cs │ └── CommentsController.cs ├── Global.asax.cs ├── Web.Debug.config ├── Web.Release.config ├── Properties │ └── AssemblyInfo.cs ├── Models │ └── Comment.cs ├── packages.config └── Web.config ├── ReactWebPack.MVC5 ├── Views │ ├── _ViewStart.cshtml │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ ├── _ReactLayout.cshtml │ │ └── _Layout.cshtml │ └── Web.config ├── favicon.ico ├── Global.asax ├── Scripts │ ├── _references.js │ └── respond.min.js ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff ├── App_Start │ ├── FilterConfig.cs │ ├── RouteConfig.cs │ ├── WebApiConfig.cs │ └── BundleConfig.cs ├── Content │ ├── Site.css │ └── kanban-styles.css ├── app │ ├── App.js │ ├── utils.js │ ├── AppDispatcher.js │ ├── components │ │ ├── KanbanBoardContainer.js │ │ ├── KanbanBoard.js │ │ ├── List.js │ │ ├── NewCard.js │ │ ├── CheckList.js │ │ ├── EditCard.js │ │ ├── CardForm.js │ │ └── Card.js │ ├── actions │ │ ├── TaskActionCreators.js │ │ └── CardActionCreators.js │ ├── stores │ │ └── DraftStore.js │ ├── constants.js │ └── api │ │ └── KanbanApi.js ├── Controllers │ └── HomeController.cs ├── Models │ └── TaskData.cs ├── Global.asax.cs ├── package.json ├── Web.Debug.config ├── Web.Release.config ├── Properties │ └── AssemblyInfo.cs ├── packages.config ├── webpack.config.js └── Web.config ├── ReactNpmTaskRunnerWindow.PNG ├── .vscode └── settings.json ├── ReactTests └── README.md ├── licence.txt ├── AspNetReactSamples.sln └── .gitattributes /ReactWebPack.CoreRC2/wwwroot/js/site.min.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/localSrc/InnerValue.js: -------------------------------------------------------------------------------- 1 | export default 42; -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "wwwroot/lib" 3 | } 4 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Write your Javascript code. 2 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactJsNet.MVC5/favicon.ico -------------------------------------------------------------------------------- /ReactNpmTaskRunnerWindow.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactNpmTaskRunnerWindow.PNG -------------------------------------------------------------------------------- /ReactWebPack.MVC5/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactWebPack.MVC5/favicon.ico -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/localSrc/InnerFunction.js: -------------------------------------------------------------------------------- 1 | export default function inner() { 2 | return 'Inner Function'; 3 | } -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using ReactWebPack.Core 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 3 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="ReactJsNet.MVC5.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/mocksEtc/MockInnerFunction.js: -------------------------------------------------------------------------------- 1 | export default function inner() { 2 | return 'Mocked Function'; 3 | } -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="ReactWebPack.MVC5.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Scripts/_references.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactJsNet.MVC5/Scripts/_references.js -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactWebPack.CoreRC2/wwwroot/favicon.ico -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Scripts/_references.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactWebPack.MVC5/Scripts/_references.js -------------------------------------------------------------------------------- /ReactJsNet.MVC5/app/app.jsx: -------------------------------------------------------------------------------- 1 | ReactDOM.render( 2 | , 3 | document.getElementById('content') 4 | ); -------------------------------------------------------------------------------- /ReactJsNet.MVC5/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactJsNet.MVC5/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /ReactJsNet.MVC5/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactJsNet.MVC5/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /ReactJsNet.MVC5/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactJsNet.MVC5/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /ReactWebPack.MVC5/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactWebPack.MVC5/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /ReactWebPack.MVC5/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactWebPack.MVC5/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /ReactWebPack.MVC5/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactWebPack.MVC5/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/tests.webpack.js: -------------------------------------------------------------------------------- 1 | var context = require.context('./JsUnitTests/Tests', true, /.test\.jsx?$/); 2 | //console.log(context.keys()); 3 | context.keys().forEach(context); 4 | module.exports = context; 5 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "About"; 3 | } 4 |

@ViewData["Title"].

5 |

@ViewData["Message"]

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactWebPack.CoreRC2/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactWebPack.CoreRC2/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactWebPack.CoreRC2/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonPSmith/AspNetReactSamples/HEAD/ReactWebPack.CoreRC2/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asp.net", 3 | "private": true, 4 | "dependencies": { 5 | "bootstrap": "3.3.6", 6 | "jquery": "2.2.0", 7 | "jquery-validation": "1.14.0", 8 | "jquery-validation-unobtrusive": "3.2.6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux' 2 | import cards from './cardReducer' 3 | import draftCard from './draftCardReducer' 4 | 5 | const reducers = combineReducers({ 6 | cards, 7 | draftCard 8 | }) 9 | 10 | export default reducers -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/css/site.min.css: -------------------------------------------------------------------------------- 1 | body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}input,select,textarea{max-width:280px}.carousel-caption p{font-size:20px;line-height:1.4}@media screen and (max-width:767px){.carousel-caption{display:none}} -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/localSrc/OuterFunction.js: -------------------------------------------------------------------------------- 1 | import InnerFunction from './InnerFunction'; 2 | import InnerValue from './InnerValue'; 3 | 4 | export default function outer() { 5 | return { 6 | innerFuncValue: InnerFunction(), 7 | innerValue:InnerValue 8 | } 9 | } -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/Tests/localTests/karam-setup.test.js: -------------------------------------------------------------------------------- 1 | var expect = require('expect'); 2 | 3 | describe('karam setup', 4 | function() { 5 | 6 | it('should run a test', 7 | function () { 8 | expect(true).toBeTruthy(); 9 | }); 10 | }); -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Error 6 | 7 | 8 |
9 |

Error.

10 |

An error occurred while processing your request.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Error 6 | 7 | 8 |
9 |

Error.

10 |

An error occurred while processing your request.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | //Setting for https://github.com/Microsoft/vscode-npm-scripts 4 | "npm.runInTerminal": true, 5 | "npm.includeDirectories": [ 6 | "ReactWebPack.MVC5", 7 | "ReactWebPack.CoreRC2" 8 | ], 9 | "npm.useRootDirectory": false 10 | } -------------------------------------------------------------------------------- /ReactJsNet.MVC5/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace ReactJsNet.MVC5 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace ReactWebPack.MVC5 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/localSrc/InnerConnect.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { connect } from 'react-redux'; 3 | 4 | export class InnerConnect extends Component { 5 | render () { 6 | return

Inner.dispatch {this.props.dispatch === undefined ? 'undefined' : 'defined' }

7 | } 8 | } 9 | 10 | export default connect()(InnerConnect) -------------------------------------------------------------------------------- /ReactJsNet.MVC5/app/CommentList.jsx: -------------------------------------------------------------------------------- 1 | var CommentList = React.createClass({ 2 | render: function() { 3 | var commentNodes = this.props.data.map(function(comment) { 4 | return ( 5 | 6 | {comment.text} 7 | 8 | ); 9 | }); 10 | return ( 11 |
12 | {commentNodes} 13 |
14 | ); 15 | } 16 | }); -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/cardUtils.js: -------------------------------------------------------------------------------- 1 | import { find, findIndex} from 'babel-polyfill'; 2 | 3 | export function getCard(cards, id) { 4 | if (!Array.isArray(cards)) { 5 | throw new Error('cards must be an array.') 6 | } 7 | return cards.find((card) => card.id == id); 8 | }; 9 | 10 | export function getCardIndex(cards, id) { 11 | if (!Array.isArray(cards)) { 12 | throw new Error('cards must be an array.') 13 | } 14 | return cards.findIndex((card) => card.id == id); 15 | }; -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/localSrc/OuterConnect.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { connect } from 'react-redux'; 3 | 4 | import InnerConnect from './InnerConnect'; 5 | 6 | export class OuterConnect extends Component { 7 | render () { 8 | return
9 |

Outer.dispatch {this.props.dispatch === undefined ? 'undefined' : 'defined' }

10 | 11 |
12 | } 13 | } 14 | 15 | export default connect()(OuterConnect) -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
-------------------------------------------------------------------------------- /ReactWebPack.MVC5/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
-------------------------------------------------------------------------------- /ReactJsNet.MVC5/app/Comment.jsx: -------------------------------------------------------------------------------- 1 | var Comment = React.createClass({ 2 | rawMarkup: function() { 3 | var rawMarkup = marked(this.props.children.toString(), {sanitize: true}); 4 | return { __html: rawMarkup }; 5 | }, 6 | 7 | render: function() { 8 | return ( 9 |
10 |

11 | {this.props.author} 12 |

13 | 14 |
15 | ); 16 | } 17 | }); -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Contact"; 3 | } 4 |

@ViewData["Title"].

5 |

@ViewData["Message"]

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
18 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/readme.txt: -------------------------------------------------------------------------------- 1 | To complete the installation of System.Web.Optimization.React, you need to create one or more 2 | bundles containing your JSX files: 3 | 4 | // In BundleConfig.cs 5 | bundles.Add(new BabelBundle("~/bundles/main").Include( 6 | // Add your JSX files here 7 | "~/Content/HelloWorld.react.jsx", 8 | "~/Content/AnythingElse.react.jsx", 9 | // You can include regular JavaScript files in the bundle too 10 | "~/Content/ajax.js", 11 | )); 12 | 13 | Please refer to http://reactjs.net/ for more details, usage examples and sample code. -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Program.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Microsoft.AspNetCore.Hosting; 3 | 4 | namespace ReactWebPack.Core 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | var host = new WebHostBuilder() 11 | .UseKestrel() 12 | .UseContentRoot(Directory.GetCurrentDirectory()) 13 | .UseIISIntegration() 14 | .UseStartup() 15 | .Build(); 16 | 17 | host.Run(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/TestUtils/CardCreators.js: -------------------------------------------------------------------------------- 1 | export function createCard(id = 0, status='done', tasks = []){ 2 | return { 3 | id, 4 | title: `Card${id} title`, 5 | description: `Card${id} description`, 6 | color: '#123456', 7 | status, 8 | tasks 9 | } 10 | } 11 | 12 | export function createCards(num = 3, status='done', tasks = []) { 13 | let result = [] 14 | for (let index = 0; index < num; index++) { 15 | result.push(createCard(index, status, tasks)); 16 | } 17 | return result; 18 | } -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/bootstrap/dist/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') -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Views/Shared/_ReactLayout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @ViewBag.Title - React Kanban example 7 | 8 | 9 | 10 |
11 | @RenderBody() 12 |
13 |
14 |

© @DateTime.Now.Year - My ASP.NET Application

15 |
16 |
17 | 18 | @RenderSection("scripts", required: false) 19 | 20 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/store/reduxStore.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from 'redux'; 2 | import thunk from 'redux-thunk'; 3 | import throttle from "redux-throttle"; 4 | import reducers from '../reducers/index'; 5 | 6 | const defaultThrottleOption = { // https://lodash.com/docs#throttle 7 | leading: true, 8 | trailing: false 9 | } 10 | 11 | const throttleMiddleWare = throttle(500, defaultThrottleOption); //default 500ms, 12 | 13 | const reduxStore = createStore( 14 | reducers, 15 | applyMiddleware(thunk, throttleMiddleWare) 16 | ); 17 | 18 | export default reduxStore; -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Set padding to keep content from hitting the edges */ 7 | .body-content { 8 | padding-left: 15px; 9 | padding-right: 15px; 10 | } 11 | 12 | /* Override the default bootstrap behavior where horizontal description lists 13 | will truncate terms that are too long to fit in the left column 14 | */ 15 | .dl-horizontal dt { 16 | white-space: normal; 17 | } 18 | 19 | /* Set width on the form input elements since they're 100% wide by default */ 20 | input, 21 | select, 22 | textarea { 23 | max-width: 280px; 24 | } 25 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Set padding to keep content from hitting the edges */ 7 | .body-content { 8 | padding-left: 15px; 9 | padding-right: 15px; 10 | } 11 | 12 | /* Override the default bootstrap behavior where horizontal description lists 13 | will truncate terms that are too long to fit in the left column 14 | */ 15 | .dl-horizontal dt { 16 | white-space: normal; 17 | } 18 | 19 | /* Set width on the form input elements since they're 100% wide by default */ 20 | input, 21 | select, 22 | textarea { 23 | max-width: 280px; 24 | } 25 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; import { render } from 'react-dom'; import { Router, Route, browserHistory } from 'react-router'; import KanbanBoardContainer from './components/KanbanBoardContainer'; import KanbanBoard from './components/KanbanBoard'; import EditCard from './components/EditCard'; import NewCard from './components/NewCard'; render(( ), document.getElementById('root')); -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ], 14 | "homepage": "https://github.com/jquery/jquery-dist", 15 | "version": "2.2.0", 16 | "_release": "2.2.0", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "2.2.0", 20 | "commit": "6fc01e29bdad0964f62ef56d01297039cdcadbe5" 21 | }, 22 | "_source": "git://github.com/jquery/jquery-dist.git", 23 | "_target": "2.2.0", 24 | "_originalSource": "jquery" 25 | } -------------------------------------------------------------------------------- /ReactJsNet.MVC5/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace ReactJsNet.MVC5 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace ReactWebPack.MVC5 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/mocksEtc/WrapTestDnD.js: -------------------------------------------------------------------------------- 1 | //See http://gaearon.github.io/react-dnd/docs-testing.html , section 'Testing the Drag and Drop Interaction' 2 | 3 | import React, { Component } from 'react'; 4 | 5 | import TestBackend from 'react-dnd-test-backend'; 6 | import { DragDropContext } from 'react-dnd'; 7 | 8 | 9 | /** 10 | * Wraps a component into a DragDropContext that uses the TestBackend. 11 | */ 12 | export function wrapInTestContext(DecoratedComponent) { 13 | return DragDropContext(TestBackend)( 14 | class TestContextContainer extends Component { 15 | render() { 16 | return ; 17 | } 18 | } 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /ReactTests/README.md: -------------------------------------------------------------------------------- 1 | # ReactTests has been removed 2 | 3 | If you arrived here then it is via an old link, as ReactTests has been removed and has become 4 | part of the 5 | [ReactWebPack.CoreRC2](https://github.com/JonPSmith/AspNetReactSamples/tree/master/ReactWebPack.CoreRC2) 6 | project. 7 | 8 | I initially set up the React Unit Tests as a separate project, but this proved to be a mistake. 9 | The problem is being seperate from the code it was testing can cause a 10 | [multiple copies of React](https://fb.me/react-refs-must-have-owner) 11 | error in some cases. 12 | 13 | Please have a look at the top-level [README file](https://github.com/JonPSmith/AspNetReactSamples) 14 | for more information on the Unit Tests and articles. 15 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Wrapping element */ 7 | /* Set some basic padding to keep content from hitting the edges */ 8 | .body-content { 9 | padding-left: 15px; 10 | padding-right: 15px; 11 | } 12 | 13 | /* Set widths on the form inputs since otherwise they're 100% wide */ 14 | input, 15 | select, 16 | textarea { 17 | max-width: 280px; 18 | } 19 | 20 | /* Carousel */ 21 | .carousel-caption p { 22 | font-size: 20px; 23 | line-height: 1.4; 24 | } 25 | /* Hide/rearrange for smaller screens */ 26 | @media screen and (max-width: 767px) { 27 | /* Hide captions */ 28 | .carousel-caption { 29 | display: none 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | 7 | namespace ReactJsNet.MVC5.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public ActionResult Index() 12 | { 13 | return View(); 14 | } 15 | 16 | public ActionResult About() 17 | { 18 | ViewBag.Message = "Your application description page."; 19 | 20 | return View(); 21 | } 22 | 23 | public ActionResult Contact() 24 | { 25 | ViewBag.Message = "Your contact page."; 26 | 27 | return View(); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | 7 | namespace ReactWebPack.MVC5.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public ActionResult Index() 12 | { 13 | return View(); 14 | } 15 | 16 | public ActionResult About() 17 | { 18 | ViewBag.Message = "Your application description page."; 19 | 20 | return View(); 21 | } 22 | 23 | public ActionResult Contact() 24 | { 25 | ViewBag.Message = "Your contact page."; 26 | 27 | return View(); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/mocksEtc/MockPromise.js: -------------------------------------------------------------------------------- 1 | //This is a super-simple mock of a JavaScript Promise 2 | //It only implement the 'then(success, failure)' function 3 | //as that is the only function that the kanban calls 4 | //in the modules that use the KanbanApi 5 | class MockPromise { 6 | constructor(returnSuccess, result) { 7 | this.returnSuccess = returnSuccess; 8 | this.result = result || (returnSuccess ? 'my data': 'my error') 9 | } 10 | 11 | then(success, failure) { 12 | if (this.returnSuccess) { 13 | success(this.result); 14 | } 15 | else { 16 | failure(this.result); 17 | } 18 | } 19 | } 20 | 21 | export default MockPromise 22 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Models/TaskData.cs: -------------------------------------------------------------------------------- 1 | #region licence 2 | // ===================================================== 3 | // AspNetReactSample solution - using React js with ASP.NET MVC 4 | // Filename: TaskData.cs 5 | // Date Created: 2016/05/03 6 | // 7 | // Under the MIT License (MIT) 8 | // 9 | // Written by Jon Smith : GitHub JonPSmith, www.thereformedprogrammer.net 10 | // ===================================================== 11 | #endregion 12 | namespace ReactWebPack.MVC5.Models 13 | { 14 | public class TaskData 15 | { 16 | // ReSharper disable InconsistentNaming 17 | public long id { get; set; } 18 | public string name { get; set; } 19 | public bool done { get; set; } 20 | // ReSharper restore InconsistentNaming 21 | } 22 | } -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/utils.js: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill'; 2 | 3 | export const throttle = (func, wait) => { 4 | let context, args, prevArgs, argsChanged, result; 5 | let previous = 0; 6 | return function() { 7 | let now, remaining; 8 | if(wait){ 9 | now = Date.now(); 10 | remaining = wait - (now - previous); 11 | } 12 | context = this; 13 | args = arguments; 14 | argsChanged = JSON.stringify(args) != JSON.stringify(prevArgs); 15 | prevArgs = Object.assign({}, args); 16 | if (argsChanged || wait && (remaining <= 0 || remaining > wait)) { 17 | if(wait){ 18 | previous = now; 19 | } 20 | result = func.apply(context, args); 21 | context = args = null; 22 | } 23 | return result; 24 | }; 25 | }; 26 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Models/TaskData.cs: -------------------------------------------------------------------------------- 1 | #region licence 2 | // ===================================================== 3 | // AspNetReactSample solution - using React js with ASP.NET MVC 4 | // Filename: TaskData.cs 5 | // Date Created: 2016/05/03 6 | // 7 | // Under the MIT License (MIT) 8 | // 9 | // Written by Jon Smith : GitHub JonPSmith, www.thereformedprogrammer.net 10 | // ===================================================== 11 | #endregion 12 | namespace ReactWebPack.Core.Models 13 | { 14 | public class TaskData 15 | { 16 | // ReSharper disable InconsistentNaming 17 | public long id { get; set; } 18 | public string name { get; set; } 19 | public bool done { get; set; } 20 | // ReSharper restore InconsistentNaming 21 | } 22 | } -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:55685/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "ReactWebPack.Core": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "launchUrl": "http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace ReactWebPack.Core.Controllers 4 | { 5 | public class HomeController : Controller 6 | { 7 | public IActionResult Index() 8 | { 9 | return View(); 10 | } 11 | 12 | public IActionResult About() 13 | { 14 | ViewData["Message"] = "Your application description page."; 15 | 16 | return View(); 17 | } 18 | 19 | public IActionResult Contact() 20 | { 21 | ViewData["Message"] = "Your contact page."; 22 | 23 | return View(); 24 | } 25 | 26 | public IActionResult Error() 27 | { 28 | return View(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Home Page"; 3 | Layout = "~/Views/Shared/_ReactLayout.cshtml"; 4 | } 5 |

6 | This is an ASP.NET Core (1.0.0) web site using React code which was built by 7 | WebPack 8 | with Babel js doing the transpiling. 9 |

10 |

11 | This application was downloaded from Pro React GitHub, Chapter 6 12 | with major changes to use Redux store instead of the original Flex store. 13 |

14 |
15 | 16 |
17 |
18 | 19 | @section scripts{ 20 | 21 | } -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = null; 3 | } 4 | 5 | 6 | Hello React 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | @Scripts.Render("~/bundles/react") 18 | 19 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/AppDispatcher.js: -------------------------------------------------------------------------------- 1 | import {Dispatcher} from 'flux'; 2 | import 'babel-polyfill'; 3 | 4 | class AppDispatcher extends Dispatcher{ 5 | /** 6 | * Dispatches three actions for an async operation represented by promise. 7 | */ 8 | dispatchAsync(promise, types, payload){ 9 | const { request, success, failure } = types; 10 | this.dispatch({ type: request, payload: Object.assign({}, payload) }); 11 | promise.then( 12 | response => this.dispatch({ 13 | type: success, 14 | payload: Object.assign({}, payload, { response }) 15 | }), 16 | error => this.dispatch({ 17 | type: failure, 18 | payload: Object.assign({}, payload, { error }) 19 | }) 20 | ); 21 | } 22 | } 23 | 24 | export default new AppDispatcher(); 25 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Error"; 3 | } 4 | 5 |

Error.

6 |

An error occurred while processing your request.

7 | 8 |

Development Mode

9 |

10 | Swapping to Development environment will display more detailed information about the error that occurred. 11 |

12 |

13 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 14 |

15 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/localSrc/CheckboxWithLabel.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | 3 | class CheckboxWithLabel extends Component { 4 | 5 | constructor() { 6 | super(...arguments); 7 | this.state = {isChecked: false}; 8 | this.onChange = this.onChange.bind(this); 9 | } 10 | 11 | onChange() { 12 | this.setState({isChecked: !this.state.isChecked}); 13 | } 14 | 15 | render() { 16 | return ( 17 | 23 | ); 24 | } 25 | } 26 | 27 | export default CheckboxWithLabel; -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/ReduxDispatcher.js: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill'; 2 | 3 | 4 | /** 5 | * This does the async request and provides Redux thunk feedback 6 | */ 7 | export function dispatchAsync(promise, dispatch, types, payload) { 8 | if (typeof dispatch !== 'function'){ 9 | throw new Error('dispatch was not a function. Did you miss an update to the call?') 10 | } 11 | const { request, success, failure } = types; 12 | dispatch({ 13 | type: request, 14 | payload: Object.assign({}, payload) 15 | }); 16 | promise.then( 17 | response => dispatch({ 18 | type: success, 19 | success: true, 20 | payload: Object.assign({}, payload, { response }) 21 | }), 22 | error => dispatch({ 23 | type: failure, 24 | success: false, 25 | payload: Object.assign({}, payload, { error }) 26 | }) 27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Http; 6 | using System.Web.Mvc; 7 | using System.Web.Optimization; 8 | using System.Web.Routing; 9 | 10 | namespace ReactWebPack.MVC5 11 | { 12 | public class MvcApplication : System.Web.HttpApplication 13 | { 14 | protected void Application_Start() 15 | { 16 | AreaRegistration.RegisterAllAreas(); 17 | 18 | // Manually installed WebAPI 2.2 after making an MVC project. 19 | GlobalConfiguration.Configure(WebApiConfig.Register); 20 | 21 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 22 | RouteConfig.RegisterRoutes(RouteTable.Routes); 23 | BundleConfig.RegisterBundles(BundleTable.Bundles); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Http; 6 | using System.Web.Mvc; 7 | using System.Web.Optimization; 8 | using System.Web.Routing; 9 | 10 | 11 | namespace ReactJsNet.MVC5 12 | { 13 | public class MvcApplication : System.Web.HttpApplication 14 | { 15 | protected void Application_Start() 16 | { 17 | AreaRegistration.RegisterAllAreas(); 18 | 19 | // Manually installed WebAPI 2.2 after making an MVC project. 20 | GlobalConfiguration.Configure(WebApiConfig.Register); 21 | 22 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 23 | RouteConfig.RegisterRoutes(RouteTable.Routes); 24 | BundleConfig.RegisterBundles(BundleTable.Bundles); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/components/KanbanBoardContainer.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import {Container} from 'flux/utils'; 3 | import KanbanBoard from './KanbanBoard'; 4 | import CardActionCreators from '../actions/CardActionCreators'; 5 | import CardStore from '../stores/CardStore'; 6 | 7 | class KanbanBoardContainer extends Component { 8 | 9 | componentDidMount(){ 10 | CardActionCreators.fetchCards(); 11 | } 12 | 13 | 14 | render() { 15 | let kanbanBoard = this.props.children && React.cloneElement(this.props.children, { 16 | cards: this.state.cards, 17 | }); 18 | 19 | return kanbanBoard; 20 | } 21 | 22 | } 23 | 24 | KanbanBoardContainer.getStores = () => ([CardStore]); 25 | KanbanBoardContainer.calculateState = (prevState) => ({ 26 | cards: CardStore.getState() 27 | }); 28 | 29 | export default Container.create(KanbanBoardContainer); 30 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import { Router, Route, browserHistory } from 'react-router'; 4 | import { Provider } from 'react-redux'; 5 | import reduxStore from './store/reduxStore'; 6 | import reducers from './reducers/index'; 7 | import KanbanBoardContainer from './components/KanbanBoardContainer'; 8 | import KanbanBoard from './components/KanbanBoard'; 9 | import EditCard from './components/EditCard'; 10 | import NewCard from './components/NewCard'; 11 | 12 | render(( 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | ), document.getElementById('root')); 24 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/reducers/draftCardReducer.js: -------------------------------------------------------------------------------- 1 | import constants from '../constants'; 2 | import update from 'react-addons-update'; 3 | 4 | let initialState = { 5 | id: Date.now(), 6 | title:'', 7 | description:'', 8 | status:'todo', 9 | color:'#c9c9c9', 10 | tasks:[] 11 | }; 12 | const initialAction = { type: 'initial state'} 13 | 14 | const draftCard = (state = initialState, action = initialAction) => { 15 | switch (action.type) { 16 | case constants.CREATE_DRAFT: 17 | if(action.payload.card){ 18 | return update(state, { 19 | $set: action.payload.card 20 | }); 21 | } else { 22 | return initialState; 23 | } 24 | 25 | case constants.UPDATE_DRAFT: 26 | return update(state, { 27 | [action.payload.field]: { 28 | $set: action.payload.value 29 | } 30 | }); 31 | 32 | default: 33 | return state; 34 | } 35 | } 36 | 37 | export default draftCard; 38 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/components/KanbanBoardContainer.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { bindActionCreators } from 'redux' 3 | import { connect } from 'react-redux'; 4 | import KanbanBoard from '../components/KanbanBoard'; 5 | import CardActionCreators from '../actions/CardActionCreators'; 6 | 7 | export class KanbanBoardContainer extends Component { 8 | 9 | componentDidMount(){ 10 | this.props.fetchCards(); 11 | } 12 | 13 | render() { 14 | let kanbanBoard = this.props.children && React.cloneElement(this.props.children, { 15 | cards: this.props.cards, 16 | }); 17 | 18 | return kanbanBoard; 19 | } 20 | } 21 | 22 | function mapStoreToProps(storeState) { 23 | return { 24 | cards: storeState.cards 25 | } 26 | } 27 | 28 | function mapDispatchToProps(dispatch) { 29 | return { 30 | fetchCards: () => dispatch(CardActionCreators.fetchCards()) 31 | } 32 | } 33 | export default connect( 34 | mapStoreToProps, 35 | mapDispatchToProps 36 | )(KanbanBoardContainer); 37 | 38 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/jquery-validation/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation", 3 | "homepage": "http://jqueryvalidation.org/", 4 | "repository": { 5 | "type": "git", 6 | "url": "git://github.com/jzaefferer/jquery-validation.git" 7 | }, 8 | "authors": [ 9 | "Jörn Zaefferer " 10 | ], 11 | "description": "Form validation made easy", 12 | "main": "dist/jquery.validate.js", 13 | "keywords": [ 14 | "forms", 15 | "validation", 16 | "validate" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "demo", 25 | "lib" 26 | ], 27 | "dependencies": { 28 | "jquery": ">= 1.7.2" 29 | }, 30 | "version": "1.14.0", 31 | "_release": "1.14.0", 32 | "_resolution": { 33 | "type": "version", 34 | "tag": "1.14.0", 35 | "commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48" 36 | }, 37 | "_source": "git://github.com/jzaefferer/jquery-validation.git", 38 | "_target": ">=1.8", 39 | "_originalSource": "jquery-validation" 40 | } -------------------------------------------------------------------------------- /ReactJsNet.MVC5/App_Start/ReactConfig.cs: -------------------------------------------------------------------------------- 1 | using React; 2 | 3 | [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(ReactJsNet.MVC5.ReactConfig), "Configure")] 4 | 5 | namespace ReactJsNet.MVC5 6 | { 7 | public static class ReactConfig 8 | { 9 | public static void Configure() 10 | { 11 | // If you want to use server-side rendering of React components, 12 | // add all the necessary JavaScript files here. This includes 13 | // your components as well as all of their dependencies. 14 | // See http://reactjs.net/ for more information. Example: 15 | //ReactSiteConfiguration.Configuration 16 | // .AddScript("~/Scripts/First.jsx") 17 | // .AddScript("~/Scripts/Second.jsx"); 18 | 19 | // If you use an external build too (for example, Babel, Webpack, 20 | // Browserify or Gulp), you can improve performance by disabling 21 | // ReactJS.NET's version of Babel and loading the pre-transpiled 22 | // scripts. Example: 23 | //ReactSiteConfiguration.Configuration 24 | // .SetLoadBabel(false) 25 | // .AddScriptWithoutTransform("~/Scripts/bundle.server.js") 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/bundleconfig.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "outputFileName": "wwwroot/css/site.min.css", 4 | "inputFiles": [ 5 | "wwwroot/css/site.css" 6 | ] 7 | }, 8 | { 9 | "outputFileName": "wwwroot/js/site.min.js", 10 | "inputFiles": [ 11 | "wwwroot/js/site.js" 12 | ], 13 | "minify": { 14 | "enabled": true, 15 | "renameLocals": true 16 | } 17 | }, 18 | { 19 | "outputFileName": "wwwroot/css/kanban-styles.min.css", 20 | "inputFiles": [ 21 | "wwwroot/css/kanban-styles.css" 22 | ] 23 | }, 24 | { 25 | "outputFileName": "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", 26 | "inputFiles": [ 27 | "wwwroot/lib/bootstrap/dist/css/bootstrap.css" 28 | ] 29 | }, 30 | { 31 | "outputFileName": "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", 32 | "inputFiles": [ 33 | "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css" 34 | ] 35 | }, 36 | { 37 | "outputFileName": "wwwroot/lib/jquery/dist/jquery.min.js", 38 | "inputFiles": [ 39 | "wwwroot/lib/jquery/dist/jquery.js" 40 | ] 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Http; 2 | 3 | //Taken from http://stackoverflow.com/a/26067297/1434764 4 | 5 | namespace ReactJsNet.MVC5 6 | { 7 | public static class WebApiConfig 8 | { 9 | public static void Register(HttpConfiguration config) 10 | { 11 | // TODO: Add any additional configuration code. 12 | 13 | // Web API routes 14 | config.MapHttpAttributeRoutes(); 15 | 16 | config.Routes.MapHttpRoute( 17 | name: "DefaultApi", 18 | routeTemplate: "api/{controller}/{id}", 19 | defaults: new { id = RouteParameter.Optional } 20 | ); 21 | 22 | // WebAPI when dealing with JSON & JavaScript! 23 | // Setup json serialization to serialize classes to camel (std. Json format) 24 | var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter; 25 | formatter.SerializerSettings.ContractResolver = 26 | new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(); 27 | 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Content/base.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #fff; 3 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 4 | font-size: 15px; 5 | line-height: 1.7; 6 | margin: 0; 7 | padding: 30px; 8 | } 9 | 10 | a { 11 | color: #4183c4; 12 | text-decoration: none; 13 | } 14 | 15 | a:hover { 16 | text-decoration: underline; 17 | } 18 | 19 | code { 20 | background-color: #f8f8f8; 21 | border: 1px solid #ddd; 22 | border-radius: 3px; 23 | font-family: "Bitstream Vera Sans Mono", Consolas, Courier, monospace; 24 | font-size: 12px; 25 | margin: 0 2px; 26 | padding: 0 5px; 27 | } 28 | 29 | h1, h2, h3, h4 { 30 | font-weight: bold; 31 | margin: 0 0 15px; 32 | padding: 0; 33 | } 34 | 35 | h1 { 36 | border-bottom: 1px solid #ddd; 37 | font-size: 2.5em; 38 | font-weight: bold; 39 | margin: 0 0 15px; 40 | padding: 0; 41 | } 42 | 43 | h2 { 44 | border-bottom: 1px solid #eee; 45 | font-size: 2em; 46 | } 47 | 48 | h3 { 49 | font-size: 1.5em; 50 | } 51 | 52 | h4 { 53 | font-size: 1.2em; 54 | } 55 | 56 | p, ul { 57 | margin: 15px 0; 58 | } 59 | 60 | ul { 61 | padding-left: 30px; 62 | } -------------------------------------------------------------------------------- /ReactWebPack.MVC5/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Http; 2 | 3 | 4 | //Taken from http://stackoverflow.com/a/26067297/1434764 5 | 6 | namespace ReactWebPack.MVC5 7 | { 8 | public static class WebApiConfig 9 | { 10 | public static void Register(HttpConfiguration config) 11 | { 12 | // TODO: Add any additional configuration code. 13 | 14 | // Web API routes 15 | config.MapHttpAttributeRoutes(); 16 | 17 | config.Routes.MapHttpRoute( 18 | name: "DefaultApi", 19 | routeTemplate: "api/{controller}/{id}", 20 | defaults: new { id = RouteParameter.Optional } 21 | ); 22 | 23 | // WebAPI when dealing with JSON & JavaScript! 24 | // Setup json serialization to serialize classes to camel (std. Json format) 25 | var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter; 26 | formatter.SerializerSettings.ContractResolver = 27 | new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(); 28 | 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/bootstrap/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": "1.9.1 - 2" 33 | }, 34 | "version": "3.3.6", 35 | "_release": "3.3.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.3.6", 39 | "commit": "81df608a40bf0629a1dc08e584849bb1e43e0b7a" 40 | }, 41 | "_source": "git://github.com/twbs/bootstrap.git", 42 | "_target": "3.3.6", 43 | "_originalSource": "bootstrap" 44 | } -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/components/KanbanBoard.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { DragDropContext } from 'react-dnd'; 3 | import HTML5Backend from 'react-dnd-html5-backend'; 4 | import { Link } from 'react-router'; 5 | import List from './List'; 6 | 7 | class KanbanBoard extends Component { 8 | render(){ 9 | return ( 10 |
11 | + 12 | 13 | card.status === "todo")} /> 16 | card.status === "in-progress")} /> 19 | card.status === "done")} /> 22 | 23 | {this.props.children} 24 |
25 | ); 26 | } 27 | }; 28 | KanbanBoard.propTypes = { 29 | cards: PropTypes.arrayOf(PropTypes.object), 30 | }; 31 | 32 | export default DragDropContext(HTML5Backend)(KanbanBoard); 33 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/components/KanbanBoard.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { DragDropContext } from 'react-dnd'; 3 | import HTML5Backend from 'react-dnd-html5-backend'; 4 | import { Link } from 'react-router'; 5 | import List from './List'; 6 | 7 | export class KanbanBoard extends Component { 8 | render(){ 9 | return ( 10 |
11 | + 12 | 13 | card.status === "todo")} /> 16 | card.status === "in-progress")} /> 19 | card.status === "done")} /> 22 | 23 | {this.props.children} 24 |
25 | ); 26 | } 27 | }; 28 | KanbanBoard.propTypes = { 29 | cards: PropTypes.arrayOf(PropTypes.object), 30 | }; 31 | 32 | export default DragDropContext(HTML5Backend)(KanbanBoard); 33 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/actions/TaskActionCreators.js: -------------------------------------------------------------------------------- 1 | import AppDispatcher from '../AppDispatcher'; 2 | import constants from '../constants'; 3 | import KanbanAPI from '../api/KanbanApi'; 4 | 5 | let TaskActionCreators = { 6 | addTask(cardId, task) { 7 | AppDispatcher.dispatchAsync(KanbanAPI.addTask(cardId, task), { 8 | request: constants.CREATE_TASK, 9 | success: constants.CREATE_TASK_SUCCESS, 10 | failure: constants.CREATE_TASK_ERROR 11 | }, {cardId, task}); 12 | }, 13 | 14 | deleteTask(cardId, task, taskIndex) { 15 | AppDispatcher.dispatchAsync(KanbanAPI.deleteTask(cardId, task), { 16 | request: constants.DELETE_TASK, 17 | success: constants.DELETE_TASK_SUCCESS, 18 | failure: constants.DELETE_TASK_ERROR 19 | }, {cardId, task, taskIndex}); 20 | }, 21 | 22 | toggleTask(cardId, task, taskIndex) { 23 | AppDispatcher.dispatchAsync(KanbanAPI.toggleTask(cardId, task), { 24 | request: constants.TOGGLE_TASK, 25 | success: constants.TOGGLE_TASK_SUCCESS, 26 | failure: constants.TOGGLE_TASK_ERROR 27 | }, {cardId, task, taskIndex}); 28 | } 29 | 30 | }; 31 | 32 | export default TaskActionCreators; 33 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/stores/DraftStore.js: -------------------------------------------------------------------------------- 1 | import AppDispatcher from '../AppDispatcher'; 2 | import constants from '../constants'; 3 | import {ReduceStore} from 'flux/utils'; 4 | import update from 'react-addons-update'; 5 | 6 | let defaultDraft = () => { 7 | return { 8 | id: Date.now(), 9 | title:'', 10 | description:'', 11 | status:'todo', 12 | color:'#c9c9c9', 13 | tasks:[] 14 | } 15 | }; 16 | 17 | class DraftStore extends ReduceStore { 18 | getInitialState() { 19 | return {}; 20 | } 21 | 22 | reduce(state, action){ 23 | switch (action.type) { 24 | case constants.CREATE_DRAFT: 25 | if(action.payload.card){ 26 | return update(this.getState(), { 27 | $set: action.payload.card 28 | }); 29 | } else { 30 | return defaultDraft(); 31 | } 32 | 33 | case constants.UPDATE_DRAFT: 34 | return update(this.getState(), { 35 | [action.payload.field]: { 36 | $set: action.payload.value 37 | } 38 | }); 39 | 40 | default: 41 | return state; 42 | } 43 | } 44 | } 45 | 46 | export default new DraftStore(AppDispatcher); 47 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2015 Twitter, Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /licence.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Jon Smith (www.thereformedprogrammer.net & JonPSmith on GitHub) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /ReactWebPack.MVC5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kanban-app", 3 | "version": "0.1.0", 4 | "description": "Example React with WebPack in ASP.NET MVC5", 5 | "author": "Jon Smith", 6 | "license": "MIT", 7 | "scripts": { 8 | "dev-build": "webpack -d --config webpack.config.js --colors", 9 | "dev-watch": "webpack -d --config webpack.config.js --watch --colors", 10 | "prod-build": "SET NODE_ENV=production&&webpack -p --config webpack.config.js --colors" 11 | }, 12 | "dependencies": { 13 | "flux": "2.1.1", 14 | "history": "2.1.1", 15 | "marked": "0.3.5", 16 | "react": "15.0.2", 17 | "react-dom": "15.0.2", 18 | "react-router": "2.4.0", 19 | "react-addons-css-transition-group": "15.0.2", 20 | "react-addons-update": "15.0.2", 21 | "react-dnd": "2.1.4", 22 | "react-dnd-html5-backend": "2.1.2", 23 | "whatwg-fetch": "1.0.0", 24 | "babel-polyfill": "6.8.0" 25 | }, 26 | "devDependencies": { 27 | "babel-core": "6.8.0", 28 | "babel-loader": "6.2.4", 29 | "babel-preset-es2015": "6.6.0", 30 | "babel-preset-react": "6.5.0", 31 | "webpack": "1.13.0", 32 | "webpack-dev-server": "1.13.0", 33 | "html-webpack-plugin": "2.16.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/components/List.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { DropTarget } from 'react-dnd'; 3 | import Card from './Card'; 4 | import constants from '../constants'; 5 | import CardActionCreators from '../actions/CardActionCreators'; 6 | 7 | const listTargetSpec = { 8 | hover(props, monitor) { 9 | const dragged = monitor.getItem(); 10 | CardActionCreators.updateCardStatus(dragged.id, props.id); 11 | } 12 | }; 13 | 14 | function collect(connect, monitor) { 15 | return { 16 | connectDropTarget: connect.dropTarget() 17 | }; 18 | } 19 | 20 | class List extends Component { 21 | render() { 22 | const { connectDropTarget } = this.props; 23 | 24 | let cards = this.props.cards.map((card) => { 25 | return 26 | }); 27 | 28 | return connectDropTarget( 29 |
30 |

{this.props.title}

31 | {cards} 32 |
33 | ); 34 | } 35 | }; 36 | List.propTypes = { 37 | title: PropTypes.string.isRequired, 38 | cards: PropTypes.arrayOf(PropTypes.object), 39 | connectDropTarget: PropTypes.func.isRequired 40 | }; 41 | 42 | export default DropTarget(constants.CARD, listTargetSpec, collect)(List); 43 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/actions/TaskActionCreators.js: -------------------------------------------------------------------------------- 1 | import { dispatchAsync } from '../ReduxDispatcher' 2 | import constants from '../constants'; 3 | import KanbanAPI from '../api/KanbanApi'; 4 | 5 | let TaskActionCreators = { 6 | addTask(cardId, task) { 7 | return (dispatch) => { 8 | dispatchAsync(KanbanAPI.addTask(cardId, task), dispatch, { 9 | request: constants.CREATE_TASK, 10 | success: constants.CREATE_TASK_SUCCESS, 11 | failure: constants.CREATE_TASK_ERROR 12 | }, { cardId, task }); 13 | } 14 | }, 15 | 16 | deleteTask(cardId, task, taskIndex) { 17 | return (dispatch) => { 18 | dispatchAsync(KanbanAPI.deleteTask(cardId, task), dispatch, { 19 | request: constants.DELETE_TASK, 20 | success: constants.DELETE_TASK_SUCCESS, 21 | failure: constants.DELETE_TASK_ERROR 22 | }, { cardId, task, taskIndex }); 23 | } 24 | }, 25 | 26 | toggleTask(cardId, task, taskIndex) { 27 | return (dispatch) => { 28 | dispatchAsync(KanbanAPI.toggleTask(cardId, task), dispatch, { 29 | request: constants.TOGGLE_TASK, 30 | success: constants.TOGGLE_TASK_SUCCESS, 31 | failure: constants.TOGGLE_TASK_ERROR 32 | }, { cardId, task, taskIndex }); 33 | } 34 | } 35 | 36 | }; 37 | 38 | export default TaskActionCreators; 39 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/components/List.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { DropTarget } from 'react-dnd'; 3 | import Card from './Card'; 4 | import constants from '../constants'; 5 | import CardActionCreators from '../actions/CardActionCreators'; 6 | import { connect } from 'react-redux'; 7 | 8 | const listTargetSpec = { 9 | hover(props, monitor) { 10 | const dragged = monitor.getItem(); 11 | props.dispatch(CardActionCreators.updateCardStatus(dragged.id, props.id)); 12 | } 13 | }; 14 | 15 | function collect(connect, monitor) { 16 | return { 17 | connectDropTarget: connect.dropTarget() 18 | }; 19 | } 20 | 21 | export class List extends Component { 22 | render() { 23 | const { connectDropTarget } = this.props; 24 | 25 | let cards = this.props.cards.map((card) => { 26 | return 27 | }); 28 | 29 | return connectDropTarget( 30 |
31 |

{this.props.title}

32 | {cards} 33 |
34 | ); 35 | } 36 | }; 37 | List.propTypes = { 38 | title: PropTypes.string.isRequired, 39 | cards: PropTypes.arrayOf(PropTypes.object), 40 | connectDropTarget: PropTypes.func.isRequired 41 | }; 42 | 43 | export default connect()(DropTarget(constants.CARD, listTargetSpec, collect)(List)) -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/components/NewCard.js: -------------------------------------------------------------------------------- 1 | import React,{Component} from 'react'; 2 | import CardForm from './CardForm'; 3 | import DraftStore from '../stores/DraftStore'; 4 | import {Container} from 'flux/utils'; 5 | import CardActionCreators from '../actions/CardActionCreators'; 6 | 7 | class NewCard extends Component{ 8 | 9 | handleChange(field, value){ 10 | CardActionCreators.updateDraft(field, value); 11 | } 12 | 13 | handleSubmit(e){ 14 | e.preventDefault(); 15 | CardActionCreators.addCard(this.state.draft); 16 | this.props.history.pushState(null,'/'); 17 | } 18 | 19 | handleClose(e){ 20 | this.props.history.pushState(null,'/'); 21 | } 22 | 23 | componentDidMount(){ 24 | setTimeout(()=>CardActionCreators.createDraft(), 0) 25 | } 26 | 27 | 28 | render(){ 29 | return ( 30 | 35 | ); 36 | } 37 | } 38 | 39 | NewCard.getStores = () => ([DraftStore]); 40 | NewCard.calculateState = (prevState) => ({ 41 | draft: DraftStore.getState() 42 | }); 43 | 44 | export default Container.create(NewCard); 45 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/app/CommentForm.jsx: -------------------------------------------------------------------------------- 1 | var CommentForm = React.createClass({ 2 | getInitialState: function() { 3 | return {author: '', text: ''}; 4 | }, 5 | handleAuthorChange: function(e) { 6 | this.setState({author: e.target.value}); 7 | }, 8 | handleTextChange: function(e) { 9 | this.setState({text: e.target.value}); 10 | }, 11 | handleSubmit: function(e) { 12 | e.preventDefault(); 13 | var author = this.state.author.trim(); 14 | var text = this.state.text.trim(); 15 | if (!text || !author) { 16 | return; 17 | } 18 | this.props.onCommentSubmit({author: author, text: text}); 19 | this.setState({author: '', text: ''}); 20 | }, 21 | render: function() { 22 | return ( 23 |
24 | 30 | 36 | 37 |
38 | ); 39 | } 40 | }); -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/jquery-validation-unobtrusive/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation-unobtrusive", 3 | "version": "3.2.6", 4 | "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive", 5 | "description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.", 6 | "main": [ 7 | "jquery.validate.unobtrusive.js" 8 | ], 9 | "ignore": [ 10 | "**/.*", 11 | "*.json", 12 | "*.md", 13 | "*.txt", 14 | "gulpfile.js" 15 | ], 16 | "keywords": [ 17 | "jquery", 18 | "asp.net", 19 | "mvc", 20 | "validation", 21 | "unobtrusive" 22 | ], 23 | "authors": [ 24 | "Microsoft" 25 | ], 26 | "license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm", 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/aspnet/jquery-validation-unobtrusive.git" 30 | }, 31 | "dependencies": { 32 | "jquery-validation": ">=1.8", 33 | "jquery": ">=1.8" 34 | }, 35 | "_release": "3.2.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.2.6", 39 | "commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7" 40 | }, 41 | "_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git", 42 | "_target": "3.2.6", 43 | "_originalSource": "jquery-validation-unobtrusive" 44 | } -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace ReactWebPack.MVC5 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at http://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js", 24 | "~/Scripts/respond.js")); 25 | 26 | bundles.Add(new StyleBundle("~/Content/css").Include( 27 | "~/Content/bootstrap.css", 28 | "~/Content/site.css")); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Home Page"; 3 | Layout = "~/Views/Shared/_ReactLayout.cshtml"; 4 | } 5 |

6 | This is an ASP.NET MVC5 web site using React code which was built by 7 | WebPack 8 | with Babel js doing the transpiling. 9 |

10 |

11 | This application was downloaded from Pro React GitHub, Chapter 6 12 | with a small change to the file KanBanApi.js 13 | to get data from this MVC application. 14 |
15 | Note: this React application uses Flux store, 16 | while the ReactWebPack.CoreRC2 17 | uses the Redux. 18 |

19 |
20 | 21 |
22 |
23 | 24 | @section scripts{ 25 | 26 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/constants.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 3 | //API_URL: 'http://kanbanapi.pro-react.com'; //original value 4 | 5 | API_URL: 'http://localhost:50120/api', //reads from MVC app 6 | 7 | CARD: 'card', 8 | 9 | FETCH_CARDS: 'fetch cards', 10 | FETCH_CARDS_SUCCESS: 'fetch cards success', 11 | FETCH_CARDS_ERROR: 'fetch cards error', 12 | 13 | TOGGLE_CARD_DETAILS: 'toggle card details', 14 | 15 | CREATE_CARD: 'create card', 16 | CREATE_CARD_SUCCESS: 'create card success', 17 | CREATE_CARD_ERROR: 'create card error', 18 | 19 | UPDATE_CARD: 'update card', 20 | UPDATE_CARD_SUCCESS: 'update card success', 21 | UPDATE_CARD_ERROR: 'update card error', 22 | 23 | UPDATE_CARD_STATUS: 'update card status', 24 | 25 | UPDATE_CARD_POSITION: 'update card position', 26 | 27 | PERSIST_CARD_DRAG: 'persist card drag', 28 | PERSIST_CARD_DRAG_SUCCESS: 'persist card drag success', 29 | PERSIST_CARD_DRAG_ERROR: 'persist card drag error', 30 | 31 | CREATE_DRAFT: 'create draft', 32 | UPDATE_DRAFT: 'update draft', 33 | 34 | CREATE_TASK: 'create task', 35 | CREATE_TASK_SUCCESS: 'create task success', 36 | CREATE_TASK_ERROR: 'create task error', 37 | 38 | DELETE_TASK: 'delete task', 39 | DELETE_TASK_SUCCESS: 'delete task success', 40 | DELETE_TASK_ERROR: 'delete task error', 41 | 42 | TOGGLE_TASK: 'toggle task', 43 | TOGGLE_TASK_SUCCESS: 'toggle task success', 44 | TOGGLE_TASK_ERROR: 'toggle task error' 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/constants.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 3 | //API_URL: 'http://kanbanapi.pro-react.com'; //original value 4 | 5 | API_URL: 'http://localhost:55685/api', //reads from ASP.NET CORE 6 | 7 | CARD: 'card', 8 | 9 | FETCH_CARDS: 'fetch cards', 10 | FETCH_CARDS_SUCCESS: 'fetch cards success', 11 | FETCH_CARDS_ERROR: 'fetch cards error', 12 | 13 | TOGGLE_CARD_DETAILS: 'toggle card details', 14 | 15 | CREATE_CARD: 'create card', 16 | CREATE_CARD_SUCCESS: 'create card success', 17 | CREATE_CARD_ERROR: 'create card error', 18 | 19 | UPDATE_CARD: 'update card', 20 | UPDATE_CARD_SUCCESS: 'update card success', 21 | UPDATE_CARD_ERROR: 'update card error', 22 | 23 | UPDATE_CARD_STATUS: 'update card status', 24 | 25 | UPDATE_CARD_POSITION: 'update card position', 26 | 27 | PERSIST_CARD_DRAG: 'persist card drag', 28 | PERSIST_CARD_DRAG_SUCCESS: 'persist card drag success', 29 | PERSIST_CARD_DRAG_ERROR: 'persist card drag error', 30 | 31 | CREATE_DRAFT: 'create draft', 32 | UPDATE_DRAFT: 'update draft', 33 | 34 | CREATE_TASK: 'create task', 35 | CREATE_TASK_SUCCESS: 'create task success', 36 | CREATE_TASK_ERROR: 'create task error', 37 | 38 | DELETE_TASK: 'delete task', 39 | DELETE_TASK_SUCCESS: 'delete task success', 40 | DELETE_TASK_ERROR: 'delete task error', 41 | 42 | TOGGLE_TASK: 'toggle task', 43 | TOGGLE_TASK_SUCCESS: 'toggle task success', 44 | TOGGLE_TASK_ERROR: 'toggle task error' 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/components/CheckList.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import TaskActionCreators from '../actions/TaskActionCreators'; 3 | 4 | 5 | class CheckList extends Component { 6 | checkInputKeyPress(evt){ 7 | if(evt.key === 'Enter'){ 8 | let newTask = {id:Date.now(), name:evt.target.value, done:false}; 9 | TaskActionCreators.addTask(this.props.cardId, newTask); 10 | evt.target.value = ''; 11 | } 12 | } 13 | 14 | render() { 15 | let tasks = this.props.tasks.map((task, taskIndex) => ( 16 |
  • 17 | 20 | {task.name}{' '} 21 | 24 |
  • 25 | )); 26 | 27 | return ( 28 |
    29 |
      {tasks}
    30 | 34 |
    35 | ); 36 | } 37 | } 38 | CheckList.propTypes = { 39 | cardId: PropTypes.number, 40 | tasks: PropTypes.arrayOf(PropTypes.object) 41 | }; 42 | export default CheckList; 43 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ReactJsNet.MVC5")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ReactJsNet.MVC5")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3baa5544-3891-4141-b3fa-c46bffd26937")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ReactWebPack.MVC5")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ReactWebPack.MVC5")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("71c2fb9a-f7f6-4ac2-8c94-3adcc34ee57a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/components/EditCard.js: -------------------------------------------------------------------------------- 1 | import React,{Component} from 'react'; 2 | import CardForm from './CardForm'; 3 | import CardStore from '../stores/CardStore'; 4 | import DraftStore from '../stores/DraftStore'; 5 | import {Container} from 'flux/utils'; 6 | import CardActionCreators from '../actions/CardActionCreators'; 7 | 8 | import 'babel-polyfill'; 9 | 10 | class EditCard extends Component{ 11 | 12 | handleChange(field, value){ 13 | CardActionCreators.updateDraft(field, value); 14 | } 15 | 16 | handleSubmit(e){ 17 | e.preventDefault(); 18 | CardActionCreators.updateCard( 19 | CardStore.getCard(this.props.params.card_id),this.state.draft 20 | ); 21 | 22 | this.props.history.pushState(null,'/'); 23 | } 24 | 25 | handleClose(e){ 26 | this.props.history.pushState(null,'/'); 27 | } 28 | 29 | componentDidMount(){ 30 | setTimeout(()=>{ 31 | CardActionCreators.createDraft(CardStore.getCard(this.props.params.card_id)) 32 | }, 0); 33 | } 34 | 35 | 36 | render(){ 37 | return ( 38 | 43 | ) 44 | } 45 | } 46 | 47 | EditCard.getStores = () => ([DraftStore]); 48 | EditCard.calculateState = (prevState) => ({ 49 | draft: DraftStore.getState() 50 | }); 51 | 52 | export default Container.create(EditCard); 53 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/components/NewCard.js: -------------------------------------------------------------------------------- 1 | import React,{Component} from 'react'; 2 | import CardForm from './CardForm'; 3 | import CardActionCreators from '../actions/CardActionCreators'; 4 | import { connect } from 'react-redux'; 5 | 6 | export class NewCard extends Component{ 7 | 8 | handleChange(field, value){ 9 | this.props.updateDraft(field, value); 10 | } 11 | 12 | handleSubmit(e){ 13 | e.preventDefault(); 14 | this.props.addCard(this.props.draft); 15 | this.props.history.pushState(null,'/'); 16 | } 17 | 18 | handleClose(e){ 19 | this.props.history.pushState(null,'/'); 20 | } 21 | 22 | componentDidMount(){ 23 | setTimeout(()=>this.props.createDraft(), 0) 24 | } 25 | 26 | 27 | render(){ 28 | return ( 29 | 34 | ); 35 | } 36 | } 37 | 38 | function mapStoreToProps(storeState) { 39 | return { 40 | draft: storeState.draftCard 41 | } 42 | } 43 | 44 | function mapDispatchToProps(dispatch) { 45 | return { 46 | updateDraft: (field, value) => dispatch(CardActionCreators.updateDraft(field, value)), 47 | addCard: (card) => dispatch(CardActionCreators.addCard(card)), 48 | createDraft: (card) => dispatch(CardActionCreators.createDraft(card)), 49 | } 50 | } 51 | 52 | export default connect( 53 | mapStoreToProps, 54 | mapDispatchToProps) 55 | (NewCard) 56 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Controllers/CommentsController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | using ReactJsNet.MVC5.Models; 6 | 7 | namespace ReactJsNet.MVC5.Controllers 8 | { 9 | [RoutePrefix("api/comments")] 10 | public class CommentsController : ApiController 11 | { 12 | private static readonly ConcurrentDictionary DataDict = 13 | new ConcurrentDictionary(Comment.SeedData().ToDictionary(x => x.id)); 14 | 15 | // GET: api/Comments 16 | public IEnumerable Get() 17 | { 18 | return DataDict.Values; 19 | } 20 | 21 | // GET: api/Comments/5 22 | public IHttpActionResult Get(long id) 23 | { 24 | Comment value = null; 25 | return DataDict.TryGetValue(id, out value) ? (IHttpActionResult)Ok(value) : NotFound(); 26 | } 27 | 28 | // POST: api/Comments 29 | public IHttpActionResult Post([FromBody]Comment value) 30 | { 31 | if (!ModelState.IsValid) 32 | { 33 | return BadRequest(ModelState); 34 | } 35 | 36 | if (DataDict.TryAdd(value.id, value)) 37 | return Ok(value); 38 | 39 | return Conflict(); 40 | } 41 | 42 | //// PUT: api/Comments/5 43 | //public void Put(int id, [FromBody]string value) 44 | //{ 45 | //} 46 | 47 | //// DELETE: api/Comments/5 48 | //public void Delete(int id) 49 | //{ 50 | //} 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/Tests/localTests/EnzymeSuimulate.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import expect from 'expect'; 4 | import {shallow, mount} from 'enzyme'; 5 | 6 | //Example taken for http://airbnb.io/enzyme/docs/api/ShallowWrapper/simulate.html 7 | class Foo extends React.Component { 8 | constructor(props) { 9 | super(props); 10 | this.state = { count: 0 }; 11 | } 12 | render() { 13 | const { count } = this.state; 14 | return ( 15 |
    23 | ); 24 | } 25 | } 26 | 27 | describe('enzyme simulate', function () { 28 | describe('shallow render', function () { 29 | it('click', 30 | () => { 31 | const wrapper = shallow(); 32 | 33 | expect(wrapper.find('.clicks-0').length).toBe(1); 34 | wrapper.find('a').simulate('click'); 35 | expect(wrapper.find('.clicks-1').length).toBe(1); 36 | }); 37 | }); 38 | 39 | describe('mount render', function () { 40 | it('click', 41 | () => { 42 | const wrapper = mount(); 43 | 44 | expect(wrapper.find('.clicks-0').length).toBe(1); 45 | wrapper.find('a').simulate('click'); 46 | expect(wrapper.find('.clicks-1').length).toBe(1); 47 | }); 48 | }); 49 | }); -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/Tests/kanbanUtils/ReduxDispatcher.test.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | import MockPromise from '../../mocksEtc/MockPromise'; 3 | 4 | import { dispatchAsync } from '../../../app/ReduxDispatcher'; 5 | 6 | describe('app/ReduxDispatcher', () => { 7 | 8 | it('Call with success', () => { 9 | let returnedActionObjects = []; 10 | const dispatch = (actionObject) => { 11 | returnedActionObjects.push(actionObject); 12 | }; 13 | dispatchAsync(new MockPromise(true), 14 | dispatch, { 15 | request: 'request', 16 | success: 'success', 17 | failure: 'failed' 18 | }); 19 | expect(returnedActionObjects.length).toEqual(2); 20 | expect(returnedActionObjects[0].type).toEqual('request'); 21 | expect(returnedActionObjects[1].type).toEqual('success'); 22 | expect(returnedActionObjects[1].payload.response).toEqual('my data'); 23 | }); 24 | 25 | it('Call with fail', () => { 26 | let returnedActionObjects = []; 27 | const dispatch = (actionObject) => { 28 | returnedActionObjects.push(actionObject); 29 | }; 30 | dispatchAsync(new MockPromise(false), 31 | dispatch, { 32 | request: 'request', 33 | success: 'success', 34 | failure: 'failed' 35 | }); 36 | expect(returnedActionObjects.length).toEqual(2); 37 | expect(returnedActionObjects[0].type).toEqual('request'); 38 | expect(returnedActionObjects[1].type).toEqual('failed'); 39 | expect(returnedActionObjects[1].payload.error).toEqual('my error'); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @ViewBag.Title - My ASP.NET Application 7 | @Styles.Render("~/Content/css") 8 | @Scripts.Render("~/bundles/modernizr") 9 | 10 | 11 | 30 |
    31 | @RenderBody() 32 |
    33 |
    34 |

    © @DateTime.Now.Year - My ASP.NET Application

    35 |
    36 |
    37 | 38 | @Scripts.Render("~/bundles/jquery") 39 | @Scripts.Render("~/bundles/bootstrap") 40 | @RenderSection("scripts", required: false) 41 | 42 | 43 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @ViewBag.Title - My ASP.NET Application 7 | @Styles.Render("~/Content/css") 8 | @Scripts.Render("~/bundles/modernizr") 9 | 10 | 11 | 30 |
    31 | @RenderBody() 32 |
    33 |
    34 |

    © @DateTime.Now.Year - My ASP.NET Application

    35 |
    36 |
    37 | 38 | @Scripts.Render("~/bundles/jquery") 39 | @Scripts.Render("~/bundles/bootstrap") 40 | @RenderSection("scripts", required: false) 41 | 42 | 43 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | using System.Web.Optimization.React; 4 | 5 | namespace ReactJsNet.MVC5 6 | { 7 | public class BundleConfig 8 | { 9 | // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862 10 | public static void RegisterBundles(BundleCollection bundles) 11 | { 12 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 13 | "~/Scripts/jquery-{version}.js")); 14 | 15 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 16 | "~/Scripts/jquery.validate*")); 17 | 18 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 19 | // ready for production, use the build tool at http://modernizr.com to pick only the tests you need. 20 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 21 | "~/Scripts/modernizr-*")); 22 | 23 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 24 | "~/Scripts/bootstrap.js", 25 | "~/Scripts/respond.js")); 26 | 27 | bundles.Add(new StyleBundle("~/Content/css").Include( 28 | "~/Content/bootstrap.css", 29 | "~/Content/site.css")); 30 | 31 | bundles.Add(new BabelBundle("~/bundles/react").Include( 32 | // Add your JSX files here 33 | "~/app/Comment.jsx", 34 | "~/app/CommentBox.jsx", 35 | "~/app/CommentList.jsx", 36 | "~/app/CommentForm.jsx", 37 | "~/app/app.jsx" 38 | )); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Views/Shared/_ReactLayout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - ReactWebPack.Core 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
    18 | @RenderBody() 19 |
    20 |
    21 |

    © 2016 - ReactWebPack.Core

    22 |
    23 |
    24 | 25 | 26 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | @RenderSection("scripts", required: false) 42 | 43 | 44 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/components/CheckList.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { bindActionCreators } from 'redux' 4 | import TaskActionCreators from '../actions/TaskActionCreators'; 5 | 6 | export class CheckList extends Component { 7 | checkInputKeyPress(evt){ 8 | if(evt.key === 'Enter'){ 9 | let newTask = {id:Date.now(), name:evt.target.value, done:false}; 10 | this.props.actions.addTask(this.props.cardId, newTask); 11 | evt.target.value = ''; 12 | } 13 | } 14 | 15 | render() { 16 | let tasks = this.props.tasks.map((task, taskIndex) => ( 17 |
  • 18 | 21 | {task.name}{' '} 22 | 25 |
  • 26 | )); 27 | 28 | return ( 29 |
    30 |
      {tasks}
    31 | 35 |
    36 | ); 37 | } 38 | } 39 | CheckList.propTypes = { 40 | cardId: PropTypes.number, 41 | tasks: PropTypes.arrayOf(PropTypes.object) 42 | }; 43 | 44 | function mapStoreToProps(storeState) { 45 | return { 46 | cards: storeState.cards 47 | } 48 | } 49 | 50 | function mapDispatchToProps(dispatch) { 51 | return { 52 | actions: bindActionCreators(TaskActionCreators, dispatch) 53 | } 54 | } 55 | export default connect( 56 | mapStoreToProps, 57 | mapDispatchToProps)(CheckList) 58 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Models/Comment.cs: -------------------------------------------------------------------------------- 1 | #region licence 2 | // ===================================================== 3 | // AspNetReactSample solution - using React js with ASP.NET MVC 4 | // Filename: Comment.cs 5 | // Date Created: 2016/05/05 6 | // 7 | // Under the MIT License (MIT) 8 | // 9 | // Written by Jon Smith : GitHub JonPSmith, www.thereformedprogrammer.net 10 | // ===================================================== 11 | #endregion 12 | 13 | using System.Collections.Generic; 14 | 15 | namespace ReactJsNet.MVC5.Models 16 | { 17 | public class Comment 18 | { 19 | // ReSharper disable InconsistentNaming 20 | public long id { get; set; } 21 | public string author { get; set; } 22 | public string text { get; set; } 23 | // ReSharper enable InconsistentNaming 24 | 25 | public static IEnumerable SeedData() 26 | { 27 | long i = 0; 28 | return new List 29 | { 30 | new Comment 31 | { 32 | id = i++, 33 | author = "Jon Smith", 34 | text = "Glad to see you got the application going!" 35 | }, 36 | new Comment 37 | { 38 | id = i++, 39 | author = "Jon Smith", 40 | text = "See [reactjs.net](http://reactjs.net/) for more about using this approach to developing **ReactJS** applications." 41 | }, 42 | new Comment 43 | { 44 | id = i++, 45 | author = "Jon Smith", 46 | text = "More on the example code I used can be found in the [React Tutorial](http://facebook.github.io/react/docs/tutorial.html). \n" + 47 | "*Note: try stopping the MVC application and notice that any new comment is removed once the POST times out.*" 48 | } 49 | }; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/Tests/localTests/CheckboxWithLabel.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import expect from 'expect'; 4 | import {shallow, mount} from 'enzyme'; 5 | 6 | import CheckboxWithLabel from '../../localSrc/CheckboxWithLabel'; 7 | 8 | 9 | describe('localSrc/CheckboxWithLabel', function () { 10 | describe('(shallow)', () => { 11 | it('defaults to unchecked and Off label', () => { 12 | const wrapper = shallow(); 13 | //console.log(wrapper.debug()); 14 | expect(wrapper.find('label').text()).toEqual('Off'); 15 | expect(wrapper.find('input').props().checked).toBeFalsy(); 16 | }); 17 | 18 | it('changes the label text after change event', () => { 19 | 20 | const wrapper = shallow(); 21 | //console.log(wrapper.debug()); 22 | wrapper.find('input').simulate('change'); 23 | expect(wrapper.find('label').text()).toEqual('On'); 24 | expect(wrapper.find('input').props().checked).toBeTruthy(); 25 | }); 26 | }); 27 | 28 | describe('(mount)', () => { 29 | it('defaults to unchecked and Off label', () => { 30 | const wrapper = mount(); 31 | //console.log(wrapper.html()); 32 | expect(wrapper.find('label').text()).toEqual('Off'); 33 | expect(wrapper.find('input').props().checked).toBeFalsy(); 34 | }); 35 | 36 | it('changes the label text after change event', () => { 37 | 38 | const wrapper = mount(); 39 | //console.log(wrapper.html()); 40 | wrapper.find('input').simulate('change'); 41 | expect(wrapper.find('label').text()).toEqual('On'); 42 | expect(wrapper.find('input').props().checked).toBeTruthy(); 43 | }); 44 | }); 45 | }); -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/api/KanbanApi.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | import 'babel-polyfill'; 3 | import constants from '../constants'; 4 | 5 | //const API_URL = 'http://kanbanapi.pro-react.com'; //The API_URL has moved into the constants file 6 | const API_HEADERS = { 7 | 'Content-Type': 'application/json', 8 | Authorization: 'any-string-you-like' 9 | } 10 | 11 | let KanbanAPI = { 12 | fetchCards() { 13 | return fetch(`${constants.API_URL}/cards`, {headers:API_HEADERS}) 14 | .then((response) => response.json()) 15 | }, 16 | 17 | addCard(card) { 18 | return fetch(`${constants.API_URL}/cards`, { 19 | method: 'post', 20 | headers: API_HEADERS, 21 | body: JSON.stringify(card) 22 | }) 23 | .then((response) => response.json()) 24 | }, 25 | 26 | updateCard(card, draftCard) { 27 | return fetch(`${constants.API_URL}/cards/${card.id}`, { 28 | method: 'put', 29 | headers: API_HEADERS, 30 | body: JSON.stringify(draftCard) 31 | }) 32 | }, 33 | 34 | persistCardDrag(cardId, status, index) { 35 | return fetch(`${constants.API_URL}/cards/${cardId}`, { 36 | method: 'put', 37 | headers: API_HEADERS, 38 | body: JSON.stringify({status, row_order_position: index}) 39 | }) 40 | }, 41 | 42 | addTask(cardId, task) { 43 | return fetch(`${constants.API_URL}/cards/${cardId}/tasks`, { 44 | method: 'post', 45 | headers: API_HEADERS, 46 | body: JSON.stringify(task) 47 | }) 48 | .then((response) => response.json()) 49 | }, 50 | 51 | deleteTask(cardId, task) { 52 | return fetch(`${constants.API_URL}/cards/${cardId}/tasks/${task.id}`, { 53 | method: 'delete', 54 | headers: API_HEADERS 55 | }) 56 | }, 57 | 58 | toggleTask(cardId, task) { 59 | return fetch(`${constants.API_URL}/cards/${cardId}/tasks/${task.id}`, { 60 | method: 'put', 61 | headers: API_HEADERS, 62 | body: JSON.stringify({done:!task.done}) 63 | }) 64 | } 65 | 66 | }; 67 | 68 | export default KanbanAPI; 69 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/api/KanbanApi.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | import 'babel-polyfill'; 3 | import constants from '../constants'; 4 | 5 | //const API_URL = 'http://kanbanapi.pro-react.com'; //The API_URL has moved into the constants file 6 | const API_HEADERS = { 7 | 'Content-Type': 'application/json', 8 | Authorization: 'any-string-you-like' 9 | } 10 | 11 | let KanbanAPI = { 12 | fetchCards() { 13 | return fetch(`${constants.API_URL}/cards`, {headers:API_HEADERS}) 14 | .then((response) => response.json()) 15 | }, 16 | 17 | addCard(card) { 18 | return fetch(`${constants.API_URL}/cards`, { 19 | method: 'post', 20 | headers: API_HEADERS, 21 | body: JSON.stringify(card) 22 | }) 23 | .then((response) => response.json()) 24 | }, 25 | 26 | updateCard(card, draftCard) { 27 | return fetch(`${constants.API_URL}/cards/${card.id}`, { 28 | method: 'put', 29 | headers: API_HEADERS, 30 | body: JSON.stringify(draftCard) 31 | }) 32 | }, 33 | 34 | persistCardDrag(cardId, status, index) { 35 | return fetch(`${constants.API_URL}/cards/${cardId}`, { 36 | method: 'put', 37 | headers: API_HEADERS, 38 | body: JSON.stringify({status, row_order_position: index}) 39 | }) 40 | }, 41 | 42 | addTask(cardId, task) { 43 | return fetch(`${constants.API_URL}/cards/${cardId}/tasks`, { 44 | method: 'post', 45 | headers: API_HEADERS, 46 | body: JSON.stringify(task) 47 | }) 48 | .then((response) => response.json()) 49 | }, 50 | 51 | deleteTask(cardId, task) { 52 | return fetch(`${constants.API_URL}/cards/${cardId}/tasks/${task.id}`, { 53 | method: 'delete', 54 | headers: API_HEADERS 55 | }) 56 | }, 57 | 58 | toggleTask(cardId, task) { 59 | return fetch(`${constants.API_URL}/cards/${cardId}/tasks/${task.id}`, { 60 | method: 'put', 61 | headers: API_HEADERS, 62 | body: JSON.stringify({done:!task.done}) 63 | }) 64 | } 65 | 66 | }; 67 | 68 | export default KanbanAPI; 69 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/karma.conf.js: -------------------------------------------------------------------------------- 1 | // see https://github.com/lelandrichardson/enzyme-example-karma-webpack/blob/master/karma.conf.js (but note extra externals with 15.0.0 React) 2 | 3 | module.exports = function (config) { 4 | config.set({ 5 | browsers: ['Chrome'], 6 | singleRun: true, 7 | frameworks: ['mocha'], 8 | files: [ 9 | 'tests.webpack.js' 10 | ], 11 | plugins: [ 12 | 'karma-chrome-launcher', 13 | 'karma-mocha', 14 | 'karma-mocha-reporter', 15 | 'karma-sourcemap-loader', 16 | 'karma-webpack' 17 | ], 18 | preprocessors: { 19 | 'tests.webpack.js': ['webpack', 'sourcemap'] 20 | }, 21 | reporters: ['mocha'], 22 | webpack: { 23 | devtool: 'inline-source-map', 24 | module: { 25 | loaders: [ 26 | { 27 | test: /\.js$/, exclude: /node_modules/, 28 | loader: 'babel-loader', 29 | query: { 30 | presets: ['es2015', 'react'] 31 | } 32 | }, 33 | //See https://github.com/airbnb/enzyme/issues/309 as to why json loader is needed. 34 | //I had to add this when I tried to use enzyme's 'render', which uses Cherrio 35 | { 36 | test: /\.json$/, 37 | loader: 'json', 38 | } 39 | ] 40 | }, 41 | //Needed for enzyme working with webpack & React 15.0.x. See http://airbnb.io/enzyme/docs/guides/webpack.html#react-15-compatability 42 | externals: { 43 | 'react/addons': true, 44 | 'react/lib/ExecutionEnvironment': true, 45 | 'react/lib/ReactContext': true 46 | }, 47 | watch: true 48 | }, 49 | webpackServer: { 50 | noInfo: true 51 | }, 52 | }); 53 | }; -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asp.net", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "Example React with WebPack in ASP.NET Core 1.0.0", 6 | "author": "Jon Smith", 7 | "license": "MIT", 8 | "scripts": { 9 | "dev-build": "webpack -d --config webpack.config.js --colors", 10 | "dev-watch": "webpack -d --config webpack.config.js --watch --colors", 11 | "prod-build": "SET NODE_ENV=production&&webpack -p --config webpack.config.js --colors", 12 | "tests-run": "karma start karma.conf.js", 13 | "tests-watch": "karma start karma.conf.js --single-run=false" 14 | }, 15 | "dependencies": { 16 | "redux": "3.5.2", 17 | "redux-thunk": "2.1.0", 18 | "redux-throttle": "0.1.1", 19 | "react-redux": "4.4.5", 20 | "history": "2.1.1", 21 | "marked": "0.3.5", 22 | "react": "15.0.2", 23 | "react-dom": "15.0.2", 24 | "react-router": "2.4.0", 25 | "react-addons-css-transition-group": "15.0.2", 26 | "react-addons-update": "15.0.2", 27 | "react-dnd": "2.1.4", 28 | "react-dnd-html5-backend": "2.1.2", 29 | "whatwg-fetch": "1.0.0", 30 | "babel-polyfill": "6.8.0" 31 | }, 32 | "devDependencies": { 33 | 34 | "babel-core": "6.8.0", 35 | "babel-loader": "6.2.4", 36 | "babel-preset-es2015": "6.6.0", 37 | "babel-preset-react": "6.5.0", 38 | "webpack": "1.13.0", 39 | "webpack-dev-server": "1.13.0", 40 | "html-webpack-plugin": "2.16.0", 41 | "jsx-loader": "0.13.2", 42 | 43 | "karma": "0.13.22", 44 | "karma-chrome-launcher": "1.0.1", 45 | "karma-cli": "1.0.0", 46 | "karma-mocha": "1.0.1", 47 | "karma-mocha-reporter": "2.0.3", 48 | "karma-sourcemap-loader": "0.3.7", 49 | "karma-webpack": "1.7.0", 50 | "mocha": "2.4.5", 51 | "react-hot-loader": "1.2.7", 52 | "react-addons-test-utils": "15.0.2", 53 | "expect": "1.19.0", 54 | "enzyme": "2.3.0", 55 | "json-loader": "0.5.4", 56 | 57 | "inject-loader": "2.0.1", 58 | "redux-mock-store": "1.1.1", 59 | "react-dnd-test-backend": "1.0.2" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/Views/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
    7 |
    8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/app/CommentBox.jsx: -------------------------------------------------------------------------------- 1 | var CommentBox = React.createClass({ 2 | loadCommentsFromServer: function() { 3 | $.ajax({ 4 | url: this.props.url, 5 | dataType: 'json', 6 | cache: false, 7 | success: function(data) { 8 | this.setState({data: data}); 9 | }.bind(this), 10 | error: function(xhr, status, err) { 11 | console.error(this.props.url, status, err.toString()); 12 | }.bind(this) 13 | }); 14 | }, 15 | handleCommentSubmit: function(comment) { 16 | var comments = this.state.data; 17 | // Optimistically set an id on the new comment. It will be replaced by an 18 | // id generated by the server. In a production application you would likely 19 | // not use Date.now() for this and would have a more robust system in place. 20 | comment.id = Date.now(); 21 | var newComments = comments.concat([comment]); 22 | this.setState({data: newComments}); 23 | $.ajax({ 24 | url: this.props.url, 25 | dataType: 'json', 26 | type: 'POST', 27 | data: comment, 28 | success: function(data) { 29 | this.setState({data: data}); 30 | }.bind(this), 31 | error: function(xhr, status, err) { 32 | this.setState({data: comments}); 33 | console.error(this.props.url, status, err.toString()); 34 | }.bind(this) 35 | }); 36 | }, 37 | getInitialState: function() { 38 | return {data: []}; 39 | }, 40 | componentDidMount: function() { 41 | this.loadCommentsFromServer(); 42 | setInterval(this.loadCommentsFromServer, this.props.pollInterval); 43 | }, 44 | render: function() { 45 | return ( 46 |
    47 |

    Comments

    48 | 49 | 50 |
    51 | ); 52 | } 53 | }); -------------------------------------------------------------------------------- /ReactWebPack.MVC5/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | var pkg = require('./package.json'); 5 | 6 | // bundle dependencies in separate vendor bundle 7 | var vendorPackages = Object.keys(pkg.dependencies).filter(function (el) { 8 | return el.indexOf('font') === -1; // exclude font packages from vendor bundle 9 | }); 10 | 11 | /* 12 | * Default webpack configuration for development 13 | */ 14 | var config = { 15 | devtool: 'eval-source-map', 16 | cache: true, 17 | entry: { 18 | main: path.join(__dirname, "app", "App.js"), 19 | vendor: vendorPackages 20 | }, 21 | output: { 22 | path: path.join(__dirname, "js"), 23 | filename: '[name].js', 24 | sourceMapFilename: "[file].map" 25 | }, 26 | resolve: { 27 | modulesDirectories: ['node_modules'] 28 | }, 29 | plugins: [ 30 | new webpack.OldWatchingPlugin(), //needed to make watch work. see http://stackoverflow.com/a/29292578/1434764 31 | new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"vendor", /* filename= */"vendor.js") 32 | ], 33 | resolveLoader: { 34 | 'fallback': path.join(__dirname, 'node_modules') 35 | }, 36 | module: { 37 | loaders: [{ 38 | test: /\.js$/, 39 | exclude: /node_modules/, 40 | loader: 'babel', 41 | query: { 42 | presets: ['es2015','react'] 43 | } 44 | }] 45 | } 46 | } 47 | 48 | /* 49 | * If bundling for production, optimize output 50 | */ 51 | if (process.env.NODE_ENV === 'production') { 52 | config.devtool = false; 53 | 54 | config.plugins = [ 55 | new webpack.optimize.OccurenceOrderPlugin(), 56 | 57 | new webpack.optimize.UglifyJsPlugin({ 58 | comments: false, 59 | compress: { warnings: false} 60 | }), 61 | new webpack.DefinePlugin({ 62 | 'process.env': {NODE_ENV: JSON.stringify('production')} 63 | }) 64 | ]; 65 | }; 66 | 67 | module.exports = config; 68 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace ReactWebPack.Core 8 | { 9 | public class Startup 10 | { 11 | public Startup(IHostingEnvironment env) 12 | { 13 | var builder = new ConfigurationBuilder() 14 | .SetBasePath(env.ContentRootPath) 15 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 16 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) 17 | .AddEnvironmentVariables(); 18 | Configuration = builder.Build(); 19 | } 20 | 21 | public IConfigurationRoot Configuration { get; } 22 | 23 | // This method gets called by the runtime. Use this method to add services to the container. 24 | public void ConfigureServices(IServiceCollection services) 25 | { 26 | // Add framework services. 27 | services.AddMvc(); 28 | } 29 | 30 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 31 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 32 | { 33 | loggerFactory.AddConsole(Configuration.GetSection("Logging")); 34 | loggerFactory.AddDebug(); 35 | 36 | if (env.IsDevelopment()) 37 | { 38 | app.UseDeveloperExceptionPage(); 39 | app.UseBrowserLink(); 40 | } 41 | else 42 | { 43 | app.UseExceptionHandler("/Home/Error"); 44 | } 45 | 46 | app.UseStaticFiles(); 47 | 48 | app.UseMvc(routes => 49 | { 50 | routes.MapRoute( 51 | name: "default", 52 | template: "{controller=Home}/{action=Index}/{id?}"); 53 | }); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ReactJsNet.MVC5/Views/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
    7 |
    8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/ReactWebPack.CoreRC2.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp1.0 5 | true 6 | ReactWebPack.CoreRC2 7 | Exe 8 | ReactWebPack.CoreRC2 9 | 1.1.1 10 | $(PackageTargetFallback);dotnet5.6;dnxcore50;portable-net45+win8 11 | 12 | 13 | 14 | 15 | PreserveNewest 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/components/EditCard.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import CardForm from './CardForm'; 3 | import CardActionCreators from '../actions/CardActionCreators'; 4 | import { connect } from 'react-redux'; 5 | import { getCard } from '../cardUtils' 6 | 7 | import 'babel-polyfill'; 8 | 9 | export class EditCard extends Component { 10 | 11 | handleChange(field, value) { 12 | this.props.updateDraft(field, value); 13 | } 14 | 15 | handleSubmit(e) { 16 | e.preventDefault(); 17 | const cards = this.context.store.getState().cards; 18 | this.props.updateCard( 19 | getCard(cards, this.props.params.card_id),this.props.draft); 20 | 21 | this.props.history.pushState(null, '/'); 22 | } 23 | 24 | handleClose(e) { 25 | this.props.history.pushState(null, '/'); 26 | } 27 | 28 | componentDidMount() { 29 | const cards = this.context.store.getState().cards; 30 | setTimeout(() => { 31 | this.props.createDraft( 32 | getCard(cards, this.props.params.card_id)) 33 | }, 0); 34 | } 35 | 36 | render(){ 37 | return ( 38 | 43 | ) 44 | } 45 | } 46 | 47 | //The code below enables access the store via the React context. 48 | //The code that uses it is in componentDidMount, line 33 49 | //see section called "Passing the Store" in http://redux.js.org/docs/basics/UsageWithReact.html for more info 50 | EditCard.contextTypes = { 51 | store: React.PropTypes.object 52 | } 53 | 54 | function mapStoreToProps(storeState) { 55 | return { 56 | draft: storeState.draftCard 57 | } 58 | } 59 | 60 | function mapDispatchToProps(dispatch) { 61 | return { 62 | updateDraft: (field, value) => dispatch(CardActionCreators.updateDraft(field, value)), 63 | updateCard: (card, draftCard) => dispatch(CardActionCreators.updateCard(card, draftCard)), 64 | createDraft: (card) => dispatch(CardActionCreators.createDraft(card)), 65 | } 66 | } 67 | 68 | export default connect( 69 | mapStoreToProps, 70 | mapDispatchToProps 71 | )(EditCard) -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/Tests/components/List.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import expect from 'expect'; 4 | import {shallow, mount} from 'enzyme'; 5 | 6 | //These are used to pass a mock store down through nested components 7 | import configureStore from 'redux-mock-store'; 8 | import { Provider, connect} from 'react-redux'; 9 | 10 | import {createCards} from '../../TestUtils/CardCreators' 11 | import {wrapInTestContext} from '../../MocksEtc/WrapTestDnD' 12 | 13 | import ListConnected, { List } from '../../../app/components/List'; 14 | 15 | describe('app/components/List', () => { 16 | describe('shallow render', () => { 17 | it('empty cards', () => { 18 | // Stub the React DnD connector functions with an identity function 19 | const identity = function (el) { return el; }; 20 | const wrapper = shallow(); 24 | //console.log(wrapper.debug()); 25 | expect(wrapper.html()).toEqual('

    To Do

    '); 26 | }); 27 | }); 28 | describe('mount render', () => { 29 | it('one card', () => { 30 | 31 | // Stub the React DnD connector functions with an identity function 32 | const identity = function (el) { return el; }; 33 | // Wrap in DnD test context 34 | const ListConnectedWithDnD = wrapInTestContext(ListConnected) ; 35 | const mockStore = configureStore([]); 36 | const store = mockStore({}); 37 | const wrapper = mount( 38 | 42 | ); 43 | //console.log(wrapper.debug()); 44 | debugger; 45 | expect(wrapper.find('div .list h1').text()).toBe('My Title'); 46 | expect(wrapper.find('div .list .card .card__title').text()).toBe('Card0 title'); 47 | expect(wrapper.find('div .list .card .card__details').text().trim()).toBe('Card0 description'); 48 | }); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | var pkg = require('./package.json'); 5 | 6 | // bundle dependencies in separate vendor bundle 7 | var vendorPackages = Object.keys(pkg.dependencies).filter(function (el) { 8 | return el.indexOf('font') === -1; // exclude font packages from vendor bundle 9 | }); 10 | 11 | /* 12 | * Default webpack configuration for development 13 | */ 14 | var config = { 15 | devtool: 'eval-source-map', 16 | cache: true, 17 | entry: { 18 | main: path.join(__dirname, "app", "App.js"), 19 | vendor: vendorPackages 20 | }, 21 | output: { 22 | path: path.join(__dirname, "wwwroot", "js"), //Note: For ASP.NET Core we need to put the output in wwwroot/js 23 | //in production mode make files have a .min.js ending - stops gulp's min:js concating them 24 | filename: process.env.NODE_ENV === 'production' ? '[name].min.js' : '[name].js', 25 | sourceMapFilename: '[file].map' 26 | }, 27 | resolve: { 28 | modulesDirectories: ['node_modules'] 29 | }, 30 | plugins: [ 31 | new webpack.OldWatchingPlugin(), //needed to make watch work. see http://stackoverflow.com/a/29292578/1434764 32 | new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"vendor", /* filename= */"vendor.js") 33 | ], 34 | resolveLoader: { 35 | 'fallback': path.join(__dirname, 'node_modules') 36 | }, 37 | module: { 38 | loaders: [{ 39 | test: /\.js$/, 40 | exclude: /node_modules/, 41 | loader: 'babel', 42 | query: { 43 | presets: ['es2015','react'] 44 | } 45 | }] 46 | } 47 | } 48 | 49 | /* 50 | * If bundling for production, optimize output 51 | */ 52 | if (process.env.NODE_ENV === 'production') { 53 | config.devtool = false; 54 | 55 | config.plugins = [ 56 | new webpack.optimize.OccurenceOrderPlugin(), 57 | 58 | new webpack.optimize.UglifyJsPlugin({ 59 | comments: false, 60 | compress: { warnings: false} 61 | }), 62 | new webpack.DefinePlugin({ 63 | 'process.env': {NODE_ENV: JSON.stringify('production')} 64 | }) 65 | ]; 66 | }; 67 | 68 | module.exports = config; 69 | -------------------------------------------------------------------------------- /AspNetReactSamples.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26403.3 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactWebPack.MVC5", "ReactWebPack.MVC5\ReactWebPack.MVC5.csproj", "{8140BA2D-5A78-4686-BB64-ED05326B916B}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactJsNet.MVC5", "ReactJsNet.MVC5\ReactJsNet.MVC5.csproj", "{6EA00B4B-1A7D-43AE-955F-3C0519440017}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{72753524-F309-4AD0-BDBA-8003EF383417}" 11 | ProjectSection(SolutionItems) = preProject 12 | licence.txt = licence.txt 13 | README.md = README.md 14 | EndProjectSection 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactWebPack.CoreRC2", "ReactWebPack.CoreRC2\ReactWebPack.CoreRC2.csproj", "{42F11D42-8BEB-4EF2-B411-278CFC1D25AC}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | Release|Any CPU = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {8140BA2D-5A78-4686-BB64-ED05326B916B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {8140BA2D-5A78-4686-BB64-ED05326B916B}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {8140BA2D-5A78-4686-BB64-ED05326B916B}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {8140BA2D-5A78-4686-BB64-ED05326B916B}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {6EA00B4B-1A7D-43AE-955F-3C0519440017}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {6EA00B4B-1A7D-43AE-955F-3C0519440017}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {6EA00B4B-1A7D-43AE-955F-3C0519440017}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {6EA00B4B-1A7D-43AE-955F-3C0519440017}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {42F11D42-8BEB-4EF2-B411-278CFC1D25AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {42F11D42-8BEB-4EF2-B411-278CFC1D25AC}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {42F11D42-8BEB-4EF2-B411-278CFC1D25AC}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {42F11D42-8BEB-4EF2-B411-278CFC1D25AC}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /ReactWebPack.MVC5/app/actions/CardActionCreators.js: -------------------------------------------------------------------------------- 1 | import AppDispatcher from '../AppDispatcher'; 2 | import constants from '../constants'; 3 | import KanbanAPI from '../api/KanbanApi'; 4 | import {throttle} from '../utils'; 5 | import CardStore from '../stores/CardStore'; 6 | 7 | 8 | let CardActionCreators = { 9 | fetchCards() { 10 | AppDispatcher.dispatchAsync(KanbanAPI.fetchCards(), { 11 | request: constants.FETCH_CARDS, 12 | success: constants.FETCH_CARDS_SUCCESS, 13 | failure: constants.FETCH_CARDS_ERROR 14 | }); 15 | }, 16 | 17 | toggleCardDetails(cardId) { 18 | AppDispatcher.dispatch({ 19 | type: constants.TOGGLE_CARD_DETAILS, 20 | payload: {cardId} 21 | }); 22 | }, 23 | 24 | 25 | addCard(card) { 26 | AppDispatcher.dispatchAsync(KanbanAPI.addCard(card), { 27 | request: constants.CREATE_CARD, 28 | success: constants.CREATE_CARD_SUCCESS, 29 | failure: constants.CREATE_CARD_ERROR 30 | }, {card}); 31 | }, 32 | 33 | updateCard(card, draftCard) { 34 | AppDispatcher.dispatchAsync(KanbanAPI.updateCard(card, draftCard), { 35 | request: constants.UPDATE_CARD, 36 | success: constants.UPDATE_CARD_SUCCESS, 37 | failure: constants.UPDATE_CARD_ERROR 38 | }, {card, draftCard}); 39 | }, 40 | 41 | updateCardStatus: throttle((cardId, listId) => { 42 | AppDispatcher.dispatch({ 43 | type: constants.UPDATE_CARD_STATUS, 44 | payload: {cardId, listId} 45 | }); 46 | }), 47 | 48 | updateCardPosition: throttle((cardId , afterId) => { 49 | AppDispatcher.dispatch({ 50 | type: constants.UPDATE_CARD_POSITION, 51 | payload: {cardId , afterId} 52 | }); 53 | },500), 54 | 55 | persistCardDrag(cardProps) { 56 | let card = CardStore.getCard(cardProps.id) 57 | let cardIndex = CardStore.getCardIndex(cardProps.id) 58 | AppDispatcher.dispatchAsync(KanbanAPI.persistCardDrag(card.id, card.status, cardIndex), { 59 | request: constants.PERSIST_CARD_DRAG, 60 | success: constants.PERSIST_CARD_DRAG_SUCCESS, 61 | failure: constants.PERSIST_CARD_DRAG_ERROR 62 | }, {cardProps}); 63 | }, 64 | 65 | createDraft(card) { 66 | AppDispatcher.dispatch({ 67 | type: constants.CREATE_DRAFT, 68 | payload: {card} 69 | }); 70 | }, 71 | 72 | updateDraft(field, value) { 73 | AppDispatcher.dispatch({ 74 | type: constants.UPDATE_DRAFT, 75 | payload: {field, value} 76 | }); 77 | } 78 | 79 | }; 80 | 81 | export default CardActionCreators; 82 | -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/JsUnitTests/Tests/localTests/TestMocking.test.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | import OuterFunction from '../../localSrc/OuterFunction'; 4 | import innerMock from '../../mocksEtc/MockInnerFunction' 5 | 6 | describe('localSrc/OuterFunction (Test Mocking example)', function () { 7 | 8 | it('check normal operation works', 9 | () => { 10 | var result = OuterFunction(); 11 | expect(result.innerFuncValue).toEqual('Inner Function'); 12 | expect(result.innerValue).toEqual(42); 13 | }); 14 | 15 | it('mock InnerFunction with a module', 16 | () => { 17 | const inject = require('inject?./InnerFunction!../../localSrc/OuterFunction'); 18 | const outerFunctionWithMock = inject({ 19 | './InnerFunction': innerMock 20 | }).default; 21 | var result = outerFunctionWithMock(); 22 | expect(result.innerFuncValue).toEqual('Mocked Function', 'Did not mock'); 23 | expect(result.innerValue).toEqual(42); 24 | }); 25 | 26 | it('mock InnerFunction with local function', 27 | () => { 28 | const localFunc = () => { return 'local mock'}; 29 | const inject = require('inject?./InnerFunction!../../localSrc/OuterFunction'); 30 | const outerFunctionWithMock = inject({ 31 | './InnerFunction': localFunc 32 | }).default; 33 | var result = outerFunctionWithMock(); 34 | expect(result.innerFuncValue).toEqual('local mock', 'Did not mock'); 35 | expect(result.innerValue).toEqual(42); 36 | }); 37 | 38 | it('mock InnerValue with new constant', 39 | () => { 40 | const inject = require('inject?./InnerValue!../../localSrc/OuterFunction'); 41 | const outerFunctionWithMock = inject({ 42 | './InnerValue': 12345 43 | }).default; 44 | var result = outerFunctionWithMock(); 45 | expect(result.innerFuncValue).toEqual('Inner Function'); 46 | expect(result.innerValue).toEqual(12345); 47 | }); 48 | 49 | it('mock InnerFunction and InnerValue', 50 | () => { 51 | const inject = require('inject!../../localSrc/OuterFunction'); 52 | const outerFunctionWithMock = inject({ 53 | './InnerFunction': () => { return 'local mock'}, 54 | './InnerValue': 12345 55 | }).default; 56 | var result = outerFunctionWithMock(); 57 | expect(result.innerFuncValue).toEqual('local mock'); 58 | expect(result.innerValue).toEqual(12345); 59 | }); 60 | }); -------------------------------------------------------------------------------- /ReactWebPack.CoreRC2/app/components/CardForm.js: -------------------------------------------------------------------------------- 1 | import React, {Component, PropTypes} from 'react'; 2 | 3 | class CardForm extends Component { 4 | 5 | handleChange(field, e){ 6 | this.props.handleChange(field, e.target.value); 7 | } 8 | 9 | handleClose(e){ 10 | e.preventDefault(); 11 | this.props.handleClose(); 12 | } 13 | 14 | render(){ 15 | return ( 16 |
    17 |
    18 |
    19 |
    25 |