Skip to content

Commit f25f4a8

Browse files
author
Marcin Drobik
committed
Fixing Code Review issues, used sample from React.Sample.MVC4
1 parent fbbaf63 commit f25f4a8

15 files changed

+281
-129
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2014-2015, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
using React.TinyIoC;
11+
12+
namespace React.Owin
13+
{
14+
/// <summary>
15+
/// Handles registration of ReactJS.NET components that are only applicable
16+
/// when used with Owin.
17+
/// </summary>
18+
public class AssemblyRegistration : IAssemblyRegistration
19+
{
20+
/// <summary>
21+
/// Registers components in the React IoC container
22+
/// </summary>
23+
/// <param name="container">Container to register components in</param>
24+
public void Register(TinyIoCContainer container)
25+
{
26+
container.Register<IFileSystem, EntryAssemblyFileSystem>();
27+
container.Register<ICache, MemoryFileCache>();
28+
}
29+
}
30+
}

src/React.Owin/JsxFileExtensions.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,12 @@ namespace React.Owin
1616
/// </summary>
1717
public static class JsxFileExtensions
1818
{
19-
/// <summary>
20-
/// Enables serving static JSX file, compiled to JavaScript, for the current request path from the current directory.
21-
/// </summary>
22-
public static IAppBuilder UseJsxFiles(this IAppBuilder builder)
23-
{
24-
return builder.UseJsxFiles(new JsxFileOptions());
25-
}
26-
2719
/// <summary>
2820
/// Enables serving static JSX file, compiled to JavaScript with the given options.
2921
/// </summary>
30-
public static IAppBuilder UseJsxFiles(this IAppBuilder builder, JsxFileOptions options)
22+
public static IAppBuilder UseJsxFiles(this IAppBuilder builder, JsxFileOptions options = null)
3123
{
32-
return builder.Use<JsxFileMiddleware>(options);
24+
return builder.Use<JsxFileMiddleware>(options ?? new JsxFileOptions());
3325
}
3426
}
3527
}

src/React.Owin/JsxFileMiddleware.cs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,6 @@ public class JsxFileMiddleware
2626
static JsxFileMiddleware()
2727
{
2828
Initializer.Initialize(_ => _);
29-
30-
// Register interface implementations required by React. By default it sets React to work with physical file system.
31-
var container = AssemblyRegistration.Container;
32-
IFileSystem tempFileSystem;
33-
if (!container.TryResolve(out tempFileSystem))
34-
AssemblyRegistration.Container.Register<IFileSystem, EntryAssemblyFileSystem>();
35-
36-
ICache tempCache;
37-
if (!container.TryResolve(out tempCache))
38-
AssemblyRegistration.Container.Register<ICache, MemoryFileCache>();
3929
}
4030

