From 3a3f216ddfbb531d7ff507fa668131d428245494 Mon Sep 17 00:00:00 2001 From: ivancheahhh Date: Tue, 2 Jan 2024 15:15:25 -0700 Subject: [PATCH] Added method to upload and delete documents from service records. --- .gitignore | 2 + Controllers/FilesController.cs | 31 ++++++++++--- Controllers/HomeController.cs | 9 ++-- Controllers/VehicleController.cs | 11 +++-- Helper/FileHelper.cs | 57 ++++++++++++++++++++++++ Models/ServiceRecord.cs | 1 + Models/ServiceRecordInput.cs | 4 +- Models/UploadedFiles.cs | 8 ++++ Program.cs | 2 + Views/Vehicle/_ServiceRecordModal.cshtml | 41 +++++++++++++++-- Views/Vehicle/_ServiceRecords.cshtml | 6 ++- wwwroot/js/vehicle.js | 23 ++++++++++ 12 files changed, 178 insertions(+), 17 deletions(-) create mode 100644 Helper/FileHelper.cs create mode 100644 Models/UploadedFiles.cs diff --git a/.gitignore b/.gitignore index 1170ce8..59b15ca 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ bin/ obj/ wwwroot/images/ cartracker.db +wwwroot/documents/ +wwwroot/temp/ diff --git a/Controllers/FilesController.cs b/Controllers/FilesController.cs index 2cd224f..d004943 100644 --- a/Controllers/FilesController.cs +++ b/Controllers/FilesController.cs @@ -7,31 +7,52 @@ using static System.Net.Mime.MediaTypeNames; using System.Drawing; using System.Linq.Expressions; using Microsoft.Extensions.Logging; +using CarCareTracker.Helper; namespace CarCareTracker.Controllers { public class FilesController : Controller { private readonly ILogger _logger; - private readonly IVehicleDataAccess _dataAccess; private readonly IWebHostEnvironment _webEnv; + private readonly IFileHelper _fileHelper; - public FilesController(ILogger logger, IWebHostEnvironment webEnv) + public FilesController(ILogger logger, IFileHelper fileHelper, IWebHostEnvironment webEnv) { _logger = logger; _webEnv = webEnv; + _fileHelper = fileHelper; } [HttpPost] public IActionResult HandleFileUpload(IFormFile file) { - var fileName = UploadImage(file); + var fileName = UploadFile(file); return Json(fileName); } - private string UploadImage(IFormFile fileToUpload) + [HttpPost] + public IActionResult HandleMultipleFileUpload(List file) { - string uploadDirectory = "images/"; + List uploadedFiles = new List(); + foreach (IFormFile fileToUpload in file) + { + var fileName = UploadFile(fileToUpload); + uploadedFiles.Add(new UploadedFiles { Name = fileToUpload.FileName, Location = fileName}); + } + return Json(uploadedFiles); + } + + [HttpPost] + public ActionResult DeleteFiles(string fileLocation) + { + var result = _fileHelper.DeleteFile(fileLocation); + return Json(result); + } + + private string UploadFile(IFormFile fileToUpload) + { + string uploadDirectory = "temp/"; string uploadPath = Path.Combine(_webEnv.WebRootPath, uploadDirectory); if (!Directory.Exists(uploadPath)) Directory.CreateDirectory(uploadPath); diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs index 512b872..7df2b57 100644 --- a/Controllers/HomeController.cs +++ b/Controllers/HomeController.cs @@ -7,6 +7,7 @@ using static System.Net.Mime.MediaTypeNames; using System.Drawing; using System.Linq.Expressions; using Microsoft.Extensions.Logging; +using CarCareTracker.Helper; namespace CarCareTracker.Controllers { @@ -14,13 +15,13 @@ namespace CarCareTracker.Controllers { private readonly ILogger _logger; private readonly IVehicleDataAccess _dataAccess; - private readonly IWebHostEnvironment _webEnv; + private readonly IFileHelper _fileHelper; - public HomeController(ILogger logger, IVehicleDataAccess dataAccess, IWebHostEnvironment webEnv) + public HomeController(ILogger logger, IVehicleDataAccess dataAccess, IFileHelper fileHelper) { _logger = logger; _dataAccess = dataAccess; - _webEnv = webEnv; + _fileHelper = fileHelper; } public IActionResult Index() @@ -41,6 +42,8 @@ namespace CarCareTracker.Controllers { try { + //move image from temp folder to images folder. + vehicleInput.ImageLocation = _fileHelper.MoveFileFromTemp(vehicleInput.ImageLocation, "images/"); //save vehicle. var result = _dataAccess.SaveVehicle(vehicleInput); return Json(result); diff --git a/Controllers/VehicleController.cs b/Controllers/VehicleController.cs index 02e07b0..b875a98 100644 --- a/Controllers/VehicleController.cs +++ b/Controllers/VehicleController.cs @@ -8,6 +8,7 @@ using System.Drawing; using System.Linq.Expressions; using Microsoft.Extensions.Logging; using CarCareTracker.External.Implementations; +using CarCareTracker.Helper; namespace CarCareTracker.Controllers { @@ -18,12 +19,14 @@ namespace CarCareTracker.Controllers private readonly INoteDataAccess _noteDataAccess; private readonly IServiceRecordDataAccess _serviceRecordDataAccess; private readonly IWebHostEnvironment _webEnv; + private readonly IFileHelper _fileHelper; - public VehicleController(ILogger logger, IVehicleDataAccess dataAccess, INoteDataAccess noteDataAccess, IServiceRecordDataAccess serviceRecordDataAccess, IWebHostEnvironment webEnv) + public VehicleController(ILogger logger, IFileHelper fileHelper, IVehicleDataAccess dataAccess, INoteDataAccess noteDataAccess, IServiceRecordDataAccess serviceRecordDataAccess, IWebHostEnvironment webEnv) { _logger = logger; _dataAccess = dataAccess; _noteDataAccess = noteDataAccess; + _fileHelper = fileHelper; _serviceRecordDataAccess = serviceRecordDataAccess; _webEnv = webEnv; } @@ -70,6 +73,8 @@ namespace CarCareTracker.Controllers [HttpPost] public IActionResult SaveServiceRecordToVehicleId(ServiceRecordInput serviceRecord) { + //move files from temp. + serviceRecord.Files = serviceRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord()); return Json(result); } @@ -82,7 +87,6 @@ namespace CarCareTracker.Controllers public IActionResult GetServiceRecordForEditById(int serviceRecordId) { var result = _serviceRecordDataAccess.GetServiceRecordById(serviceRecordId); - //retrieve uploaded files. //convert to Input object. var convertedResult = new ServiceRecordInput { Id = result.Id, Cost = result.Cost, @@ -90,7 +94,8 @@ namespace CarCareTracker.Controllers Description = result.Description, Mileage = result.Mileage, Notes = result.Notes, - VehicleId = result.VehicleId + VehicleId = result.VehicleId, + Files = result.Files }; return PartialView("_ServiceRecordModal", convertedResult); } diff --git a/Helper/FileHelper.cs b/Helper/FileHelper.cs new file mode 100644 index 0000000..1e07e7e --- /dev/null +++ b/Helper/FileHelper.cs @@ -0,0 +1,57 @@ +namespace CarCareTracker.Helper +{ + public interface IFileHelper + { + public string MoveFileFromTemp(string currentFilePath, string newFolder); + public bool DeleteFile(string currentFilePath); + } + public class FileHelper: IFileHelper + { + private readonly IWebHostEnvironment _webEnv; + public FileHelper(IWebHostEnvironment webEnv) + { + _webEnv = webEnv; + } + public string MoveFileFromTemp(string currentFilePath, string newFolder) + { + string tempPath = "temp/"; + if (!currentFilePath.StartsWith("/temp/")) //file is not in temp directory. + { + return currentFilePath; + } + if (currentFilePath.StartsWith("/")) { + currentFilePath = currentFilePath.Substring(1); + } + string uploadPath = Path.Combine(_webEnv.WebRootPath, newFolder); + string oldFilePath = Path.Combine(_webEnv.WebRootPath, currentFilePath); + if (!Directory.Exists(uploadPath)) + Directory.CreateDirectory(uploadPath); + string newFileUploadPath = oldFilePath.Replace(tempPath, newFolder); + if (File.Exists(oldFilePath)) + { + File.Move(oldFilePath, newFileUploadPath); + } + string newFilePathToReturn = "/" + currentFilePath.Replace(tempPath, newFolder); + return newFilePathToReturn; + } + public bool DeleteFile(string currentFilePath) + { + if (currentFilePath.StartsWith("/")) + { + currentFilePath = currentFilePath.Substring(1); + } + string filePath = Path.Combine(_webEnv.WebRootPath, currentFilePath); + if (File.Exists(filePath)) + { + File.Delete(filePath); + } + if (!File.Exists(filePath)) //verify file no longer exists. + { + return true; + } else + { + return false; + } + } + } +} diff --git a/Models/ServiceRecord.cs b/Models/ServiceRecord.cs index 732f973..30867c6 100644 --- a/Models/ServiceRecord.cs +++ b/Models/ServiceRecord.cs @@ -9,5 +9,6 @@ public string Description { get; set; } public decimal Cost { get; set; } public string Notes { get; set; } + public List Files { get; set; } } } diff --git a/Models/ServiceRecordInput.cs b/Models/ServiceRecordInput.cs index 520d1c0..19d92c1 100644 --- a/Models/ServiceRecordInput.cs +++ b/Models/ServiceRecordInput.cs @@ -9,7 +9,7 @@ public string Description { get; set; } public decimal Cost { get; set; } public string Notes { get; set; } - public List Files { get; set; } = new List(); - public ServiceRecord ToServiceRecord() { return new ServiceRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Cost = Cost, Mileage = Mileage, Description = Description, Notes = Notes }; } + public List Files { get; set; } = new List(); + public ServiceRecord ToServiceRecord() { return new ServiceRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Cost = Cost, Mileage = Mileage, Description = Description, Notes = Notes, Files = Files }; } } } diff --git a/Models/UploadedFiles.cs b/Models/UploadedFiles.cs new file mode 100644 index 0000000..94810ba --- /dev/null +++ b/Models/UploadedFiles.cs @@ -0,0 +1,8 @@ +namespace CarCareTracker.Models +{ + public class UploadedFiles + { + public string Name { get; set; } + public string Location { get; set; } + } +} diff --git a/Program.cs b/Program.cs index e95a769..4baec00 100644 --- a/Program.cs +++ b/Program.cs @@ -1,5 +1,6 @@ using CarCareTracker.External.Implementations; using CarCareTracker.External.Interfaces; +using CarCareTracker.Helper; var builder = WebApplication.CreateBuilder(args); @@ -8,6 +9,7 @@ builder.Services.AddControllersWithViews(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); +builder.Services.AddSingleton(); var app = builder.Build(); diff --git a/Views/Vehicle/_ServiceRecordModal.cshtml b/Views/Vehicle/_ServiceRecordModal.cshtml index 2a06978..814205f 100644 --- a/Views/Vehicle/_ServiceRecordModal.cshtml +++ b/Views/Vehicle/_ServiceRecordModal.cshtml @@ -7,6 +7,7 @@
+
@@ -22,6 +23,26 @@
+ @if (Model.Files.Any()) + { +
+ + @foreach (UploadedFiles filesUploaded in Model.Files) + { + + } + + +
+ } + else + { + + + }
@@ -36,12 +57,25 @@ @if (Model.Id == 0) { - } else if (Model.Id > 0) + } + else if (Model.Id > 0) { }
\ No newline at end of file diff --git a/Views/Vehicle/_ServiceRecords.cshtml b/Views/Vehicle/_ServiceRecords.cshtml index 252cc32..0441cc4 100644 --- a/Views/Vehicle/_ServiceRecords.cshtml +++ b/Views/Vehicle/_ServiceRecords.cshtml @@ -1,6 +1,10 @@ @model List
-
+
+
+ @($"Total: {Model.Sum(x=>x.Cost).ToString("C")}") + @($"# of Service Records: {Model.Count()}") +
diff --git a/wwwroot/js/vehicle.js b/wwwroot/js/vehicle.js index 49691f8..0291877 100644 --- a/wwwroot/js/vehicle.js +++ b/wwwroot/js/vehicle.js @@ -81,6 +81,7 @@ function hideAddServiceRecordModal() { $('#serviceRecordModal').modal('hide'); } function deleteServiceRecord(serviceRecordId) { + $("#workAroundInput").show(); Swal.fire({ title: "Confirm Deletion?", text: "Deleted Service Records cannot be restored.", @@ -99,6 +100,8 @@ function deleteServiceRecord(serviceRecordId) { errorToast("An error has occurred, please try again later."); } }); + } else { + $("#workAroundInput").hide(); } }); } @@ -120,4 +123,24 @@ function saveServiceRecordToVehicle(isEdit) { errorToast("An error has occurred, please try again later."); } }) +} +function uploadServiceRecordFilesAsync() { + let formData = new FormData(); + var files = $("#serviceRecordFiles")[0].files; + for (var x = 0; x < files.length; x++) { + formData.append("file", files[x]); + } + $.ajax({ + url: "/Files/HandleMultipleFileUpload", + data: formData, + cache: false, + processData: false, + contentType: false, + type: 'POST', + success: function (response) { + if (response.length > 0) { + uploadedFiles.push.apply(uploadedFiles, response); + } + } + }); } \ No newline at end of file