diff --git a/.gitignore b/.gitignore index 52a509f..1747694 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ **/packages/** **/.vs/** **dotsettings +**.DotSettings.user diff --git a/RaceLapTimer/RaceLapTimer/ApiControllers/MonitorApiModule.cs b/RaceLapTimer/RaceLapTimer/ApiControllers/MonitorApiModule.cs index b11404c..177e329 100644 --- a/RaceLapTimer/RaceLapTimer/ApiControllers/MonitorApiModule.cs +++ b/RaceLapTimer/RaceLapTimer/ApiControllers/MonitorApiModule.cs @@ -15,7 +15,7 @@ namespace RaceLapTimer.ApiControllers private dynamic GetRootMonitorData(dynamic args) { - return Response.AsJson(new { data=_provider.GetRaceSessions(true)}); + return Response.AsJson(new { data = _provider.GetRaceSessions(true)}); } } } diff --git a/RaceLapTimer/RaceLapTimer/ApiControllers/PilotApiModule.cs b/RaceLapTimer/RaceLapTimer/ApiControllers/PilotApiModule.cs index 2d14a9c..b88b4cc 100644 --- a/RaceLapTimer/RaceLapTimer/ApiControllers/PilotApiModule.cs +++ b/RaceLapTimer/RaceLapTimer/ApiControllers/PilotApiModule.cs @@ -1,21 +1,66 @@ -using System.Web.Http; +using System; +using System.IO; +using System.Linq; +using System.Web.Http; using Interfaces; using Nancy; +using Nancy.Extensions; using Nancy.ModelBinding; +using Nancy.Responses; namespace RaceLapTimer.ApiControllers { public class PilotApiModule:NancyModule { private readonly IDbProvider _provider; - public PilotApiModule(IDbProvider provider) : base("/api/pilot") + private readonly IRootPathProvider _rootPathProvider; + + public PilotApiModule(IDbProvider provider, IRootPathProvider pathProvider) : base("/api/pilot") { _provider = provider; + _rootPathProvider = pathProvider; Get["/{id}"] = args => GetPilot(args); Post["/edit"] = args => EditCreatePilot(args); Post["/create"] = args => EditCreatePilot(args); Get["/delete/{id}"] = args => DeletePilot(args); + Post["/upload/{id}"] = args => UploadPicture(args); + } + + private dynamic UploadPicture(dynamic args) + { + var pilotId = args.Id; + var pilot = (Pilot)_provider.GetPilot(pilotId); + var oldImagePath = pilot.ImageUrl; + + var uploadDirectory = Path.Combine(_rootPathProvider.GetRootPath(), "images"); + + if (!Directory.Exists(uploadDirectory)) + { + Directory.CreateDirectory(uploadDirectory); + } + + var file = Request.Files.First(); + + var newFileName = Guid.NewGuid(); + var generatedFileName = string.Format("{0}{1}",newFileName,Path.GetExtension(file.Name)); //0000-0000.....ext + + var filename = Path.Combine(uploadDirectory, generatedFileName); + + using (FileStream fileStream = new FileStream(filename, FileMode.Create)) + { + file.Value.CopyTo(fileStream); + fileStream.Flush(); + fileStream.Close(); + } + + pilot.ImageUrl = "/images/" + generatedFileName; + _provider.UpdatePilot(pilot); + + File.Delete(Path.Combine(uploadDirectory, oldImagePath)); + + string returnurl = "/pilot/edit/" + pilotId; + return Context.GetRedirect(returnurl); } private dynamic DeletePilot(dynamic args) @@ -34,9 +79,7 @@ namespace RaceLapTimer.ApiControllers { var pilotObject = this.Bind(); var resp = _provider.CreatePilot(pilotObject); - if(resp) - return new {url = "/pilots"}; - return "error"; + return Context.GetRedirect("/pilots"); } } } diff --git a/RaceLapTimer/RaceLapTimer/ApiControllers/RaceSessionApiModule.cs b/RaceLapTimer/RaceLapTimer/ApiControllers/RaceSessionApiModule.cs index 8d2ea26..c4d0c97 100644 --- a/RaceLapTimer/RaceLapTimer/ApiControllers/RaceSessionApiModule.cs +++ b/RaceLapTimer/RaceLapTimer/ApiControllers/RaceSessionApiModule.cs @@ -1,12 +1,13 @@ using System.Collections.Generic; using Interfaces; using Nancy; +using Nancy.Extensions; using Nancy.ModelBinding; using Nancy.Responses; namespace RaceLapTimer.ApiControllers { - public class RaceSessionApiModule:NancyModule + public class RaceSessionApiModule : NancyModule { private readonly IDbProvider _provider; public RaceSessionApiModule(IDbProvider provider) : base("/api/racesession") @@ -20,19 +21,20 @@ namespace RaceLapTimer.ApiControllers private dynamic GetHistoricRaceSessions() { var sessions = _provider.GetRaceSessions(false); - return Response.AsJson(new {data= sessions}); + return Response.AsJson(new { data = sessions }); } private dynamic GetRaceSessions() { var sessions = _provider.GetRaceSessions(true); - return Response.AsJson(new {data= sessions}); + return Response.AsJson(new { data = sessions }); } private dynamic CreateRaceSession(dynamic args) { - var postObject = this.Bind(); - return new {url="/racedirector"}; + var session = this.Bind(); + var res = _provider.CreateRaceSession(session); + return Context.GetRedirect("/racedirector"); } } } \ No newline at end of file diff --git a/RaceLapTimer/RaceLapTimer/IDbProvider.cs b/RaceLapTimer/RaceLapTimer/IDbProvider.cs index f267c70..51d9dcd 100644 --- a/RaceLapTimer/RaceLapTimer/IDbProvider.cs +++ b/RaceLapTimer/RaceLapTimer/IDbProvider.cs @@ -1,18 +1,25 @@ using System.Collections.Generic; using Interfaces; +using RaceLapTimer.ApiControllers; -namespace RaceLapTimer.ApiControllers +namespace RaceLapTimer { public interface IDbProvider { List GetRaceSessions(bool getActive); + bool CreateRaceSession(RaceSession session); + + bool StopRaceSession(RaceSession session); + List GetPilotsList(); Pilot GetPilot(int pilotId); bool CreatePilot(Pilot pilot); + bool UpdatePilot(Pilot pilot); + int GetLastScannedId(); void StoreTransponderLog(SatelliteLog log); diff --git a/RaceLapTimer/RaceLapTimer/Modules/PilotModule.cs b/RaceLapTimer/RaceLapTimer/Modules/PilotModule.cs index 9211af0..6435161 100644 --- a/RaceLapTimer/RaceLapTimer/Modules/PilotModule.cs +++ b/RaceLapTimer/RaceLapTimer/Modules/PilotModule.cs @@ -18,7 +18,7 @@ namespace RaceLapTimer.Modules private dynamic EditPilot(dynamic args) { - return View["EditPilot.cshtml"]; + return View["EditPilot.cshtml", new {Id=args.id}]; } } } diff --git a/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj b/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj index bf79b05..a643791 100644 --- a/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj +++ b/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj @@ -155,6 +155,13 @@ + + + + + + Always + Always @@ -178,10 +185,7 @@ Always - - - - + {bc7dea8b-5029-459a-aa54-ea81eb390f87} @@ -199,9 +203,32 @@ PreserveNewest + + + + + + Always + + Always + + + + Always + + + Always + + + + Always + + + Always + Always diff --git a/RaceLapTimer/RaceLapTimer/TestProvider.cs b/RaceLapTimer/RaceLapTimer/TestProvider.cs index bdabdca..a89ca43 100644 --- a/RaceLapTimer/RaceLapTimer/TestProvider.cs +++ b/RaceLapTimer/RaceLapTimer/TestProvider.cs @@ -2,12 +2,14 @@ using System.Collections.Generic; using System.Linq; using Interfaces; +using RaceLapTimer.ApiControllers; -namespace RaceLapTimer.ApiControllers +namespace RaceLapTimer { public class TestProvider : IDbProvider { - readonly List _pilots; + private readonly List _pilots; + private readonly List _sessions; public TestProvider() { @@ -21,7 +23,7 @@ namespace RaceLapTimer.ApiControllers TeamName = "PilotTeam 1", ThingyName = "Kart1", TransponderToken = 222, - ImageUrl = "images/pilotPic.png" + ImageUrl = "/images/pilotPic.png" }, new Pilot { @@ -31,13 +33,10 @@ namespace RaceLapTimer.ApiControllers ThingyName = "Kart2", TransponderToken = 200 } - }; + }; #endregion - } - - public List GetRaceSessions(bool getActive) - { - return new List + #region RaceSessions + _sessions = new List { #region Session 1 new RaceSession @@ -72,7 +71,7 @@ namespace RaceLapTimer.ApiControllers #region Session 3 new RaceSession { - Active = getActive, + Active = false, CreatedAt = DateTime.UtcNow, HotSeatEnabled = false, Id = 3, @@ -87,7 +86,7 @@ namespace RaceLapTimer.ApiControllers #region Session 3 new RaceSession { - Active = getActive, + Active = false, CreatedAt = DateTime.UtcNow, HotSeatEnabled = false, Id = 4, @@ -100,6 +99,34 @@ namespace RaceLapTimer.ApiControllers } #endregion }; + #endregion + } + + public List GetRaceSessions(bool getActive) + { + return getActive ? _sessions.Where(x => x.Active == getActive).ToList() : _sessions; + } + + public bool CreateRaceSession(RaceSession session) + { + _sessions.Add(session); + return true; + } + + public bool StopRaceSession(RaceSession session) + { + var selectedSession = _sessions.FirstOrDefault(x => x.CreatedAt == session.CreatedAt + && x.Title == session.Title + && x.MaxLaps == session.MaxLaps + && x.Mode == session.Mode + && x.IdleTimeSeconds == session.IdleTimeSeconds); + if (selectedSession == null) + { + return false; + } + selectedSession.Active = false; + selectedSession.UpdatedAt = DateTime.UtcNow; + return true; } public List GetPilotsList() @@ -121,6 +148,21 @@ namespace RaceLapTimer.ApiControllers return true; } + public bool UpdatePilot(Pilot pilot) + { + if (_pilots.All(x => x.Id != pilot.Id)) + { + return false; + } + var p = _pilots.First(x => x.Id == pilot.Id); + p.ImageUrl = pilot.ImageUrl; + p.TransponderToken = pilot.TransponderToken; + p.Name = pilot.Name; + p.TeamName = pilot.TeamName; + p.ThingyName = pilot.ThingyName; + return true; + } + public bool DeletePilot(int id) { return _pilots.Remove(_pilots.FirstOrDefault(x => x.Id == id)); diff --git a/RaceLapTimer/RaceLapTimer/www/Views/EditPilot.cshtml b/RaceLapTimer/RaceLapTimer/www/Views/EditPilot.cshtml new file mode 100644 index 0000000..742069a --- /dev/null +++ b/RaceLapTimer/RaceLapTimer/www/Views/EditPilot.cshtml @@ -0,0 +1,47 @@ +@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase +@{ + Layout = "razor-layout.cshtml"; + ViewBag.Title = "Pilot Editor"; + ViewBag.EditPilotEndpoint = "/api/pilot/edit"; + ViewBag.UploadImageUrl = "/api/pilot/upload/" + Model.Id; +} + +

@ViewBag.Title

+ +
+ @Html.AntiForgeryToken() + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + pilotImage +
+ +
+
+
+
+ + +
+ +
+ + + \ No newline at end of file diff --git a/RaceLapTimer/RaceLapTimer/www/Views/Monitor.cshtml b/RaceLapTimer/RaceLapTimer/www/Views/Monitor.cshtml index 0b8adde..dbd4442 100644 --- a/RaceLapTimer/RaceLapTimer/www/Views/Monitor.cshtml +++ b/RaceLapTimer/RaceLapTimer/www/Views/Monitor.cshtml @@ -21,33 +21,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/RaceLapTimer/RaceLapTimer/www/Views/Pilots.cshtml b/RaceLapTimer/RaceLapTimer/www/Views/Pilots.cshtml index 52a5899..4996f4b 100644 --- a/RaceLapTimer/RaceLapTimer/www/Views/Pilots.cshtml +++ b/RaceLapTimer/RaceLapTimer/www/Views/Pilots.cshtml @@ -5,7 +5,7 @@ ViewBag.CreateUserEndpoint = "/api/pilot/create"; }

@ViewBag.Title

- +
@Html.AntiForgeryToken() diff --git a/RaceLapTimer/RaceLapTimer/www/Views/RaceDirector.cshtml b/RaceLapTimer/RaceLapTimer/www/Views/RaceDirector.cshtml index 018a61b..685f107 100644 --- a/RaceLapTimer/RaceLapTimer/www/Views/RaceDirector.cshtml +++ b/RaceLapTimer/RaceLapTimer/www/Views/RaceDirector.cshtml @@ -15,16 +15,40 @@

Last Lap Times

- +
- - + +
- +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + \ 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 7d32d07..b71df0e 100644 --- a/RaceLapTimer/RaceLapTimer/www/Views/razor-layout.cshtml +++ b/RaceLapTimer/RaceLapTimer/www/Views/razor-layout.cshtml @@ -4,14 +4,10 @@ @**@ @* - - *@ - @* - - - - *@ - + + *@ + + @@ -20,39 +16,39 @@ Razor Localization Demo -
- -
- -