Added method to upload and delete documents from service records.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,3 +3,5 @@ bin/
|
||||
obj/
|
||||
wwwroot/images/
|
||||
cartracker.db
|
||||
wwwroot/documents/
|
||||
wwwroot/temp/
|
||||
|
||||
@@ -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<FilesController> _logger;
|
||||
private readonly IVehicleDataAccess _dataAccess;
|
||||
private readonly IWebHostEnvironment _webEnv;
|
||||
private readonly IFileHelper _fileHelper;
|
||||
|
||||
public FilesController(ILogger<FilesController> logger, IWebHostEnvironment webEnv)
|
||||
public FilesController(ILogger<FilesController> 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<IFormFile> file)
|
||||
{
|
||||
string uploadDirectory = "images/";
|
||||
List<UploadedFiles> uploadedFiles = new List<UploadedFiles>();
|
||||
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);
|
||||
|
||||
@@ -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<HomeController> _logger;
|
||||
private readonly IVehicleDataAccess _dataAccess;
|
||||
private readonly IWebHostEnvironment _webEnv;
|
||||
private readonly IFileHelper _fileHelper;
|
||||
|
||||
public HomeController(ILogger<HomeController> logger, IVehicleDataAccess dataAccess, IWebHostEnvironment webEnv)
|
||||
public HomeController(ILogger<HomeController> 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);
|
||||
|
||||
@@ -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<HomeController> logger, IVehicleDataAccess dataAccess, INoteDataAccess noteDataAccess, IServiceRecordDataAccess serviceRecordDataAccess, IWebHostEnvironment webEnv)
|
||||
public VehicleController(ILogger<HomeController> 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);
|
||||
}
|
||||
|
||||
57
Helper/FileHelper.cs
Normal file
57
Helper/FileHelper.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,5 +9,6 @@
|
||||
public string Description { get; set; }
|
||||
public decimal Cost { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public List<UploadedFiles> Files { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
public string Description { get; set; }
|
||||
public decimal Cost { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public List<string> Files { get; set; } = new List<string>();
|
||||
public ServiceRecord ToServiceRecord() { return new ServiceRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Cost = Cost, Mileage = Mileage, Description = Description, Notes = Notes }; }
|
||||
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
|
||||
public ServiceRecord ToServiceRecord() { return new ServiceRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Cost = Cost, Mileage = Mileage, Description = Description, Notes = Notes, Files = Files }; }
|
||||
}
|
||||
}
|
||||
|
||||
8
Models/UploadedFiles.cs
Normal file
8
Models/UploadedFiles.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class UploadedFiles
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Location { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -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<IVehicleDataAccess, VehicleDataAccess>();
|
||||
builder.Services.AddSingleton<INoteDataAccess, NoteDataAccess>();
|
||||
builder.Services.AddSingleton<IServiceRecordDataAccess, ServiceRecordDataAccess>();
|
||||
builder.Services.AddSingleton<IFileHelper, FileHelper>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12">
|
||||
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
|
||||
<label for="serviceRecordDate">Date</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="serviceRecordDate" class="form-control" value="@Model.Date">
|
||||
@@ -22,6 +23,26 @@
|
||||
<div class="col-md-6 col-12">
|
||||
<label for="serviceRecordNotes">Notes(optional)</label>
|
||||
<textarea id="serviceRecordNotes" class="form-control" rows="5">@Model.Notes</textarea>
|
||||
@if (Model.Files.Any())
|
||||
{
|
||||
<div>
|
||||
<label>Uploaded Documents</label>
|
||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||
{
|
||||
<div class="d-flex justify-content-between">
|
||||
<a type="button" class="btn btn-link" href="@filesUploaded.Location" target="_blank">@filesUploaded.Name</a>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger" onclick="deleteServiceRecordFile('@filesUploaded.Location', this)"><i class="bi bi-trash"></i></button>
|
||||
</div>
|
||||
}
|
||||
<label for="serviceRecordFiles">Upload more documents</label>
|
||||
<input onChange="uploadServiceRecordFilesAsync()" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="serviceRecordFiles">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<label for="serviceRecordFiles">Upload documents(optional)</label>
|
||||
<input onChange="uploadServiceRecordFilesAsync()" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="serviceRecordFiles">
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -36,12 +57,25 @@
|
||||
@if (Model.Id == 0)
|
||||
{
|
||||
<button type="button" id="addServiceRecordButton" class="btn btn-primary" onclick="saveServiceRecordToVehicle()">Add New Service Record</button>
|
||||
} else if (Model.Id > 0)
|
||||
}
|
||||
else if (Model.Id > 0)
|
||||
{
|
||||
<button type="button" id="editServiceRecordButton" class="btn btn-primary" onclick="saveServiceRecordToVehicle(true)">Edit Service Record</button>
|
||||
}
|
||||
</div>
|
||||
<script>
|
||||
var uploadedFiles = [];
|
||||
getUploadedFilesFromModel();
|
||||
function getUploadedFilesFromModel() {
|
||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||
{
|
||||
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
|
||||
}
|
||||
}
|
||||
function deleteServiceRecordFile(fileLocation, event) {
|
||||
event.parentElement.remove();
|
||||
uploadedFiles = uploadedFiles.filter(x => x.location != fileLocation);
|
||||
}
|
||||
function getAndValidateServiceRecordValues() {
|
||||
var serviceDate = $("#serviceRecordDate").val();
|
||||
var serviceMileage = $("#serviceRecordMileage").val();
|
||||
@@ -51,7 +85,7 @@
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
//validation
|
||||
var hasError = false;
|
||||
if (serviceDate.trim() == '' || !isDate(serviceDate)) { //eliminates whitespace.
|
||||
if (serviceDate.trim() == '') { //eliminates whitespace.
|
||||
hasError = true;
|
||||
$("#serviceRecordDate").addClass("is-invalid");
|
||||
} else {
|
||||
@@ -83,7 +117,8 @@
|
||||
mileage: serviceMileage,
|
||||
description: serviceDescription,
|
||||
cost: serviceCost,
|
||||
notes: serviceNotes
|
||||
notes: serviceNotes,
|
||||
files: uploadedFiles
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,6 +1,10 @@
|
||||
@model List<ServiceRecord>
|
||||
<div class="row">
|
||||
<div class="d-flex flex-row-reverse">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="badge bg-primary">@($"Total: {Model.Sum(x=>x.Cost).ToString("C")}")</span>
|
||||
<span class="ms-2 badge bg-success">@($"# of Service Records: {Model.Count()}")</span>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="showAddServiceRecordModal()" class="btn btn-primary btn-md mt-1 mb-1"><i class="bi bi-pencil-square"></i>Add Service Record</button>
|
||||
</div>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user