Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 974bb59

Browse files
committedMay 20, 2018
demo 6 (WIP) - manage state with vuex
1 parent 872c2a3 commit 974bb59

20 files changed

+8402
-1
lines changed
 

‎src/demo5/client/stream-adapter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { IStreamResult } from "@aspnet/signalr";
22
import { Subject, Observable } from "rxjs";
33

4-
export function adapt<T = any>(stream: IStreamResult<T>): Observable<T> {
4+
export function adapt<T>(stream: IStreamResult<T>): Observable<T> {
55
const subject = new Subject<T>();
66
stream.subscribe(subject);
77
return subject.asObservable();
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Threading.Tasks;
2+
using demo6.Hubs;
3+
using demo6.Models;
4+
using Microsoft.AspNetCore.Mvc;
5+
using Microsoft.AspNetCore.SignalR;
6+
7+
namespace demo6.Controllers
8+
{
9+
10+
[ApiController]
11+
[Route("/message")]
12+
public class MessageController : Controller
13+
{
14+
public IHubContext<ApplicationHub> _hubContext { get; }
15+
16+
public MessageController(IHubContext<ApplicationHub> hubContext)
17+
{
18+
_hubContext = hubContext;
19+
}
20+
21+
[HttpPost]
22+
public Task PostMessage(ChatMessage message)
23+
{
24+
return _hubContext.Clients.All.SendAsync("Send", message.Message);
25+
}
26+
}
27+
}

‎src/demo6/Hubs/ApplicationHub.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Microsoft.AspNetCore.SignalR;
2+
using System.Threading.Tasks;
3+
using demo6.Models;
4+
using System.Threading.Channels;
5+
using System;
6+
7+
namespace demo6.Hubs
8+
{
9+
public class ApplicationHub : Hub
10+
{
11+
public Task Send(ChatMessage message){
12+
return Clients.All.SendAsync("Send", message.Message);
13+
}
14+
15+
public ChannelReader<int> CountDown(int count) {
16+
var channel = Channel.CreateUnbounded<int>();
17+
18+
_ = WriteToChannel(channel.Writer, count);
19+
20+
return channel.Reader;
21+
22+
async Task WriteToChannel(ChannelWriter<int> writer, int thing) {
23+
for (int i = thing; i >= 0 ; i--)
24+
{
25+
await writer.WriteAsync(i);
26+
await Task.Delay(TimeSpan.FromSeconds(0.75));
27+
}
28+
29+
writer.Complete();
30+
}
31+
}
32+
}
33+
}

‎src/demo6/Models/ChatMessage.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace demo6.Models
2+
{
3+
public class ChatMessage
4+
{
5+
public string Message { get; set; }
6+
}
7+
}

‎src/demo6/Program.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Threading.Tasks;
6+
using Microsoft.AspNetCore;
7+
using Microsoft.AspNetCore.Hosting;
8+
using Microsoft.Extensions.Configuration;
9+
using Microsoft.Extensions.Logging;
10+
11+
namespace demo6
12+
{
13+
public class Program
14+
{
15+
public static void Main(string[] args)
16+
{
17+
CreateWebHostBuilder(args).Build().Run();
18+
}
19+
20+
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21+
WebHost.CreateDefaultBuilder(args)
22+
.UseStartup<Startup>();
23+
}
24+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"iisSettings": {
3+
"windowsAuthentication": false,
4+
"anonymousAuthentication": true,
5+
"iisExpress": {
6+
"applicationUrl": "http://localhost:29196",
7+
"sslPort": 44355
8+
}
9+
},
10+
"profiles": {
11+
"IIS Express": {
12+
"commandName": "IISExpress",
13+
"launchBrowser": true,
14+
"environmentVariables": {
15+
"ASPNETCORE_ENVIRONMENT": "Development"
16+
}
17+
},
18+
"demo6": {
19+
"commandName": "Project",
20+
"launchBrowser": true,
21+
"applicationUrl": "https://localhost:5001;http://localhost:5000",
22+
"environmentVariables": {
23+
"ASPNETCORE_ENVIRONMENT": "Development"
24+
}
25+
}
26+
}
27+
}

‎src/demo6/Startup.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using demo6.Hubs;
6+
using Microsoft.AspNetCore.Builder;
7+
using Microsoft.AspNetCore.Hosting;
8+
using Microsoft.AspNetCore.Http;
9+
using Microsoft.Extensions.DependencyInjection;
10+
11+
namespace demo6
12+
{
13+
public class Startup
14+
{
15+
// This method gets called by the runtime. Use this method to add services to the container.
16+
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
17+
public void ConfigureServices(IServiceCollection services)
18+
{
19+
services.AddMvc();
20+
services.AddSignalR()
21+
.AddMessagePackProtocol() ;
22+
}
23+
24+
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
25+
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
26+
{
27+
if (env.IsDevelopment())
28+
{
29+
app.UseDeveloperExceptionPage();
30+
}
31+
32+
app.UseFileServer();
33+
app.UseMvc();
34+
app.UseSignalR(routes =>
35+
{
36+
routes.MapHub<ApplicationHub>("/app");
37+
});
38+
}
39+
}
40+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { HubConnectionBuilder, HubConnection, LogLevel } from "@aspnet/signalr";
2+
import { MessagePackHubProtocol } from "@aspnet/signalr-protocol-msgpack";
3+
4+
import Vue from "vue";
5+
import { Component } from "vue-property-decorator";
6+
7+
import { map, filter, switchMap } from 'rxjs/operators';
8+
import {adapt} from '../stream-adapter';
9+
10+
@Component({})
11+
export default class MainComponent extends Vue {
12+
connection: HubConnection = null;
13+
14+
get messages(): string[] {
15+
return this.$store.state.messages;
16+
}
17+
18+
get newMessage():string {
19+
return this.$store.state.newMessage;
20+
}
21+
22+
set newMessage(value: string) {
23+
this.$store.commit('updateNewMessage', value);
24+
}
25+
26+
get newRestMessage():string {
27+
return this.$store.state.newRestMessage;
28+
}
29+
30+
set newRestMessage(value: string) {
31+
this.$store.commit('updateNewRestMessage', value);
32+
}
33+
34+
get number():string {
35+
return this.$store.state.number;
36+
}
37+
38+
set number(value: string) {
39+
this.$store.commit('updateNumber', value);
40+
}
41+
42+
created() {
43+
this.connection = new HubConnectionBuilder()
44+
.configureLogging(LogLevel.Information)
45+
.withUrl("/app")
46+
.withHubProtocol(new MessagePackHubProtocol())
47+
.build();
48+
49+
console.log(this.connection);
50+
51+
this.connection.on("Send", message => {
52+
this.$store.commit("addNewMessage",message);
53+
});
54+
55+
this.connection.start().catch(error => console.error(error));
56+
}
57+
58+
async addMessage() {
59+
await this.connection.invoke("Send", { Message: this.newMessage });
60+
this.$store.commit("updateNewMessage", null);
61+
}
62+
63+
async addRestMessage() {
64+
await fetch("/message", {
65+
method: "post",
66+
body: JSON.stringify({ Message: this.newRestMessage }),
67+
headers: {
68+
"content-type": "application/json"
69+
}
70+
});
71+
this.$store.commit("updateNewMessage", null);
72+
}
73+
74+
async countDown() {
75+
var stream = this.connection.stream<string>("CountDown", parseInt(this.number));
76+
var store = this.$store;
77+
78+
adapt(stream).pipe(
79+
filter(x => parseInt(x) % 2 === 0)
80+
).subscribe(x => store.commit("addNewMessage",x));
81+
82+
this.number = null;
83+
}
84+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<template>
2+
<div>
3+
<h2>Hub API</h2>
4+
<form v-on:submit.prevent="addMessage">
5+
<input type="text" v-model="newMessage">
6+
<input type="submit" value="Send">
7+
</form>
8+
9+
<h2>REST API</h2>
10+
<form v-on:submit.prevent="addRestMessage">
11+
<input type="text" v-model="newRestMessage">
12+
<input type="submit" value="Send">
13+
</form>
14+
15+
<h2>Streaming Hub</h2>
16+
<form v-on:submit.prevent="countDown">
17+
<input type="text" v-model="number">
18+
<input type="submit" value="Send">
19+
</form>
20+
21+
<ul>
22+
<li v-for="(message, index) in messages" :key="index">{{message}}</li>
23+
</ul>
24+
</div>
25+
</template>
26+
27+
<script lang="ts" src="./main-component.ts"></script>

‎src/demo6/client/main.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Vue from "vue";
2+
import { store } from "./store";
3+
4+
new Vue({
5+
el: "#app",
6+
store: store,
7+
components: {
8+
MainComponent: () => import('./main-component/main-component.vue')
9+
}
10+
});

‎src/demo6/client/store.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import Vue from "vue";
2+
import Vuex, { Store } from "vuex";
3+
4+
export interface StoreState {
5+
messages: string[];
6+
newMessage: string;
7+
newRestMessage: string;
8+
number: string;
9+
}
10+
11+
Vue.use(Vuex);
12+
13+
export const store = new Store<StoreState>({
14+
state: {
15+
messages: [],
16+
newMessage: "",
17+
newRestMessage: "",
18+
number: ""
19+
},
20+
mutations: {
21+
addNewMessage(state: StoreState, message: string) {
22+
state.messages.push(message);
23+
},
24+
25+
updateNewMessage(state: StoreState, newMessage: string) {
26+
state.newMessage = newMessage;
27+
},
28+
29+
updateNewRestMessage(state: StoreState, newRestMessage: string) {
30+
state.newRestMessage = newRestMessage;
31+
},
32+
33+
updateNumber(state: StoreState, number: string) {
34+
state.number = number;
35+
}
36+
}
37+
});

‎src/demo6/client/stream-adapter.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { IStreamResult } from "@aspnet/signalr";
2+
import { Subject, Observable } from "rxjs";
3+
4+
export function adapt<T>(stream: IStreamResult<T>): Observable<T> {
5+
const subject = new Subject<T>();
6+
stream.subscribe(subject);
7+
return subject.asObservable();
8+
}

‎src/demo6/custom.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
declare module '*.html' {
2+
var _: string;
3+
export default _;
4+
}
5+
6+
declare module "*.vue" {
7+
import Vue from 'vue'
8+
export default Vue
9+
}

‎src/demo6/demo6.csproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp2.1</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<Folder Include="wwwroot\" />
9+
</ItemGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Microsoft.AspNetCore.App" />
13+
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="1.0.0-rc1-final" />
14+
</ItemGroup>
15+
16+
</Project>

‎src/demo6/package-lock.json

Lines changed: 7933 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/demo6/package.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "demo6",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"build-dev": "webpack",
8+
"build-prod": "webpack --env=prod"
9+
},
10+
"keywords": [],
11+
"author": "",
12+
"license": "ISC",
13+
"devDependencies": {
14+
"@types/node": "^10.1.1",
15+
"html-loader": "^0.5.5",
16+
"ts-loader": "^4.3.0",
17+
"typescript": "^2.8.3",
18+
"vue-class-component": "^6.2.0",
19+
"vue-loader": "^15.0.12",
20+
"vue-property-decorator": "^6.0.0",
21+
"vue-template-compiler": "^2.5.16",
22+
"webpack": "^4.8.3",
23+
"webpack-cli": "^2.1.3"
24+
},
25+
"dependencies": {
26+
"@aspnet/signalr": "^1.0.0-rc1-update1",
27+
"@aspnet/signalr-protocol-msgpack": "^1.0.0-rc1-update1",
28+
"msgpack5": "^4.1.0",
29+
"rxjs": "^6.1.0",
30+
"vue": "^2.5.16",
31+
"vuex": "^3.0.1"
32+
}
33+
}

‎src/demo6/tsconfig.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"compilerOptions": {
3+
"noImplicitAny": false,
4+
"allowSyntheticDefaultImports": true,
5+
"emitDecoratorMetadata": true,
6+
"experimentalDecorators": true,
7+
"noEmitOnError": false,
8+
"sourceMap": true,
9+
"target": "es2015",
10+
"module": "commonjs",
11+
"moduleResolution": "node"
12+
},
13+
"include": [
14+
"client/**/*",
15+
"custom.d.ts"
16+
],
17+
"exclude": [
18+
"node_modules"
19+
]
20+
}

‎src/demo6/webpack.config.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// @ts-nocheck
2+
const path = require("path");
3+
const webpack = require("webpack");
4+
const { VueLoaderPlugin } = require('vue-loader');
5+
6+
module.exports = function (env) {
7+
const isProduction = env === "prod";
8+
return {
9+
mode: isProduction ? 'production' : 'development',
10+
context: path.join(__dirname, "./client"),
11+
resolve: {
12+
extensions: [".ts", ".js", '.vue'],
13+
alias: {
14+
'vue$': 'vue/dist/vue.esm.js'
15+
}
16+
},
17+
entry: {
18+
main: "./main"
19+
},
20+
output: {
21+
publicPath: "/",
22+
path: path.join(__dirname, "./wwwroot"),
23+
filename: isProduction ? "[name].build.min.js" : "[name].build.js"
24+
},
25+
plugins: [
26+
new VueLoaderPlugin()
27+
],
28+
module: {
29+
rules: [
30+
{ test: /\.(ts|js)$/, use: { loader: "ts-loader", options: { appendTsSuffixTo: [/\.vue$/] } }, exclude: /node_modules/ },
31+
{ test: /\.vue$/, loader: 'vue-loader', options: { esModule: true, loaders: {}} },
32+
{ test: /\.html$/, use: [{ loader: 'html-loader', options: { minimize: false } }]}
33+
]
34+
}
35+
};
36+
};

‎src/demo6/wwwroot/index.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<html lang="en">
2+
<head>
3+
<meta charset="UTF-8">
4+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
5+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
6+
<title>SignalR Demo</title>
7+
</head>
8+
9+
<body>
10+
<div id="app">
11+
<main-component></main-component>
12+
</div>
13+
14+
<script src="main.build.js"></script>
15+
</body>
16+
</html>

‎src/signalrcore-demos.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "demo4", "demo4\demo4.csproj
1313
EndProject
1414
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "demo5", "demo5\demo5.csproj", "{057E41B5-B8E2-490B-96E7-BB7E355556C2}"
1515
EndProject
16+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "demo6", "demo6\demo6.csproj", "{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}"
17+
EndProject
1618
Global
1719
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1820
Debug|Any CPU = Debug|Any CPU
@@ -86,5 +88,17 @@ Global
8688
{057E41B5-B8E2-490B-96E7-BB7E355556C2}.Release|x64.Build.0 = Release|Any CPU
8789
{057E41B5-B8E2-490B-96E7-BB7E355556C2}.Release|x86.ActiveCfg = Release|Any CPU
8890
{057E41B5-B8E2-490B-96E7-BB7E355556C2}.Release|x86.Build.0 = Release|Any CPU
91+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
92+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
93+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Debug|x64.ActiveCfg = Debug|Any CPU
94+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Debug|x64.Build.0 = Debug|Any CPU
95+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Debug|x86.ActiveCfg = Debug|Any CPU
96+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Debug|x86.Build.0 = Debug|Any CPU
97+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
98+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Release|Any CPU.Build.0 = Release|Any CPU
99+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Release|x64.ActiveCfg = Release|Any CPU
100+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Release|x64.Build.0 = Release|Any CPU
101+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Release|x86.ActiveCfg = Release|Any CPU
102+
{91E6B66C-BD80-458C-A756-22F4DC0F9C5D}.Release|x86.Build.0 = Release|Any CPU
89103
EndGlobalSection
90104
EndGlobal

0 commit comments

Comments
 (0)
Please sign in to comment.