Merge pull request #782 from hargata/Hargata/697
added API method that generates a calendar of reminders for the user.
This commit is contained in:
@@ -1166,6 +1166,19 @@ namespace CarCareTracker.Controllers
|
|||||||
return Json(results);
|
return Json(results);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
[HttpGet]
|
||||||
|
[Route("/api/calendar")]
|
||||||
|
public IActionResult Calendar()
|
||||||
|
{
|
||||||
|
var vehiclesStored = _dataAccess.GetVehicles();
|
||||||
|
if (!User.IsInRole(nameof(UserData.IsRootUser)))
|
||||||
|
{
|
||||||
|
vehiclesStored = _userLogic.FilterUserVehicles(vehiclesStored, GetUserID());
|
||||||
|
}
|
||||||
|
var reminders = _vehicleLogic.GetReminders(vehiclesStored, true);
|
||||||
|
var calendarContent = StaticHelper.RemindersToCalendar(reminders);
|
||||||
|
return File(calendarContent, "text/calendar");
|
||||||
|
}
|
||||||
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("/api/vehicle/reminders/send")]
|
[Route("/api/vehicle/reminders/send")]
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
using CsvHelper;
|
using CsvHelper;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace CarCareTracker.Helper
|
namespace CarCareTracker.Helper
|
||||||
@@ -754,5 +756,52 @@ namespace CarCareTracker.Helper
|
|||||||
_csv.NextRecord();
|
_csv.NextRecord();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static byte[] RemindersToCalendar(List<ReminderRecordViewModel> reminders)
|
||||||
|
{
|
||||||
|
//converts reminders to iCal file
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
//start the calendar item
|
||||||
|
sb.AppendLine("BEGIN:VCALENDAR");
|
||||||
|
sb.AppendLine("VERSION:2.0");
|
||||||
|
sb.AppendLine("PRODID:lubelogger.com");
|
||||||
|
sb.AppendLine("CALSCALE:GREGORIAN");
|
||||||
|
sb.AppendLine("METHOD:PUBLISH");
|
||||||
|
|
||||||
|
//create events.
|
||||||
|
foreach(ReminderRecordViewModel reminder in reminders)
|
||||||
|
{
|
||||||
|
var dtStart = reminder.Date.Date.ToString("yyyyMMddTHHmm00");
|
||||||
|
var dtEnd = reminder.Date.Date.AddDays(1).AddMilliseconds(-1).ToString("yyyyMMddTHHmm00");
|
||||||
|
var calendarUID = new Guid(MD5.HashData(Encoding.UTF8.GetBytes($"{dtStart}_{reminder.Description}")));
|
||||||
|
sb.AppendLine("BEGIN:VEVENT");
|
||||||
|
sb.AppendLine("DTSTAMP:" + DateTime.Now.ToString("yyyyMMddTHHmm00"));
|
||||||
|
sb.AppendLine("UID:" + calendarUID);
|
||||||
|
sb.AppendLine("DTSTART:" + dtStart);
|
||||||
|
sb.AppendLine("DTEND:" + dtEnd);
|
||||||
|
sb.AppendLine($"SUMMARY:{reminder.Description}");
|
||||||
|
sb.AppendLine($"DESCRIPTION:{reminder.Description}");
|
||||||
|
switch (reminder.Urgency)
|
||||||
|
{
|
||||||
|
case ReminderUrgency.NotUrgent:
|
||||||
|
sb.AppendLine("PRIORITY:3");
|
||||||
|
break;
|
||||||
|
case ReminderUrgency.Urgent:
|
||||||
|
sb.AppendLine("PRIORITY:2");
|
||||||
|
break;
|
||||||
|
case ReminderUrgency.VeryUrgent:
|
||||||
|
sb.AppendLine("PRIORITY:1");
|
||||||
|
break;
|
||||||
|
case ReminderUrgency.PastDue:
|
||||||
|
sb.AppendLine("PRIORITY:1");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sb.AppendLine("END:VEVENT");
|
||||||
|
}
|
||||||
|
|
||||||
|
//end calendar item
|
||||||
|
sb.AppendLine("END:VCALENDAR");
|
||||||
|
string calendarContent = sb.ToString();
|
||||||
|
return Encoding.UTF8.GetBytes(calendarContent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
38
Program.cs
38
Program.cs
@@ -106,11 +106,15 @@ var app = builder.Build();
|
|||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
app.UseExceptionHandler("/Home/Error");
|
app.UseExceptionHandler("/Home/Error");
|
||||||
|
|
||||||
|
app.UseStaticFiles();
|
||||||
app.UseStaticFiles(new StaticFileOptions
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
{
|
{
|
||||||
|
FileProvider = new PhysicalFileProvider(
|
||||||
|
Path.Combine(builder.Environment.ContentRootPath, "data", "images")),
|
||||||
|
RequestPath = "/images",
|
||||||
OnPrepareResponse = ctx =>
|
OnPrepareResponse = ctx =>
|
||||||
{
|
{
|
||||||
if (ctx.Context.Request.Path.StartsWithSegments("/images") || ctx.Context.Request.Path.StartsWithSegments("/documents"))
|
if (ctx.Context.Request.Path.StartsWithSegments("/images"))
|
||||||
{
|
{
|
||||||
ctx.Context.Response.Headers.Add("Cache-Control", "no-store");
|
ctx.Context.Response.Headers.Add("Cache-Control", "no-store");
|
||||||
if (!ctx.Context.User.Identity.IsAuthenticated)
|
if (!ctx.Context.User.Identity.IsAuthenticated)
|
||||||
@@ -121,16 +125,21 @@ app.UseStaticFiles(new StaticFileOptions
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
app.UseStaticFiles(new StaticFileOptions
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
{
|
|
||||||
FileProvider = new PhysicalFileProvider(
|
|
||||||
Path.Combine(builder.Environment.ContentRootPath, "data", "images")),
|
|
||||||
RequestPath = "/images"
|
|
||||||
});
|
|
||||||
app.UseStaticFiles(new StaticFileOptions
|
|
||||||
{
|
{
|
||||||
FileProvider = new PhysicalFileProvider(
|
FileProvider = new PhysicalFileProvider(
|
||||||
Path.Combine(builder.Environment.ContentRootPath, "data", "documents")),
|
Path.Combine(builder.Environment.ContentRootPath, "data", "documents")),
|
||||||
RequestPath = "/documents"
|
RequestPath = "/documents",
|
||||||
|
OnPrepareResponse = ctx =>
|
||||||
|
{
|
||||||
|
if (ctx.Context.Request.Path.StartsWithSegments("/documents"))
|
||||||
|
{
|
||||||
|
ctx.Context.Response.Headers.Add("Cache-Control", "no-store");
|
||||||
|
if (!ctx.Context.User.Identity.IsAuthenticated)
|
||||||
|
{
|
||||||
|
ctx.Context.Response.Redirect("/Login");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
app.UseStaticFiles(new StaticFileOptions
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
{
|
{
|
||||||
@@ -142,7 +151,18 @@ app.UseStaticFiles(new StaticFileOptions
|
|||||||
{
|
{
|
||||||
FileProvider = new PhysicalFileProvider(
|
FileProvider = new PhysicalFileProvider(
|
||||||
Path.Combine(builder.Environment.ContentRootPath, "data", "temp")),
|
Path.Combine(builder.Environment.ContentRootPath, "data", "temp")),
|
||||||
RequestPath = "/temp"
|
RequestPath = "/temp",
|
||||||
|
OnPrepareResponse = ctx =>
|
||||||
|
{
|
||||||
|
if (ctx.Context.Request.Path.StartsWithSegments("/temp"))
|
||||||
|
{
|
||||||
|
ctx.Context.Response.Headers.Add("Cache-Control", "no-store");
|
||||||
|
if (!ctx.Context.User.Identity.IsAuthenticated)
|
||||||
|
{
|
||||||
|
ctx.Context.Response.Redirect("/Login");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
<title>@ViewData["Title"] - LubeLogger</title>
|
<title>@ViewData["Title"] - LubeLogger</title>
|
||||||
|
<link rel="icon" type="image/x-icon" href="~/favicon.ico">
|
||||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
|
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
|
||||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap-icons.css" />
|
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap-icons.css" />
|
||||||
<link rel="stylesheet" href="~/lib/bootstrap-datepicker/css/bootstrap-datepicker.min.css" />
|
<link rel="stylesheet" href="~/lib/bootstrap-datepicker/css/bootstrap-datepicker.min.css" />
|
||||||
|
|||||||
Reference in New Issue
Block a user