├── 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 |
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 |
18 |
21 | {this.state.isChecked ? this.props.labelOn : this.props.labelOff}
22 |
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 |
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 |
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 |
12 |
13 |
21 |
22 |
23 | @Html.ActionLink("Home", "Index", "Home")
24 | @Html.ActionLink("About", "About", "Home")
25 | @Html.ActionLink("Contact", "Contact", "Home")
26 |
27 |
28 |
29 |
30 |
31 | @RenderBody()
32 |
33 |
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 |
12 |
13 |
21 |
22 |
23 | @Html.ActionLink("Home", "Index", "Home")
24 | @Html.ActionLink("About", "About", "Home")
25 | @Html.ActionLink("Contact", "Contact", "Home")
26 |
27 |
28 |
29 |
30 |
31 | @RenderBody()
32 |
33 |
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 |
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 |
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 |
53 | );
54 | }
55 | }
56 |
57 | CardForm.propTypes = {
58 | buttonLabel: PropTypes.string.isRequired,
59 | draftCard: PropTypes.shape({
60 | title: PropTypes.string,
61 | description: PropTypes.string,
62 | status: PropTypes.string,
63 | color: PropTypes.string
64 | }).isRequired,
65 | handleChange: PropTypes.func.isRequired,
66 | handleSubmit: PropTypes.func.isRequired,
67 | handleClose: PropTypes.func.isRequired,
68 | }
69 |
70 | export default CardForm;
71 |
--------------------------------------------------------------------------------
/ReactWebPack.MVC5/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 |
53 | );
54 | }
55 | }
56 |
57 | CardForm.propTypes = {
58 | buttonLabel: PropTypes.string.isRequired,
59 | draftCard: PropTypes.shape({
60 | title: PropTypes.string,
61 | description: PropTypes.string,
62 | status: PropTypes.string,
63 | color: PropTypes.string
64 | }).isRequired,
65 | handleChange: PropTypes.func.isRequired,
66 | handleSubmit: PropTypes.func.isRequired,
67 | handleClose: PropTypes.func.isRequired,
68 | }
69 |
70 | export default CardForm;
71 |
--------------------------------------------------------------------------------
/ReactWebPack.CoreRC2/wwwroot/css/kanban-styles.min.css:
--------------------------------------------------------------------------------
1 | *{box-sizing:border-box}html,body,#root{height:100%;margin:0;padding:0}body{background:#eee;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}h1{font-weight:200;color:#3b414c;font-size:20px}ul{list-style-type:none;padding:0;margin:0}.app{white-space:nowrap;height:100%}.list{position:relative;display:inline-block;vertical-align:top;white-space:normal;height:100%;width:33%;padding:0 20px;overflow:auto}.list:not(:last-child):after{content:"";position:absolute;top:0;right:0;width:1px;height:99%;background:linear-gradient(to bottom,#eee 0%,#ccc 50%,#eee 100%) fixed}.card{position:relative;z-index:1;background:#fff;width:100%;padding:10px 10px 10px 15px;margin:0 0 10px 0;overflow:auto;border:1px solid #e5e5df;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.25)}.card__title{font-weight:bold;border-bottom:solid 5px transparent}.card__title:before{display:inline-block;width:1em;content:'▸'}.card__title--is-open:before{content:'▾'}.card.big{position:absolute;width:450px;height:200px;margin:auto;padding:15px;top:0;left:0;bottom:100px;right:0;z-index:3}.card.big input[type=text],textarea{width:100%;margin:3px 0;font-size:13px;border:none}.card.big input[type=text]{font-size:20px;font-weight:bold}.card.big input[type=text]:focus,.card.big textarea:focus{outline:dashed thin #999;outline-offset:2px}.card.big label{margin:3px 0 7px 3px;color:#a7a7a7;display:inline-block;width:60px}.actions{margin-top:10px;text-align:right}.card.big button{font-size:14px;padding:8px}.card__edit{position:absolute;top:10px;right:10px;opacity:0;transition:opacity .25s ease-in}.card:hover .card__edit{opacity:1}.card__edit a{text-decoration:none;color:#999;font-size:17px}.overlay{position:absolute;width:100%;height:100%;top:0;left:0;bottom:0;right:0;z-index:2;background-color:rgba(0,0,0,.6)}.toggle-enter{max-height:0;overflow:hidden}.toggle-enter.toggle-enter-active{max-height:300px;overflow:hidden;transition:max-height .25s ease-in}.toggle-leave{max-height:300px;overflow:hidden}.toggle-leave.toggle-leave-active{max-height:0;overflow:hidden;transition:max-height .25s ease-out}.checklist__task:first-child{margin-top:10px;padding-top:10px;border-top:dashed 1px #ddd}.checklist__task--remove:after{display:inline-block;color:#d66;content:"✖"}.checklist--add-task{border:1px dashed #bbb;width:100%;padding:10px;margin-top:5px;border-radius:3px}.float-button{position:absolute;height:56px;width:56px;z-index:2;right:20px;bottom:20px;background:#d43a2f;color:#fff;border-radius:100%;font-size:34px;text-align:center;text-decoration:none;line-height:50px;box-shadow:0 5px 10px rgba(0,0,0,.5)}
--------------------------------------------------------------------------------
/ReactJsNet.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 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/ReactWebPack.CoreRC2/app/actions/CardActionCreators.js:
--------------------------------------------------------------------------------
1 | import { dispatchAsync } from '../ReduxDispatcher';
2 | import constants from '../constants';
3 | import KanbanAPI from '../api/KanbanApi';
4 | import { getCard, getCardIndex } from '../cardUtils'
5 |
6 | let CardActionCreators = {
7 | fetchCards() {
8 | return (dispatch) => {
9 | dispatchAsync(KanbanAPI.fetchCards(), dispatch, {
10 | request: constants.FETCH_CARDS,
11 | success: constants.FETCH_CARDS_SUCCESS,
12 | failure: constants.FETCH_CARDS_ERROR
13 | });
14 | }
15 | },
16 |
17 | toggleCardDetails(cardId) {
18 | return {
19 | type: constants.TOGGLE_CARD_DETAILS,
20 | payload: {cardId}
21 | };
22 | },
23 |
24 | addCard(card) {
25 | return (dispatch) => {
26 | dispatchAsync(KanbanAPI.addCard(card), dispatch, {
27 | request: constants.CREATE_CARD,
28 | success: constants.CREATE_CARD_SUCCESS,
29 | failure: constants.CREATE_CARD_ERROR
30 | }, { card });
31 | }
32 | },
33 |
34 | updateCard(card, draftCard) {
35 | return (dispatch) => {
36 | dispatchAsync(KanbanAPI.updateCard(card, draftCard), dispatch, {
37 | request: constants.UPDATE_CARD,
38 | success: constants.UPDATE_CARD_SUCCESS,
39 | failure: constants.UPDATE_CARD_ERROR
40 | }, { card, draftCard });
41 | }
42 | },
43 |
44 | updateCardStatus(cardId, listId) {
45 | return {
46 | type: constants.UPDATE_CARD_STATUS,
47 | payload: { cardId, listId },
48 | meta: {
49 | throttle: true
50 | }
51 | };
52 | },
53 |
54 | updateCardPosition(cardId, afterId) {
55 | return {
56 | type: constants.UPDATE_CARD_POSITION,
57 | payload: { cardId, afterId },
58 | meta: {
59 | throttle: true
60 | }
61 | };
62 | },
63 |
64 | //Warning: This type of usage does not support server-side rendering.
65 | //see this SO answer for more on this http://stackoverflow.com/a/35674575/1434764
66 | persistCardDrag(cardProps) {
67 | return (dispatch, getState) => {
68 | let card = getCard(getState().cards, cardProps.id)
69 | let cardIndex = getCardIndex(getState().cards, cardProps.id)
70 | dispatchAsync(KanbanAPI.persistCardDrag(card.id, card.status, cardIndex), dispatch, {
71 | request: constants.PERSIST_CARD_DRAG,
72 | success: constants.PERSIST_CARD_DRAG_SUCCESS,
73 | failure: constants.PERSIST_CARD_DRAG_ERROR
74 | }, {cardProps});
75 | }
76 | },
77 |
78 | createDraft(card) {
79 | return {
80 | type: constants.CREATE_DRAFT,
81 | payload: {card}
82 | }
83 | },
84 |
85 | updateDraft(field, value) {
86 | return {
87 | type: constants.UPDATE_DRAFT,
88 | payload: { field, value }
89 | }
90 | }
91 | };
92 |
93 | export default CardActionCreators;
94 |
--------------------------------------------------------------------------------
/ReactWebPack.CoreRC2/JsUnitTests/Tests/reducers/CardReducer.test.js:
--------------------------------------------------------------------------------
1 | import expect from 'expect';
2 |
3 | import constants from '../../../app/constants';
4 | import cardReducer from '../../../app/reducers/cardReducer';
5 |
6 | describe('app/reducers/cardReducer', () => {
7 | function createDummyCard(id) {
8 | if (id === undefined){
9 | throw new Error('You forgot to define the dummy card id')
10 | }
11 | return {
12 | id,
13 | title: `Card${id}`
14 | }
15 | }
16 |
17 | it('Initial state', () => {
18 | const cards = cardReducer();
19 | expect(cards).toEqual([]);
20 | });
21 |
22 | it('FETCH_CARDS_SUCCESS', () => {
23 | const action = {
24 | type: constants.FETCH_CARDS_SUCCESS,
25 | payload: { response : 'all cards'}
26 | }
27 | const cards = cardReducer([], action);
28 | expect(cards).toEqual('all cards');
29 | });
30 |
31 | it('CREATE_CARD, empty state', () => {
32 | const card1 = createDummyCard(1);
33 | const action = {
34 | type: constants.CREATE_CARD,
35 | payload: { card : card1}
36 | }
37 | const cards = cardReducer([], action);
38 | expect(cards).toEqual([card1]);
39 | });
40 |
41 | it('CREATE_CARD, existing state', () => {
42 | const card1 = createDummyCard(1);
43 | const card2 = createDummyCard(2);
44 | const action = {
45 | type: constants.CREATE_CARD,
46 | payload: { card : card2}
47 | }
48 | const cards = cardReducer([card1], action);
49 | expect(cards).toEqual([card1, card2]);
50 | });
51 |
52 | it('CREATE_CARD, check new instance of state', () => {
53 | //This checks that the reducer retuns a new instance of the state
54 | const card1 = createDummyCard(1);
55 | const card2 = createDummyCard(2);
56 | const action = {
57 | type: constants.CREATE_CARD,
58 | payload: { card : card2}
59 | }
60 | const startState = [card1];
61 | const endState = cardReducer(startState, action);
62 | expect(startState === endState).toEqual(false);
63 | });
64 |
65 | it('CREATE_CARD_SUCCESS', () => {
66 | const card1 = createDummyCard(1);
67 | const card2 = createDummyCard(2);
68 | const action = {
69 | type: constants.CREATE_CARD_SUCCESS,
70 | payload: {
71 | card : card2,
72 | response : {id: 200}
73 | }
74 | }
75 | const cards = cardReducer([card1,card2], action);
76 | expect(cards).toEqual([card1, {id : 200, title : 'Card2'}]);
77 | });
78 |
79 | it('... more tests of a similar style', () => {
80 | //... I could write more but you get the idea. This is only an example after all!
81 | })
82 | });
83 |
--------------------------------------------------------------------------------
/ReactWebPack.CoreRC2/JsUnitTests/localSrc/Decoded CheckboxWithLabel.js:
--------------------------------------------------------------------------------
1 | //This contains the output of Babel & Webpack of the CheckboxWithLabel.js file
2 |
3 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
4 |
5 | var _react = __webpack_require__(468);
6 |
7 | var _react2 = _interopRequireDefault(_react);
8 |
9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
12 |
13 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
14 |
15 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
16 |
17 |
18 | var CheckboxWithLabel = function (_Component) {
19 | _inherits(CheckboxWithLabel, _Component);
20 |
21 | function CheckboxWithLabel() {
22 | _classCallCheck(this, CheckboxWithLabel);
23 |
24 | var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(CheckboxWithLabel).apply(this, arguments));
25 |
26 | _this.state = { isChecked: false };
27 | _this.onChange = _this.onChange.bind(_this);
28 | return _this;
29 | }
30 |
31 | _createClass(CheckboxWithLabel, [{
32 | key: "onChange",
33 | value: function onChange() {
34 | this.setState({ isChecked: !this.state.isChecked });
35 | }
36 | }, {
37 | key: "render",
38 | value: function render() {
39 | return _react2.default.createElement(
40 | "label",
41 | null,
42 | _react2.default.createElement("input", {
43 | type: "checkbox",
44 | checked: this.state.isChecked,
45 | onChange: this.onChange
46 | }),
47 | this.state.isChecked ? this.props.labelOn : this.props.labelOff
48 | );
49 | }
50 | }]);
51 |
52 | return CheckboxWithLabel;
53 | }(_react.Component);
54 |
55 | exports.default = CheckboxWithLabel;
--------------------------------------------------------------------------------
/ReactWebPack.CoreRC2/Views/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | @ViewData["Title"] - ReactWebPack.Core
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
40 |
41 | @RenderBody()
42 |
43 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
58 |
62 |
63 |
64 |
65 | @RenderSection("scripts", required: false)
66 |
67 |
68 |
--------------------------------------------------------------------------------
/ReactWebPack.CoreRC2/wwwroot/_references.js:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 | ///
5 | ///
6 | ///
7 | ///
8 | ///
9 | ///
10 | ///
11 | ///
12 | ///
13 | ///
14 | ///
15 | ///
16 | ///
17 | ///
18 | ///
19 | ///
20 | ///
21 | ///
22 | ///
23 | ///
24 | ///
25 | ///
26 | ///
27 | ///
28 | ///
29 | ///
30 | ///
31 | ///
32 | ///
33 | ///
34 | ///
35 | ///
36 | ///
37 | ///
38 | ///
39 | ///
40 | ///
41 | ///
42 | ///
43 | ///
44 | ///
45 | ///
46 | ///
47 | ///
48 | ///
49 | ///
50 | ///
51 | ///
52 | ///
53 |
--------------------------------------------------------------------------------
/ReactWebPack.CoreRC2/JsUnitTests/Tests/components/Card.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 {createCard} from '../../TestUtils/CardCreators'
11 | import {wrapInTestContext} from '../../MocksEtc/WrapTestDnD'
12 |
13 | import CardConnected, { Card } from '../../../app/components/Card';
14 |
15 | describe('app/components/Card', () => {
16 | describe('shallow render', () => {
17 | it('one card, check props', () => {
18 | // Stub the React DnD connector functions with an identity function
19 | const identity = function (el) { return el; };
20 | // Wrap in DnD test context
21 | const CardWithDnD = wrapInTestContext(Card);
22 | const card = createCard();
23 | const wrapper = shallow(
24 | { return null; } } //This is a dummy func to meet the propTypes validation
27 | connectDropTarget={identity}/>
28 | );
29 | //console.log(wrapper.debug());
30 | //Check the props
31 | const cardKeys = Object.keys(card)
32 | expect(Object.keys(wrapper.props()).slice(0, cardKeys.length)).toEqual(cardKeys);
33 | const cardValues = cardKeys.map((key) => { return card[key] });
34 | expect(cardKeys.map((key) => { return wrapper.prop(key) })).toEqual(cardValues);
35 | });
36 | });
37 | describe('mount render one card', () => {
38 | // Stub the React DnD connector functions with an identity function
39 | const identity = function (el) { return el; };
40 | // Wrap in DnD test context
41 | const CardConnectedWithDnD = wrapInTestContext(CardConnected);
42 | const mockStore = configureStore([]);
43 | const store = mockStore({});
44 | const card = createCard();
45 | let wrapper;
46 | beforeEach(() => {
47 | wrapper = mount(
48 |
49 |
52 | );
53 | store.clearActions();
54 | });
55 | it('renders card info', () => {
56 | expect(wrapper.find('div .card__title').text()).toBe(card.title);
57 | expect(wrapper.find('div .card__details').text().trim()).toBe(card.description);
58 | });
59 | it('call close card event', () => {
60 | expect(store.getActions().length).toBe(0);
61 | wrapper.find('div .card__title').simulate('click')
62 | expect(store.getActions().length).toBe(1);
63 | expect(store.getActions()[0]).toEqual({ payload: { cardId: 0 }, type: 'toggle card details' });
64 | });
65 | it('card with showDetails false', () => {
66 | let card = createCard();
67 | card.showDetails = false;
68 | wrapper = mount(
69 |
70 |
73 | );
74 | expect(wrapper.find('div .card__title').text()).toBe(card.title);
75 | expect(wrapper.find('div .card__details').length).toBe(0);
76 | });
77 |
78 | });
79 | });
80 |
--------------------------------------------------------------------------------
/ReactWebPack.MVC5/app/components/Card.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
3 | import marked from 'marked';
4 | import { DragSource, DropTarget } from 'react-dnd';
5 | import constants from '../constants';
6 | import CheckList from './CheckList';
7 | import {Link} from 'react-router';
8 | import CardActionCreators from '../actions/CardActionCreators';
9 |
10 | let titlePropType = (props, propName, componentName) => {
11 | if (props[propName]) {
12 | let value = props[propName];
13 | if (typeof value !== 'string' || value.length > 80) {
14 | return new Error(
15 | `${propName} in ${componentName} is longer than 80 characters`
16 | );
17 | }
18 | }
19 | };
20 |
21 | const cardDragSpec = {
22 | beginDrag(props) {
23 | return {
24 | id: props.id,
25 | status: props.status
26 | };
27 | },
28 | endDrag(props) {
29 | CardActionCreators.persistCardDrag(props);
30 | }
31 | }
32 |
33 | const cardDropSpec = {
34 | hover(props, monitor) {
35 | const draggedId = monitor.getItem().id;
36 | if(props.id !== draggedId){
37 | CardActionCreators.updateCardPosition(draggedId, props.id);
38 | }
39 |
40 | }
41 | }
42 |
43 | let collectDrag = (connect, monitor) => {
44 | return {
45 | connectDragSource: connect.dragSource()
46 | };
47 | }
48 |
49 | let collectDrop = (connect, monitor) => {
50 | return {
51 | connectDropTarget: connect.dropTarget(),
52 | };
53 | }
54 |
55 | class Card extends Component {
56 | toggleDetails() {
57 | CardActionCreators.toggleCardDetails(this.props.id);
58 | }
59 |
60 |
61 | render() {
62 | const { connectDragSource, connectDropTarget } = this.props;
63 |
64 | let cardDetails;
65 | if (this.props.showDetails !== false) {
66 | cardDetails = (
67 |
68 |
69 |
71 |
72 | );
73 | }
74 |
75 | let sideColor = {
76 | position: 'absolute',
77 | zIndex: -1,
78 | top: 0,
79 | bottom: 0,
80 | left: 0,
81 | width: 7,
82 | backgroundColor: this.props.color
83 | };
84 |
85 | return connectDropTarget(connectDragSource(
86 |
87 |
88 |
✎
89 |
92 | {this.props.title}
93 |
94 |
97 | {cardDetails}
98 |
99 |
100 | ));
101 | }
102 | }
103 | Card.propTypes = {
104 | id: PropTypes.number,
105 | title: titlePropType,
106 | description: PropTypes.string,
107 | color: PropTypes.string,
108 | tasks: PropTypes.arrayOf(PropTypes.object),
109 | connectDragSource: PropTypes.func.isRequired,
110 | connectDropTarget: PropTypes.func.isRequired
111 | };
112 |
113 | const dragHighOrderCard = DragSource(constants.CARD, cardDragSpec, collectDrag)(Card);
114 | const dragDropHighOrderCard = DropTarget(constants.CARD, cardDropSpec, collectDrop)(dragHighOrderCard);
115 | export default dragDropHighOrderCard
116 |
--------------------------------------------------------------------------------
/ReactWebPack.MVC5/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/ReactWebPack.CoreRC2/JsUnitTests/Tests/components/KanbanBoard.test.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | import expect from 'expect';
4 | import {shallow, mount} from 'enzyme';
5 | import {createCards} from '../../TestUtils/CardCreators'
6 |
7 | //These are used to pass a mock store down through nested components
8 | import configureStore from 'redux-mock-store';
9 | import { Provider, connect} from 'react-redux';
10 |
11 | import KanbanBoardConnected, {KanbanBoard} from '../../../app/components/KanbanBoard';
12 |
13 | describe('app/components/KanbanBoard', () => {
14 | describe('shallow render', () => {
15 | //This tests the inner class, i.e. without the connected
16 | it('class is created OK', () => {
17 | // Stub the React DnD connector functions with an identity function
18 | const identity = function (el) { return el; };
19 |
20 | //create mocked Redux store
21 | const mockStore = configureStore([]);
22 | const store = mockStore({});
23 | const wrapper = shallow(
24 |
25 |
28 | );
29 | expect(wrapper.text()).toBe(' ');
30 | //Could check props here...
31 | });
32 | //This tests the default export, i.e. class with Redux connect
33 | it('connected class is created OK', () => {
34 | // Stub the React DnD connector functions with an identity function
35 | const identity = function (el) { return el; };
36 |
37 | //create mocked Redux store
38 | const mockStore = configureStore([]);
39 | const store = mockStore({});
40 | const wrapper = shallow(
41 |
42 |
45 | );
46 | expect(wrapper.text()).toBe(' ');
47 | //Could check props here...
48 | });
49 | });
50 |
51 | describe('mount render', () => {
52 | it('forms three columns and Done col has one card', () => {
53 | // Stub the React DnD connector functions with an identity function
54 | const identity = function (el) { return el; };
55 |
56 | //create mocked Redux store
57 | const mockStore = configureStore([]);
58 | const store = mockStore({});
59 | const wrapper = mount(
60 |
61 |
64 | );
65 | //console.log(wrapper.debug());
66 |
67 | //Check we have the three columns
68 | const h1Parts = wrapper.find('div .list');
69 | expect(h1Parts.length).toBe(3);
70 | //Now check that we only have one card and its in the 'done' column
71 | expect(h1Parts.nodes[0].children.length).toBe(1);
72 | expect(h1Parts.nodes[0].children[0].textContent).toBe('To Do');
73 | expect(h1Parts.nodes[1].children.length).toBe(1);
74 | expect(h1Parts.nodes[1].children[0].textContent).toBe('In Progress');
75 | expect(h1Parts.nodes[2].children.length).toBe(2);
76 | expect(h1Parts.nodes[2].children[0].textContent).toBe('Done');
77 | //now check that Done column has a single card
78 | expect(h1Parts.nodes[2].children[1].classList.length).toBe(1);
79 | expect(h1Parts.nodes[2].children[1].classList[0]).toBe('card');
80 | });
81 | });
82 | });
83 |
--------------------------------------------------------------------------------
/ReactWebPack.CoreRC2/app/components/Card.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
3 | import marked from 'marked';
4 | import { DragSource, DropTarget } from 'react-dnd';
5 | import constants from '../constants';
6 | import CheckList from './CheckList';
7 | import {Link} from 'react-router';
8 | import CardActionCreators from '../actions/CardActionCreators';
9 | import { connect } from 'react-redux';
10 |
11 | let titlePropType = (props, propName, componentName) => {
12 | if (props[propName]) {
13 | let value = props[propName];
14 | if (typeof value !== 'string' || value.length > 80) {
15 | return new Error(
16 | `${propName} in ${componentName} is longer than 80 characters`
17 | );
18 | }
19 | }
20 | };
21 |
22 | const cardDragSpec = {
23 | beginDrag(props) {
24 | return {
25 | id: props.id,
26 | status: props.status
27 | };
28 | },
29 | endDrag(props) {
30 | props.persistCardDrag(props);
31 | }
32 | }
33 |
34 | const cardDropSpec = {
35 | hover(props, monitor) {
36 | const draggedId = monitor.getItem().id;
37 | if(props.id !== draggedId){
38 | props.updateCardPosition(draggedId, props.id);
39 | }
40 |
41 | }
42 | }
43 |
44 | let collectDrag = (connect, monitor) => {
45 | return {
46 | connectDragSource: connect.dragSource()
47 | };
48 | }
49 |
50 | let collectDrop = (connect, monitor) => {
51 | return {
52 | connectDropTarget: connect.dropTarget(),
53 | };
54 | }
55 |
56 | export class Card extends Component {
57 | toggleDetails() {
58 | this.props.toggleCardDetails(this.props.id);
59 | }
60 |
61 | render() {
62 | const { connectDragSource, connectDropTarget } = this.props;
63 |
64 | let cardDetails;
65 | if (this.props.showDetails !== false) {
66 | cardDetails = (
67 |
68 |
69 |
71 |
72 | );
73 | }
74 |
75 | let sideColor = {
76 | position: 'absolute',
77 | zIndex: -1,
78 | top: 0,
79 | bottom: 0,
80 | left: 0,
81 | width: 7,
82 | backgroundColor: this.props.color
83 | };
84 |
85 | return connectDropTarget(connectDragSource(
86 |
87 |
88 |
✎
89 |
92 | {this.props.title}
93 |
94 |
97 | {cardDetails}
98 |
99 |
100 | ));
101 | }
102 | }
103 | Card.propTypes = {
104 | id: PropTypes.number,
105 | title: titlePropType,
106 | description: PropTypes.string,
107 | color: PropTypes.string,
108 | tasks: PropTypes.arrayOf(PropTypes.object),
109 | connectDragSource: PropTypes.func.isRequired,
110 | connectDropTarget: PropTypes.func.isRequired
111 | };
112 |
113 | function mapDispatchToProps(dispatch) {
114 | return {
115 | persistCardDrag: (props) => dispatch(CardActionCreators.persistCardDrag(props)),
116 | updateCardPosition: (draggedId, id) => dispatch(CardActionCreators.updateCardPosition(draggedId, id)),
117 | toggleCardDetails: (id) => dispatch(CardActionCreators.toggleCardDetails(id))
118 | }
119 | }
120 |
121 | const dragHighOrderCard = DragSource(constants.CARD, cardDragSpec, collectDrag)(Card);
122 | const dragDropHighOrderCard = DropTarget(constants.CARD, cardDropSpec, collectDrop)(dragHighOrderCard);
123 | export default connect(
124 | null,
125 | mapDispatchToProps
126 | )(dragDropHighOrderCard);
127 |
--------------------------------------------------------------------------------
/ReactWebPack.MVC5/Content/kanban-styles.css:
--------------------------------------------------------------------------------
1 | *{
2 | box-sizing: border-box;
3 | }
4 |
5 | html,body,#root {
6 | height:100%;
7 | margin: 0;
8 | padding: 0;
9 | }
10 |
11 | body {
12 | background: #eee;
13 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
14 | }
15 |
16 | h1{
17 | font-weight: 200;
18 | color: #3b414c;
19 | font-size: 20px;
20 | }
21 |
22 | ul {
23 | list-style-type: none;
24 | padding: 0;
25 | margin: 0;
26 | }
27 |
28 | .app {
29 | white-space: nowrap;
30 | height:100%;
31 | }
32 |
33 | .list {
34 | position: relative;
35 | display: inline-block;
36 | vertical-align: top;
37 | white-space: normal;
38 | height: 100%;
39 | width: 33%;
40 | padding: 0 20px;
41 | overflow: auto;
42 | }
43 |
44 | .list:not(:last-child):after{
45 | content: "";
46 | position: absolute;
47 | top: 0;
48 | right: 0;
49 | width: 1px;
50 | height: 99%;
51 | background: linear-gradient(to bottom, #eee 0%, #ccc 50%, #eee 100%) fixed;
52 | }
53 |
54 | .card {
55 | position: relative;
56 | z-index: 1;
57 | background: #fff;
58 | width: 100%;
59 | padding: 10px 10px 10px 15px;
60 | margin: 0 0 10px 0;
61 | overflow: auto;
62 | border: 1px solid #e5e5df;
63 | border-radius: 3px;
64 | box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
65 | }
66 |
67 | .card__title {
68 | font-weight: bold;
69 | border-bottom: solid 5px transparent;
70 | }
71 |
72 | .card__title:before {
73 | display: inline-block;
74 | width: 1em;
75 | content: '▸';
76 | }
77 |
78 | .card__title--is-open:before {
79 | content: '▾';
80 | }
81 |
82 | .card.big {
83 | position: absolute;
84 | width: 450px;
85 | height: 200px;
86 | margin: auto;
87 | padding: 15px;
88 | top: 0; left: 0; bottom: 100px; right: 0;
89 | z-index: 3;
90 | }
91 |
92 | .card.big input[type=text], textarea {
93 | width : 100%;
94 | margin: 3px 0;
95 | font-size: 13px;
96 | border: none;
97 | }
98 |
99 | .card.big input[type=text] {
100 | font-size: 20px;
101 | font-weight: bold;
102 | }
103 |
104 | .card.big input[type=text]:focus,
105 | .card.big textarea:focus {
106 | outline: dashed thin #999;
107 | outline-offset: 2px;
108 | }
109 |
110 | .card.big label {
111 | margin: 3px 0 7px 3px;
112 | color: #a7a7a7;
113 | display: inline-block;
114 | width: 60px;
115 | }
116 |
117 | .actions {
118 | margin-top: 10px;
119 | text-align: right;
120 | }
121 |
122 | .card.big button {
123 | font-size:14px;
124 | padding: 8px;
125 | }
126 |
127 | .card__edit{
128 | position: absolute;
129 | top:10px;
130 | right: 10px;
131 | opacity: 0;
132 | transition: opacity .25s ease-in;
133 | }
134 |
135 | .card:hover .card__edit{
136 | opacity: 1;
137 | }
138 |
139 | .card__edit a{
140 | text-decoration: none;
141 | color: #999;
142 | font-size: 17px;
143 | }
144 |
145 | .overlay {
146 | position: absolute;
147 | width: 100%;
148 | height: 100%;
149 | top: 0; left: 0; bottom: 0; right: 0;
150 | z-index: 2;
151 | background-color: rgba(0, 0, 0, 0.6);
152 | }
153 |
154 | .toggle-enter {
155 | max-height: 0;
156 | overflow: hidden;
157 | }
158 |
159 | .toggle-enter.toggle-enter-active {
160 | max-height: 300px;
161 | overflow: hidden;
162 | transition: max-height .25s ease-in;
163 | }
164 |
165 | .toggle-leave {
166 | max-height: 300px;
167 | overflow: hidden;
168 | }
169 |
170 | .toggle-leave.toggle-leave-active {
171 | max-height: 0;
172 | overflow: hidden;
173 | transition: max-height .25s ease-out;
174 | }
175 |
176 | .checklist__task:first-child {
177 | margin-top: 10px;
178 | padding-top: 10px;
179 | border-top: dashed 1px #ddd;
180 | }
181 |
182 | .checklist__task--remove:after{
183 | display: inline-block;
184 | color: #d66;
185 | content: "✖";
186 | }
187 |
188 | .checklist--add-task {
189 | border: 1px dashed #bbb;
190 | width: 100%;
191 | padding: 10px;
192 | margin-top: 5px;
193 | border-radius: 3px;
194 | }
195 |
196 | .float-button {
197 | position: absolute;
198 | height: 56px;
199 | width: 56px;
200 | z-index: 2;
201 | right: 20px;
202 | bottom: 20px;
203 | background: #D43A2F;
204 | color: white;
205 | border-radius: 100%;
206 | font-size: 34px;
207 | text-align: center;
208 | text-decoration: none;
209 | line-height: 50px;
210 | box-shadow: 0 5px 10px rgba(0, 0, 0, 0.5);
211 | }
212 |
--------------------------------------------------------------------------------
/ReactWebPack.CoreRC2/wwwroot/css/kanban-styles.css:
--------------------------------------------------------------------------------
1 | *{
2 | box-sizing: border-box;
3 | }
4 |
5 | html,body,#root {
6 | height:100%;
7 | margin: 0;
8 | padding: 0;
9 | }
10 |
11 | body {
12 | background: #eee;
13 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
14 | }
15 |
16 | h1{
17 | font-weight: 200;
18 | color: #3b414c;
19 | font-size: 20px;
20 | }
21 |
22 | ul {
23 | list-style-type: none;
24 | padding: 0;
25 | margin: 0;
26 | }
27 |
28 | .app {
29 | white-space: nowrap;
30 | height:100%;
31 | }
32 |
33 | .list {
34 | position: relative;
35 | display: inline-block;
36 | vertical-align: top;
37 | white-space: normal;
38 | height: 100%;
39 | width: 33%;
40 | padding: 0 20px;
41 | overflow: auto;
42 | }
43 |
44 | .list:not(:last-child):after{
45 | content: "";
46 | position: absolute;
47 | top: 0;
48 | right: 0;
49 | width: 1px;
50 | height: 99%;
51 | background: linear-gradient(to bottom, #eee 0%, #ccc 50%, #eee 100%) fixed;
52 | }
53 |
54 | .card {
55 | position: relative;
56 | z-index: 1;
57 | background: #fff;
58 | width: 100%;
59 | padding: 10px 10px 10px 15px;
60 | margin: 0 0 10px 0;
61 | overflow: auto;
62 | border: 1px solid #e5e5df;
63 | border-radius: 3px;
64 | box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
65 | }
66 |
67 | .card__title {
68 | font-weight: bold;
69 | border-bottom: solid 5px transparent;
70 | }
71 |
72 | .card__title:before {
73 | display: inline-block;
74 | width: 1em;
75 | content: '▸';
76 | }
77 |
78 | .card__title--is-open:before {
79 | content: '▾';
80 | }
81 |
82 | .card.big {
83 | position: absolute;
84 | width: 450px;
85 | height: 200px;
86 | margin: auto;
87 | padding: 15px;
88 | top: 0; left: 0; bottom: 100px; right: 0;
89 | z-index: 3;
90 | }
91 |
92 | .card.big input[type=text], textarea {
93 | width : 100%;
94 | margin: 3px 0;
95 | font-size: 13px;
96 | border: none;
97 | }
98 |
99 | .card.big input[type=text] {
100 | font-size: 20px;
101 | font-weight: bold;
102 | }
103 |
104 | .card.big input[type=text]:focus,
105 | .card.big textarea:focus {
106 | outline: dashed thin #999;
107 | outline-offset: 2px;
108 | }
109 |
110 | .card.big label {
111 | margin: 3px 0 7px 3px;
112 | color: #a7a7a7;
113 | display: inline-block;
114 | width: 60px;
115 | }
116 |
117 | .actions {
118 | margin-top: 10px;
119 | text-align: right;
120 | }
121 |
122 | .card.big button {
123 | font-size:14px;
124 | padding: 8px;
125 | }
126 |
127 | .card__edit{
128 | position: absolute;
129 | top:10px;
130 | right: 10px;
131 | opacity: 0;
132 | transition: opacity .25s ease-in;
133 | }
134 |
135 | .card:hover .card__edit{
136 | opacity: 1;
137 | }
138 |
139 | .card__edit a{
140 | text-decoration: none;
141 | color: #999;
142 | font-size: 17px;
143 | }
144 |
145 | .overlay {
146 | position: absolute;
147 | width: 100%;
148 | height: 100%;
149 | top: 0; left: 0; bottom: 0; right: 0;
150 | z-index: 2;
151 | background-color: rgba(0, 0, 0, 0.6);
152 | }
153 |
154 | .toggle-enter {
155 | max-height: 0;
156 | overflow: hidden;
157 | }
158 |
159 | .toggle-enter.toggle-enter-active {
160 | max-height: 300px;
161 | overflow: hidden;
162 | transition: max-height .25s ease-in;
163 | }
164 |
165 | .toggle-leave {
166 | max-height: 300px;
167 | overflow: hidden;
168 | }
169 |
170 | .toggle-leave.toggle-leave-active {
171 | max-height: 0;
172 | overflow: hidden;
173 | transition: max-height .25s ease-out;
174 | }
175 |
176 | .checklist__task:first-child {
177 | margin-top: 10px;
178 | padding-top: 10px;
179 | border-top: dashed 1px #ddd;
180 | }
181 |
182 | .checklist__task--remove:after{
183 | display: inline-block;
184 | color: #d66;
185 | content: "✖";
186 | }
187 |
188 | .checklist--add-task {
189 | border: 1px dashed #bbb;
190 | width: 100%;
191 | padding: 10px;
192 | margin-top: 5px;
193 | border-radius: 3px;
194 | }
195 |
196 | .float-button {
197 | position: absolute;
198 | height: 56px;
199 | width: 56px;
200 | z-index: 2;
201 | right: 20px;
202 | bottom: 20px;
203 | background: #D43A2F;
204 | color: white;
205 | border-radius: 100%;
206 | font-size: 34px;
207 | text-align: center;
208 | text-decoration: none;
209 | line-height: 50px;
210 | box-shadow: 0 5px 10px rgba(0, 0, 0, 0.5);
211 | }
212 |
--------------------------------------------------------------------------------
/ReactJsNet.MVC5/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/ReactJsNet.MVC5/Scripts/respond.min.js:
--------------------------------------------------------------------------------
1 | /* NUGET: BEGIN LICENSE TEXT
2 | *
3 | * Microsoft grants you the right to use these script files for the sole
4 | * purpose of either: (i) interacting through your browser with the Microsoft
5 | * website or online service, subject to the applicable licensing or use
6 | * terms; or (ii) using the files as included with a Microsoft product subject
7 | * to that product's license terms. Microsoft reserves all other rights to the
8 | * files not expressly granted by Microsoft, whether by implication, estoppel
9 | * or otherwise. Insofar as a script file is dual licensed under GPL,
10 | * Microsoft neither took the code under GPL nor distributes it thereunder but
11 | * under the terms set out in this paragraph. All notices and licenses
12 | * below are for informational purposes only.
13 | *
14 | * NUGET: END LICENSE TEXT */
15 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
16 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
17 | window.matchMedia=window.matchMedia||(function(e,f){var c,a=e.documentElement,b=a.firstElementChild||a.firstChild,d=e.createElement("body"),g=e.createElement("div");g.id="mq-test-1";g.style.cssText="position:absolute;top:-100em";d.style.background="none";d.appendChild(g);return function(h){g.innerHTML='';a.insertBefore(d,b);c=g.offsetWidth==42;a.removeChild(d);return{matches:c,media:h}}})(document);
18 |
19 | /*! Respond.js v1.2.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
20 | (function(e){e.respond={};respond.update=function(){};respond.mediaQueriesSupported=e.matchMedia&&e.matchMedia("only all").matches;if(respond.mediaQueriesSupported){return}var w=e.document,s=w.documentElement,i=[],k=[],q=[],o={},h=30,f=w.getElementsByTagName("head")[0]||s,g=w.getElementsByTagName("base")[0],b=f.getElementsByTagName("link"),d=[],a=function(){var D=b,y=D.length,B=0,A,z,C,x;for(;B-1,minw:F.match(/\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:F.match(/\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}}j()},l,r,v=function(){var z,A=w.createElement("div"),x=w.body,y=false;A.style.cssText="position:absolute;font-size:1em;width:1em";if(!x){x=y=w.createElement("body");x.style.background="none"}x.appendChild(A);s.insertBefore(x,s.firstChild);z=A.offsetWidth;if(y){s.removeChild(x)}else{x.removeChild(A)}z=p=parseFloat(z);return z},p,j=function(I){var x="clientWidth",B=s[x],H=w.compatMode==="CSS1Compat"&&B||w.body[x]||B,D={},G=b[b.length-1],z=(new Date()).getTime();if(I&&l&&z-l-1?(p||v()):1)}if(!!J){J=parseFloat(J)*(J.indexOf(y)>-1?(p||v()):1)}if(!K.hasquery||(!A||!L)&&(A||H>=C)&&(L||H<=J)){if(!D[K.media]){D[K.media]=[]}D[K.media].push(k[K.rules])}}for(var E in q){if(q[E]&&q[E].parentNode===f){f.removeChild(q[E])}}for(var E in D){var M=w.createElement("style"),F=D[E].join("\n");M.type="text/css";M.media=E;f.insertBefore(M,G.nextSibling);if(M.styleSheet){M.styleSheet.cssText=F}else{M.appendChild(w.createTextNode(F))}q.push(M)}},n=function(x,z){var y=c();if(!y){return}y.open("GET",x,true);y.onreadystatechange=function(){if(y.readyState!=4||y.status!=200&&y.status!=304){return}z(y.responseText)};if(y.readyState==4){return}y.send(null)},c=(function(){var x=false;try{x=new XMLHttpRequest()}catch(y){x=new ActiveXObject("Microsoft.XMLHTTP")}return function(){return x}})();a();respond.update=a;function t(){j(true)}if(e.addEventListener){e.addEventListener("resize",t,false)}else{if(e.attachEvent){e.attachEvent("onresize",t)}}})(this);
--------------------------------------------------------------------------------
/ReactWebPack.MVC5/Scripts/respond.min.js:
--------------------------------------------------------------------------------
1 | /* NUGET: BEGIN LICENSE TEXT
2 | *
3 | * Microsoft grants you the right to use these script files for the sole
4 | * purpose of either: (i) interacting through your browser with the Microsoft
5 | * website or online service, subject to the applicable licensing or use
6 | * terms; or (ii) using the files as included with a Microsoft product subject
7 | * to that product's license terms. Microsoft reserves all other rights to the
8 | * files not expressly granted by Microsoft, whether by implication, estoppel
9 | * or otherwise. Insofar as a script file is dual licensed under GPL,
10 | * Microsoft neither took the code under GPL nor distributes it thereunder but
11 | * under the terms set out in this paragraph. All notices and licenses
12 | * below are for informational purposes only.
13 | *
14 | * NUGET: END LICENSE TEXT */
15 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
16 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
17 | window.matchMedia=window.matchMedia||(function(e,f){var c,a=e.documentElement,b=a.firstElementChild||a.firstChild,d=e.createElement("body"),g=e.createElement("div");g.id="mq-test-1";g.style.cssText="position:absolute;top:-100em";d.style.background="none";d.appendChild(g);return function(h){g.innerHTML='';a.insertBefore(d,b);c=g.offsetWidth==42;a.removeChild(d);return{matches:c,media:h}}})(document);
18 |
19 | /*! Respond.js v1.2.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
20 | (function(e){e.respond={};respond.update=function(){};respond.mediaQueriesSupported=e.matchMedia&&e.matchMedia("only all").matches;if(respond.mediaQueriesSupported){return}var w=e.document,s=w.documentElement,i=[],k=[],q=[],o={},h=30,f=w.getElementsByTagName("head")[0]||s,g=w.getElementsByTagName("base")[0],b=f.getElementsByTagName("link"),d=[],a=function(){var D=b,y=D.length,B=0,A,z,C,x;for(;B-1,minw:F.match(/\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:F.match(/\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}}j()},l,r,v=function(){var z,A=w.createElement("div"),x=w.body,y=false;A.style.cssText="position:absolute;font-size:1em;width:1em";if(!x){x=y=w.createElement("body");x.style.background="none"}x.appendChild(A);s.insertBefore(x,s.firstChild);z=A.offsetWidth;if(y){s.removeChild(x)}else{x.removeChild(A)}z=p=parseFloat(z);return z},p,j=function(I){var x="clientWidth",B=s[x],H=w.compatMode==="CSS1Compat"&&B||w.body[x]||B,D={},G=b[b.length-1],z=(new Date()).getTime();if(I&&l&&z-l-1?(p||v()):1)}if(!!J){J=parseFloat(J)*(J.indexOf(y)>-1?(p||v()):1)}if(!K.hasquery||(!A||!L)&&(A||H>=C)&&(L||H<=J)){if(!D[K.media]){D[K.media]=[]}D[K.media].push(k[K.rules])}}for(var E in q){if(q[E]&&q[E].parentNode===f){f.removeChild(q[E])}}for(var E in D){var M=w.createElement("style"),F=D[E].join("\n");M.type="text/css";M.media=E;f.insertBefore(M,G.nextSibling);if(M.styleSheet){M.styleSheet.cssText=F}else{M.appendChild(w.createTextNode(F))}q.push(M)}},n=function(x,z){var y=c();if(!y){return}y.open("GET",x,true);y.onreadystatechange=function(){if(y.readyState!=4||y.status!=200&&y.status!=304){return}z(y.responseText)};if(y.readyState==4){return}y.send(null)},c=(function(){var x=false;try{x=new XMLHttpRequest()}catch(y){x=new ActiveXObject("Microsoft.XMLHTTP")}return function(){return x}})();a();respond.update=a;function t(){j(true)}if(e.addEventListener){e.addEventListener("resize",t,false)}else{if(e.attachEvent){e.attachEvent("onresize",t)}}})(this);
--------------------------------------------------------------------------------