diff --git a/docker-compose-windows.yml b/docker-compose-windows.yml new file mode 100644 index 0000000..85e24c4 --- /dev/null +++ b/docker-compose-windows.yml @@ -0,0 +1,42 @@ +version: "3.2" + +services: + vote: + build: + context: ./vote/dotnet + ports: + - "5000:80" + depends_on: + - message-queue + + result: + build: + context: ./result/dotnet + ports: + - "5001:80" + environment: + - "Data:ConnectionString=Server=db;Port=4000;Database=votes;User=root;SslMode=None" + depends_on: + - db + + worker: + build: + context: ./worker/dotnet + environment: + - "Data:ConnectionString=Server=db;Port=4000;Database=votes;User=root;SslMode=None" + depends_on: + - message-queue + - db + + message-queue: + image: nats:nanoserver + + db: + image: dockersamples/tidb:nanoserver + ports: + - "3306:4000" + +networks: + default: + external: + name: nat \ No newline at end of file diff --git a/result/dotnet/Dockerfile b/result/dotnet/Dockerfile new file mode 100644 index 0000000..f2e108c --- /dev/null +++ b/result/dotnet/Dockerfile @@ -0,0 +1,16 @@ +FROM microsoft/dotnet:2.1-sdk as builder + +WORKDIR /Result +COPY Result/Result.csproj . +RUN dotnet restore + +COPY /Result . +RUN dotnet publish -c Release -o /out Result.csproj + +# app image +FROM microsoft/dotnet:2.1-aspnetcore-runtime + +WORKDIR /app +ENTRYPOINT ["dotnet", "Result.dll"] + +COPY --from=builder /out . \ No newline at end of file diff --git a/result/dotnet/Result/Hubs/ResultsHub.cs b/result/dotnet/Result/Hubs/ResultsHub.cs index 6240117..f852803 100644 --- a/result/dotnet/Result/Hubs/ResultsHub.cs +++ b/result/dotnet/Result/Hubs/ResultsHub.cs @@ -1,14 +1,9 @@ -using System.Threading.Tasks; -using Microsoft.AspNetCore.SignalR; -using Result.Models; +using Microsoft.AspNetCore.SignalR; namespace Result.Hubs { public class ResultsHub : Hub { - public async Task UpdateResults(ResultsModel results) - { - await Clients.All.SendAsync("UpdateResults", results); - } + //no public methods, only used for push from PublishRTesultsTimer } } diff --git a/result/dotnet/Result/Models/ResultsModel.cs b/result/dotnet/Result/Models/ResultsModel.cs index cf8a6bf..65309bd 100644 --- a/result/dotnet/Result/Models/ResultsModel.cs +++ b/result/dotnet/Result/Models/ResultsModel.cs @@ -7,9 +7,5 @@ public int OptionB { get; set; } public int VoteCount { get; set; } - - public double OptionAPercent { get; set; } - - public double OptionBPercent { get; set; } } } diff --git a/result/dotnet/Result/Pages/Index.cshtml b/result/dotnet/Result/Pages/Index.cshtml index cb4483c..cfeef01 100644 --- a/result/dotnet/Result/Pages/Index.cshtml +++ b/result/dotnet/Result/Pages/Index.cshtml @@ -1,14 +1,16 @@ @page +@model Result.Pages.IndexModel + - Cats vs Dogs -- Result + @Model.OptionA vs @Model.OptionB -- Result - +
@@ -22,22 +24,20 @@
-
-
Cats
+
+
@Model.OptionA
-
-
Dogs
+
+
@Model.OptionB
- No votes yet - {{total}} vote - {{total}} votes + No votes yet
diff --git a/result/dotnet/Result/Pages/Index.cshtml.cs b/result/dotnet/Result/Pages/Index.cshtml.cs index d78cbe9..3d9cca2 100644 --- a/result/dotnet/Result/Pages/Index.cshtml.cs +++ b/result/dotnet/Result/Pages/Index.cshtml.cs @@ -4,14 +4,30 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Configuration; namespace Result.Pages { public class IndexModel : PageModel { + private string _optionA; + private string _optionB; + protected readonly IConfiguration _configuration; + + public string OptionA { get; private set; } + public string OptionB { get; private set; } + + public IndexModel(IConfiguration configuration) + { + _configuration = configuration; + _optionA = _configuration.GetValue("Voting:OptionA"); + _optionB = _configuration.GetValue("Voting:OptionB"); + } + public void OnGet() { - + OptionA = _optionA; + OptionB = _optionB; } } } diff --git a/result/dotnet/Result/Properties/launchSettings.json b/result/dotnet/Result/Properties/launchSettings.json index 60ec38e..1f33ca1 100644 --- a/result/dotnet/Result/Properties/launchSettings.json +++ b/result/dotnet/Result/Properties/launchSettings.json @@ -1,10 +1,10 @@ -{ +{ "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, + "windowsAuthentication": false, + "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:56785", - "sslPort": 44369 + "sslPort": 0 } }, "profiles": { @@ -18,10 +18,10 @@ "Result": { "commandName": "Project", "launchBrowser": true, - "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" } } } \ No newline at end of file diff --git a/result/dotnet/Result/Startup.cs b/result/dotnet/Result/Startup.cs index 316abd1..3b9945b 100644 --- a/result/dotnet/Result/Startup.cs +++ b/result/dotnet/Result/Startup.cs @@ -1,15 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Result.Hubs; +using Result.Timers; namespace Result { @@ -26,6 +21,7 @@ namespace Result { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddSignalR(); + services.AddSingleton(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) @@ -45,6 +41,9 @@ namespace Result routes.MapHub("/resultsHub"); }); app.UseMvc(); + + var timer = app.ApplicationServices.GetService(); + timer.Start(); } } } diff --git a/result/dotnet/Result/Timers/PublishResultsTimer.cs b/result/dotnet/Result/Timers/PublishResultsTimer.cs new file mode 100644 index 0000000..20a140a --- /dev/null +++ b/result/dotnet/Result/Timers/PublishResultsTimer.cs @@ -0,0 +1,47 @@ +using System; +using System.Timers; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Configuration; +using Result.Hubs; +using Result.Models; + +namespace Result.Timers +{ + public class PublishResultsTimer + { + private readonly IHubContext _hubContext; + private readonly Timer _timer; + //TODO- temp + private static Random _Random = new Random(); + + public PublishResultsTimer(IHubContext hubContext, IConfiguration configuration) + { + _hubContext = hubContext; + var publishMilliseconds = configuration.GetValue("ResultsTimer:PublishMilliseconds"); + _timer = new Timer(publishMilliseconds) + { + Enabled = false + }; + _timer.Elapsed += PublishResults; + } + + public void Start() + { + if (!_timer.Enabled) + { + _timer.Start(); + } + } + + private void PublishResults(object sender, ElapsedEventArgs e) + { + var model = new ResultsModel + { + OptionA = _Random.Next(0, 100), + OptionB = _Random.Next(0, 100) + }; + model.VoteCount = model.OptionA + model.OptionB; + _hubContext.Clients.All.SendAsync("UpdateResults", model); + } + } +} diff --git a/result/dotnet/Result/appsettings.json b/result/dotnet/Result/appsettings.json index def9159..9f58e0f 100644 --- a/result/dotnet/Result/appsettings.json +++ b/result/dotnet/Result/appsettings.json @@ -1,4 +1,11 @@ { + "Voting": { + "OptionA": "Cats", + "OptionB": "Dogs" + }, + "ResultsTimer": { + "PublishMilliseconds": 1500 + }, "Logging": { "LogLevel": { "Default": "Warning" diff --git a/result/dotnet/Result/wwwroot/css/site.css b/result/dotnet/Result/wwwroot/css/site.css index 07c3f2c..1ecece3 100644 --- a/result/dotnet/Result/wwwroot/css/site.css +++ b/result/dotnet/Result/wwwroot/css/site.css @@ -95,12 +95,12 @@ body { text-transform: uppercase; } - #choice .choice.dogs { + #choice .choice.resultb { color: #00cbca; float: right; } - #choice .choice.cats { + #choice .choice.resulta { color: #2196f3; float: left; } diff --git a/result/dotnet/Result/wwwroot/js/results.js b/result/dotnet/Result/wwwroot/js/results.js index e74e997..69b879f 100644 --- a/result/dotnet/Result/wwwroot/js/results.js +++ b/result/dotnet/Result/wwwroot/js/results.js @@ -3,14 +3,23 @@ var connection = new signalR.HubConnectionBuilder().withUrl("/resultsHub").build(); connection.on("UpdateResults", function (results) { - data = JSON.parse(json); + document.body.style.opacity=1; - var a = parseInt(data.optionA || 0); - var b = parseInt(data.optionB || 0); + var a = parseInt(results.optionA || 0); + var b = parseInt(results.optionB || 0); var percentages = getPercentages(a, b); document.getElementById("optionA").innerText = percentages.a + "%"; document.getElementById("optionB").innerText = percentages.b + "%"; + if (results.voteCount > 0) { + var totalVotes = results.voteCount + (results.voteCount > 1 ? " votes" : " vote"); + document.getElementById("totalVotes").innerText = totalVotes; + } + + var bg1 = document.getElementById('background-stats-1'); + var bg2 = document.getElementById('background-stats-2'); + bg1.style.width = percentages.a + "%"; + bg2.style.width = percentages.b + "%"; }); connection.start().catch(function (err) { diff --git a/result/dotnet/Result/wwwroot/js/site.js b/result/dotnet/Result/wwwroot/js/site.js deleted file mode 100644 index 3c76e6d..0000000 --- a/result/dotnet/Result/wwwroot/js/site.js +++ /dev/null @@ -1,4 +0,0 @@ -// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification -// for details on configuring this project to bundle and minify static web assets. - -// Write your Javascript code. diff --git a/result/dotnet/Result/wwwroot/js/site.min.js b/result/dotnet/Result/wwwroot/js/site.min.js deleted file mode 100644 index e69de29..0000000