added sfloader for file uploads.

This commit is contained in:
ivancheahhh
2024-01-03 14:37:04 -07:00
parent 193a2ab471
commit af75f1fe6b
14 changed files with 171 additions and 7 deletions

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@ wwwroot/images/
cartracker.db
wwwroot/documents/
wwwroot/temp/
wwwroot/imports/

View File

@@ -11,6 +11,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="30.0.1" />
<PackageReference Include="LiteDB" Version="5.0.17" />
</ItemGroup>

View File

@@ -9,6 +9,9 @@ using System.Linq.Expressions;
using Microsoft.Extensions.Logging;
using CarCareTracker.External.Implementations;
using CarCareTracker.Helper;
using CsvHelper;
using System.Globalization;
using System.Runtime.InteropServices;
namespace CarCareTracker.Controllers
{
@@ -157,6 +160,56 @@ namespace CarCareTracker.Controllers
}
return PartialView("_Gas", computedResults);
}
[HttpGet]
public IActionResult GetBulkImportModalPartialView(string mode)
{
return PartialView("_BulkDataImporter", mode);
}
[HttpPost]
public IActionResult ImportToVehicleIdFromCsv(int vehicleId, string mode, string fileName)
{
var fullFileName = _fileHelper.GetFullFilePath(fileName);
if (vehicleId == default || string.IsNullOrWhiteSpace(fullFileName))
{
return Json(false);
}
try
{
using (var reader = new StreamReader(fullFileName))
{
var config = new CsvHelper.Configuration.CsvConfiguration(System.Globalization.CultureInfo.InvariantCulture);
config.MissingFieldFound = null;
config.HeaderValidated = null;
using (var csv = new CsvReader(reader, config))
{
if (mode == "gas")
{
var records = csv.GetRecords<GasRecordImport>().ToList();
if (records.Any())
{
foreach (GasRecordImport gasRecordToInsert in records)
{
var convertedGasRecord = new GasRecord()
{
VehicleId = vehicleId,
Date = gasRecordToInsert.Date,
Mileage = gasRecordToInsert.Odometer,
Gallons = gasRecordToInsert.FuelConsumed,
Cost = gasRecordToInsert.Cost
};
_gasRecordDataAccess.SaveGasRecordToVehicle(convertedGasRecord);
}
}
}
}
}
return Json(true);
} catch (Exception ex)
{
_logger.LogError(ex, "Error Occurred While Bulk Inserting");
return Json(false);
}
}
[HttpPost]
public IActionResult SaveGasRecordToVehicleId(GasRecordInput gasRecord)
{

View File

@@ -13,7 +13,7 @@ namespace CarCareTracker.External.Implementations
using (var db = new LiteDatabase(dbName))
{
var table = db.GetCollection<GasRecord>(tableName);
var gasRecords = table.Find(Query.EQ(nameof(GasRecord.VehicleId), vehicleId)).OrderBy(x => x.Date);
var gasRecords = table.Find(Query.EQ(nameof(GasRecord.VehicleId), vehicleId)).OrderBy(x => x.Date).ThenBy(x=>x.Mileage);
return gasRecords.ToList() ?? new List<GasRecord>();
};
}

View File

