Added CSV Import and Export
This commit is contained in:
@@ -258,6 +258,32 @@ namespace CarCareTracker.Controllers
|
||||
return Json($"/{fileNameToExport}");
|
||||
}
|
||||
}
|
||||
else if (mode == ImportMode.PlanRecord)
|
||||
{
|
||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
||||
var vehicleRecords = _planRecordDataAccess.GetPlanRecordsByVehicleId(vehicleId);
|
||||
if (vehicleRecords.Any())
|
||||
{
|
||||
var exportData = vehicleRecords.Select(x => new PlanRecordExportModel {
|
||||
DateCreated = x.DateCreated.ToString("G"),
|
||||
DateModified = x.DateModified.ToString("G"),
|
||||
Description = x.Description,
|
||||
Cost = x.Cost.ToString("C"),
|
||||
Type = x.ImportMode.ToString(),
|
||||
Priority = x.Priority.ToString(),
|
||||
Progress = x.Progress.ToString(),
|
||||
Notes = x.Notes });
|
||||
using (var writer = new StreamWriter(fullExportFilePath))
|
||||
{
|
||||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||
{
|
||||
csv.WriteRecords(exportData);
|
||||
}
|
||||
}
|
||||
return Json($"/{fileNameToExport}");
|
||||
}
|
||||
}
|
||||
else if (mode == ImportMode.GasRecord)
|
||||
{
|
||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
||||
@@ -376,6 +402,25 @@ namespace CarCareTracker.Controllers
|
||||
};
|
||||
_serviceRecordDataAccess.SaveServiceRecordToVehicle(convertedRecord);
|
||||
}
|
||||
else if (mode == ImportMode.PlanRecord)
|
||||
{
|
||||
var progressIsEnum = Enum.TryParse(importModel.Progress, out PlanProgress parsedProgress);
|
||||
var typeIsEnum = Enum.TryParse(importModel.Type, out ImportMode parsedType);
|
||||
var priorityIsEnum = Enum.TryParse(importModel.Priority, out PlanPriority parsedPriority);
|
||||
var convertedRecord = new PlanRecord()
|
||||
{
|
||||
VehicleId = vehicleId,
|
||||
DateCreated = DateTime.Parse(importModel.DateCreated),
|
||||
DateModified = DateTime.Parse(importModel.DateModified),
|
||||
Progress = parsedProgress,
|
||||
ImportMode = parsedType,
|
||||
Priority = parsedPriority,
|
||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Plan Record on {importModel.DateCreated}" : importModel.Description,
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any)
|
||||
};
|
||||
_planRecordDataAccess.SavePlanRecordToVehicle(convertedRecord);
|
||||
}
|
||||
else if (mode == ImportMode.RepairRecord)
|
||||
{
|
||||
var convertedRecord = new CollisionRecord()
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
NoteRecord = 6,
|
||||
SupplyRecord = 7,
|
||||
Dashboard = 8,
|
||||
PlanRecord = 9
|
||||
PlanRecord = 9,
|
||||
OdometerRecord = 10
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace CarCareTracker.Helper
|
||||
var filesToUpload = Directory.GetFiles(imagePath);
|
||||
foreach(string file in filesToUpload)
|
||||
{
|
||||
File.Copy(file, $"{existingPath}/{Path.GetFileName(file)}");
|
||||
File.Copy(file, $"{existingPath}/{Path.GetFileName(file)}", true);
|
||||
}
|
||||
}
|
||||
if (Directory.Exists(documentPath))
|
||||
@@ -82,7 +82,7 @@ namespace CarCareTracker.Helper
|
||||
var filesToUpload = Directory.GetFiles(documentPath);
|
||||
foreach (string file in filesToUpload)
|
||||
{
|
||||
File.Copy(file, $"{existingPath}/{Path.GetFileName(file)}");
|
||||
File.Copy(file, $"{existingPath}/{Path.GetFileName(file)}", true);
|
||||
}
|
||||
}
|
||||
if (File.Exists(dataPath))
|
||||
|
||||
@@ -8,6 +8,8 @@ namespace CarCareTracker.MapProfile
|
||||
public ImportMapper()
|
||||
{
|
||||
Map(m => m.Date).Name(["date", "fuelup_date"]);
|
||||
Map(m => m.DateCreated).Name(["datecreated"]);
|
||||
Map(m => m.DateModified).Name(["datemodified"]);
|
||||
Map(m => m.Odometer).Name(["odometer"]);
|
||||
Map(m => m.FuelConsumed).Name(["gallons", "liters", "litres", "consumption", "quantity", "fuelconsumed"]);
|
||||
Map(m => m.Cost).Name(["cost", "total cost", "totalcost", "total price"]);
|
||||
@@ -20,6 +22,9 @@ namespace CarCareTracker.MapProfile
|
||||
Map(m => m.PartSupplier).Name(["partsupplier"]);
|
||||
Map(m => m.PartQuantity).Name(["partquantity"]);
|
||||
Map(m => m.PartNumber).Name(["partnumber"]);
|
||||
Map(m => m.Progress).Name(["progress"]);
|
||||
Map(m => m.Type).Name(["type"]);
|
||||
Map(m => m.Priority).Name(["priority"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
public class ImportModel
|
||||
{
|
||||
public string Date { get; set; }
|
||||
public string DateCreated { get; set; }
|
||||
public string DateModified { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Priority { get; set; }
|
||||
public string Progress { get; set; }
|
||||
public string Odometer { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Notes { get; set; }
|
||||
@@ -65,4 +70,16 @@
|
||||
public string Metric { get; set; }
|
||||
public string Notes { get; set; }
|
||||
}
|
||||
public class PlanRecordExportModel
|
||||
{
|
||||
public string DateCreated { get; set; }
|
||||
public string DateModified { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Priority { get; set; }
|
||||
public string Progress { get; set; }
|
||||
public string Cost { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,14 +50,14 @@
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" disabled class="form-check-input me-1" type="checkbox" value="Dashboard" id="dashboardTab" @(Model.VisibleTabs.Contains(ImportMode.Dashboard) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="dashboardTab">Dashboard</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="ServiceRecord" id="serviceRecordTab" @(Model.VisibleTabs.Contains(ImportMode.ServiceRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="serviceRecordTab">Service Records</label>
|
||||
</li>
|
||||
<li class="list-group-item d-none">
|
||||
<input onChange="updateSettings()" disabled class="form-check-input me-1" type="checkbox" value="Dashboard" id="dashboardTab" @(Model.VisibleTabs.Contains(ImportMode.Dashboard) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="dashboardTab">Dashboard</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="RepairRecord" id="repairRecordTab" @(Model.VisibleTabs.Contains(ImportMode.RepairRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="repairRecordTab">Repairs</label>
|
||||
@@ -70,6 +70,10 @@
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="GasRecord" id="gasRecordTab" @(Model.VisibleTabs.Contains(ImportMode.GasRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="gasRecordTab">Fuel</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="OdometerRecord" id="odometerRecordTab" @(Model.VisibleTabs.Contains(ImportMode.OdometerRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="odometerRecordTab">Odometer</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
@@ -111,6 +115,7 @@
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.ReminderRecord)) value="ReminderRecord">Reminders</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.SupplyRecord)) value="SupplyRecord">Supplies</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.PlanRecord)) value="PlanRecord">Planner</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.OdometerRecord)) value="OdometerRecord">Odometer</!option>
|
||||
</select>
|
||||
</div>
|
||||
@if (User.IsInRole(nameof(UserData.IsRootUser)))
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
} else if (Model == ImportMode.SupplyRecord)
|
||||
{
|
||||
<a class="btn btn-link" href="/defaults/supplysample.csv" target="_blank">Download Sample</a>
|
||||
} else if (Model == ImportMode.PlanRecord)
|
||||
{
|
||||
<a class="btn btn-link" href="/defaults/plansample.csv" target="_blank">Download Sample</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -67,6 +70,8 @@
|
||||
getVehicleUpgradeRecords(vehicleId);
|
||||
} else if (mode == "SupplyRecord") {
|
||||
getVehicleSupplyRecords(vehicleId);
|
||||
} else if (mode == "PlanRecord"){
|
||||
getVehiclePlanRecords(vehicleId);
|
||||
}
|
||||
} else {
|
||||
errorToast("An error has occurred, please double check the data and try again.");
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
@model PlanRecord
|
||||
<div class="taskCard user-select-none" draggable="true" ondragstart="dragStart(event, @Model.Id)" onclick="showEditPlanRecordModal(@Model.Id)">
|
||||
<div class="taskCard text-dark user-select-none mb-2" draggable="true" ondragstart="dragStart(event, @Model.Id)" onclick="showEditPlanRecordModal(@Model.Id)">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-8">
|
||||
<span class="taskCard-title text-truncate">@Model.Description</span>
|
||||
</div>
|
||||
<div class="col-12 col-lg-4 d-flex align-items-center">
|
||||
<span class="text-muted text-truncate">@Model.Cost.ToString("C2")</span>
|
||||
<span class="text-truncate">@Model.Cost.ToString("C2")</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<div class="col-3 d-flex flex-column swimlane mid" ondragover="dragOver(event)" ondrop="dropBox(event, 'Backlog')">
|
||||
<div class="row">
|
||||
<div class="col-12 d-flex justify-content-center" style="height:5vh;">
|
||||
<span class="lead">Planned</span>
|
||||
<span class="display-7">Planned</span>
|
||||
</div>
|
||||
</div>
|
||||
@foreach (PlanRecord planRecord in backLogItems)
|
||||
@@ -57,7 +57,7 @@
|
||||
<div class="col-3 d-flex flex-column swimlane mid" ondragover="dragOver(event)" ondrop="dropBox(event, 'InProgress')">
|
||||
<div class="row">
|
||||
<div class="col-12 d-flex justify-content-center" style="height:5vh;">
|
||||
<span class="lead">Doing</span>
|
||||
<span class="display-7">Doing</span>
|
||||
</div>
|
||||
</div>
|
||||
@foreach (PlanRecord planRecord in inProgressItems)
|
||||
@@ -68,7 +68,7 @@
|
||||
<div class="col-3 d-flex flex-column swimlane" ondragover="dragOver(event)" ondrop="dropBox(event, 'Testing')">
|
||||
<div class="row">
|
||||
<div class="col-12 d-flex justify-content-center" style="height:5vh;">
|
||||
<span class="lead">Testing</span>
|
||||
<span class="display-7">Testing</span>
|
||||
</div>
|
||||
</div>
|
||||
@foreach (PlanRecord planRecord in testingItems)
|
||||
@@ -79,7 +79,7 @@
|
||||
<div class="col-3 d-flex flex-column swimlane end" ondragover="dragOver(event)" ondrop="dropBox(event, 'Done')">
|
||||
<div class="row">
|
||||
<div class="col-12 d-flex justify-content-center" style="height:5vh;">
|
||||
<span class="lead">Done</span>
|
||||
<span class="display-7">Done</span>
|
||||
</div>
|
||||
</div>
|
||||
@foreach (PlanRecord planRecord in doneItems)
|
||||
|
||||
@@ -286,10 +286,8 @@ input[type="file"] {
|
||||
max-height:10vh;
|
||||
}
|
||||
[data-bs-theme=dark] .taskCard {
|
||||
color: #000;
|
||||
background-color: rgba(255,255,255,0.5);
|
||||
}
|
||||
[data-bs-theme=light] .taskCard {
|
||||
color: #000;
|
||||
background-color: rgba(80,80,80,0.25);
|
||||
}
|
||||
2
wwwroot/defaults/plansample.csv
Normal file
2
wwwroot/defaults/plansample.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
DateCreated,DateModified,Description,Notes,Type,Priority,Progress,Cost
|
||||
1/19/2024 6:01:02 PM,1/19/2024 7:32:58 PM,Repair Exhaust,,RepairRecord,Normal,Testing,$50.00
|
||||
|
Reference in New Issue
Block a user