diff --git a/Controllers/APIController.cs b/Controllers/APIController.cs index eba424d6..b6320fa4 100644 --- a/Controllers/APIController.cs +++ b/Controllers/APIController.cs @@ -34,6 +34,7 @@ public class APIController : Controller private readonly IFileHelper _fileHelper; private readonly IMailHelper _mailHelper; private readonly IConfigHelper _config; + private readonly IWebHostEnvironment _webEnv; public APIController(IVehicleDataAccess dataAccess, IGasHelper gasHelper, IReminderHelper reminderHelper, @@ -55,7 +56,8 @@ public APIController(IVehicleDataAccess dataAccess, IConfigHelper config, IUserLogic userLogic, IVehicleLogic vehicleLogic, - IOdometerLogic odometerLogic) + IOdometerLogic odometerLogic, + IWebHostEnvironment webEnv) { _dataAccess = dataAccess; _noteDataAccess = noteDataAccess; @@ -79,6 +81,7 @@ public APIController(IVehicleDataAccess dataAccess, _vehicleLogic = vehicleLogic; _fileHelper = fileHelper; _config = config; + _webEnv = webEnv; } public IActionResult Index() { @@ -163,7 +166,7 @@ public IActionResult ServiceRecords(int vehicleId) return Json(response); } var vehicleRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId); - var result = vehicleRecords.Select(x => new GenericRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields, Tags = string.Join(' ', x.Tags) }); + var result = vehicleRecords.Select(x => new GenericRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields, Files = x.Files, Tags = string.Join(' ', x.Tags) }); if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) { return Json(result, StaticHelper.GetInvariantOption()); @@ -206,6 +209,7 @@ public IActionResult AddServiceRecord(int vehicleId, GenericRecordExportModel in Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes, Cost = decimal.Parse(input.Cost), ExtraFields = input.ExtraFields, + Files = input.Files, Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList() }; _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord); @@ -291,6 +295,7 @@ public IActionResult UpdateServiceRecord(GenericRecordExportModel input) existingRecord.Description = input.Description; existingRecord.Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes; existingRecord.Cost = decimal.Parse(input.Cost); + existingRecord.Files = input.Files; existingRecord.ExtraFields = input.ExtraFields; existingRecord.Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList(); _serviceRecordDataAccess.SaveServiceRecordToVehicle(existingRecord); @@ -322,7 +327,7 @@ public IActionResult RepairRecords(int vehicleId) return Json(response); } var vehicleRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId); - var result = vehicleRecords.Select(x => new GenericRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields, Tags = string.Join(' ', x.Tags) }); + var result = vehicleRecords.Select(x => new GenericRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields, Files = x.Files, Tags = string.Join(' ', x.Tags) }); if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) { return Json(result, StaticHelper.GetInvariantOption()); @@ -366,6 +371,7 @@ public IActionResult AddRepairRecord(int vehicleId, GenericRecordExportModel inp Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes, Cost = decimal.Parse(input.Cost), ExtraFields = input.ExtraFields, + Files = input.Files, Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList() }; _collisionRecordDataAccess.SaveCollisionRecordToVehicle(repairRecord); @@ -453,6 +459,7 @@ public IActionResult UpdateRepairRecord(GenericRecordExportModel input) existingRecord.Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes; existingRecord.Cost = decimal.Parse(input.Cost); existingRecord.ExtraFields = input.ExtraFields; + existingRecord.Files = input.Files; existingRecord.Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList(); _collisionRecordDataAccess.SaveCollisionRecordToVehicle(existingRecord); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromGenericRecord(existingRecord, "repairrecord.update.api", User.Identity.Name)); @@ -484,7 +491,7 @@ public IActionResult UpgradeRecords(int vehicleId) return Json(response); } var vehicleRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId); - var result = vehicleRecords.Select(x => new GenericRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields, Tags = string.Join(' ', x.Tags) }); + var result = vehicleRecords.Select(x => new GenericRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields, Files = x.Files, Tags = string.Join(' ', x.Tags) }); if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) { return Json(result, StaticHelper.GetInvariantOption()); @@ -528,6 +535,7 @@ public IActionResult AddUpgradeRecord(int vehicleId, GenericRecordExportModel in Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes, Cost = decimal.Parse(input.Cost), ExtraFields = input.ExtraFields, + Files = input.Files, Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList() }; _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord); @@ -614,6 +622,7 @@ public IActionResult UpdateUpgradeRecord(GenericRecordExportModel input) existingRecord.Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes; existingRecord.Cost = decimal.Parse(input.Cost); existingRecord.ExtraFields = input.ExtraFields; + existingRecord.Files = input.Files; existingRecord.Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList(); _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(existingRecord); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromGenericRecord(existingRecord, "upgraderecord.update.api", User.Identity.Name)); @@ -644,7 +653,7 @@ public IActionResult TaxRecords(int vehicleId) Response.StatusCode = 400; return Json(response); } - var result = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId).Select(x => new TaxRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, ExtraFields = x.ExtraFields, Tags = string.Join(' ', x.Tags) }); + var result = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId).Select(x => new TaxRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, ExtraFields = x.ExtraFields, Files = x.Files, Tags = string.Join(' ', x.Tags) }); if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) { return Json(result, StaticHelper.GetInvariantOption()); @@ -721,6 +730,7 @@ public IActionResult AddTaxRecord(int vehicleId, TaxRecordExportModel input) Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes, Cost = decimal.Parse(input.Cost), ExtraFields = input.ExtraFields, + Files = input.Files, Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList() }; _taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord); @@ -790,6 +800,7 @@ public IActionResult UpdateTaxRecord(TaxRecordExportModel input) existingRecord.Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes; existingRecord.Cost = decimal.Parse(input.Cost); existingRecord.ExtraFields = input.ExtraFields; + existingRecord.Files = input.Files; existingRecord.Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList(); _taxRecordDataAccess.SaveTaxRecordToVehicle(existingRecord); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromTaxRecord(existingRecord, "taxrecord.update.api", User.Identity.Name)); @@ -840,7 +851,7 @@ public IActionResult OdometerRecords(int vehicleId) { vehicleRecords = _odometerLogic.AutoConvertOdometerRecord(vehicleRecords); } - var result = vehicleRecords.Select(x => new OdometerRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), InitialOdometer = x.InitialMileage.ToString(), Odometer = x.Mileage.ToString(), Notes = x.Notes, ExtraFields = x.ExtraFields, Tags = string.Join(' ', x.Tags) }); + var result = vehicleRecords.Select(x => new OdometerRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), InitialOdometer = x.InitialMileage.ToString(), Odometer = x.Mileage.ToString(), Notes = x.Notes, ExtraFields = x.ExtraFields, Files = x.Files, Tags = string.Join(' ', x.Tags) }); if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) { return Json(result, StaticHelper.GetInvariantOption()); @@ -881,6 +892,7 @@ public IActionResult AddOdometerRecord(int vehicleId, OdometerRecordExportModel InitialMileage = (string.IsNullOrWhiteSpace(input.InitialOdometer) || int.Parse(input.InitialOdometer) == default) ? _odometerLogic.GetLastOdometerRecordMileage(vehicleId, new List()) : int.Parse(input.InitialOdometer), Mileage = int.Parse(input.Odometer), ExtraFields = input.ExtraFields, + Files = input.Files, Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList() }; _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord); @@ -948,6 +960,7 @@ public IActionResult UpdateOdometerRecord(OdometerRecordExportModel input) existingRecord.InitialMileage = int.Parse(input.InitialOdometer); existingRecord.Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes; existingRecord.ExtraFields = input.ExtraFields; + existingRecord.Files = input.Files; existingRecord.Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList(); _odometerRecordDataAccess.SaveOdometerRecordToVehicle(existingRecord); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromOdometerRecord(existingRecord, "odometerrecord.update.api", User.Identity.Name)); @@ -991,6 +1004,7 @@ public IActionResult GasRecords(int vehicleId, bool useMPG, bool useUKMPG) MissedFuelUp = x.MissedFuelUp.ToString(), Notes = x.Notes, ExtraFields = x.ExtraFields, + Files = x.Files, Tags = string.Join(' ', x.Tags) }); if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) @@ -1179,6 +1193,37 @@ public IActionResult Calendar() var calendarContent = StaticHelper.RemindersToCalendar(reminders); return File(calendarContent, "text/calendar"); } + [HttpPost] + [Route("/api/documents/upload")] + public IActionResult UploadDocument(List documents) + { + if (documents.Any()) + { + List uploadedFiles = new List(); + string uploadDirectory = "documents/"; + string uploadPath = Path.Combine(_webEnv.ContentRootPath, "data", uploadDirectory); + if (!Directory.Exists(uploadPath)) + Directory.CreateDirectory(uploadPath); + foreach (IFormFile document in documents) + { + string fileName = Guid.NewGuid() + Path.GetExtension(document.FileName); + string filePath = Path.Combine(uploadPath, fileName); + using (var stream = System.IO.File.Create(filePath)) + { + document.CopyTo(stream); + } + uploadedFiles.Add(new UploadedFiles + { + Location = Path.Combine("/", uploadDirectory, fileName), + Name = Path.GetFileName(document.FileName) + }); + } + return Json(uploadedFiles); + } else + { + return Json(OperationResponse.Failed("No files to upload")); + } + } [Authorize(Roles = nameof(UserData.IsRootUser))] [HttpGet] [Route("/api/vehicle/reminders/send")] diff --git a/Helper/GasHelper.cs b/Helper/GasHelper.cs index a7c340f0..59d23155 100644 --- a/Helper/GasHelper.cs +++ b/Helper/GasHelper.cs @@ -76,7 +76,8 @@ public List GetGasRecordViewModels(List result, b MissedFuelUp = currentObject.MissedFuelUp, Notes = currentObject.Notes, Tags = currentObject.Tags, - ExtraFields = currentObject.ExtraFields + ExtraFields = currentObject.ExtraFields, + Files = currentObject.Files }; if (currentObject.MissedFuelUp) { @@ -130,7 +131,8 @@ public List GetGasRecordViewModels(List result, b MissedFuelUp = currentObject.MissedFuelUp, Notes = currentObject.Notes, Tags = currentObject.Tags, - ExtraFields = currentObject.ExtraFields + ExtraFields = currentObject.ExtraFields, + Files = currentObject.Files }); } previousMileage = currentObject.Mileage; diff --git a/Models/GasRecord/GasRecordViewModel.cs b/Models/GasRecord/GasRecordViewModel.cs index a4b3f30a..2e90f4d1 100644 --- a/Models/GasRecord/GasRecordViewModel.cs +++ b/Models/GasRecord/GasRecordViewModel.cs @@ -23,6 +23,7 @@ public class GasRecordViewModel public string Notes { get; set; } public List Tags { get; set; } = new List(); public List ExtraFields { get; set; } = new List(); + public List Files { get; set; } = new List(); public bool IncludeInAverage { get { return MilesPerGallon > 0 || (!IsFillToFull && !MissedFuelUp); } } } } diff --git a/Models/Shared/ImportModel.cs b/Models/Shared/ImportModel.cs index 88d9d726..07909c81 100644 --- a/Models/Shared/ImportModel.cs +++ b/Models/Shared/ImportModel.cs @@ -43,7 +43,7 @@ public class SupplyRecordExportModel public string Cost { get; set; } public string Notes { get; set; } public string Tags { get; set; } - public List ExtraFields { get; set; } + public List ExtraFields { get; set; } = new List(); } public class GenericRecordExportModel { @@ -58,7 +58,8 @@ public class GenericRecordExportModel [JsonConverter(typeof(FromDecimalOptional))] public string Cost { get; set; } public string Tags { get; set; } - public List ExtraFields { get; set; } + public List ExtraFields { get; set; } = new List(); + public List Files { get; set; } = new List(); } public class OdometerRecordExportModel { @@ -72,7 +73,8 @@ public class OdometerRecordExportModel public string Odometer { get; set; } public string Notes { get; set; } public string Tags { get; set; } - public List ExtraFields { get; set; } + public List ExtraFields { get; set; } = new List(); + public List Files { get; set; } = new List(); } public class TaxRecordExportModel { @@ -85,7 +87,8 @@ public class TaxRecordExportModel [JsonConverter(typeof(FromDecimalOptional))] public string Cost { get; set; } public string Tags { get; set; } - public List ExtraFields { get; set; } + public List ExtraFields { get; set; } = new List(); + public List Files { get; set; } = new List(); } public class GasRecordExportModel { @@ -107,7 +110,8 @@ public class GasRecordExportModel public string MissedFuelUp { get; set; } public string Notes { get; set; } public string Tags { get; set; } - public List ExtraFields { get; set; } + public List ExtraFields { get; set; } = new List(); + public List Files { get; set; } = new List(); } public class ReminderExportModel { @@ -130,6 +134,6 @@ public class PlanRecordExportModel public string Priority { get; set; } public string Progress { get; set; } public string Cost { get; set; } - public List ExtraFields { get; set; } + public List ExtraFields { get; set; } = new List(); } } diff --git a/Views/API/Index.cshtml b/Views/API/Index.cshtml index b46d5aad..f817f1e4 100644 --- a/Views/API/Index.cshtml +++ b/Views/API/Index.cshtml @@ -118,6 +118,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -140,6 +141,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -192,6 +194,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -215,6 +218,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -267,6 +271,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -290,6 +295,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -342,6 +348,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -365,6 +372,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -430,6 +438,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -452,6 +461,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -510,6 +520,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -535,6 +546,7 @@ notes - notes(optional)
tags - tags separated by space(optional)
extrafields - extrafields(optional)
+ files - attachments(optional)
} @@ -566,6 +578,22 @@ vehicleId - Id of Vehicle +
+
+ POST +
+
+ /api/documents/upload +
+
+ Upload Documents +
+
+ Body(form-data): {
+ documents[] - Files to Upload
+ } +
+
@if (User.IsInRole(nameof(UserData.IsRootUser))) {
@@ -624,4 +652,11 @@ icon: "info" }); } + function showAttachmentsInfo(){ + Swal.fire({ + title: "Attaching Files", + html: "The Document Upload Endpoint will upload the files and provide a formatted output which you can pass into this method", + icon: "info" + }); + } \ No newline at end of file