@@ -2,6 +2,7 @@
{
public interface IFileHelper
{
string GetFullFilePath(string currentFilePath);
public string MoveFileFromTemp(string currentFilePath, string newFolder);
public bool DeleteFile(string currentFilePath);
}
@@ -12,6 +13,21 @@
{
_webEnv = webEnv;
}
public string GetFullFilePath(string currentFilePath)
{
if (currentFilePath.StartsWith("/"))
{
currentFilePath = currentFilePath.Substring(1);
}
string oldFilePath = Path.Combine(_webEnv.WebRootPath, currentFilePath);
if (File.Exists(oldFilePath))
{
return oldFilePath;
} else
{
return string.Empty;
}
}
public string MoveFileFromTemp(string currentFilePath, string newFolder)
{
string tempPath = "temp/";

View File

@@ -0,0 +1,10 @@
namespace CarCareTracker.Models
{
public class GasRecordImport
{
public DateTime Date { get; set; }
public int Odometer { get; set; }
public decimal FuelConsumed { get; set; }
public decimal Cost { get; set; }
}
}

View File

@@ -16,7 +16,7 @@
<button class="nav-link active" id="garage-tab" data-bs-toggle="tab" data-bs-target="#garage-tab-pane" type="button" role="tab" aria-selected="true"><i class="bi bi-car-front me-2"></i>Garage</button>
</li>
<li class="nav-item ms-auto" role="presentation">
<button class="nav-link" id="help-tab" data-bs-toggle="tab" data-bs-target="#help-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-gear me-2"></i>Help</button>
<button class="nav-link" id="help-tab" data-bs-toggle="tab" data-bs-target="#help-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-question-circle me-2"></i>Help</button>
</li>
</ul>
<div class="tab-content" id="homeTab">

View File

@@ -71,6 +71,12 @@
</div>
</div>
</div>
<div class="modal fade" id="bulkImportModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content" id="bulkImportModalContent">
</div>
</div>
</div>
<script>
function GetVehicleId() {
return { vehicleId: @Model.Id};

View File

@@ -0,0 +1,55 @@
@model string
<div class="modal-header">
<h5 class="modal-title">Import Data from CSV</h5>
<button type="button" class="btn-close" onclick="hideBulkImportModal()" aria-label="Close"></button>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<div class="form-group">
<div class="col-12">
<div class="alert alert-warning" role="alert">
In order for this utility to function properly, your CSV file MUST be formatted exactly like the provided sample.
Dates must be supplied in a string.
Numbers must be supplied as numbers without currency formatting.
</div>
<div class="alert alert-danger" role="alert">
Failure to format the data correctly can cause data corruption. Please make sure you make a copy of the local database before proceeding.
</div>
@if (Model == "gas")
{
<a class="btn btn-link" href="/defaults/gassample.csv" target="_blank">Download Sample</a>
}
</div>
</div>
<div class="row mt-2">
<div class="col-12">
<label for="csvFileUploader">Upload CSV File</label>
<input onChange="uploadFileAsync(this)" type="file" multiple accept=".csv" class="form-control-file" id="csvFileUploader">
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="hideBulkImportModal()">Cancel</button>
<button type="button" onclick="importFromCsv()" class="btn btn-primary">Import</button>
</div>
<script>
var uploadedFile = "";
function importFromCsv() {
var vehicleId = GetVehicleId().vehicleId;
var mode = "@Model";
$.post('/Vehicle/ImportToVehicleIdFromCsv', { vehicleId: vehicleId, mode: mode, fileName: uploadedFile }, function (data) {
if (data) {
successToast("Data Imported Successfully");
hideBulkImportModal();
if (mode == "gas") {
getVehicleGasRecords();
}
} else {
errorToast("An error has occurred, please double check the data and try again.");
}
});
}
</script>

View File

@@ -12,8 +12,14 @@
<span class="ms-2 badge bg-success">@($"Total Fuel Consumed: {Model.Sum(x=>x.Gallons)}")</span>
<span class="ms-2 badge bg-success">@($"Total Cost: {Model.Sum(x => x.Cost).ToString("C")}")</span>
</div>
<div>
<div class="btn-group">
<button onclick="showAddGasRecordModal()" class="btn btn-primary btn-md mt-1 mb-1"><i class="bi bi-pencil-square me-2"></i>Add Gas Record</button>
<button type="button" class="btn btn-md btn-primary btn-md mt-1 mb-1 dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="showBulkImportModal('gas')">Import via CSV</a></li>
</ul>
</div>
</div>
</div>

View File

@@ -22,11 +22,11 @@
@if (!string.IsNullOrWhiteSpace(Model.ImageLocation))
{
<label for="inputImage">Replace picture(optional)</label>
<input onChange="uploadFileAsync()" type="file" accept=".png,.jpg,.jpeg" class="form-control-file" id="inputImage">
<input onChange="uploadFileAsync(this)" type="file" accept=".png,.jpg,.jpeg" class="form-control-file" id="inputImage">
} else
{
<label for="inputImage">Upload a picture(optional)</label>
<input onChange="uploadFileAsync()" type="file" accept=".png,.jpg,.jpeg" class="form-control-file" id="inputImage">
<input onChange="uploadFileAsync(this)" type="file" accept=".png,.jpg,.jpeg" class="form-control-file" id="inputImage">
}
</div>
</form>

View File

@@ -0,0 +1,3 @@
Date,Odometer,FuelConsumed,Cost
5/8/2020,204836,8.331,16.24
5/30/2020,205056,11.913,25.72
1 Date Odometer FuelConsumed Cost
2 5/8/2020 204836 8.331 16.24
3 5/30/2020 205056 11.913 25.72

View File

@@ -90,9 +90,10 @@ function saveVehicle(isEdit) {
}
});
}
function uploadFileAsync() {
function uploadFileAsync(event) {
let formData = new FormData();
formData.append("file", $("#inputImage")[0].files[0]);
formData.append("file", event.files[0]);
sloader.show();
$.ajax({
url: "/Files/HandleFileUpload",
data: formData,
@@ -101,6 +102,7 @@ function uploadFileAsync() {
contentType: false,
type: 'POST',
success: function (response) {
sloader.hide();
if (response.trim() != '') {
uploadedFile = response;
}

View File

@@ -96,6 +96,17 @@ function editVehicle(vehicleId) {
function hideEditVehicleModal() {
$('#editVehicleModal').modal('hide');
}
function showBulkImportModal(mode) {
$.get(`/Vehicle/GetBulkImportModalPartialView?mode=${mode}`, function (data) {
if (data) {
$("#bulkImportModalContent").html(data);
$("#bulkImportModal").modal('show');
}
})
}
function hideBulkImportModal(){
$("#bulkImportModal").modal('hide');
}
function deleteVehicle(vehicleId) {
Swal.fire({
title: "Confirm Deletion?",