diff --git a/RaceLapTimer/RaceLapTimer/ApiControllers/MonitorApiModule.cs b/RaceLapTimer/RaceLapTimer/ApiControllers/MonitorApiModule.cs index 9e5e84d..b11404c 100644 --- a/RaceLapTimer/RaceLapTimer/ApiControllers/MonitorApiModule.cs +++ b/RaceLapTimer/RaceLapTimer/ApiControllers/MonitorApiModule.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using Interfaces; +using System.Runtime.InteropServices; using Nancy; namespace RaceLapTimer.ApiControllers @@ -20,141 +18,4 @@ namespace RaceLapTimer.ApiControllers return Response.AsJson(new { data=_provider.GetRaceSessions(true)}); } } - - public interface IDbProvider - { - List GetRaceSessions(bool getActive); - - List GetPilotsList(); - - Pilot GetPilot(int pilotId); - - bool CreatePilot(Pilot pilot); - - int GetLastScannedId(); - - void StoreTransponderLog(SatelliteLog log); - } - - public class TestProvider : IDbProvider - { - public List GetRaceSessions(bool getActive) - { - return new List - { - #region Session 1 - new RaceSession - { - Active = true, - CreatedAt = DateTime.UtcNow, - HotSeatEnabled = false, - Id = 1, - IdleTimeSeconds = 400, - Mode = RaceMode.STANDARD, - MaxLaps = 20, - SatelliteCount = 1, - TimePenaltyPerSatellite = 100, - Title = "TEST Session 1" - }, - #endregion - #region Session 2 - new RaceSession - { - Active = true, - CreatedAt = DateTime.UtcNow, - HotSeatEnabled = false, - Id = 2, - IdleTimeSeconds = 400, - Mode = RaceMode.STANDARD, - MaxLaps = 10, - SatelliteCount = 1, - TimePenaltyPerSatellite = 100, - Title = "TEST Session 2" - }, - #endregion - #region Session 3 - new RaceSession - { - Active = getActive, - CreatedAt = DateTime.UtcNow, - HotSeatEnabled = false, - Id = 3, - IdleTimeSeconds = 400, - Mode = RaceMode.STANDARD, - MaxLaps = 10, - SatelliteCount = 1, - TimePenaltyPerSatellite = 100, - Title = "TEST Session 3" - }, - #endregion - #region Session 3 - new RaceSession - { - Active = getActive, - CreatedAt = DateTime.UtcNow, - HotSeatEnabled = false, - Id = 4, - IdleTimeSeconds = 400, - Mode = RaceMode.STANDARD, - MaxLaps = 10, - SatelliteCount = 1, - TimePenaltyPerSatellite = 100, - Title = "TEST Session 4" - } - #endregion - }; - } - - public List GetPilotsList() - { - return new List - { - new Pilot - { - Name = "Pilot1", - TeamName = "PilotTeam 1", - ThingyName = "Kart1", - TransponderToken = 222, - ImageUrl = "images/pilotPic.png" - }, - new Pilot - { - Name = "Pilot 2", - TeamName = "Pilot Team 2", - ThingyName = "Kart2", - TransponderToken = 200 - } - }; - } - - public Pilot GetPilot(int pilotId) - { - return new Pilot - { - Id = pilotId, - Name = "Pilot " + pilotId, - TeamName = "Team " + pilotId, - ThingyName = "Id:" + pilotId, - TransponderToken = pilotId - }; - } - - public bool CreatePilot(Pilot pilot) - { - var rand = new Random(); - var numb = rand.NextDouble(); - return numb > 0.5; - } - - public int GetLastScannedId() - { - var rand = new Random(); - return rand.Next(0, 100); - } - - public void StoreTransponderLog(SatelliteLog log) - { - //do nothing. - } - } } diff --git a/RaceLapTimer/RaceLapTimer/ApiControllers/PilotApiModule.cs b/RaceLapTimer/RaceLapTimer/ApiControllers/PilotApiModule.cs index d255ad2..2d14a9c 100644 --- a/RaceLapTimer/RaceLapTimer/ApiControllers/PilotApiModule.cs +++ b/RaceLapTimer/RaceLapTimer/ApiControllers/PilotApiModule.cs @@ -7,12 +7,21 @@ namespace RaceLapTimer.ApiControllers { public class PilotApiModule:NancyModule { - private IDbProvider _provider; + private readonly IDbProvider _provider; public PilotApiModule(IDbProvider provider) : base("/api/pilot") { _provider = provider; + Get["/{id}"] = args => GetPilot(args); Post["/edit"] = args => EditCreatePilot(args); + Post["/create"] = args => EditCreatePilot(args); + Get["/delete/{id}"] = args => DeletePilot(args); + } + + private dynamic DeletePilot(dynamic args) + { + var res = _provider.DeletePilot(args.Id); + return Response.AsRedirect("/pilots"); } private dynamic GetPilot(dynamic args) @@ -25,7 +34,9 @@ namespace RaceLapTimer.ApiControllers { var pilotObject = this.Bind(); var resp = _provider.CreatePilot(pilotObject); - return Response.AsRedirect("/pilots"); + if(resp) + return new {url = "/pilots"}; + return "error"; } } } diff --git a/RaceLapTimer/RaceLapTimer/ApiControllers/RaceSessionApiModule.cs b/RaceLapTimer/RaceLapTimer/ApiControllers/RaceSessionApiModule.cs index 114cebf..8d2ea26 100644 --- a/RaceLapTimer/RaceLapTimer/ApiControllers/RaceSessionApiModule.cs +++ b/RaceLapTimer/RaceLapTimer/ApiControllers/RaceSessionApiModule.cs @@ -2,6 +2,7 @@ using Interfaces; using Nancy; using Nancy.ModelBinding; +using Nancy.Responses; namespace RaceLapTimer.ApiControllers { @@ -31,7 +32,7 @@ namespace RaceLapTimer.ApiControllers private dynamic CreateRaceSession(dynamic args) { var postObject = this.Bind(); - return Response.AsRedirect("/racedirector"); + return new {url="/racedirector"}; } } } \ No newline at end of file diff --git a/RaceLapTimer/RaceLapTimer/AuthenticationBootstrapper.cs b/RaceLapTimer/RaceLapTimer/AuthenticationBootstrapper.cs index bdb1778..da3b537 100644 --- a/RaceLapTimer/RaceLapTimer/AuthenticationBootstrapper.cs +++ b/RaceLapTimer/RaceLapTimer/AuthenticationBootstrapper.cs @@ -16,6 +16,12 @@ namespace RaceLapTimer { public class FormsAuthBootstrapper : NinjectNancyBootstrapper { + protected override void ApplicationStartup(IKernel container, IPipelines pipelines) + { + base.ApplicationStartup(container, pipelines); + Nancy.Security.Csrf.Enable(pipelines); + } + protected override void ConfigureApplicationContainer(IKernel container) { // We don't call "base" here to prevent auto-discovery of @@ -25,7 +31,7 @@ namespace RaceLapTimer container.Bind().To(); container.Bind().To(); container.Bind().To().InSingletonScope(); - container.Bind().To(); + container.Bind().To().InSingletonScope(); //load dynamic plugins..: var cfgFilePath = Path.Combine(container.Get().GetPath, "NinjectConfig.xml"); @@ -81,6 +87,9 @@ namespace RaceLapTimer conventions.StaticContentsConventions.Add( StaticContentConventionBuilder.AddDirectory("images","images") ); + conventions.StaticContentsConventions.Add( + StaticContentConventionBuilder.AddDirectory("js", "js") + ); } } } diff --git a/RaceLapTimer/RaceLapTimer/IDbProvider.cs b/RaceLapTimer/RaceLapTimer/IDbProvider.cs new file mode 100644 index 0000000..f267c70 --- /dev/null +++ b/RaceLapTimer/RaceLapTimer/IDbProvider.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using Interfaces; + +namespace RaceLapTimer.ApiControllers +{ + public interface IDbProvider + { + List GetRaceSessions(bool getActive); + + List GetPilotsList(); + + Pilot GetPilot(int pilotId); + + bool CreatePilot(Pilot pilot); + + int GetLastScannedId(); + + void StoreTransponderLog(SatelliteLog log); + + bool DeletePilot(int id); + } +} \ No newline at end of file diff --git a/RaceLapTimer/RaceLapTimer/Modules/PilotModule.cs b/RaceLapTimer/RaceLapTimer/Modules/PilotModule.cs index c9f53f4..9211af0 100644 --- a/RaceLapTimer/RaceLapTimer/Modules/PilotModule.cs +++ b/RaceLapTimer/RaceLapTimer/Modules/PilotModule.cs @@ -13,6 +13,12 @@ namespace RaceLapTimer.Modules public PilotModule() : base("/pilot") { this.RequiresAuthentication(); + Get["/edit/{id}"] = args => EditPilot(args); + } + + private dynamic EditPilot(dynamic args) + { + return View["EditPilot.cshtml"]; } } } diff --git a/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj b/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj index c8189b0..bf79b05 100644 --- a/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj +++ b/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj @@ -114,6 +114,7 @@ + @@ -121,6 +122,7 @@ + @@ -179,7 +181,6 @@ - @@ -201,6 +202,15 @@ Always + + Always + + + Always + + + Always + diff --git a/RaceLapTimer/RaceLapTimer/TestProvider.cs b/RaceLapTimer/RaceLapTimer/TestProvider.cs new file mode 100644 index 0000000..bdabdca --- /dev/null +++ b/RaceLapTimer/RaceLapTimer/TestProvider.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Interfaces; + +namespace RaceLapTimer.ApiControllers +{ + public class TestProvider : IDbProvider + { + readonly List _pilots; + + public TestProvider() + { + #region Pilots + _pilots = new List + { + new Pilot + { + Id=1, + Name = "Pilot1", + TeamName = "PilotTeam 1", + ThingyName = "Kart1", + TransponderToken = 222, + ImageUrl = "images/pilotPic.png" + }, + new Pilot + { + Id=2, + Name = "Pilot 2", + TeamName = "Pilot Team 2", + ThingyName = "Kart2", + TransponderToken = 200 + } + }; + #endregion + } + + public List GetRaceSessions(bool getActive) + { + return new List + { + #region Session 1 + new RaceSession + { + Active = true, + CreatedAt = DateTime.UtcNow, + HotSeatEnabled = false, + Id = 1, + IdleTimeSeconds = 400, + Mode = RaceMode.STANDARD, + MaxLaps = 20, + SatelliteCount = 1, + TimePenaltyPerSatellite = 100, + Title = "TEST Session 1" + }, + #endregion + #region Session 2 + new RaceSession + { + Active = true, + CreatedAt = DateTime.UtcNow, + HotSeatEnabled = false, + Id = 2, + IdleTimeSeconds = 400, + Mode = RaceMode.STANDARD, + MaxLaps = 10, + SatelliteCount = 1, + TimePenaltyPerSatellite = 100, + Title = "TEST Session 2" + }, + #endregion + #region Session 3 + new RaceSession + { + Active = getActive, + CreatedAt = DateTime.UtcNow, + HotSeatEnabled = false, + Id = 3, + IdleTimeSeconds = 400, + Mode = RaceMode.STANDARD, + MaxLaps = 10, + SatelliteCount = 1, + TimePenaltyPerSatellite = 100, + Title = "TEST Session 3" + }, + #endregion + #region Session 3 + new RaceSession + { + Active = getActive, + CreatedAt = DateTime.UtcNow, + HotSeatEnabled = false, + Id = 4, + IdleTimeSeconds = 400, + Mode = RaceMode.STANDARD, + MaxLaps = 10, + SatelliteCount = 1, + TimePenaltyPerSatellite = 100, + Title = "TEST Session 4" + } + #endregion + }; + } + + public List GetPilotsList() + { + return _pilots; + } + + public Pilot GetPilot(int pilotId) + { + return _pilots.FirstOrDefault(x => x.Id == pilotId); + } + + public bool CreatePilot(Pilot pilot) + { + if (_pilots.Any(x => x.TransponderToken == pilot.TransponderToken)) + return false; + pilot.Id= _pilots.Max(x => x.Id) + 1; + _pilots.Add(pilot); + return true; + } + + public bool DeletePilot(int id) + { + return _pilots.Remove(_pilots.FirstOrDefault(x => x.Id == id)); + } + + public int GetLastScannedId() + { + var rand = new Random(); + return rand.Next(0, 100); + } + + public void StoreTransponderLog(SatelliteLog log) + { + //do nothing. + } + } +} \ No newline at end of file diff --git a/RaceLapTimer/RaceLapTimer/www/Views/Monitor.cshtml b/RaceLapTimer/RaceLapTimer/www/Views/Monitor.cshtml index df76d4d..0b8adde 100644 --- a/RaceLapTimer/RaceLapTimer/www/Views/Monitor.cshtml +++ b/RaceLapTimer/RaceLapTimer/www/Views/Monitor.cshtml @@ -7,18 +7,18 @@ - - - - - + + + + + - - - - - + + + + +
Race NameIdle Time (s)Lap Count
Race NameIdle Time (s)Lap Count
\ No newline at end of file diff --git a/RaceLapTimer/RaceLapTimer/www/Views/razor-layout.cshtml b/RaceLapTimer/RaceLapTimer/www/Views/razor-layout.cshtml index daf6cf6..7d32d07 100644 --- a/RaceLapTimer/RaceLapTimer/www/Views/razor-layout.cshtml +++ b/RaceLapTimer/RaceLapTimer/www/Views/razor-layout.cshtml @@ -77,7 +77,7 @@
-
+
@RenderBody()
diff --git a/RaceLapTimer/RaceLapTimer/www/js/pilots.js b/RaceLapTimer/RaceLapTimer/www/js/pilots.js new file mode 100644 index 0000000..1c8bb4c --- /dev/null +++ b/RaceLapTimer/RaceLapTimer/www/js/pilots.js @@ -0,0 +1,16 @@ +function ViewModel() { + "use strict"; + var self = this; + self.pilotsList = ko.observable(); + + $.get("/api/pilots", {}, self.pilotsList); + + self.getData = function () { + $.get("/api/pilots", {}, self.pilotsList); + }; +}; + +ViewModel.prototype.dispose = function () { + "use strict"; +}; +ko.applyBindings(new ViewModel()); \ No newline at end of file diff --git a/RaceLapTimer/RaceLapTimer/www/js/raceDirector.js b/RaceLapTimer/RaceLapTimer/www/js/raceDirector.js new file mode 100644 index 0000000..a70d65b --- /dev/null +++ b/RaceLapTimer/RaceLapTimer/www/js/raceDirector.js @@ -0,0 +1,27 @@ +function ViewModel() { + "use strict"; + var self = this; + self.raceSessions = ko.observable(); + + $.get("/api/monitor", {}, self.raceSessions); + self.tmrHandle = setTimeout(function () { + self.getData(); + }, 2000); + + self.getData = function () { + $.get("/api/monitor", {}, self.raceSessions) + .done(function () { + console.log("done"); + }) + .always(function () { + self.tmrHandle = setTimeout(self.getData, 2000); + }); + }; +}; + +ViewModel.prototype.dispose = function () { + "use strict"; + window.clearInterval(self.tmrHandle); + console.log("disposed of timer"); +}; +ko.applyBindings(new ViewModel()); \ No newline at end of file diff --git a/RaceLapTimer/RaceLapTimer/www/js/supportingPages.js b/RaceLapTimer/RaceLapTimer/www/js/supportingPages.js new file mode 100644 index 0000000..fc28be6 --- /dev/null +++ b/RaceLapTimer/RaceLapTimer/www/js/supportingPages.js @@ -0,0 +1,29 @@ +function jsonPostForm(formName, url) { + var formData = JSON.stringify($(("#" + formName)).serializeObject()); + console.log(formData + "url: " + url); + $.ajax({ + type: "POST", + url: url, + data: formData, + dataType: "json", + contentType: "application/json" + }).done(function(a) { + window.location.replace(a.url); + }); + return false; +}; +$.fn.serializeObject = function () { + var o = {}; + var a = this.serializeArray(); + $.each(a, function () { + if (o[this.name] !== undefined) { + if (!o[this.name].push) { + o[this.name] = [o[this.name]]; + } + o[this.name].push(this.value || ""); + } else { + o[this.name] = this.value || ""; + } + }); + return o; +}; \ No newline at end of file