4131
public JsxFileMiddleware(Func<IDictionary<string, object>, Task> next, JsxFileOptions options)
@@ -49,7 +39,7 @@ public JsxFileMiddleware(Func<IDictionary<string, object>, Task> next, JsxFileOp
4939
var fileOptions = options.StaticFileOptions ?? new StaticFileOptions();
5040

5141
// Wrap the file system with JSX file system
52-
var reactEnvironment = AssemblyRegistration.Container.Resolve<IReactEnvironment>();
42+
var reactEnvironment = React.AssemblyRegistration.Container.Resolve<IReactEnvironment>();
5343
_internalStaticMiddleware = new StaticFileMiddleware(
5444
next,
5545
new StaticFileOptions()

src/React.Owin/React.Owin.csproj

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<ErrorReport>prompt</ErrorReport>
2323
<WarningLevel>4</WarningLevel>
2424
<Prefer32Bit>false</Prefer32Bit>
25+
<DocumentationFile>..\..\bin\Debug\React.Owin\React.Owin.XML</DocumentationFile>
2526
</PropertyGroup>
2627
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
2728
<DebugType>pdbonly</DebugType>
@@ -31,6 +32,12 @@
3132
<ErrorReport>prompt</ErrorReport>
3233
<WarningLevel>4</WarningLevel>
3334
<Prefer32Bit>false</Prefer32Bit>
35+
<DocumentationFile>..\..\bin\Release\React.Owin\React.Owin.XML</DocumentationFile>
36+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
37+
<NoWarn>1607</NoWarn>
38+
</PropertyGroup>
39+
<PropertyGroup>
40+
<AssemblyOriginatorKeyFile>..\Key.snk</AssemblyOriginatorKeyFile>
3441
</PropertyGroup>
3542
<ItemGroup>
3643
<Reference Include="Microsoft.Owin, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@@ -51,11 +58,7 @@
5158
<Reference Include="System" />
5259
<Reference Include="System.Core" />
5360
<Reference Include="System.Runtime.Caching" />
54-
<Reference Include="System.Xml.Linq" />
55-
<Reference Include="System.Data.DataSetExtensions" />
5661
<Reference Include="Microsoft.CSharp" />
57-
<Reference Include="System.Data" />
58-
<Reference Include="System.Xml" />
5962
</ItemGroup>
6063
<ItemGroup>
6164
<Compile Include="..\SharedAssemblyInfo.cs">
@@ -64,6 +67,7 @@
6467
<Compile Include="..\SharedAssemblyVersionInfo.cs">
6568
<Link>Properties\SharedAssemblyVersionInfo.cs</Link>
6669
</Compile>
70+
<Compile Include="AssemblyRegistration.cs" />
6771
<Compile Include="EntryAssemblyFileSystem.cs" />
6872
<Compile Include="MemoryFileCache.cs" />
6973
<Compile Include="JsxFileMiddleware.cs" />

src/React.Sample.Owin/App.config

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright (c) 2014-2015, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
using System;
11+
using System.Collections.Generic;
12+
using System.Linq;
13+
using System.Threading.Tasks;
14+
15+
using Microsoft.Owin;
16+
17+
using Newtonsoft.Json;
18+
19+
using React.Sample.Owin.Models;
20+
21+
namespace React.Sample.Owin.Models
22+
{
23+
public class AuthorModel
24+
{
25+
public string Name { get; set; }
26+
public string Facebook { get; set; }
27+
}
28+
public class CommentModel
29+
{
30+
public AuthorModel Author { get; set; }
31+
public string Text { get; set; }
32+
}
33+
}
34+
35+
namespace React.Sample.Owin
36+
{
37+
internal class CommentsMiddleware
38+
{
39+
private const int COMMENTS_PER_PAGE = 3;
40+
41+
private readonly Func<IDictionary<string, object>, Task> _next;
42+
private readonly List<CommentModel> _comments;
43+
44+
public CommentsMiddleware(Func<IDictionary<string, object>, Task> next)
45+
{
46+
_next = next;
47+
48+
// In reality, you would use a repository or something for fetching data
49+
// For clarity, we'll just use a hard-coded list.
50+
var authors = new Dictionary<string, AuthorModel>
51+
{
52+
{"daniel", new AuthorModel { Name = "Daniel Lo Nigro", Facebook = "daaniel" }},
53+
{"vjeux", new AuthorModel { Name = "Christopher Chedeau", Facebook = "vjeux" }},
54+
{"cpojer", new AuthorModel { Name = "Christoph Pojer", Facebook = "cpojer" }},
55+
{"jordwalke", new AuthorModel { Name = "Jordan Walke", Facebook = "jordwalke" }},
56+
{"zpao", new AuthorModel { Name = "Paul O'Shannessy", Facebook = "zpao" }},
57+
};
58+
59+
_comments = new List<CommentModel>
60+
{
61+
new CommentModel { Author = authors["daniel"], Text = "First!!!!111!" },
62+
new CommentModel { Author = authors["zpao"], Text = "React is awesome!" },
63+
new CommentModel { Author = authors["cpojer"], Text = "Awesome!" },
64+
new CommentModel { Author = authors["vjeux"], Text = "Hello World" },
65+
new CommentModel { Author = authors["daniel"], Text = "Foo" },
66+
new CommentModel { Author = authors["daniel"], Text = "Bar" },
67+
new CommentModel { Author = authors["daniel"], Text = "FooBarBaz" },
68+
};
69+
}
70+
71+
public async Task Invoke(IDictionary<string, object> environment)
72+
{
73+
var context = new OwinContext(environment);
74+
75+
// Determine if this middleware should handle the request
76+
if (!context.Request.Path.Value.StartsWith("/comments/page-") || context.Request.Method != "GET")
77+
{
78+
await _next(environment);
79+
return;
80+
}
81+
82+
// prepare the response data
83+
int page = int.Parse(context.Request.Path.Value.Replace("/comments/page-", string.Empty));
84+
var responseObject = new
85+
{
86+
comments = _comments.Skip((page - 1) * COMMENTS_PER_PAGE).Take(COMMENTS_PER_PAGE),
87+
hasMore = page * COMMENTS_PER_PAGE < _comments.Count
88+
};
89+
90+
var json = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(responseObject));
91+
92+
await context.Response.WriteAsync(json);
93+
}
94+
}
95+
}

src/React.Sample.Owin/Content/Index.html

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,17 @@
44
<head>
55
<meta charset="utf-8" />
66
<title>React OWIN Sample</title>
7-
<script src="react-0.12.2.js"></script>
8-
<script src="jquery-1.10.0.min.js"></script>
9-
<link href="Todo.css" media="all" rel="stylesheet" type="text/css">
7+
<link href="Sample.css" media="all" rel="stylesheet" type="text/css">
108
</head>
11-
<body>
12-
<div id="container"></div>
13-
<script type="text/javascript" src="Todo.jsx"></script>
14-
<script type="text/javascript">
15-
React.render(
16-
React.createElement(TodoApp, null),
17-
document.getElementById('container')
18-
);
19-
</script>
20-
</body>
9+
<body>
10+
<div id="container"></div>
11+
<script src="http://fb.me/react-0.12.2.min.js"></script>
12+
<script type="text/javascript" src="Sample.jsx"></script>
13+
<script type="text/javascript">
14+
React.render(
15+
React.createElement(CommentsBox),
16+
document.getElementById('container')
17+
);
18+
</script>
19+
</body>
2120
</html>

src/React.Sample.Owin/Content/Todo.css renamed to src/React.Sample.Owin/Content/Sample.css

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ body {
1111
font-family: Calibri, Verdana, sans-serif;
1212
}
1313

14-
ul li {
15-
color: brown
14+
.commentList {
15+
list-style-type: none;
16+
margin: 0;
17+
padding: 0;
18+
}
19+
20+
.commentList li {
21+
border-bottom: 1px solid #999;
22+
padding: 0.5em 0;
1623
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/**
2+
* Copyright (c) 2014-2015, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
CommentsBox = React.createClass({
11+
propTypes: {
12+
initialComments: React.PropTypes.array.isRequired
13+
},
14+
getInitialState() {
15+
return {
16+
comments: this.props.initialComments || [],
17+
page: 0,
18+
hasMore: true,
19+
loadingMore: false
20+
};
21+
},
22+
loadMoreClicked(evt) {
23+
var nextPage = this.state.page + 1;
24+
this.setState({
25+
page: nextPage,
26+
loadingMore: true
27+
});
28+
29+
var url = evt.target.href;
30+
var xhr = new XMLHttpRequest();
31+
xhr.open('GET', url, true);
32+
xhr.onload = () => {
33+
var data = JSON.parse(xhr.responseText);
34+
this.setState({
35+
comments: this.state.comments.concat(data.comments),
36+
hasMore: data.hasMore,
37+
loadingMore: false
38+
});
39+
};
40+
xhr.send();
41+
return false;
42+
},
43+
componentDidMount: function() {
44+
this.loadMoreClicked({ target: { href: "/comments/page-1" } });
45+
},
46+
render() {
47+
var commentNodes = this.state.comments.map(comment =>
48+
<Comment author={comment.Author}>{comment.Text}</Comment>
49+
);
50+
51+
return (
52+
<div className="comments">
53+
<h1>Comments</h1>
54+
<ol className="commentList">
55+
{commentNodes}
56+
</ol>
57+
{this.renderMoreLink()}
58+
</div>
59+
);
60+
},
61+
renderMoreLink() {
62+
if (this.state.loadingMore) {
63+
return <em>Loading...</em>;
64+
} else if (this.state.hasMore) {
65+
return (
66+
<a href={'comments/page-' + (this.state.page + 1)} onClick={this.loadMoreClicked}>
67+
Load More
68+
</a>
69+
);
70+
} else {
71+
return <em>No more comments</em>;
72+
}
73+
}
74+
});
75+
76+
var Comment = React.createClass({
77+
propTypes: {
78+
author: React.PropTypes.object.isRequired
79+
},
80+
render() {
81+
return (
82+
<li>
83+
<Avatar author={this.props.author} />
84+
<strong>{this.props.author.Name}</strong>{': '}
85+
{this.props.children}
86+
</li>
87+
);
88+
}
89+
});
90+
91+
var Avatar = React.createClass({
92+
propTypes: {
93+
author: React.PropTypes.object.isRequired
94+
},
95+
render() {
96+
return (
97+
<img
98+
src={this.getPhotoUrl(this.props.author)}
99+
alt={'Photo of ' + this.props.author.Name}
100+
width={50}
101+
height={50}
102+
className="commentPhoto"
103+
/>
104+
);
105+
},
106+
getPhotoUrl(author) {
107+
return 'http://graph.facebook.com/' + author.Facebook + '/picture';
108+
}
109+
});

0 commit comments

Comments
 (0)