diff --git a/.gitignore b/.gitignore index 3c4efe2..2608a78 100644 --- a/.gitignore +++ b/.gitignore @@ -258,4 +258,6 @@ paket-files/ # Python Tools for Visual Studio (PTVS) __pycache__/ -*.pyc \ No newline at end of file +*.pyc + +SeniorAssistant/SeniorAssistant/wwwroot/* \ No newline at end of file diff --git a/SeniorAssistant/Controllers/HomeController.cs b/SeniorAssistant/Controllers/HomeController.cs index 225a94c..6c081ea 100644 --- a/SeniorAssistant/Controllers/HomeController.cs +++ b/SeniorAssistant/Controllers/HomeController.cs @@ -2,6 +2,7 @@ namespace SeniorAssistant.Controllers { + [ApiExplorerSettings(IgnoreApi = true)] public class HomeController : Controller { [Route("")] @@ -17,5 +18,23 @@ namespace SeniorAssistant.Controllers { return View(); } + + [Route("Sleep")] + public IActionResult Sleep() + { + return View(); + } + + [Route("Step")] + public IActionResult Step() + { + return View(); + } + + [Route("{User}")] + public IActionResult SingleUser(string user) + { + return View("user", user); + } } } \ No newline at end of file diff --git a/SeniorAssistant/Controllers/Services/ApiControllers.cs b/SeniorAssistant/Controllers/Services/ApiControllers.cs new file mode 100644 index 0000000..71414cf --- /dev/null +++ b/SeniorAssistant/Controllers/Services/ApiControllers.cs @@ -0,0 +1,21 @@ +using Microsoft.AspNetCore.Mvc; +using SeniorAssistant.Models; + +namespace SeniorAssistant.Controllers.Services +{ + [Route("api/[controller]")] + public class HeartbeatController : CrudTimeController + { } + + [Route("api/[controller]")] + public class SleepController : CrudTimeController + { } + + [Route("api/[controller]")] + public class StepController : CrudTimeController + { } + + [Route("api/[controller]")] + public class UserController : CrudController + { } +} diff --git a/SeniorAssistant/Controllers/BaseController.cs b/SeniorAssistant/Controllers/Services/BaseController.cs similarity index 100% rename from SeniorAssistant/Controllers/BaseController.cs rename to SeniorAssistant/Controllers/Services/BaseController.cs diff --git a/SeniorAssistant/Controllers/Services/CrudTimeController.cs b/SeniorAssistant/Controllers/Services/CrudTimeController.cs index 5db31b7..9e3d1c3 100644 --- a/SeniorAssistant/Controllers/Services/CrudTimeController.cs +++ b/SeniorAssistant/Controllers/Services/CrudTimeController.cs @@ -11,6 +11,8 @@ namespace SeniorAssistant.Controllers.Services public class CrudTimeController : BaseController where TEntity : class, IHasTime { + static readonly object Empty = new { }; + [HttpGet] public async Task> Read() => await Db.GetTable().ToListAsync(); @@ -18,31 +20,54 @@ namespace SeniorAssistant.Controllers.Services public async Task> Read(string username) => await Db.GetTable().Where(e => e.Username.Equals(username)).ToListAsync(); [HttpGet("{username}/{date:regex((today|\\d{{4}}-\\d{{2}}-\\d{{2}}))}/{hour:range(0, 23)?}")] - public async Task> Read(string username, string date, int hour = -1) - { - DateTime time = (date.Equals("today") ? DateTime.Now : DateTime.ParseExact(date, "yyyy-MM-dd", null) ); + public async Task> Read(string username, string date, int hour = -1) => await Read(username, date, date, hour); - return await Db.GetTable().Where(e => - e.Username.Equals(username) && - (time.Year == 0 || e.Time.Year == time.Year) && - (time.Month == 0 || e.Time.Month == time.Month) && - (time.Day == 0 || e.Time.Day == time.Day) && - (hour < 0 || e.Time.Hour == hour) - ).ToListAsync(); + [HttpGet("{username}/{from:regex((today|\\d{{4}}-\\d{{2}}-\\d{{2}}))}/{to:regex((today|\\d{{4}}-\\d{{2}}-\\d{{2}}))}/{hour:range(0, 23)?}")] + public async Task> Read(string username, string from, string to, int hour = -1) + { + try + { + DateTime dateFrom = (from.Equals("today") ? DateTime.Now : DateTime.ParseExact(from, "yyyy-MM-dd", null)); + DateTime dateTo = (to.Equals("today") ? DateTime.Now : DateTime.ParseExact(to, "yyyy-MM-dd", null)); + + return await Db.GetTable().Where(e => e.Username.Equals(username) && dateFrom.Date<=e.Time.Date && dateTo.Date>=e.Time.Date && (hour < 0 || e.Time.Hour == hour)).ToListAsync(); + } + catch + { + return new List(); + } + } + + [HttpGet("{username}/last/{hour:min(1)}")] + public async Task> Read(string username, int hour) + { + DateTime date = DateTime.Now.AddHours(-hour); + return await Db.GetTable().Where(e => e.Username.Equals(username) && date <= e.Time).ToListAsync(); + } + + [NonAction] + public async Task Read(string username, DateTime date) => await Db.GetTable().FirstOrDefaultAsync(e => e.Username.Equals(username) && date == e.Time); + + [HttpPost] + public async Task Create([FromBody]TEntity item) => await Db.InsertAsync(item); + + [HttpPut] + public async Task Update([FromBody]TEntity item) + { + var e = await Read(item.Username, item.Time); + if (e == null) + { + await Create(item); + } + else + { + await Db.UpdateAsync(item); + } + + return Empty; } /* - [HttpPost("{username}")] - public async Task Create([FromBody]TEntity item) => await Db.InsertAsync(item); - - [HttpPut("{username}/{date}/{time}")] - public async Task Update(string username, [FromBody]TEntity item) - { - item.Username = username; - - await Db.UpdateAsync(item); - } - [HttpDelete("{username}")] public async Task Delete(string username) => await Db.GetTable().Where(c => c.Username.Equals(username)).DeleteAsync(); */ diff --git a/SeniorAssistant/Controllers/Services/HeartbeatController.cs b/SeniorAssistant/Controllers/Services/HeartbeatController.cs deleted file mode 100644 index ef6bc73..0000000 --- a/SeniorAssistant/Controllers/Services/HeartbeatController.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using SeniorAssistant.Models; - -namespace SeniorAssistant.Controllers.Services -{ - [Route("api/[controller]")] - public class HeartbeatController : CrudTimeController - { } -} diff --git a/SeniorAssistant/Controllers/Services/UserController.cs b/SeniorAssistant/Controllers/Services/UserController.cs deleted file mode 100644 index bb98bc1..0000000 --- a/SeniorAssistant/Controllers/Services/UserController.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using SeniorAssistant.Models; - -namespace SeniorAssistant.Controllers.Services -{ - [Route("api/[controller]")] - public class UserController : CrudController - { } -} \ No newline at end of file diff --git a/SeniorAssistant/Models/Sleep.cs b/SeniorAssistant/Models/Sleep.cs new file mode 100644 index 0000000..2ca6db8 --- /dev/null +++ b/SeniorAssistant/Models/Sleep.cs @@ -0,0 +1,21 @@ +using LinqToDB.Mapping; +using System; + +namespace SeniorAssistant.Models +{ + public class Sleep : IHasTime + { + [PrimaryKey] + [NotNull] + public string Username { get; set; } + + [PrimaryKey] + [NotNull] + public DateTime Time { get; set; } + + [Association(ThisKey = nameof(Username), OtherKey = nameof(User.Username), CanBeNull = false)] + public User user { get; set; } + + public long Value { get; set; } + } +} diff --git a/SeniorAssistant/Models/Step.cs b/SeniorAssistant/Models/Step.cs new file mode 100644 index 0000000..73d5ad3 --- /dev/null +++ b/SeniorAssistant/Models/Step.cs @@ -0,0 +1,21 @@ +using LinqToDB.Mapping; +using System; + +namespace SeniorAssistant.Models +{ + public class Step : IHasTime + { + [PrimaryKey] + [NotNull] + public string Username { get; set; } + + [PrimaryKey] + [NotNull] + public DateTime Time { get; set; } + + [Association(ThisKey = nameof(Username), OtherKey = nameof(User.Username), CanBeNull = false)] + public User user { get; set; } + + public long Value { get; set; } + } +} diff --git a/SeniorAssistant/Properties/launchSettings.json b/SeniorAssistant/Properties/launchSettings.json index 76fa1f6..741e5b1 100644 --- a/SeniorAssistant/Properties/launchSettings.json +++ b/SeniorAssistant/Properties/launchSettings.json @@ -2,9 +2,13 @@ "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, + "iis": { + "applicationUrl": "http://localhost/SeniorAssistant", + "sslPort": 0 + }, "iisExpress": { "applicationUrl": "http://localhost:50361", - "sslPort": 44348 + "sslPort": 44387 } }, "profiles": { @@ -27,6 +31,9 @@ "commandName": "Docker", "launchBrowser": true, "launchUrl": "{Scheme}://{ServiceHost}" + }, + "Snapshot Debugger (servizio app di Azure)": { + "commandName": "Snapshot Debugger (servizio app di Azure)" } } } \ No newline at end of file diff --git a/SeniorAssistant/SeniorAssistant.csproj b/SeniorAssistant/SeniorAssistant.csproj index a7010d0..dcde378 100644 --- a/SeniorAssistant/SeniorAssistant.csproj +++ b/SeniorAssistant/SeniorAssistant.csproj @@ -17,6 +17,7 @@ + diff --git a/SeniorAssistant/Startup.cs b/SeniorAssistant/Startup.cs index a45d662..b5aecc2 100644 --- a/SeniorAssistant/Startup.cs +++ b/SeniorAssistant/Startup.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using LinqToDB; using LinqToDB.DataProvider.SQLite; using Microsoft.AspNetCore.Builder; @@ -11,8 +10,9 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using SeniorAssistant.Configuration; using SeniorAssistant.Data; -using SeniorAssistant.Extensions; using SeniorAssistant.Models; +using SeniorAssistant.Extensions; +using Swashbuckle.AspNetCore.Swagger; namespace SeniorAssistant { @@ -31,6 +31,23 @@ namespace SeniorAssistant { services.AddMvc(); + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new Info + { + Version = "v1", + Title = "Senior REST APIs", + Description = "REST APIs for old people", + TermsOfService = "None" + }); + + // Se decommento ottengo un'eccezione quando ho un controller (es. CategoriesController) che estende un altro controller. + // Set the comments path for the Swagger JSON and UI. + //var basePath = AppContext.BaseDirectory; + //var xmlPath = Path.Combine(basePath, "REST.xml"); + //c.IncludeXmlComments(xmlPath); + }); + services.Configure(Configuration.GetSection("kendo")); services.Configure(Configuration.GetSection("theme")); @@ -43,8 +60,8 @@ namespace SeniorAssistant { new MenuItem("User", "/"), new MenuItem("Heartbeat", "/heartbeat"), - new MenuItem("Sleep"), - new MenuItem("Step") + new MenuItem("Sleep", "/sleep"), + new MenuItem("Step", "/step") } }, }); @@ -68,6 +85,15 @@ namespace SeniorAssistant app.UseStaticFiles(); + // Enable middleware to serve generated Swagger as a JSON endpoint. + app.UseSwagger(); + + // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint. + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/api/v1.json", "V1"); + }); + /* Shortcut per: @@ -88,38 +114,65 @@ namespace SeniorAssistant { using (var db = dataContext.Create()) { + const string baseUsername = "vecchio"; + string[] users = { "Mario", "Giovanni", "Aldo", "Giacomo", "Marcello", "Filippo" }; + + db.CreateTableIfNotExists(); + db.CreateTableIfNotExists(); + db.CreateTableIfNotExists(); try { db.CreateTable(); - db.CreateTable(); - - const string baseUsername = "vecchio"; - - string[] users = { "Mario", "Giovanni", "Aldo", "Giacomo", "Marcello", "Filippo" }; - int num = 0; + int count = 0; foreach (string user in users) { - db.InsertOrReplace(new User { Name = user, Username = baseUsername+(num==0?"":""+num) }); - num++; - } - - Random rnd = new Random(); - for (int i=0; i<50; i++) - { - int random = rnd.Next(num); - string user = baseUsername + (random==0? "":""+random); - DateTime time = DateTime.Now.AddHours(rnd.Next(-24, +24)); - int beat = rnd.Next(50, 90); - - Heartbeat heart = new Heartbeat { Username = user, Time = time, Value = beat }; - db.Insert(heart); + db.InsertOrReplace(new User { Name = user, Username = baseUsername + (count == 0 ? "" : "" + count) }); + count++; } } - catch (SqliteException) + catch + { } + + Random rnd = new Random(); + DateTime now = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day); + now = now.AddHours(DateTime.Now.Hour).AddMinutes(30); + double totalHours = 50; + try { - // Do nothing + DateTime time = db.GetTable().MaxAsync(x => x.Time).Result; + TimeSpan span = now.Subtract(time); + totalHours = span.TotalHours; } + catch { } + + for (int i = 0; i -@{ +@{ ViewBag.Title = "Hello Razor"; } diff --git a/SeniorAssistant/Views/Home/Sleep.cshtml b/SeniorAssistant/Views/Home/Sleep.cshtml new file mode 100644 index 0000000..90454bf --- /dev/null +++ b/SeniorAssistant/Views/Home/Sleep.cshtml @@ -0,0 +1,42 @@ +@{ + ViewBag.Title = "Hello Razor"; +} + +
+ + \ No newline at end of file diff --git a/SeniorAssistant/Views/Home/Step.cshtml b/SeniorAssistant/Views/Home/Step.cshtml new file mode 100644 index 0000000..7534cf2 --- /dev/null +++ b/SeniorAssistant/Views/Home/Step.cshtml @@ -0,0 +1,42 @@ +@{ + ViewBag.Title = "Hello Razor"; +} + +
+ + \ No newline at end of file diff --git a/SeniorAssistant/Views/Home/User.cshtml b/SeniorAssistant/Views/Home/User.cshtml new file mode 100644 index 0000000..0c038bf --- /dev/null +++ b/SeniorAssistant/Views/Home/User.cshtml @@ -0,0 +1,82 @@ +@model string +@{ + ViewBag.Title = "Hello Razor"; +} + +
+ + \ No newline at end of file diff --git a/SeniorAssistant/senior.db b/SeniorAssistant/senior.db index 352f364..adbf9bd 100644 Binary files a/SeniorAssistant/senior.db and b/SeniorAssistant/senior.db differ