mirror of
https://github.com/hargata/lubelog.git
synced 2025-12-10 00:46:08 -06:00
Merge pull request #1105 from hargata/Hargata/cost.data.fix
Version 1.5.4 Changes
This commit is contained in:
commit
3d33a798f1
@ -13,9 +13,9 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CsvHelper" Version="33.1.0" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.17" />
|
||||
<PackageReference Include="MailKit" Version="4.13.0" />
|
||||
<PackageReference Include="MailKit" Version="4.14.1" />
|
||||
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.14.0" />
|
||||
<PackageReference Include="Npgsql" Version="9.0.3" />
|
||||
<PackageReference Include="Npgsql" Version="9.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -24,6 +24,8 @@ namespace CarCareTracker.Controllers
|
||||
private readonly ISupplyRecordDataAccess _supplyRecordDataAccess;
|
||||
private readonly IPlanRecordDataAccess _planRecordDataAccess;
|
||||
private readonly IPlanRecordTemplateDataAccess _planRecordTemplateDataAccess;
|
||||
private readonly IInspectionRecordDataAccess _inspectionRecordDataAccess;
|
||||
private readonly IInspectionRecordTemplateDataAccess _inspectionRecordTemplateDataAccess;
|
||||
private readonly IUserAccessDataAccess _userAccessDataAccess;
|
||||
private readonly IUserRecordDataAccess _userRecordDataAccess;
|
||||
private readonly IReminderHelper _reminderHelper;
|
||||
@ -49,6 +51,8 @@ namespace CarCareTracker.Controllers
|
||||
ISupplyRecordDataAccess supplyRecordDataAccess,
|
||||
IPlanRecordDataAccess planRecordDataAccess,
|
||||
IPlanRecordTemplateDataAccess planRecordTemplateDataAccess,
|
||||
IInspectionRecordDataAccess inspectionRecordDataAccess,
|
||||
IInspectionRecordTemplateDataAccess inspectionRecordTemplateDataAccess,
|
||||
IUserAccessDataAccess userAccessDataAccess,
|
||||
IUserRecordDataAccess userRecordDataAccess,
|
||||
IMailHelper mailHelper,
|
||||
@ -71,6 +75,8 @@ namespace CarCareTracker.Controllers
|
||||
_supplyRecordDataAccess = supplyRecordDataAccess;
|
||||
_planRecordDataAccess = planRecordDataAccess;
|
||||
_planRecordTemplateDataAccess = planRecordTemplateDataAccess;
|
||||
_inspectionRecordDataAccess = inspectionRecordDataAccess;
|
||||
_inspectionRecordTemplateDataAccess = inspectionRecordTemplateDataAccess;
|
||||
_userAccessDataAccess = userAccessDataAccess;
|
||||
_userRecordDataAccess = userRecordDataAccess;
|
||||
_mailHelper = mailHelper;
|
||||
@ -533,7 +539,8 @@ namespace CarCareTracker.Controllers
|
||||
VehicleId = vehicleId,
|
||||
Date = DateTime.Parse(input.Date),
|
||||
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||
Mileage = int.Parse(input.Odometer)
|
||||
Mileage = int.Parse(input.Odometer),
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.ServiceRecord, serviceRecord.Id, serviceRecord.Description)
|
||||
};
|
||||
_odometerLogic.AutoInsertOdometerRecord(odometerRecord);
|
||||
}
|
||||
@ -728,7 +735,8 @@ namespace CarCareTracker.Controllers
|
||||
VehicleId = vehicleId,
|
||||
Date = DateTime.Parse(input.Date),
|
||||
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||
Mileage = int.Parse(input.Odometer)
|
||||
Mileage = int.Parse(input.Odometer),
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.RepairRecord, repairRecord.Id, repairRecord.Description)
|
||||
};
|
||||
_odometerLogic.AutoInsertOdometerRecord(odometerRecord);
|
||||
}
|
||||
@ -925,7 +933,8 @@ namespace CarCareTracker.Controllers
|
||||
VehicleId = vehicleId,
|
||||
Date = DateTime.Parse(input.Date),
|
||||
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||
Mileage = int.Parse(input.Odometer)
|
||||
Mileage = int.Parse(input.Odometer),
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.UpgradeRecord, upgradeRecord.Id, upgradeRecord.Description)
|
||||
};
|
||||
_odometerLogic.AutoInsertOdometerRecord(odometerRecord);
|
||||
}
|
||||
@ -1546,7 +1555,8 @@ namespace CarCareTracker.Controllers
|
||||
VehicleId = vehicleId,
|
||||
Date = DateTime.Parse(input.Date),
|
||||
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||
Mileage = int.Parse(input.Odometer)
|
||||
Mileage = int.Parse(input.Odometer),
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.GasRecord, gasRecord.Id, $"Gas Record - {gasRecord.Mileage.ToString()}")
|
||||
};
|
||||
_odometerLogic.AutoInsertOdometerRecord(odometerRecord);
|
||||
}
|
||||
@ -1652,7 +1662,7 @@ namespace CarCareTracker.Controllers
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
[HttpGet]
|
||||
[Route("/api/vehicle/reminders")]
|
||||
public IActionResult Reminders(int vehicleId, List<ReminderUrgency> urgencies)
|
||||
public IActionResult Reminders(int vehicleId, List<ReminderUrgency> urgencies, string tags)
|
||||
{
|
||||
if (vehicleId == default)
|
||||
{
|
||||
@ -1668,6 +1678,11 @@ namespace CarCareTracker.Controllers
|
||||
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
||||
var reminderResults = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, DateTime.Now);
|
||||
reminderResults.RemoveAll(x => !urgencies.Contains(x.Urgency));
|
||||
if (!string.IsNullOrWhiteSpace(tags))
|
||||
{
|
||||
var tagsFilter = tags.Split(' ').Distinct();
|
||||
reminderResults.RemoveAll(x => !x.Tags.Any(y => tagsFilter.Contains(y)));
|
||||
}
|
||||
var results = reminderResults.Select(x=> new ReminderAPIExportModel { Id = x.Id.ToString(), Description = x.Description, Urgency = x.Urgency.ToString(), Metric = x.Metric.ToString(), UserMetric = x.UserMetric.ToString(), Notes = x.Notes, DueDate = x.Date.ToShortDateString(), DueOdometer = x.Mileage.ToString(), DueDays = x.DueDays.ToString(), DueDistance = x.DueMileage.ToString(), Tags = string.Join(' ', x.Tags) });
|
||||
if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant"))
|
||||
{
|
||||
@ -1904,7 +1919,7 @@ namespace CarCareTracker.Controllers
|
||||
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||
[HttpGet]
|
||||
[Route("/api/vehicle/reminders/send")]
|
||||
public IActionResult SendReminders(List<ReminderUrgency> urgencies)
|
||||
public IActionResult SendReminders(List<ReminderUrgency> urgencies, string tags)
|
||||
{
|
||||
if (!urgencies.Any())
|
||||
{
|
||||
@ -1914,6 +1929,7 @@ namespace CarCareTracker.Controllers
|
||||
var vehicles = _dataAccess.GetVehicles();
|
||||
List<OperationResponse> operationResponses = new List<OperationResponse>();
|
||||
var defaultEmailAddress = _config.GetDefaultReminderEmail();
|
||||
List<string> tagsFilter = !string.IsNullOrWhiteSpace(tags) ? tags.Split(' ').Distinct().ToList() : new List<string>();
|
||||
foreach(Vehicle vehicle in vehicles)
|
||||
{
|
||||
var vehicleId = vehicle.Id;
|
||||
@ -1922,6 +1938,10 @@ namespace CarCareTracker.Controllers
|
||||
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
||||
var results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, DateTime.Now).OrderByDescending(x => x.Urgency).ToList();
|
||||
results.RemoveAll(x => !urgencies.Contains(x.Urgency));
|
||||
if (tagsFilter.Any())
|
||||
{
|
||||
results.RemoveAll(x => !x.Tags.Any(y => tagsFilter.Contains(y)));
|
||||
}
|
||||
if (!results.Any())
|
||||
{
|
||||
continue;
|
||||
@ -2004,6 +2024,8 @@ namespace CarCareTracker.Controllers
|
||||
vehicleDocuments.AddRange(_supplyRecordDataAccess.GetSupplyRecordsByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||
vehicleDocuments.AddRange(_planRecordDataAccess.GetPlanRecordsByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||
vehicleDocuments.AddRange(_planRecordTemplateDataAccess.GetPlanRecordTemplatesByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||
vehicleDocuments.AddRange(_inspectionRecordDataAccess.GetInspectionRecordsByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||
vehicleDocuments.AddRange(_inspectionRecordTemplateDataAccess.GetInspectionRecordTemplatesByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||
}
|
||||
//shop supplies
|
||||
vehicleDocuments.AddRange(_supplyRecordDataAccess.GetSupplyRecordsByVehicleId(0).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||
|
||||
@ -102,7 +102,7 @@ namespace CarCareTracker.Controllers
|
||||
string filePath = Path.Combine(uploadPath, fileName);
|
||||
string fileData = string.Join("\r\n", coordinates);
|
||||
System.IO.File.WriteAllText(filePath, fileData);
|
||||
var uploadedFile = new UploadedFiles { Name = "coordinates.csv", Location = Path.Combine("/", uploadDirectory, fileName) };
|
||||
var uploadedFile = new UploadedFiles { Name = "coordinates.csv", Location = Path.Combine("/", uploadDirectory, fileName), IsPending = true };
|
||||
return Json(uploadedFile);
|
||||
}
|
||||
public IActionResult PreviewFile(string fileName, string fileLocation)
|
||||
|
||||
@ -321,13 +321,13 @@ namespace CarCareTracker.Controllers
|
||||
[HttpPost]
|
||||
public IActionResult ExportTranslation(IFormFile file)
|
||||
{
|
||||
var translationData = new Dictionary<string, string>();
|
||||
var result = string.Empty;
|
||||
using (var sReader = new StreamReader(file.OpenReadStream()))
|
||||
{
|
||||
var fileName = $"{Guid.NewGuid()}.json";
|
||||
var sData = sReader.ReadToEnd();
|
||||
translationData = JsonSerializer.Deserialize<Dictionary<string, string>>(sData);
|
||||
result = _fileHelper.WriteFileToTemp(fileName, sData);
|
||||
}
|
||||
var result = _translationHelper.ExportTranslation(translationData);
|
||||
return Json(result);
|
||||
}
|
||||
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||
|
||||
@ -52,7 +52,9 @@ namespace CarCareTracker.Controllers
|
||||
"CREATE TABLE IF NOT EXISTS app.tokenrecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, body TEXT not null, emailaddress TEXT not null)",
|
||||
"CREATE TABLE IF NOT EXISTS app.userconfigrecords (id INT primary key, data jsonb not null)",
|
||||
"CREATE TABLE IF NOT EXISTS app.useraccessrecords (userId INT, vehicleId INT, PRIMARY KEY(userId, vehicleId))",
|
||||
"CREATE TABLE IF NOT EXISTS app.extrafields (id INT primary key, data jsonb not null)"
|
||||
"CREATE TABLE IF NOT EXISTS app.extrafields (id INT primary key, data jsonb not null)",
|
||||
"CREATE TABLE IF NOT EXISTS app.inspectionrecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
|
||||
"CREATE TABLE IF NOT EXISTS app.inspectionrecordtemplates (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)"
|
||||
};
|
||||
foreach(string cmd in cmds)
|
||||
{
|
||||
@ -99,6 +101,8 @@ namespace CarCareTracker.Controllers
|
||||
var useraccessrecords = new List<UserAccess>();
|
||||
|
||||
var extrafields = new List<RecordExtraField>();
|
||||
var inspectionrecords = new List<InspectionRecord>();
|
||||
var inspectionrecordtemplates = new List<InspectionRecordInput>();
|
||||
#region "Part1"
|
||||
string cmd = $"SELECT data FROM app.vehicles";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
@ -416,6 +420,41 @@ namespace CarCareTracker.Controllers
|
||||
table.Upsert(record);
|
||||
};
|
||||
}
|
||||
cmd = $"SELECT data FROM app.inspectionrecords";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
using (NpgsqlDataReader reader = ctext.ExecuteReader())
|
||||
while (reader.Read())
|
||||
{
|
||||
inspectionrecords.Add(JsonSerializer.Deserialize<InspectionRecord>(reader["data"] as string));
|
||||
}
|
||||
}
|
||||
foreach (var record in inspectionrecords)
|
||||
{
|
||||
using (var db = new LiteDatabase(fullFileName))
|
||||
{
|
||||
var table = db.GetCollection<InspectionRecord>("inspectionrecords");
|
||||
table.Upsert(record);
|
||||
}
|
||||
;
|
||||
}
|
||||
cmd = $"SELECT data FROM app.inspectionrecordtemplates";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
using (NpgsqlDataReader reader = ctext.ExecuteReader())
|
||||
while (reader.Read())
|
||||
{
|
||||
inspectionrecordtemplates.Add(JsonSerializer.Deserialize<InspectionRecordInput>(reader["data"] as string));
|
||||
}
|
||||
}
|
||||
foreach (var record in inspectionrecordtemplates)
|
||||
{
|
||||
using (var db = new LiteDatabase(fullFileName))
|
||||
{
|
||||
var table = db.GetCollection<InspectionRecordInput>("inspectionrecordtemplates");
|
||||
table.Upsert(record);
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
var destFilePath = $"{fullFolderPath}.zip";
|
||||
ZipFile.CreateFromDirectory(fullFolderPath, destFilePath);
|
||||
@ -464,6 +503,8 @@ namespace CarCareTracker.Controllers
|
||||
var useraccessrecords = new List<UserAccess>();
|
||||
|
||||
var extrafields = new List<RecordExtraField>();
|
||||
var inspectionrecords = new List<InspectionRecord>();
|
||||
var inspectionrecordtemplates = new List<InspectionRecordInput>();
|
||||
#region "Part1"
|
||||
using (var db = new LiteDatabase(fullFileName))
|
||||
{
|
||||
@ -743,6 +784,38 @@ namespace CarCareTracker.Controllers
|
||||
ctext.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
using (var db = new LiteDatabase(fullFileName))
|
||||
{
|
||||
var table = db.GetCollection<InspectionRecord>("inspectionrecords");
|
||||
inspectionrecords = table.FindAll().ToList();
|
||||
};
|
||||
foreach (var record in inspectionrecords)
|
||||
{
|
||||
string cmd = $"INSERT INTO app.inspectionrecords (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.inspectionrecords_id_seq', (SELECT MAX(id) from app.inspectionrecords));";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("id", record.Id);
|
||||
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
|
||||
ctext.Parameters.AddWithValue("data", JsonSerializer.Serialize(record));
|
||||
ctext.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
using (var db = new LiteDatabase(fullFileName))
|
||||
{
|
||||
var table = db.GetCollection<InspectionRecordInput>("inspectionrecordtemplates");
|
||||
inspectionrecordtemplates = table.FindAll().ToList();
|
||||
};
|
||||
foreach (var record in inspectionrecordtemplates)
|
||||
{
|
||||
string cmd = $"INSERT INTO app.inspectionrecordtemplates (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.inspectionrecordtemplates_id_seq', (SELECT MAX(id) from app.inspectionrecordtemplates));";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("id", record.Id);
|
||||
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
|
||||
ctext.Parameters.AddWithValue("data", JsonSerializer.Serialize(record));
|
||||
ctext.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
return Json(OperationResponse.Succeed("Data Imported Successfully"));
|
||||
}
|
||||
|
||||
@ -40,22 +40,24 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
return Json(false);
|
||||
}
|
||||
if (gasRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
gasRecord.Files = gasRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||
var convertedRecord = gasRecord.ToGasRecord();
|
||||
var result = _gasRecordDataAccess.SaveGasRecordToVehicle(convertedRecord);
|
||||
if (result)
|
||||
{
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromGasRecord(convertedRecord, gasRecord.Id == default ? "gasrecord.add" : "gasrecord.update", User.Identity.Name));
|
||||
}
|
||||
if (convertedRecord.Id != default && gasRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
{
|
||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||
{
|
||||
Date = DateTime.Parse(gasRecord.Date),
|
||||
VehicleId = gasRecord.VehicleId,
|
||||
Mileage = gasRecord.Mileage,
|
||||
Notes = $"Auto Insert From Gas Record. {gasRecord.Notes}"
|
||||
Notes = $"Auto Insert From Gas Record. {gasRecord.Notes}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.GasRecord, convertedRecord.Id, $"Gas Record - {gasRecord.Mileage.ToString()}")
|
||||
});
|
||||
}
|
||||
gasRecord.Files = gasRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||
var result = _gasRecordDataAccess.SaveGasRecordToVehicle(gasRecord.ToGasRecord());
|
||||
if (result)
|
||||
{
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromGasRecord(gasRecord.ToGasRecord(), gasRecord.Id == default ? "gasrecord.add" : "gasrecord.update", User.Identity.Name));
|
||||
}
|
||||
return Json(result);
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
|
||||
@ -505,7 +505,8 @@ namespace CarCareTracker.Controllers
|
||||
Date = convertedRecord.Date,
|
||||
VehicleId = convertedRecord.VehicleId,
|
||||
Mileage = convertedRecord.Mileage,
|
||||
Notes = $"Auto Insert From Gas Record via CSV Import. {convertedRecord.Notes}"
|
||||
Notes = $"Auto Insert From Gas Record via CSV Import. {convertedRecord.Notes}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.GasRecord, convertedRecord.Id, $"Gas Record - {convertedRecord.Mileage.ToString()}")
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -531,7 +532,8 @@ namespace CarCareTracker.Controllers
|
||||
Date = convertedRecord.Date,
|
||||
VehicleId = convertedRecord.VehicleId,
|
||||
Mileage = convertedRecord.Mileage,
|
||||
Notes = $"Auto Insert From Service Record via CSV Import. {convertedRecord.Notes}"
|
||||
Notes = $"Auto Insert From Service Record via CSV Import. {convertedRecord.Notes}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.ServiceRecord, convertedRecord.Id, convertedRecord.Description)
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -590,7 +592,8 @@ namespace CarCareTracker.Controllers
|
||||
Date = convertedRecord.Date,
|
||||
VehicleId = convertedRecord.VehicleId,
|
||||
Mileage = convertedRecord.Mileage,
|
||||
Notes = $"Auto Insert From Repair Record via CSV Import. {convertedRecord.Notes}"
|
||||
Notes = $"Auto Insert From Repair Record via CSV Import. {convertedRecord.Notes}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.RepairRecord, convertedRecord.Id, convertedRecord.Description)
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -615,7 +618,8 @@ namespace CarCareTracker.Controllers
|
||||
Date = convertedRecord.Date,
|
||||
VehicleId = convertedRecord.VehicleId,
|
||||
Mileage = convertedRecord.Mileage,
|
||||
Notes = $"Auto Insert From Upgrade Record via CSV Import. {convertedRecord.Notes}"
|
||||
Notes = $"Auto Insert From Upgrade Record via CSV Import. {convertedRecord.Notes}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.UpgradeRecord, convertedRecord.Id, convertedRecord.Description)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
230
Controllers/Vehicle/InspectionController.cs
Normal file
230
Controllers/Vehicle/InspectionController.cs
Normal file
@ -0,0 +1,230 @@
|
||||
using CarCareTracker.Filter;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace CarCareTracker.Controllers
|
||||
{
|
||||
public partial class VehicleController
|
||||
{
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
[HttpGet]
|
||||
public IActionResult GetInspectionRecordTemplatesByVehicleId(int vehicleId)
|
||||
{
|
||||
var result = _inspectionRecordTemplateDataAccess.GetInspectionRecordTemplatesByVehicleId(vehicleId);
|
||||
return PartialView("Inspection/_InspectionRecordTemplateSelector", result);
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
[HttpGet]
|
||||
public IActionResult GetInspectionRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
var result = _inspectionRecordDataAccess.GetInspectionRecordsByVehicleId(vehicleId);
|
||||
bool _useDescending = _config.GetUserConfig(User).UseDescending;
|
||||
if (_useDescending)
|
||||
{
|
||||
result = result.OrderByDescending(x => x.Date).ThenByDescending(x => x.Mileage).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = result.OrderBy(x => x.Date).ThenBy(x => x.Mileage).ToList();
|
||||
}
|
||||
return PartialView("Inspection/_InspectionRecords", result);
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetAddInspectionRecordTemplatePartialView()
|
||||
{
|
||||
return PartialView("Inspection/_InspectionRecordTemplateEditModal", new InspectionRecordInput());
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetEditInspectionRecordTemplatePartialView(int inspectionRecordTemplateId)
|
||||
{
|
||||
var result = _inspectionRecordTemplateDataAccess.GetInspectionRecordTemplateById(inspectionRecordTemplateId);
|
||||
//security check.
|
||||
if (!_userLogic.UserCanEditVehicle(GetUserID(), result.VehicleId))
|
||||
{
|
||||
return Redirect("/Error/Unauthorized");
|
||||
}
|
||||
return PartialView("Inspection/_InspectionRecordTemplateEditModal", result);
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetAddInspectionRecordFieldPartialView()
|
||||
{
|
||||
return PartialView("Inspection/_InspectionRecordField", new InspectionRecordTemplateField());
|
||||
}
|
||||
public IActionResult GetAddInspectionRecordFieldOptionsPartialView()
|
||||
{
|
||||
return PartialView("Inspection/_InspectionRecordFieldOptions", new List<InspectionRecordTemplateFieldOption>());
|
||||
}
|
||||
public IActionResult GetAddInspectionRecordFieldOptionPartialView()
|
||||
{
|
||||
return PartialView("Inspection/_InspectionRecordFieldOption", new InspectionRecordTemplateFieldOption());
|
||||
}
|
||||
[HttpPost]
|
||||
public IActionResult SaveInspectionRecordTemplateToVehicleId(InspectionRecordInput inspectionRecordTemplate)
|
||||
{
|
||||
//security check.
|
||||
if (!_userLogic.UserCanEditVehicle(GetUserID(), inspectionRecordTemplate.VehicleId))
|
||||
{
|
||||
return Json(false);
|
||||
}
|
||||
var result = _inspectionRecordTemplateDataAccess.SaveInspectionReportTemplateToVehicle(inspectionRecordTemplate);
|
||||
return Json(result);
|
||||
}
|
||||
private bool DeleteInspectionRecordTemplateWithChecks(int inspectionRecordTemplateId)
|
||||
{
|
||||
var existingRecord = _inspectionRecordTemplateDataAccess.GetInspectionRecordTemplateById(inspectionRecordTemplateId);
|
||||
//security check.
|
||||
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var result = _inspectionRecordTemplateDataAccess.DeleteInspectionRecordTemplateById(existingRecord.Id);
|
||||
return result;
|
||||
}
|
||||
private bool DeleteInspectionRecordWithChecks(int inspectionRecordId)
|
||||
{
|
||||
var existingRecord = _inspectionRecordDataAccess.GetInspectionRecordById(inspectionRecordId);
|
||||
//security check.
|
||||
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var result = _inspectionRecordDataAccess.DeleteInspectionRecordById(existingRecord.Id);
|
||||
if (result)
|
||||
{
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromInspectionRecord(existingRecord, "inspectionrecord.delete", User.Identity.Name));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
[HttpPost]
|
||||
public IActionResult DeleteInspectionRecordTemplateById(int inspectionRecordTemplateId)
|
||||
{
|
||||
var result = DeleteInspectionRecordTemplateWithChecks(inspectionRecordTemplateId);
|
||||
return Json(result);
|
||||
}
|
||||
[HttpPost]
|
||||
public IActionResult DeleteInspectionRecordById(int inspectionRecordId)
|
||||
{
|
||||
var result = DeleteInspectionRecordWithChecks(inspectionRecordId);
|
||||
return Json(result);
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetAddInspectionRecordPartialView(int inspectionRecordTemplateId)
|
||||
{
|
||||
var result = _inspectionRecordTemplateDataAccess.GetInspectionRecordTemplateById(inspectionRecordTemplateId);
|
||||
//security check.
|
||||
if (!_userLogic.UserCanEditVehicle(GetUserID(), result.VehicleId))
|
||||
{
|
||||
return Redirect("/Error/Unauthorized");
|
||||
}
|
||||
//populate date
|
||||
result.Date = DateTime.Now.ToShortDateString();
|
||||
return PartialView("Inspection/_InspectionRecordModal", result);
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetViewInspectionRecordPartialView(int inspectionRecordId)
|
||||
{
|
||||
var result = _inspectionRecordDataAccess.GetInspectionRecordById(inspectionRecordId);
|
||||
//security check.
|
||||
if (!_userLogic.UserCanEditVehicle(GetUserID(), result.VehicleId))
|
||||
{
|
||||
return Redirect("/Error/Unauthorized");
|
||||
}
|
||||
return PartialView("Inspection/_InspectionRecordViewModal", result);
|
||||
}
|
||||
[HttpPost]
|
||||
public IActionResult SaveInspectionRecordToVehicleId(InspectionRecordInput inspectionRecord)
|
||||
{
|
||||
//security check.
|
||||
if (!_userLogic.UserCanEditVehicle(GetUserID(), inspectionRecord.VehicleId))
|
||||
{
|
||||
return Json(false);
|
||||
}
|
||||
//move files from temp.
|
||||
inspectionRecord.Files = inspectionRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||
//push back any reminders
|
||||
if (inspectionRecord.ReminderRecordId.Any())
|
||||
{
|
||||
foreach (int reminderRecordId in inspectionRecord.ReminderRecordId)
|
||||
{
|
||||
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(inspectionRecord.Date), inspectionRecord.Mileage);
|
||||
}
|
||||
}
|
||||
var convertedRecord = inspectionRecord.ToInspectionRecord();
|
||||
var result = _inspectionRecordDataAccess.SaveInspectionRecordToVehicle(convertedRecord);
|
||||
if (result)
|
||||
{
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromInspectionRecord(convertedRecord, "inspectionrecord.add", User.Identity.Name));
|
||||
}
|
||||
if (convertedRecord.Id != 0)
|
||||
{
|
||||
//insert into service record
|
||||
List<UploadedFiles> newAttachments = new List<UploadedFiles>();
|
||||
newAttachments.Add(new UploadedFiles { Name = inspectionRecord.Description, Location = StaticHelper.GetRecordAttachment(ImportMode.InspectionRecord, convertedRecord.Id)});
|
||||
newAttachments.AddRange(inspectionRecord.Files);
|
||||
_serviceRecordDataAccess.SaveServiceRecordToVehicle(new ServiceRecord
|
||||
{
|
||||
Date = DateTime.Parse(inspectionRecord.Date),
|
||||
VehicleId = inspectionRecord.VehicleId,
|
||||
Mileage = inspectionRecord.Mileage,
|
||||
Description = inspectionRecord.Description,
|
||||
Cost = inspectionRecord.Cost,
|
||||
Notes = $"Auto Insert From Inspection Record: {inspectionRecord.Description}",
|
||||
Files = newAttachments
|
||||
});
|
||||
//auto-insert into odometer if configured
|
||||
if (inspectionRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
{
|
||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||
{
|
||||
Date = DateTime.Parse(inspectionRecord.Date),
|
||||
VehicleId = inspectionRecord.VehicleId,
|
||||
Mileage = inspectionRecord.Mileage,
|
||||
Notes = $"Auto Insert From Inspection Record: {inspectionRecord.Description}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.InspectionRecord, convertedRecord.Id, convertedRecord.Description)
|
||||
});
|
||||
}
|
||||
//create action items
|
||||
var inspectionFieldsWithActionItems = inspectionRecord.Fields.Where(x => x.HasActionItem);
|
||||
if (inspectionFieldsWithActionItems.Any())
|
||||
{
|
||||
foreach (InspectionRecordTemplateField inspectionField in inspectionFieldsWithActionItems)
|
||||
{
|
||||
if (inspectionField.ToInspectionRecordResult().Failed)
|
||||
{
|
||||
_planRecordDataAccess.SavePlanRecordToVehicle(new PlanRecord
|
||||
{
|
||||
DateCreated = DateTime.Now,
|
||||
DateModified = DateTime.Now,
|
||||
VehicleId = inspectionRecord.VehicleId,
|
||||
Description = inspectionField.ActionItemDescription,
|
||||
ImportMode = inspectionField.ActionItemType,
|
||||
Priority = inspectionField.ActionItemPriority,
|
||||
Notes = $"Auto Insert From Inspection Record: {inspectionRecord.Description}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.InspectionRecord, convertedRecord.Id, convertedRecord.Description)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Json(result);
|
||||
}
|
||||
[HttpPost]
|
||||
public IActionResult UpdateInspectionRecordTags(int inspectionRecordId, List<string> tags)
|
||||
{
|
||||
var existingRecord = _inspectionRecordDataAccess.GetInspectionRecordById(inspectionRecordId);
|
||||
//security check.
|
||||
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId))
|
||||
{
|
||||
return Json(false);
|
||||
}
|
||||
existingRecord.Tags = tags;
|
||||
var result = _inspectionRecordDataAccess.SaveInspectionRecordToVehicle(existingRecord);
|
||||
if (result)
|
||||
{
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromInspectionRecord(existingRecord, "inspectionrecord.update", User.Identity.Name));
|
||||
}
|
||||
return Json(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -46,10 +46,11 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
//move files from temp.
|
||||
odometerRecord.Files = odometerRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||
var result = _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord.ToOdometerRecord());
|
||||
var convertedRecord = odometerRecord.ToOdometerRecord();
|
||||
var result = _odometerRecordDataAccess.SaveOdometerRecordToVehicle(convertedRecord);
|
||||
if (result)
|
||||
{
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromOdometerRecord(odometerRecord.ToOdometerRecord(), odometerRecord.Id == default ? "odometerrecord.add" : "odometerrecord.update", User.Identity.Name));
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromOdometerRecord(convertedRecord, odometerRecord.Id == default ? "odometerrecord.add" : "odometerrecord.update", User.Identity.Name));
|
||||
}
|
||||
return Json(result);
|
||||
}
|
||||
|
||||
@ -196,17 +196,7 @@ namespace CarCareTracker.Controllers
|
||||
var result = _planRecordDataAccess.SavePlanRecordToVehicle(existingRecord);
|
||||
if (planProgress == PlanProgress.Done)
|
||||
{
|
||||
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
{
|
||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||
{
|
||||
Date = DateTime.Now.Date,
|
||||
VehicleId = existingRecord.VehicleId,
|
||||
Mileage = odometer,
|
||||
Notes = $"Auto Insert From Plan Record: {existingRecord.Description}",
|
||||
ExtraFields = existingRecord.ExtraFields
|
||||
});
|
||||
}
|
||||
int newRecordId = 0;
|
||||
//convert plan record to service/upgrade/repair record.
|
||||
if (existingRecord.ImportMode == ImportMode.ServiceRecord)
|
||||
{
|
||||
@ -223,6 +213,7 @@ namespace CarCareTracker.Controllers
|
||||
ExtraFields = existingRecord.ExtraFields
|
||||
};
|
||||
_serviceRecordDataAccess.SaveServiceRecordToVehicle(newRecord);
|
||||
newRecordId = newRecord.Id;
|
||||
}
|
||||
else if (existingRecord.ImportMode == ImportMode.RepairRecord)
|
||||
{
|
||||
@ -239,6 +230,7 @@ namespace CarCareTracker.Controllers
|
||||
ExtraFields = existingRecord.ExtraFields
|
||||
};
|
||||
_collisionRecordDataAccess.SaveCollisionRecordToVehicle(newRecord);
|
||||
newRecordId = newRecord.Id;
|
||||
}
|
||||
else if (existingRecord.ImportMode == ImportMode.UpgradeRecord)
|
||||
{
|
||||
@ -255,6 +247,19 @@ namespace CarCareTracker.Controllers
|
||||
ExtraFields = existingRecord.ExtraFields
|
||||
};
|
||||
_upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(newRecord);
|
||||
newRecordId = newRecord.Id;
|
||||
}
|
||||
if (newRecordId != default && _config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
{
|
||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||
{
|
||||
Date = DateTime.Now.Date,
|
||||
VehicleId = existingRecord.VehicleId,
|
||||
Mileage = odometer,
|
||||
Notes = $"Auto Insert From Plan Record: {existingRecord.Description}",
|
||||
ExtraFields = existingRecord.ExtraFields,
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(existingRecord.ImportMode, newRecordId, existingRecord.Description)
|
||||
});
|
||||
}
|
||||
//push back any reminders
|
||||
if (existingRecord.ReminderRecordId != default)
|
||||
|
||||
@ -82,6 +82,11 @@ namespace CarCareTracker.Controllers
|
||||
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecordId);
|
||||
if (existingReminder is not null && existingReminder.Id != default && existingReminder.IsRecurring)
|
||||
{
|
||||
//security check
|
||||
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingReminder.VehicleId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder, currentDate, currentMileage);
|
||||
//save to db.
|
||||
var reminderUpdateResult = _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
|
||||
|
||||
@ -31,16 +31,6 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
return Json(false);
|
||||
}
|
||||
if (collisionRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
{
|
||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||
{
|
||||
Date = DateTime.Parse(collisionRecord.Date),
|
||||
VehicleId = collisionRecord.VehicleId,
|
||||
Mileage = collisionRecord.Mileage,
|
||||
Notes = $"Auto Insert From Repair Record: {collisionRecord.Description}"
|
||||
});
|
||||
}
|
||||
//move files from temp.
|
||||
collisionRecord.Files = collisionRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||
if (collisionRecord.Supplies.Any())
|
||||
@ -63,10 +53,22 @@ namespace CarCareTracker.Controllers
|
||||
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(collisionRecord.Date), collisionRecord.Mileage);
|
||||
}
|
||||
}
|
||||
var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord());
|
||||
var convertedRecord = collisionRecord.ToCollisionRecord();
|
||||
var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(convertedRecord);
|
||||
if (result)
|
||||
{
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromGenericRecord(collisionRecord.ToCollisionRecord(), collisionRecord.Id == default ? "repairrecord.add" : "repairrecord.update", User.Identity.Name));
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromGenericRecord(convertedRecord, collisionRecord.Id == default ? "repairrecord.add" : "repairrecord.update", User.Identity.Name));
|
||||
}
|
||||
if (convertedRecord.Id != default && collisionRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
{
|
||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||
{
|
||||
Date = DateTime.Parse(collisionRecord.Date),
|
||||
VehicleId = collisionRecord.VehicleId,
|
||||
Mileage = collisionRecord.Mileage,
|
||||
Notes = $"Auto Insert From Repair Record: {collisionRecord.Description}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.RepairRecord, convertedRecord.Id, convertedRecord.Description)
|
||||
});
|
||||
}
|
||||
return Json(result);
|
||||
}
|
||||
|
||||
@ -31,16 +31,6 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
return Json(false);
|
||||
}
|
||||
if (serviceRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
{
|
||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||
{
|
||||
Date = DateTime.Parse(serviceRecord.Date),
|
||||
VehicleId = serviceRecord.VehicleId,
|
||||
Mileage = serviceRecord.Mileage,
|
||||
Notes = $"Auto Insert From Service Record: {serviceRecord.Description}"
|
||||
});
|
||||
}
|
||||
//move files from temp.
|
||||
serviceRecord.Files = serviceRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||
if (serviceRecord.Supplies.Any())
|
||||
@ -63,10 +53,22 @@ namespace CarCareTracker.Controllers
|
||||
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(serviceRecord.Date), serviceRecord.Mileage);
|
||||
}
|
||||
}
|
||||
var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord());
|
||||
var convertedRecord = serviceRecord.ToServiceRecord();
|
||||
var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(convertedRecord);
|
||||
if (result)
|
||||
{
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromGenericRecord(serviceRecord.ToServiceRecord(), serviceRecord.Id == default ? "servicerecord.add" : "servicerecord.update", User.Identity.Name));
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromGenericRecord(convertedRecord, serviceRecord.Id == default ? "servicerecord.add" : "servicerecord.update", User.Identity.Name));
|
||||
}
|
||||
if (convertedRecord.Id != default && serviceRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
{
|
||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||
{
|
||||
Date = DateTime.Parse(serviceRecord.Date),
|
||||
VehicleId = serviceRecord.VehicleId,
|
||||
Mileage = serviceRecord.Mileage,
|
||||
Notes = $"Auto Insert From Service Record: {serviceRecord.Description}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.ServiceRecord, convertedRecord.Id, convertedRecord.Description)
|
||||
});
|
||||
}
|
||||
return Json(result);
|
||||
}
|
||||
|
||||
@ -31,16 +31,6 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
return Json(false);
|
||||
}
|
||||
if (upgradeRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
{
|
||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||
{
|
||||
Date = DateTime.Parse(upgradeRecord.Date),
|
||||
VehicleId = upgradeRecord.VehicleId,
|
||||
Mileage = upgradeRecord.Mileage,
|
||||
Notes = $"Auto Insert From Upgrade Record: {upgradeRecord.Description}"
|
||||
});
|
||||
}
|
||||
//move files from temp.
|
||||
upgradeRecord.Files = upgradeRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||
if (upgradeRecord.Supplies.Any())
|
||||
@ -63,10 +53,22 @@ namespace CarCareTracker.Controllers
|
||||
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(upgradeRecord.Date), upgradeRecord.Mileage);
|
||||
}
|
||||
}
|
||||
var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord.ToUpgradeRecord());
|
||||
var convertedRecord = upgradeRecord.ToUpgradeRecord();
|
||||
var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(convertedRecord);
|
||||
if (result)
|
||||
{
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromGenericRecord(upgradeRecord.ToUpgradeRecord(), upgradeRecord.Id == default ? "upgraderecord.add" : "upgraderecord.update", User.Identity.Name));
|
||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromGenericRecord(convertedRecord, upgradeRecord.Id == default ? "upgraderecord.add" : "upgraderecord.update", User.Identity.Name));
|
||||
}
|
||||
if (convertedRecord != default && upgradeRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
{
|
||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||
{
|
||||
Date = DateTime.Parse(upgradeRecord.Date),
|
||||
VehicleId = upgradeRecord.VehicleId,
|
||||
Mileage = upgradeRecord.Mileage,
|
||||
Notes = $"Auto Insert From Upgrade Record: {upgradeRecord.Description}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(ImportMode.UpgradeRecord, convertedRecord.Id, convertedRecord.Description)
|
||||
});
|
||||
}
|
||||
return Json(result);
|
||||
}
|
||||
|
||||
@ -27,6 +27,8 @@ namespace CarCareTracker.Controllers
|
||||
private readonly IPlanRecordDataAccess _planRecordDataAccess;
|
||||
private readonly IPlanRecordTemplateDataAccess _planRecordTemplateDataAccess;
|
||||
private readonly IOdometerRecordDataAccess _odometerRecordDataAccess;
|
||||
private readonly IInspectionRecordDataAccess _inspectionRecordDataAccess;
|
||||
private readonly IInspectionRecordTemplateDataAccess _inspectionRecordTemplateDataAccess;
|
||||
private readonly IWebHostEnvironment _webEnv;
|
||||
private readonly IConfigHelper _config;
|
||||
private readonly IFileHelper _fileHelper;
|
||||
@ -60,7 +62,9 @@ namespace CarCareTracker.Controllers
|
||||
IOdometerLogic odometerLogic,
|
||||
IVehicleLogic vehicleLogic,
|
||||
IWebHostEnvironment webEnv,
|
||||
IConfigHelper config)
|
||||
IConfigHelper config,
|
||||
IInspectionRecordDataAccess inspectionRecordDataAccess,
|
||||
IInspectionRecordTemplateDataAccess inspectionRecordTemplateDataAccess)
|
||||
{
|
||||
_logger = logger;
|
||||
_dataAccess = dataAccess;
|
||||
@ -78,6 +82,8 @@ namespace CarCareTracker.Controllers
|
||||
_supplyRecordDataAccess = supplyRecordDataAccess;
|
||||
_planRecordDataAccess = planRecordDataAccess;
|
||||
_planRecordTemplateDataAccess = planRecordTemplateDataAccess;
|
||||
_inspectionRecordDataAccess = inspectionRecordDataAccess;
|
||||
_inspectionRecordTemplateDataAccess = inspectionRecordTemplateDataAccess;
|
||||
_odometerRecordDataAccess = odometerRecordDataAccess;
|
||||
_extraFieldDataAccess = extraFieldDataAccess;
|
||||
_userLogic = userLogic;
|
||||
@ -159,6 +165,8 @@ namespace CarCareTracker.Controllers
|
||||
_upgradeRecordDataAccess.DeleteAllUpgradeRecordsByVehicleId(vehicleId) &&
|
||||
_planRecordDataAccess.DeleteAllPlanRecordsByVehicleId(vehicleId) &&
|
||||
_planRecordTemplateDataAccess.DeleteAllPlanRecordTemplatesByVehicleId(vehicleId) &&
|
||||
_inspectionRecordDataAccess.DeleteAllInspectionRecordsByVehicleId(vehicleId) &&
|
||||
_inspectionRecordTemplateDataAccess.DeleteAllInspectionReportTemplatesByVehicleId(vehicleId) &&
|
||||
_supplyRecordDataAccess.DeleteAllSupplyRecordsByVehicleId(vehicleId) &&
|
||||
_odometerRecordDataAccess.DeleteAllOdometerRecordsByVehicleId(vehicleId) &&
|
||||
_userLogic.DeleteAllAccessToVehicle(vehicleId) &&
|
||||
@ -187,6 +195,8 @@ namespace CarCareTracker.Controllers
|
||||
_upgradeRecordDataAccess.DeleteAllUpgradeRecordsByVehicleId(vehicleId) &&
|
||||
_planRecordDataAccess.DeleteAllPlanRecordsByVehicleId(vehicleId) &&
|
||||
_planRecordTemplateDataAccess.DeleteAllPlanRecordTemplatesByVehicleId(vehicleId) &&
|
||||
_inspectionRecordDataAccess.DeleteAllInspectionRecordsByVehicleId(vehicleId) &&
|
||||
_inspectionRecordTemplateDataAccess.DeleteAllInspectionReportTemplatesByVehicleId(vehicleId) &&
|
||||
_supplyRecordDataAccess.DeleteAllSupplyRecordsByVehicleId(vehicleId) &&
|
||||
_odometerRecordDataAccess.DeleteAllOdometerRecordsByVehicleId(vehicleId) &&
|
||||
_userLogic.DeleteAllAccessToVehicle(vehicleId) &&
|
||||
@ -455,6 +465,19 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ImportMode.InspectionRecord:
|
||||
{
|
||||
var results = _inspectionRecordDataAccess.GetInspectionRecordsByVehicleId(vehicleId);
|
||||
if (caseSensitive)
|
||||
{
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.InspectionRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
|
||||
}
|
||||
else
|
||||
{
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).ToLower().Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.InspectionRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return PartialView("_GlobalSearchResult", searchResults);
|
||||
@ -536,10 +559,85 @@ namespace CarCareTracker.Controllers
|
||||
searchResults.AddRange(results.Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.ReminderRecord, Description = $"{x.Description}" }));
|
||||
}
|
||||
break;
|
||||
case ImportMode.InspectionRecord:
|
||||
{
|
||||
var results = _inspectionRecordDataAccess.GetInspectionRecordsByVehicleId(vehicleId);
|
||||
results.RemoveAll(x => !x.Tags.Any(y => tagsFilter.Contains(y)));
|
||||
searchResults.AddRange(results.Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.InspectionRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return PartialView("_MapSearchResult", searchResults);
|
||||
}
|
||||
[HttpPost]
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
public IActionResult CheckRecordExist(int vehicleId, ImportMode importMode, int recordId)
|
||||
{
|
||||
if (recordId == default)
|
||||
{
|
||||
return Json(OperationResponse.Failed("Invalid Record"));
|
||||
}
|
||||
switch (importMode)
|
||||
{
|
||||
case ImportMode.ServiceRecord:
|
||||
{
|
||||
var results = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
||||
return Json(OperationResponse.Conditional(results.Any(x => x.Id == recordId), "", "Service Record Not Found"));
|
||||
}
|
||||
case ImportMode.RepairRecord:
|
||||
{
|
||||
var results = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
|
||||
return Json(OperationResponse.Conditional(results.Any(x => x.Id == recordId), "", "Repair Record Not Found"));
|
||||
}
|
||||
case ImportMode.UpgradeRecord:
|
||||
{
|
||||
var results = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
||||
return Json(OperationResponse.Conditional(results.Any(x => x.Id == recordId), "", "Upgrade Record Not Found"));
|
||||
}
|
||||
case ImportMode.TaxRecord:
|
||||
{
|
||||
var results = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
|
||||
return Json(OperationResponse.Conditional(results.Any(x => x.Id == recordId), "", "Tax Record Not Found"));
|
||||
}
|
||||
case ImportMode.SupplyRecord:
|
||||
{
|
||||
var results = _supplyRecordDataAccess.GetSupplyRecordsByVehicleId(vehicleId);
|
||||
return Json(OperationResponse.Conditional(results.Any(x => x.Id == recordId), "", "Supply Record Not Found"));
|
||||
}
|
||||
case ImportMode.PlanRecord:
|
||||
{
|
||||
var results = _planRecordDataAccess.GetPlanRecordsByVehicleId(vehicleId);
|
||||
return Json(OperationResponse.Conditional(results.Any(x => x.Id == recordId), "", "Plan Record Not Found"));
|
||||
}
|
||||
case ImportMode.OdometerRecord:
|
||||
{
|
||||
var results = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||
return Json(OperationResponse.Conditional(results.Any(x => x.Id == recordId), "", "Odometer Record Not Found"));
|
||||
}
|
||||
case ImportMode.GasRecord:
|
||||
{
|
||||
var results = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
|
||||
return Json(OperationResponse.Conditional(results.Any(x => x.Id == recordId), "", "Gas Record Not Found"));
|
||||
}
|
||||
case ImportMode.NoteRecord:
|
||||
{
|
||||
var results = _noteDataAccess.GetNotesByVehicleId(vehicleId);
|
||||
return Json(OperationResponse.Conditional(results.Any(x => x.Id == recordId), "", "Note Record Not Found"));
|
||||
}
|
||||
case ImportMode.ReminderRecord:
|
||||
{
|
||||
var results = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
||||
return Json(OperationResponse.Conditional(results.Any(x => x.Id == recordId), "", "Reminder Not Found"));
|
||||
}
|
||||
case ImportMode.InspectionRecord:
|
||||
{
|
||||
var results = _inspectionRecordDataAccess.GetInspectionRecordsByVehicleId(vehicleId);
|
||||
return Json(OperationResponse.Conditional(results.Any(x => x.Id == recordId), "", "Inspection Record Not Found"));
|
||||
}
|
||||
}
|
||||
return Json(OperationResponse.Failed("Record Not Found"));
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
public IActionResult GetMaxMileage(int vehicleId)
|
||||
{
|
||||
@ -683,6 +781,9 @@ namespace CarCareTracker.Controllers
|
||||
case ImportMode.ReminderRecord:
|
||||
result = DeleteReminderRecordWithChecks(recordId);
|
||||
break;
|
||||
case ImportMode.InspectionRecord:
|
||||
result = DeleteInspectionRecordWithChecks(recordId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
@ -969,6 +1070,18 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ImportMode.InspectionRecord:
|
||||
{
|
||||
var existingRecord = _inspectionRecordTemplateDataAccess.GetInspectionRecordTemplateById(recordId);
|
||||
existingRecord.Id = default;
|
||||
existingRecord.ReminderRecordId = new List<int>();
|
||||
foreach (int vehicleId in vehicleIds)
|
||||
{
|
||||
existingRecord.VehicleId = vehicleId;
|
||||
result = _inspectionRecordTemplateDataAccess.SaveInspectionReportTemplateToVehicle(existingRecord);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
@ -993,7 +1106,8 @@ namespace CarCareTracker.Controllers
|
||||
Date = existingRecord.Date,
|
||||
VehicleId = existingRecord.VehicleId,
|
||||
Mileage = existingRecord.Mileage,
|
||||
Notes = $"Auto Insert From Service Record: {existingRecord.Description}"
|
||||
Notes = $"Auto Insert From Service Record: {existingRecord.Description}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(importMode, existingRecord.Id, existingRecord.Description)
|
||||
});
|
||||
}
|
||||
break;
|
||||
@ -1005,7 +1119,8 @@ namespace CarCareTracker.Controllers
|
||||
Date = existingRecord.Date,
|
||||
VehicleId = existingRecord.VehicleId,
|
||||
Mileage = existingRecord.Mileage,
|
||||
Notes = $"Auto Insert From Repair Record: {existingRecord.Description}"
|
||||
Notes = $"Auto Insert From Repair Record: {existingRecord.Description}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(importMode, existingRecord.Id, existingRecord.Description)
|
||||
});
|
||||
}
|
||||
break;
|
||||
@ -1017,7 +1132,8 @@ namespace CarCareTracker.Controllers
|
||||
Date = existingRecord.Date,
|
||||
VehicleId = existingRecord.VehicleId,
|
||||
Mileage = existingRecord.Mileage,
|
||||
Notes = $"Auto Insert From Upgrade Record: {existingRecord.Description}"
|
||||
Notes = $"Auto Insert From Upgrade Record: {existingRecord.Description}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(importMode, existingRecord.Id, existingRecord.Description)
|
||||
});
|
||||
}
|
||||
break;
|
||||
@ -1029,7 +1145,8 @@ namespace CarCareTracker.Controllers
|
||||
Date = existingRecord.Date,
|
||||
VehicleId = existingRecord.VehicleId,
|
||||
Mileage = existingRecord.Mileage,
|
||||
Notes = $"Auto Insert From Gas Record. {existingRecord.Notes}"
|
||||
Notes = $"Auto Insert From Gas Record. {existingRecord.Notes}",
|
||||
Files = StaticHelper.CreateAttachmentFromRecord(importMode, existingRecord.Id, $"Gas Record - {existingRecord.Mileage.ToString()}")
|
||||
});
|
||||
}
|
||||
break;
|
||||
@ -1367,6 +1484,14 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ImportMode.InspectionRecord:
|
||||
foreach (int recordId in recordIds)
|
||||
{
|
||||
var record = _inspectionRecordDataAccess.GetInspectionRecordById(recordId);
|
||||
stickerViewModel.InspectionRecords.Add(record);
|
||||
recordsAdded++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (recordsAdded > 0)
|
||||
{
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
Dashboard = 8,
|
||||
PlanRecord = 9,
|
||||
OdometerRecord = 10,
|
||||
VehicleRecord = 11
|
||||
VehicleRecord = 11,
|
||||
InspectionRecord = 12
|
||||
}
|
||||
}
|
||||
|
||||
9
Enum/InspectionFieldType.cs
Normal file
9
Enum/InspectionFieldType.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public enum InspectionFieldType
|
||||
{
|
||||
Text = 0,
|
||||
Check = 1,
|
||||
Radio = 2
|
||||
}
|
||||
}
|
||||
54
External/Implementations/Litedb/InspectionRecordDataAccess.cs
vendored
Normal file
54
External/Implementations/Litedb/InspectionRecordDataAccess.cs
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Models;
|
||||
using CarCareTracker.Helper;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class InspectionRecordDataAccess : IInspectionRecordDataAccess
|
||||
{
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "inspectionrecords";
|
||||
public InspectionRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<InspectionRecord> GetInspectionRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<InspectionRecord>(tableName);
|
||||
var inspectionRecords = table.Find(Query.EQ(nameof(InspectionRecord.VehicleId), vehicleId));
|
||||
return inspectionRecords.ToList() ?? new List<InspectionRecord>();
|
||||
}
|
||||
public InspectionRecord GetInspectionRecordById(int inspectionRecordId)
|
||||
{
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<InspectionRecord>(tableName);
|
||||
return table.FindById(inspectionRecordId);
|
||||
}
|
||||
public bool DeleteInspectionRecordById(int inspectionRecordId)
|
||||
{
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<InspectionRecord>(tableName);
|
||||
table.Delete(inspectionRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SaveInspectionRecordToVehicle(InspectionRecord inspectionRecordId)
|
||||
{
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<InspectionRecord>(tableName);
|
||||
table.Upsert(inspectionRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllInspectionRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<InspectionRecord>(tableName);
|
||||
var planRecords = table.DeleteMany(Query.EQ(nameof(InspectionRecord.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
External/Implementations/Litedb/InspectionRecordTemplateDataAccess.cs
vendored
Normal file
54
External/Implementations/Litedb/InspectionRecordTemplateDataAccess.cs
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Models;
|
||||
using CarCareTracker.Helper;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class InspectionRecordTemplateDataAccess : IInspectionRecordTemplateDataAccess
|
||||
{
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "inspectionrecordtemplates";
|
||||
public InspectionRecordTemplateDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<InspectionRecordInput> GetInspectionRecordTemplatesByVehicleId(int vehicleId)
|
||||
{
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<InspectionRecordInput>(tableName);
|
||||
var inspectionRecords = table.Find(Query.EQ(nameof(InspectionRecordInput.VehicleId), vehicleId));
|
||||
return inspectionRecords.ToList() ?? new List<InspectionRecordInput>();
|
||||
}
|
||||
public InspectionRecordInput GetInspectionRecordTemplateById(int inspectionRecordTemplateId)
|
||||
{
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<InspectionRecordInput>(tableName);
|
||||
return table.FindById(inspectionRecordTemplateId);
|
||||
}
|
||||
public bool DeleteInspectionRecordTemplateById(int inspectionRecordTemplateId)
|
||||
{
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<InspectionRecordInput>(tableName);
|
||||
table.Delete(inspectionRecordTemplateId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SaveInspectionReportTemplateToVehicle(InspectionRecordInput inspectionRecordTemplate)
|
||||
{
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<InspectionRecordInput>(tableName);
|
||||
table.Upsert(inspectionRecordTemplate);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllInspectionReportTemplatesByVehicleId(int vehicleId)
|
||||
{
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<InspectionRecordInput>(tableName);
|
||||
var planRecords = table.DeleteMany(Query.EQ(nameof(InspectionRecordInput.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
160
External/Implementations/Postgres/InspectionRecordDataAccess.cs
vendored
Normal file
160
External/Implementations/Postgres/InspectionRecordDataAccess.cs
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Models;
|
||||
using Npgsql;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class PGInspectionRecordDataAccess : IInspectionRecordDataAccess
|
||||
{
|
||||
private NpgsqlDataSource pgDataSource;
|
||||
private readonly ILogger<PGInspectionRecordDataAccess> _logger;
|
||||
private static string tableName = "inspectionrecords";
|
||||
public PGInspectionRecordDataAccess(IConfiguration config, ILogger<PGInspectionRecordDataAccess> logger)
|
||||
{
|
||||
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
|
||||
_logger = logger;
|
||||
try
|
||||
{
|
||||
//create table if not exist.
|
||||
string initCMD = $"CREATE SCHEMA IF NOT EXISTS app; CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
|
||||
using (var ctext = pgDataSource.CreateCommand(initCMD))
|
||||
{
|
||||
ctext.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
}
|
||||
}
|
||||
public List<InspectionRecord> GetInspectionRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
try
|
||||
{
|
||||
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
|
||||
var results = new List<InspectionRecord>();
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
|
||||
using (NpgsqlDataReader reader = ctext.ExecuteReader())
|
||||
while (reader.Read())
|
||||
{
|
||||
InspectionRecord inspectionRecord = JsonSerializer.Deserialize<InspectionRecord>(reader["data"] as string);
|
||||
results.Add(inspectionRecord);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return new List<InspectionRecord>();
|
||||
}
|
||||
}
|
||||
public InspectionRecord GetInspectionRecordById(int inspectionRecordId)
|
||||
{
|
||||
try
|
||||
{
|
||||
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
|
||||
var result = new InspectionRecord();
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("id", inspectionRecordId);
|
||||
using (NpgsqlDataReader reader = ctext.ExecuteReader())
|
||||
while (reader.Read())
|
||||
{
|
||||
InspectionRecord inspectionRecord = JsonSerializer.Deserialize<InspectionRecord>(reader["data"] as string);
|
||||
result = inspectionRecord;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return new InspectionRecord();
|
||||
}
|
||||
}
|
||||
public bool DeleteInspectionRecordById(int inspectionRecordId)
|
||||
{
|
||||
try
|
||||
{
|
||||
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("id", inspectionRecordId);
|
||||
return ctext.ExecuteNonQuery() > 0;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public bool SaveInspectionRecordToVehicle(InspectionRecord inspectionRecordId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (inspectionRecordId.Id == default)
|
||||
{
|
||||
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("vehicleId", inspectionRecordId.VehicleId);
|
||||
ctext.Parameters.AddWithValue("data", "{}");
|
||||
inspectionRecordId.Id = Convert.ToInt32(ctext.ExecuteScalar());
|
||||
//update json data
|
||||
if (inspectionRecordId.Id != default)
|
||||
{
|
||||
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
|
||||
using (var ctextU = pgDataSource.CreateCommand(cmdU))
|
||||
{
|
||||
var serializedData = JsonSerializer.Serialize(inspectionRecordId);
|
||||
ctextU.Parameters.AddWithValue("id", inspectionRecordId.Id);
|
||||
ctextU.Parameters.AddWithValue("data", serializedData);
|
||||
return ctextU.ExecuteNonQuery() > 0;
|
||||
}
|
||||
}
|
||||
return inspectionRecordId.Id != default;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
var serializedData = JsonSerializer.Serialize(inspectionRecordId);
|
||||
ctext.Parameters.AddWithValue("id", inspectionRecordId.Id);
|
||||
ctext.Parameters.AddWithValue("data", serializedData);
|
||||
return ctext.ExecuteNonQuery() > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public bool DeleteAllInspectionRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
try
|
||||
{
|
||||
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||
ctext.ExecuteNonQuery();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
160
External/Implementations/Postgres/InspectionRecordTemplateDataAccess.cs
vendored
Normal file
160
External/Implementations/Postgres/InspectionRecordTemplateDataAccess.cs
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Models;
|
||||
using Npgsql;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class PGInspectionRecordTemplateDataAccess : IInspectionRecordTemplateDataAccess
|
||||
{
|
||||
private NpgsqlDataSource pgDataSource;
|
||||
private readonly ILogger<PGInspectionRecordTemplateDataAccess> _logger;
|
||||
private static string tableName = "inspectionrecordtemplates";
|
||||
public PGInspectionRecordTemplateDataAccess(IConfiguration config, ILogger<PGInspectionRecordTemplateDataAccess> logger)
|
||||
{
|
||||
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
|
||||
_logger = logger;
|
||||
try
|
||||
{
|
||||
//create table if not exist.
|
||||
string initCMD = $"CREATE SCHEMA IF NOT EXISTS app; CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
|
||||
using (var ctext = pgDataSource.CreateCommand(initCMD))
|
||||
{
|
||||
ctext.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
}
|
||||
}
|
||||
public List<InspectionRecordInput> GetInspectionRecordTemplatesByVehicleId(int vehicleId)
|
||||
{
|
||||
try
|
||||
{
|
||||
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
|
||||
var results = new List<InspectionRecordInput>();
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
|
||||
using (NpgsqlDataReader reader = ctext.ExecuteReader())
|
||||
while (reader.Read())
|
||||
{
|
||||
InspectionRecordInput inspectionRecord = JsonSerializer.Deserialize<InspectionRecordInput>(reader["data"] as string);
|
||||
results.Add(inspectionRecord);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return new List<InspectionRecordInput>();
|
||||
}
|
||||
}
|
||||
public InspectionRecordInput GetInspectionRecordTemplateById(int inspectionRecordTemplateId)
|
||||
{
|
||||
try
|
||||
{
|
||||
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
|
||||
var result = new InspectionRecordInput();
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("id", inspectionRecordTemplateId);
|
||||
using (NpgsqlDataReader reader = ctext.ExecuteReader())
|
||||
while (reader.Read())
|
||||
{
|
||||
InspectionRecordInput inspectionRecord = JsonSerializer.Deserialize<InspectionRecordInput>(reader["data"] as string);
|
||||
result = inspectionRecord;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return new InspectionRecordInput();
|
||||
}
|
||||
}
|
||||
public bool DeleteInspectionRecordTemplateById(int inspectionRecordTemplateId)
|
||||
{
|
||||
try
|
||||
{
|
||||
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("id", inspectionRecordTemplateId);
|
||||
return ctext.ExecuteNonQuery() > 0;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public bool SaveInspectionReportTemplateToVehicle(InspectionRecordInput inspectionRecordTemplate)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (inspectionRecordTemplate.Id == default)
|
||||
{
|
||||
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("vehicleId", inspectionRecordTemplate.VehicleId);
|
||||
ctext.Parameters.AddWithValue("data", "{}");
|
||||
inspectionRecordTemplate.Id = Convert.ToInt32(ctext.ExecuteScalar());
|
||||
//update json data
|
||||
if (inspectionRecordTemplate.Id != default)
|
||||
{
|
||||
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
|
||||
using (var ctextU = pgDataSource.CreateCommand(cmdU))
|
||||
{
|
||||
var serializedData = JsonSerializer.Serialize(inspectionRecordTemplate);
|
||||
ctextU.Parameters.AddWithValue("id", inspectionRecordTemplate.Id);
|
||||
ctextU.Parameters.AddWithValue("data", serializedData);
|
||||
return ctextU.ExecuteNonQuery() > 0;
|
||||
}
|
||||
}
|
||||
return inspectionRecordTemplate.Id != default;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
var serializedData = JsonSerializer.Serialize(inspectionRecordTemplate);
|
||||
ctext.Parameters.AddWithValue("id", inspectionRecordTemplate.Id);
|
||||
ctext.Parameters.AddWithValue("data", serializedData);
|
||||
return ctext.ExecuteNonQuery() > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public bool DeleteAllInspectionReportTemplatesByVehicleId(int vehicleId)
|
||||
{
|
||||
try
|
||||
{
|
||||
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
|
||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||
{
|
||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||
ctext.ExecuteNonQuery();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
External/Interfaces/IInspectionRecordDataAccess.cs
vendored
Normal file
13
External/Interfaces/IInspectionRecordDataAccess.cs
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
using CarCareTracker.Models;
|
||||
|
||||
namespace CarCareTracker.External.Interfaces
|
||||
{
|
||||
public interface IInspectionRecordDataAccess
|
||||
{
|
||||
public List<InspectionRecord> GetInspectionRecordsByVehicleId(int vehicleId);
|
||||
public InspectionRecord GetInspectionRecordById(int inspectionRecordId);
|
||||
public bool DeleteInspectionRecordById(int inspectionRecordId);
|
||||
public bool SaveInspectionRecordToVehicle(InspectionRecord inspectionRecordId);
|
||||
public bool DeleteAllInspectionRecordsByVehicleId(int vehicleId);
|
||||
}
|
||||
}
|
||||
13
External/Interfaces/IInspectionRecordTemplateDataAccess.cs
vendored
Normal file
13
External/Interfaces/IInspectionRecordTemplateDataAccess.cs
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
using CarCareTracker.Models;
|
||||
|
||||
namespace CarCareTracker.External.Interfaces
|
||||
{
|
||||
public interface IInspectionRecordTemplateDataAccess
|
||||
{
|
||||
public List<InspectionRecordInput> GetInspectionRecordTemplatesByVehicleId(int vehicleId);
|
||||
public InspectionRecordInput GetInspectionRecordTemplateById(int inspectionRecordTemplateId);
|
||||
public bool DeleteInspectionRecordTemplateById(int inspectionRecordTemplateId);
|
||||
public bool SaveInspectionReportTemplateToVehicle(InspectionRecordInput inspectionRecordTemplate);
|
||||
public bool DeleteAllInspectionReportTemplatesByVehicleId(int vehicleId);
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,7 @@ namespace CarCareTracker.Helper
|
||||
bool WidgetsExist();
|
||||
bool SaveWidgets(string widgetsData);
|
||||
bool DeleteWidgets();
|
||||
string WriteFileToTemp(string fileName, string data);
|
||||
}
|
||||
public class FileHelper : IFileHelper
|
||||
{
|
||||
@ -514,5 +515,25 @@ namespace CarCareTracker.Helper
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public string WriteFileToTemp(string fileName, string data)
|
||||
{
|
||||
try
|
||||
{
|
||||
//check if temp folder exists
|
||||
var tempFolder = GetFullFilePath("/temp", false);
|
||||
if (!Directory.Exists(tempFolder))
|
||||
{
|
||||
Directory.CreateDirectory(tempFolder);
|
||||
}
|
||||
var tempFileName = $"/temp/{fileName}";
|
||||
var fullTempFileName = GetFullFilePath(tempFileName, false);
|
||||
File.WriteAllText(fullTempFileName, data);
|
||||
return tempFileName;
|
||||
} catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ namespace CarCareTracker.Helper
|
||||
/// </summary>
|
||||
public static class StaticHelper
|
||||
{
|
||||
public const string VersionNumber = "1.5.3";
|
||||
public const string VersionNumber = "1.5.4";
|
||||
public const string DbName = "data/cartracker.db";
|
||||
public const string UserConfigPath = "data/config/userConfig.json";
|
||||
public const string ServerConfigPath = "data/config/serverConfig.json";
|
||||
@ -449,6 +449,8 @@ namespace CarCareTracker.Helper
|
||||
return "bi-journal-bookmark";
|
||||
case ImportMode.ReminderRecord:
|
||||
return "bi-bell";
|
||||
case ImportMode.InspectionRecord:
|
||||
return "bi-clipboard-check";
|
||||
default:
|
||||
return "bi-file-bar-graph";
|
||||
}
|
||||
@ -755,10 +757,46 @@ namespace CarCareTracker.Helper
|
||||
var imageExtensions = new[] { ".png", ".jpg", ".jpeg" };
|
||||
return imageExtensions.Contains(fileExt);
|
||||
}
|
||||
public static bool GetAttachmentIsRecord(string fileLocation, out ImportMode importMode, out int recordId)
|
||||
{
|
||||
var urlMatchesPattern = fileLocation.StartsWith("::") && fileLocation.Split(':').Length == 4;
|
||||
importMode = ImportMode.Dashboard;
|
||||
recordId = 0;
|
||||
if (urlMatchesPattern)
|
||||
{
|
||||
var recordType = fileLocation.Split(':')[2];
|
||||
var recordTypeIsEnum = Enum.TryParse(recordType, out ImportMode recordMode);
|
||||
if (recordTypeIsEnum)
|
||||
{
|
||||
importMode = recordMode;
|
||||
recordId = int.Parse(fileLocation.Split(':')[3]);
|
||||
}
|
||||
}
|
||||
return urlMatchesPattern;
|
||||
}
|
||||
public static string GetRecordAttachment(ImportMode importMode, int recordId)
|
||||
{
|
||||
return $"::{importMode.ToString()}:{recordId.ToString()}";
|
||||
}
|
||||
public static List<UploadedFiles> CreateAttachmentFromRecord(ImportMode importMode, int recordId, string description)
|
||||
{
|
||||
return new List<UploadedFiles>
|
||||
{
|
||||
new UploadedFiles
|
||||
{
|
||||
Name = description,
|
||||
Location = GetRecordAttachment(importMode, recordId)
|
||||
}
|
||||
};
|
||||
}
|
||||
public static string GetIconByFileExtension(string fileLocation)
|
||||
{
|
||||
var fileExt = Path.GetExtension(fileLocation);
|
||||
if (GetAttachmentIsLink(fileLocation))
|
||||
if (GetAttachmentIsRecord(fileLocation, out ImportMode recordType, out int recordId))
|
||||
{
|
||||
return GetImportModeIcon(recordType);
|
||||
}
|
||||
else if (GetAttachmentIsLink(fileLocation))
|
||||
{
|
||||
return "bi-link-45deg";
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ namespace CarCareTracker.Helper
|
||||
string Translate(string userLanguage, string text);
|
||||
Dictionary<string, string> GetTranslations(string userLanguage);
|
||||
OperationResponse SaveTranslation(string userLanguage, Dictionary<string, string> translations);
|
||||
string ExportTranslation(Dictionary<string, string> translations);
|
||||
}
|
||||
public class TranslationHelper : ITranslationHelper
|
||||
{
|
||||
@ -167,31 +166,5 @@ namespace CarCareTracker.Helper
|
||||
return OperationResponse.Failed();
|
||||
}
|
||||
}
|
||||
public string ExportTranslation(Dictionary<string, string> translations)
|
||||
{
|
||||
try
|
||||
{
|
||||
var tempFileName = $"/temp/{Guid.NewGuid()}.json";
|
||||
string uploadDirectory = _fileHelper.GetFullFilePath("temp/", false);
|
||||
if (!Directory.Exists(uploadDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(uploadDirectory);
|
||||
}
|
||||
var saveFilePath = _fileHelper.GetFullFilePath(tempFileName, false);
|
||||
//standardize translation format for export only.
|
||||
Dictionary<string, string> sortedTranslations = new Dictionary<string, string>();
|
||||
foreach (var translation in translations.OrderBy(x => x.Key))
|
||||
{
|
||||
sortedTranslations.Add(translation.Key, translation.Value);
|
||||
};
|
||||
File.WriteAllText(saveFilePath, JsonSerializer.Serialize(sortedTranslations, new JsonSerializerOptions { WriteIndented = true }));
|
||||
return tempFileName;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
Models/InspectionRecord/InspectionRecord.cs
Normal file
16
Models/InspectionRecord/InspectionRecord.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class InspectionRecord
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int VehicleId { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
public int Mileage { get; set; }
|
||||
public decimal Cost { get; set; }
|
||||
public string Description { get; set; }
|
||||
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
public List<InspectionRecordResult> Results { get; set; } = new List<InspectionRecordResult>();
|
||||
public bool Failed { get { return Results.Any(x => x.Failed); } }
|
||||
}
|
||||
}
|
||||
31
Models/InspectionRecord/InspectionRecordInput.cs
Normal file
31
Models/InspectionRecord/InspectionRecordInput.cs
Normal file
@ -0,0 +1,31 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class InspectionRecordInput
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int VehicleId { get; set; }
|
||||
public string Date { get; set; } = DateTime.Now.ToShortDateString();
|
||||
public int Mileage { get; set; }
|
||||
public decimal Cost { get; set; }
|
||||
public string Description { get; set; }
|
||||
public List<int> ReminderRecordId { get; set; } = new List<int>();
|
||||
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
public List<InspectionRecordTemplateField> Fields { get; set; } = new List<InspectionRecordTemplateField>();
|
||||
public InspectionRecord ToInspectionRecord()
|
||||
{
|
||||
return new InspectionRecord
|
||||
{
|
||||
Id = Id,
|
||||
VehicleId = VehicleId,
|
||||
Date = DateTime.Parse(Date),
|
||||
Cost = Cost,
|
||||
Mileage = Mileage,
|
||||
Description = Description,
|
||||
Results = Fields.Select(x => x.ToInspectionRecordResult()).ToList(),
|
||||
Files = Files,
|
||||
Tags = Tags
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
46
Models/InspectionRecord/InspectionRecordTemplateField.cs
Normal file
46
Models/InspectionRecord/InspectionRecordTemplateField.cs
Normal file
@ -0,0 +1,46 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class InspectionRecordTemplateField
|
||||
{
|
||||
public string Description { get; set; }
|
||||
public InspectionFieldType FieldType { get; set; } = InspectionFieldType.Text;
|
||||
public List<InspectionRecordTemplateFieldOption> Options { get; set; } = new List<InspectionRecordTemplateFieldOption>();
|
||||
public ImportMode ActionItemType { get; set; } = ImportMode.ServiceRecord;
|
||||
public string ActionItemDescription { get; set; }
|
||||
public PlanPriority ActionItemPriority { get; set; } = PlanPriority.Normal;
|
||||
public bool HasNotes { get; set; }
|
||||
public bool HasActionItem { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public InspectionRecordResult ToInspectionRecordResult()
|
||||
{
|
||||
return Options.Any() ? new InspectionRecordResult
|
||||
{
|
||||
Description = Description,
|
||||
FieldType = FieldType,
|
||||
Values = Options.Select(x => new InspectionRecordResultValue{Description = x.Description, IsSelected = x.IsSelected, IsFail = x.IsFail }).ToList(),
|
||||
Failed = (FieldType == InspectionFieldType.Radio && Options.Any(x => x.IsSelected && x.IsFail)) || (FieldType == InspectionFieldType.Check && Options.Any(x=> !x.IsSelected && x.IsFail)),
|
||||
Notes = HasNotes ? Notes : string.Empty
|
||||
} : new InspectionRecordResult();
|
||||
}
|
||||
}
|
||||
public class InspectionRecordTemplateFieldOption
|
||||
{
|
||||
public string Description { get; set; }
|
||||
public bool IsFail { get; set; }
|
||||
public bool IsSelected { get; set; }
|
||||
}
|
||||
public class InspectionRecordResult
|
||||
{
|
||||
public string Description { get; set; }
|
||||
public List<InspectionRecordResultValue> Values { get; set; } = new List<InspectionRecordResultValue>();
|
||||
public bool Failed { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public InspectionFieldType FieldType { get; set; } = InspectionFieldType.Text;
|
||||
}
|
||||
public class InspectionRecordResultValue
|
||||
{
|
||||
public string Description { get; set; }
|
||||
public bool IsSelected { get; set; }
|
||||
public bool IsFail { get; set; }
|
||||
}
|
||||
}
|
||||
@ -7,5 +7,6 @@
|
||||
public List<ReminderRecord> ReminderRecords { get; set; } = new List<ReminderRecord>();
|
||||
public List<GenericRecord> GenericRecords { get; set; } = new List<GenericRecord>();
|
||||
public List<SupplyRecord> SupplyRecords { get; set; } = new List<SupplyRecord>();
|
||||
public List<InspectionRecord> InspectionRecords { get; set; } = new List<InspectionRecord>();
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,6 +184,22 @@ namespace CarCareTracker.Models
|
||||
Action = $"{userName} {GetFriendlyActionType(actionType)} Description: {planRecord.Description}"
|
||||
};
|
||||
}
|
||||
public static WebHookPayload FromInspectionRecord(InspectionRecord inspectionRecord, string actionType, string userName)
|
||||
{
|
||||
Dictionary<string, string> payloadDictionary = new Dictionary<string, string>();
|
||||
payloadDictionary.Add("user", userName);
|
||||
payloadDictionary.Add("description", inspectionRecord.Description);
|
||||
payloadDictionary.Add("vehicleId", inspectionRecord.VehicleId.ToString());
|
||||
payloadDictionary.Add("cost", inspectionRecord.Cost.ToString("F2"));
|
||||
return new WebHookPayload
|
||||
{
|
||||
Type = actionType,
|
||||
Data = payloadDictionary,
|
||||
VehicleId = inspectionRecord.VehicleId.ToString(),
|
||||
Username = userName,
|
||||
Action = $"{userName} {GetFriendlyActionType(actionType)} Description: {inspectionRecord.Description}"
|
||||
};
|
||||
}
|
||||
public static WebHookPayload FromReminderRecord(ReminderRecord reminderRecord, string actionType, string userName)
|
||||
{
|
||||
Dictionary<string, string> payloadDictionary = new Dictionary<string, string>();
|
||||
|
||||
@ -51,6 +51,7 @@
|
||||
ImportMode.SupplyRecord,
|
||||
ImportMode.TaxRecord,
|
||||
ImportMode.NoteRecord,
|
||||
ImportMode.InspectionRecord,
|
||||
ImportMode.ReminderRecord
|
||||
};
|
||||
}
|
||||
|
||||
@ -58,6 +58,8 @@ if (!string.IsNullOrWhiteSpace(builder.Configuration["POSTGRES_CONNECTION"])){
|
||||
builder.Services.AddSingleton<ITokenRecordDataAccess, PGTokenRecordDataAccess>();
|
||||
builder.Services.AddSingleton<IUserAccessDataAccess, PGUserAccessDataAccess>();
|
||||
builder.Services.AddSingleton<IExtraFieldDataAccess, PGExtraFieldDataAccess>();
|
||||
builder.Services.AddSingleton<IInspectionRecordDataAccess, PGInspectionRecordDataAccess>();
|
||||
builder.Services.AddSingleton<IInspectionRecordTemplateDataAccess, PGInspectionRecordTemplateDataAccess>();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -78,6 +80,8 @@ else
|
||||
builder.Services.AddSingleton<ITokenRecordDataAccess, TokenRecordDataAccess>();
|
||||
builder.Services.AddSingleton<IUserAccessDataAccess, UserAccessDataAccess>();
|
||||
builder.Services.AddSingleton<IExtraFieldDataAccess, ExtraFieldDataAccess>();
|
||||
builder.Services.AddSingleton<IInspectionRecordDataAccess, InspectionRecordDataAccess>();
|
||||
builder.Services.AddSingleton<IInspectionRecordTemplateDataAccess, InspectionRecordTemplateDataAccess>();
|
||||
}
|
||||
|
||||
//configure helpers
|
||||
|
||||
@ -5,9 +5,16 @@
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
var attachmentIsRecord = StaticHelper.GetAttachmentIsRecord(Model.Location, out ImportMode importMode, out int recordId);
|
||||
}
|
||||
<div class="modal-header">
|
||||
@if (StaticHelper.GetAttachmentIsLink(Model.Location))
|
||||
@if (attachmentIsRecord)
|
||||
{
|
||||
<a href="#" onclick="loadRecordAttachment(@recordId, '@importMode')">
|
||||
<span class="link-body-emphasis"><i class="bi @StaticHelper.GetImportModeIcon(importMode)"></i></span>
|
||||
</a>
|
||||
}
|
||||
else if (StaticHelper.GetAttachmentIsLink(Model.Location))
|
||||
{
|
||||
<a href="@Model.Location" target="_blank">
|
||||
<span class="link-body-emphasis"><i class="bi bi-box-arrow-up-right"></i></span>
|
||||
@ -23,7 +30,13 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="d-flex justify-content-center" style="height:100%; width:100%;" onclick="closeAttachmentPreview()">
|
||||
@if (StaticHelper.GetAttachmentIsLink(Model.Location))
|
||||
@if (attachmentIsRecord)
|
||||
{
|
||||
<div class="align-self-center">
|
||||
<button onclick="loadRecordAttachment(@recordId, '@importMode')" class="btn btn-primary"><span class="me-2">@translator.Translate(userLanguage, "Go To Record")</span><span><i class="bi @StaticHelper.GetImportModeIcon(importMode)"></i></span></button>
|
||||
</div>
|
||||
}
|
||||
else if (StaticHelper.GetAttachmentIsLink(Model.Location))
|
||||
{
|
||||
<div class="align-self-center">
|
||||
<a href="@Model.Location" target="_blank" onclick="noPropagation()" class="btn btn-primary"><span class="me-2">@translator.Translate(userLanguage, "Open Link in New Tab")</span><span><i class="bi bi-box-arrow-up-right"></i></span></a>
|
||||
|
||||
@ -123,6 +123,7 @@
|
||||
<li><a class="context-menu-active-single dropdown-item @StaticHelper.DefaultActiveTab(userConfig, ImportMode.SupplyRecord)" href="#" onclick="viewVehicleWithTab(selectedVehicles, 'supply')"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Supplies")</span><i class="bi bi-shop"></i></div></a></li>
|
||||
<li><a class="context-menu-active-single dropdown-item @StaticHelper.DefaultActiveTab(userConfig, ImportMode.TaxRecord)" href="#" onclick="viewVehicleWithTab(selectedVehicles, 'tax')"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Taxes")</span><i class="bi bi-currency-dollar"></i></div></a></li>
|
||||
<li><a class="context-menu-active-single dropdown-item @StaticHelper.DefaultActiveTab(userConfig, ImportMode.NoteRecord)" href="#" onclick="viewVehicleWithTab(selectedVehicles, 'notes')"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Notes")</span><i class="bi bi-journal-bookmark"></i></div></a></li>
|
||||
<li><a class="context-menu-active-single dropdown-item @StaticHelper.DefaultActiveTab(userConfig, ImportMode.InspectionRecord)" href="#" onclick="viewVehicleWithTab(selectedVehicles, 'inspection')"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Inspections")</span><i class="bi bi-clipboard-check"></i></div></a></li>
|
||||
<li><a class="context-menu-active-single dropdown-item @StaticHelper.DefaultActiveTab(userConfig, ImportMode.ReminderRecord)" href="#" onclick="viewVehicleWithTab(selectedVehicles, 'reminder')"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Reminders")</span><i class="bi bi-bell"></i></div></a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item text-danger" href="#" onclick="deleteVehicles(selectedVehicles)"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Delete")</span><i class="bi bi-trash"></i></div></a></li>
|
||||
|
||||
@ -132,13 +132,13 @@
|
||||
<div class="col-12 col-md-6">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="ServiceRecord" id="serviceRecordTab" @(Model.UserConfig.VisibleTabs.Contains(ImportMode.ServiceRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="serviceRecordTab">@translator.Translate(userLanguage, "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.UserConfig.VisibleTabs.Contains(ImportMode.Dashboard) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="dashboardTab">@translator.Translate(userLanguage, "Dashboard")</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="ServiceRecord" id="serviceRecordTab" @(Model.UserConfig.VisibleTabs.Contains(ImportMode.ServiceRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="serviceRecordTab">@translator.Translate(userLanguage, "Service Records")</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="RepairRecord" id="repairRecordTab" @(Model.UserConfig.VisibleTabs.Contains(ImportMode.RepairRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="repairRecordTab">@translator.Translate(userLanguage, "Repairs")</label>
|
||||
@ -179,6 +179,10 @@
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="PlanRecord" id="planRecordTab" @(Model.UserConfig.VisibleTabs.Contains(ImportMode.PlanRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="planRecordTab">@translator.Translate(userLanguage, "Planner")</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="InspectionRecord" id="inspectionRecordTab" @(Model.UserConfig.VisibleTabs.Contains(ImportMode.InspectionRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="inspectionRecordTab">@translator.Translate(userLanguage, "Inspections")</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -197,6 +201,7 @@
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model.UserConfig, ImportMode.SupplyRecord)) value="SupplyRecord">@translator.Translate(userLanguage, "Supplies")</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model.UserConfig, ImportMode.PlanRecord)) value="PlanRecord">@translator.Translate(userLanguage, "Planner")</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model.UserConfig, ImportMode.OdometerRecord)) value="OdometerRecord">@translator.Translate(userLanguage, "Odometer")</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model.UserConfig, ImportMode.InspectionRecord)) value="InspectionRecord">@translator.Translate(userLanguage, "Inspections")</!option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
@ -378,6 +383,7 @@
|
||||
<li class="list-group-item" style="order: @Model.UserConfig.TabOrder.FindIndex(x=>x == ImportMode.SupplyRecord)" draggable="true" data-tab="@ImportMode.SupplyRecord">@translator.Translate(userLanguage, "Supplies")</li>
|
||||
<li class="list-group-item" style="order: @Model.UserConfig.TabOrder.FindIndex(x=>x == ImportMode.TaxRecord)" draggable="true" data-tab="@ImportMode.TaxRecord">@translator.Translate(userLanguage, "Taxes")</li>
|
||||
<li class="list-group-item" style="order: @Model.UserConfig.TabOrder.FindIndex(x=>x == ImportMode.NoteRecord)" draggable="true" data-tab="@ImportMode.NoteRecord">@translator.Translate(userLanguage, "Notes")</li>
|
||||
<li class="list-group-item" style="order: @Model.UserConfig.TabOrder.FindIndex(x => x == ImportMode.InspectionRecord)" draggable="true" data-tab="@ImportMode.InspectionRecord">@translator.Translate(userLanguage, "Inspections")</li>
|
||||
<li class="list-group-item" style="order: @Model.UserConfig.TabOrder.FindIndex(x=>x == ImportMode.ReminderRecord)" draggable="true" data-tab="@ImportMode.ReminderRecord">@translator.Translate(userLanguage, "Reminder")</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
<div class="row">
|
||||
<div class="col-1">
|
||||
<a href="/Home" class="btn btn-secondary btn-md mt-1 mb-1"><i class="bi bi-arrow-left-square"></i></a>
|
||||
</div>
|
||||
<div class="col-11">
|
||||
<h1>Access Denied</h1>
|
||||
</div>
|
||||
</div>
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@{
|
||||
var userLanguage = config.GetServerLanguage();
|
||||
}
|
||||
@{
|
||||
ViewData["Title"] = "Access Denied";
|
||||
}
|
||||
<div class="no-top-pad d-flex align-items-center justify-content-center" style="height:100vh;">
|
||||
<div class="flex-column d-flex">
|
||||
<span class="display-1">@translator.Translate(userLanguage, "Access Denied")</span>
|
||||
<hr />
|
||||
<div class="d-flex justify-content-center">
|
||||
<a href="/Home" class="btn btn-outline-secondary"><i class="bi bi-car-front me-2"></i>@translator.Translate(userLanguage, "Return to Garage")</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
<script src="~/js/supplyrecord.js?v=@StaticHelper.VersionNumber"></script>
|
||||
<script src="~/js/planrecord.js?v=@StaticHelper.VersionNumber"></script>
|
||||
<script src="~/js/odometerrecord.js?v=@StaticHelper.VersionNumber"></script>
|
||||
<script src="~/js/inspectionrecord.js?v=@StaticHelper.VersionNumber"></script>
|
||||
<script src="~/lib/chart-js/chart.umd.js"></script>
|
||||
<script src="~/lib/drawdown/drawdown.js"></script>
|
||||
}
|
||||
@ -67,6 +68,9 @@
|
||||
<li class="nav-item" role="presentation" style="order: @userConfig.TabOrder.FindIndex(x=>x == ImportMode.NoteRecord)">
|
||||
<button class="nav-link resizable-nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.NoteRecord)" id="notes-tab" data-bs-toggle="tab" data-bs-target="#notes-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-journal-bookmark"></i><span class="ms-2">@translator.Translate(userLanguage, "Notes")</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation" style="order: @userConfig.TabOrder.FindIndex(x => x == ImportMode.InspectionRecord)">
|
||||
<button class="nav-link resizable-nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.InspectionRecord)" id="inspection-tab" data-bs-toggle="tab" data-bs-target="#inspection-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-clipboard-check"></i><span class="ms-2">@translator.Translate(userLanguage, "Inspections")</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation" style="order: @userConfig.TabOrder.FindIndex(x=>x == ImportMode.ReminderRecord)">
|
||||
<button class="nav-link resizable-nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.ReminderRecord)" id="reminder-tab" data-bs-toggle="tab" data-bs-target="#reminder-tab-pane" type="button" role="tab" aria-selected="false"><div class="reminderBellDiv" style="display:inline-flex;"><i class="reminderBell bi bi-bell"></i></div><span class="ms-2">@translator.Translate(userLanguage, "Reminders")</span></button>
|
||||
</li>
|
||||
@ -129,6 +133,9 @@
|
||||
<li class="nav-item" role="presentation" style="order: @userConfig.TabOrder.FindIndex(x=>x == ImportMode.NoteRecord)">
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.NoteRecord)" id="notes-tab" data-bs-toggle="tab" data-bs-target="#notes-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-journal-bookmark me-2"></i>@translator.Translate(userLanguage, "Notes")</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation" style="order: @userConfig.TabOrder.FindIndex(x => x == ImportMode.InspectionRecord)">
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.InspectionRecord)" id="inspection-tab" data-bs-toggle="tab" data-bs-target="#inspection-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-clipboard-check me-2"></i>@translator.Translate(userLanguage, "Inspections")</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation" style="order: @userConfig.TabOrder.FindIndex(x=>x == ImportMode.ReminderRecord)">
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.ReminderRecord)" id="reminder-tab" data-bs-toggle="tab" data-bs-target="#reminder-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><div class="reminderBellDiv" style="display:inline-flex;"><i class="reminderBell bi bi-bell me-2"></i></div>@translator.Translate(userLanguage, "Reminders")</span></button>
|
||||
</li>
|
||||
@ -147,6 +154,7 @@
|
||||
<div class="tab-pane fade" id="supply-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="plan-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="odometer-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="inspection-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" data-bs-focus="false" id="editVehicleModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
|
||||
63
Views/Vehicle/Inspection/_InspectionRecordField.cshtml
Normal file
63
Views/Vehicle/Inspection/_InspectionRecordField.cshtml
Normal file
@ -0,0 +1,63 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model InspectionRecordTemplateField
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div data-type="field">
|
||||
<label>@translator.Translate(userLanguage, "Description")</label>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<input type="text" data-type="fieldDescription" class="form-control" placeholder="@translator.Translate(userLanguage, "Description of Inspected Item")" value="@Model.Description">
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm ms-2" onclick="moveInspectionRecordField(this)"><i class="bi bi-arrow-up"></i></button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm ms-2" onclick="moveInspectionRecordField(this, true)"><i class="bi bi-arrow-down"></i></button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm ms-2" onclick="duplicateInspectionRecordField(this)"><i class="bi bi-copy"></i></button>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm ms-2" onclick="deleteInspectionRecordField(this)"><i class="bi bi-trash"></i></button>
|
||||
</div>
|
||||
<label>@translator.Translate(userLanguage, "Type")</label>
|
||||
<select class="form-select" data-type="fieldType" onchange="handleInspectionRecordFieldTypeChange(this)">
|
||||
<!option value="Text" @(Model.FieldType == InspectionFieldType.Text ? "selected" : "")>@translator.Translate(userLanguage, "Text")</!option>
|
||||
<!option value="Check" @(Model.FieldType == InspectionFieldType.Check ? "selected" : "")>@translator.Translate(userLanguage, "Check")</!option>
|
||||
<!option value="Radio" @(Model.FieldType == InspectionFieldType.Radio ? "selected" : "")>@translator.Translate(userLanguage, "Radio")</!option>
|
||||
</select>
|
||||
<div data-type="fieldOptions">
|
||||
@if (Model.Options.Any())
|
||||
{
|
||||
@switch (Model.FieldType)
|
||||
{
|
||||
case InspectionFieldType.Radio:
|
||||
case InspectionFieldType.Check:
|
||||
@await Html.PartialAsync("Inspection/_InspectionRecordFieldOptions", Model.Options)
|
||||
break;
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div data-type="fieldActionItem" style="@(Model.FieldType == InspectionFieldType.Text ? "display:none;" : "")">
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" data-type="fieldHasNotes" type="checkbox" role="switch" @(Model.HasNotes ? "checked" : "")>
|
||||
<label class="form-check-label" onclick="stretchedLinkClick(this)">@translator.Translate(userLanguage, "Has Notes")</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" data-type="fieldHasActionItem" type="checkbox" role="switch" onchange="handleInspectionRecordFieldHasActionItemChange(this)" @(Model.HasActionItem ? "checked" : "")>
|
||||
<label class="form-check-label" onclick="stretchedLinkClick(this)">@translator.Translate(userLanguage, "Has Action Item")</label>
|
||||
</div>
|
||||
<div class="collapse @(Model.HasActionItem ? "show" : "")" data-type="fieldActionItemContainer">
|
||||
<label>@translator.Translate(userLanguage, "Action Item Description")</label>
|
||||
<input type="text" data-type="fieldActionItemDescription" class="form-control" placeholder="@translator.Translate(userLanguage, "Description of Action Item")" value="@Model.ActionItemDescription">
|
||||
<label>@translator.Translate(userLanguage, "Action Item Type")</label>
|
||||
<select class="form-select" data-type="fieldActionItemType" onchange="setDropDownOptionSelected(this)">
|
||||
<!option value="ServiceRecord" @(Model.ActionItemType == ImportMode.ServiceRecord ? "selected" : "")>@translator.Translate(userLanguage, "Service")</!option>
|
||||
<!option value="RepairRecord" @(Model.ActionItemType == ImportMode.RepairRecord ? "selected" : "")>@translator.Translate(userLanguage, "Repair")</!option>
|
||||
<!option value="UpgradeRecord" @(Model.ActionItemType == ImportMode.UpgradeRecord ? "selected" : "")>@translator.Translate(userLanguage, "Upgrade")</!option>
|
||||
</select>
|
||||
<label>@translator.Translate(userLanguage, "Action Item Priority")</label>
|
||||
<select class="form-select" data-type="fieldActionItemPriority" onchange="setDropDownOptionSelected(this)">
|
||||
<!option value="Critical" @(Model.ActionItemPriority == PlanPriority.Critical ? "selected" : "")>@translator.Translate(userLanguage, "Critical")</!option>
|
||||
<!option value="Normal" @(Model.ActionItemPriority == PlanPriority.Normal ? "selected" : "")>@translator.Translate(userLanguage, "Normal")</!option>
|
||||
<!option value="Low" @(Model.ActionItemPriority == PlanPriority.Low ? "selected" : "")>@translator.Translate(userLanguage, "Low")</!option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
</div>
|
||||
16
Views/Vehicle/Inspection/_InspectionRecordFieldOption.cshtml
Normal file
16
Views/Vehicle/Inspection/_InspectionRecordFieldOption.cshtml
Normal file
@ -0,0 +1,16 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model InspectionRecordTemplateFieldOption
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div data-type="fieldOption" class="d-flex justify-content-between align-items-center mt-2">
|
||||
<input type="text" data-type="fieldOptionText" class="form-control" value="@Model.Description">
|
||||
<div class="ms-2 form-check form-check-inline">
|
||||
<input class="form-check-input" data-type="fieldOptionIsFail" type="checkbox" role="switch" @(Model.IsFail ? "checked" : "")>
|
||||
<label class="form-check-label" onclick="stretchedLinkClick(this)">@translator.Translate(userLanguage, "Fail")</label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm" onclick="deleteInspectionRecordFieldOption(this)"><i class="bi bi-trash"></i></button>
|
||||
</div>
|
||||
@ -0,0 +1,15 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model List<InspectionRecordTemplateFieldOption>
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="d-grid p-2">
|
||||
<button type="button" class="btn btn-outline-warning" onclick="addInspectionRecordFieldOption(this)">@translator.Translate(userLanguage, "Add Option")</button>
|
||||
</div>
|
||||
@foreach (InspectionRecordTemplateFieldOption fieldOption in Model)
|
||||
{
|
||||
@await Html.PartialAsync("Inspection/_InspectionRecordFieldOption", fieldOption)
|
||||
}
|
||||
135
Views/Vehicle/Inspection/_InspectionRecordModal.cshtml
Normal file
135
Views/Vehicle/Inspection/_InspectionRecordModal.cshtml
Normal file
@ -0,0 +1,135 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model InspectionRecordInput
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(translator.Translate(userLanguage, "Add New Inspection Record"))</h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddInspectionRecordModal(true)" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body" onkeydown="handleEnter(this)">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
|
||||
<label for="inspectionRecordDate">@translator.Translate(userLanguage, "Date")</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="inspectionRecordDate" class="form-control" placeholder="@translator.Translate(userLanguage, "Date inspection was performed")" value="@Model.Date">
|
||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||
</div>
|
||||
<label for="inspectionRecordMileage">@translator.Translate(userLanguage, "Odometer")</label>
|
||||
<div class="input-group">
|
||||
<input type="number" inputmode="numeric" id="inspectionRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage, "Odometer reading when inspected")" value="">
|
||||
<div class="input-group-text">
|
||||
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('inspectionRecordMileage')"><i class="bi bi-plus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<label for="inspectionRecordDescription">@translator.Translate(userLanguage, "Description")</label>
|
||||
<input type="text" id="inspectionRecordDescription" class="form-control" placeholder="@translator.Translate(userLanguage, "Description of Inspection performed")" value="@Model.Description">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<a onclick="showRecurringReminderSelector('inspectionRecordDescription', 'inspectionRecordNotes')" class="btn btn-link">@translator.Translate(userLanguage, "Select Reminder")</a>
|
||||
</div>
|
||||
</div>
|
||||
<label for="inspectionRecordCost">@translator.Translate(userLanguage, "Cost")</label>
|
||||
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="fixDecimalInput(this, 2)" id="inspectionRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage, "Cost of the inspection")" value="">
|
||||
@if (Model.Fields.Any())
|
||||
{
|
||||
<hr />
|
||||
<div id="inspectionRecordFields">
|
||||
@foreach (InspectionRecordTemplateField templateField in Model.Fields)
|
||||
{
|
||||
var templateFieldName = Guid.NewGuid().ToString();
|
||||
<div data-type="field" data-fieldtype="@templateField.FieldType">
|
||||
<label data-type="fieldDescription">@templateField.Description</label>
|
||||
<div data-type="fieldOptions">
|
||||
@if (templateField.FieldType == InspectionFieldType.Text)
|
||||
{
|
||||
<input type="text" class="form-control" data-type="fieldOption" placeholder="@templateField.Description">
|
||||
}
|
||||
else if (templateField.FieldType == InspectionFieldType.Check)
|
||||
{
|
||||
<div class="d-flex justify-content-between">
|
||||
@foreach (InspectionRecordTemplateFieldOption fieldOption in templateField.Options)
|
||||
{
|
||||
<div class="form-check form-check-inline" data-type="fieldOptionContainer">
|
||||
<input class="form-check-input" data-type="fieldOption" type="checkbox" role="switch" data-field="@(fieldOption.IsFail ? "fail" : "")">
|
||||
<label class="form-check-label" data-type="fieldOptionText" onclick="stretchedLinkClick(this)">@fieldOption.Description</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else if (templateField.FieldType == InspectionFieldType.Radio)
|
||||
{
|
||||
<div class="d-flex justify-content-between">
|
||||
@foreach (InspectionRecordTemplateFieldOption fieldOption in templateField.Options)
|
||||
{
|
||||
<div class="form-check form-check-inline" data-type="fieldOptionContainer">
|
||||
<input class="form-check-input" data-type="fieldOption" type="radio" role="switch" name="@templateFieldName" data-field="@(fieldOption.IsFail ? "fail" : "")">
|
||||
<label class="form-check-label" data-type="fieldOptionText" onclick="stretchedLinkClick(this)">@fieldOption.Description</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@if (templateField.HasNotes)
|
||||
{
|
||||
<div>
|
||||
<label for="@($"{templateFieldName}Notes")">@translator.Translate(userLanguage, "Notes")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
||||
<textarea id="@($"{templateFieldName}Notes")" data-type="fieldNotes" class="form-control" rows="5"></textarea>
|
||||
</div>
|
||||
}
|
||||
@if (templateField.HasActionItem)
|
||||
{
|
||||
<div data-type="fieldActionItemContainer" style="display:none;">
|
||||
<input type="text" data-type="fieldActionItemDescription" class="form-control" value="@templateField.ActionItemDescription">
|
||||
<input type="text" data-type="fieldActionItemType" class="form-control" value="@templateField.ActionItemType">
|
||||
<input type="text" data-type="fieldActionItemPriority" class="form-control" value="@templateField.ActionItemPriority">
|
||||
</div>
|
||||
}
|
||||
<hr />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" value="" id="addReminderCheck">
|
||||
<label class="form-check-label" for="addReminderCheck">
|
||||
@translator.Translate(userLanguage, "Add Reminder")
|
||||
</label>
|
||||
</div>
|
||||
<label for="inspectionRecordTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
|
||||
<select multiple class="form-select" id="inspectionRecordTag">
|
||||
@foreach (string tag in Model.Tags)
|
||||
{
|
||||
<!option value="@tag">@tag</!option>
|
||||
}
|
||||
</select>
|
||||
<div>
|
||||
@await Html.PartialAsync("_UploadedFiles", Model.Files)
|
||||
@await Html.PartialAsync("_FileUploader", Model.Files.Any())
|
||||
</div>
|
||||
<div id="filesPendingUpload"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" onclick="hideAddInspectionRecordModal(true)">@translator.Translate(userLanguage, "Cancel")</button>
|
||||
<button type="button" class="btn btn-primary" onclick="saveinspectionRecordToVehicle()">@translator.Translate(userLanguage, "Add New Inspection Record")</button>
|
||||
</div>
|
||||
<script>
|
||||
var recurringReminderRecordId = [];
|
||||
function getInspectionRecordModelData() {
|
||||
return { id: @Model.Id}
|
||||
}
|
||||
@foreach(int reminderRecordId in Model.ReminderRecordId)
|
||||
{
|
||||
@:recurringReminderRecordId.push(@reminderRecordId);
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,80 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model InspectionRecordInput
|
||||
@{
|
||||
var isNew = Model.Id == 0;
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew? translator.Translate(userLanguage, "Add New Inspection Record Template") : translator.Translate(userLanguage, "Edit Inspection Record Template"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditInspectionRecordTemplateModal({Model.Id}, true)")'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
|
||||
<button type="button" class="btn-close" onclick="hideInspectionRecordTemplateModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body" onkeydown="handleEnter(this)">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
|
||||
<label for="inspectionRecordDescription">@translator.Translate(userLanguage, "Description")</label>
|
||||
<input type="text" id="inspectionRecordDescription" class="form-control" placeholder="@translator.Translate(userLanguage, "Description of Inspection")" value="@Model.Description">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<a onclick="showRecurringReminderSelector('inspectionRecordDescription', 'inspectionRecordNotes')" class="btn btn-link">@translator.Translate(userLanguage, "Select Reminder")</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="inspectionRecordFields" style="overflow-y:auto;">
|
||||
@foreach (InspectionRecordTemplateField inspectionRecordField in Model.Fields)
|
||||
{
|
||||
@await Html.PartialAsync("Inspection/_InspectionRecordField", inspectionRecordField)
|
||||
}
|
||||
</div>
|
||||
<div class="d-grid p-2">
|
||||
<button type="button" class="btn btn-warning" onclick="addInspectionRecordField()">@translator.Translate(userLanguage, "Add Field")</button>
|
||||
</div>
|
||||
<label for="inspectionRecordTemplateTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
|
||||
<select multiple class="form-select" id="inspectionRecordTemplateTag">
|
||||
@foreach (string tag in Model.Tags)
|
||||
{
|
||||
<!option value="@tag">@tag</!option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@if (!isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-danger me-auto" onclick="deleteInspectionRecordTemplate(@Model.Id)">@translator.Translate(userLanguage, "Delete")</button>
|
||||
}
|
||||
<button type="button" class="btn btn-secondary" onclick="hideInspectionRecordTemplateModal()">@translator.Translate(userLanguage, "Cancel")</button>
|
||||
@if (isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" onclick="saveInspectionRecordTemplateToVehicle()">@translator.Translate(userLanguage, "Add")</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary btn-md mt-1 mb-1" onclick="saveInspectionRecordTemplateToVehicle(true)">@translator.Translate(userLanguage, "Edit")</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="duplicateInspectionRecordTemplateToVehicle()">@translator.Translate(userLanguage, "Duplicate To Vehicle")</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<script>
|
||||
var recurringReminderRecordId = [];
|
||||
function getInspectionRecordModelData() {
|
||||
return { id: @Model.Id}
|
||||
}
|
||||
@foreach (int reminderRecordId in Model.ReminderRecordId)
|
||||
{
|
||||
@:recurringReminderRecordId.push(@reminderRecordId);
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,63 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model List<InspectionRecordInput>
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(translator.Translate(userLanguage, "Select Inspection Record Template"))</h5>
|
||||
<button type="button" class="btn-close" onclick="hideInspectionRecordTemplateSelectorModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@if (Model.Any())
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-12" style="max-height:50vh; overflow-y:auto;">
|
||||
<table class="table table-hover">
|
||||
<thead class="sticky-top">
|
||||
<tr class="d-flex">
|
||||
<th scope="col" class="col-8">@translator.Translate(userLanguage, "Description")</th>
|
||||
<th scope="col" class="col-2">@translator.Translate(userLanguage, "Use")</th>
|
||||
<th scope="col" class="col-2">@translator.Translate(userLanguage, "Edit")</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (InspectionRecordInput inspectionRecordTemplate in Model)
|
||||
{
|
||||
<tr class="d-flex" id="supplyRows">
|
||||
<td class="col-8 text-truncate">
|
||||
@StaticHelper.TruncateStrings(inspectionRecordTemplate.Description)
|
||||
@if (inspectionRecordTemplate.ReminderRecordId.Any())
|
||||
{
|
||||
<i class="bi bi-bell ms-2"></i>
|
||||
}
|
||||
@if (inspectionRecordTemplate.Fields.Any(x=>x.HasActionItem))
|
||||
{
|
||||
<i class="bi bi-tools ms-2"></i>
|
||||
}
|
||||
</td>
|
||||
<td class="col-2"><button type="button" class="btn btn-primary" onclick="useInspectionRecordTemplate(@inspectionRecordTemplate.Id)"><i class="bi bi-plus-square"></i></button></td>
|
||||
<td class="col-2"><button type="button" class="btn btn-warning" onclick="showEditInspectionRecordTemplateModal(@inspectionRecordTemplate.Id)"><i class="bi bi-pencil-square"></i></button></td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="text-center">
|
||||
<h4>@translator.Translate(userLanguage, "No templates are found.")</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" onclick="showAddInspectionRecordTemplateModal()">@translator.Translate(userLanguage, "Add New Inspection Template")</button>
|
||||
</div>
|
||||
101
Views/Vehicle/Inspection/_InspectionRecordViewModal.cshtml
Normal file
101
Views/Vehicle/Inspection/_InspectionRecordViewModal.cshtml
Normal file
@ -0,0 +1,101 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model InspectionRecord
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
var hideZero = userConfig.HideZero;
|
||||
var resultFields = Model.Results.Where(x => x.FieldType == InspectionFieldType.Check || x.FieldType == InspectionFieldType.Radio);
|
||||
var textFields = Model.Results.Where(x => x.FieldType == InspectionFieldType.Text);
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(translator.Translate(userLanguage, "View Inspection Record"))</h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddInspectionRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body" onkeydown="handleEnter(this)">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
|
||||
<div class="d-flex"><label>@($"{translator.Translate(userLanguage, "Date")}: {Model.Date.ToShortDateString()}")</label></div>
|
||||
<div class="d-flex"><label>@($"{translator.Translate(userLanguage, "Odometer")}: {Model.Mileage.ToString()}")</label></div>
|
||||
<div class="d-flex"><label>@($"{translator.Translate(userLanguage, "Description")}: {Model.Description}")</label></div>
|
||||
<div class="d-flex"><label>@($"{translator.Translate(userLanguage, "Result")}: {translator.Translate(userLanguage, Model.Failed ? "Fail" : "Pass")}")</label></div>
|
||||
<div class="d-flex"><label>@($"{translator.Translate(userLanguage, "Cost")}: {(StaticHelper.HideZeroCost(Model.Cost, hideZero))}")</label></div>
|
||||
@foreach(InspectionRecordResult textResult in textFields)
|
||||
{
|
||||
<div class="d-flex"><label>@($"{textResult.Description}: {textResult.Values?.FirstOrDefault(x => x.IsSelected)?.Description}")</label></div>
|
||||
}
|
||||
@if (resultFields.Any())
|
||||
{
|
||||
<hr />
|
||||
<table class="table table-hover">
|
||||
<thead class="sticky-top">
|
||||
<tr class="d-flex">
|
||||
<th scope="col" class="col-9 flex-grow-1 flex-shrink-1 text-truncate">@translator.Translate(userLanguage, "Description")</th>
|
||||
<th scope="col" class="col-3 flex-grow-1 flex-shrink-1 text-truncate">@translator.Translate(userLanguage, "Result")</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (InspectionRecordResult fieldResult in resultFields)
|
||||
{
|
||||
<tr class="d-flex user-select-none">
|
||||
<td class="col-9 flex-grow-1 flex-shrink-1 text-truncate">
|
||||
@fieldResult.Description
|
||||
<div class="d-flex flex-wrap">
|
||||
@foreach (InspectionRecordResultValue fieldValue in fieldResult.Values)
|
||||
{
|
||||
if (fieldResult.FieldType == InspectionFieldType.Radio)
|
||||
{
|
||||
<span class="inspection-value me-2 @(fieldValue.IsFail && fieldValue.IsSelected ? "inspection-value-fail text-danger" : "") @(fieldValue.IsSelected ? "inspection-value-selected" : "")">@fieldValue.Description</span>
|
||||
}
|
||||
else if (fieldResult.FieldType == InspectionFieldType.Check)
|
||||
{
|
||||
<span class="inspection-value me-2 @(fieldValue.IsFail && !fieldValue.IsSelected ? "text-danger" : "")"><i class="bi @(fieldValue.IsSelected ? "bi-check-lg" : "bi-x-lg") me-2"></i>@fieldValue.Description</span>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
<td class="col-3 flex-grow-1 flex-shrink-1 text-truncate">
|
||||
@(fieldResult.Failed? translator.Translate(userLanguage, "Fail") : translator.Translate(userLanguage, "Pass"))
|
||||
</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrWhiteSpace(fieldResult.Notes))
|
||||
{
|
||||
<tr class="d-flex user-select-none">
|
||||
<td class="col-12 flex-grow-1 flex-shrink-1 flex-wrap">
|
||||
<div class="stickerNote ms-1 me-1 p-1">
|
||||
@(fieldResult.Notes)
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
<label for="inspectionRecordTag">@translator.Translate(userLanguage, "Tags")</label>
|
||||
<select multiple class="form-select" id="inspectionRecordTag">
|
||||
@foreach (string tag in Model.Tags)
|
||||
{
|
||||
<!option value="@tag">@tag</!option>
|
||||
}
|
||||
</select>
|
||||
<div>
|
||||
@await Html.PartialAsync("_UploadedFiles", Model.Files)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger me-auto" onclick="deleteInspectionRecord(@Model.Id)">@translator.Translate(userLanguage, "Delete")</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="hideAddInspectionRecordModal()">@translator.Translate(userLanguage, "Close")</button>
|
||||
<button type="button" class="btn btn-primary" onclick="updateInspectionRecordTag(@Model.Id)">@translator.Translate(userLanguage, "Edit")</button>
|
||||
</div>
|
||||
<script>
|
||||
setMarkDownStickerNotes();
|
||||
</script>
|
||||
168
Views/Vehicle/Inspection/_InspectionRecords.cshtml
Normal file
168
Views/Vehicle/Inspection/_InspectionRecords.cshtml
Normal file
@ -0,0 +1,168 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model List<InspectionRecord>
|
||||
@{
|
||||
var recordTags = Model.SelectMany(x => x.Tags).Distinct();
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
var enableCsvImports = userConfig.EnableCsvImports;
|
||||
var hideZero = userConfig.HideZero;
|
||||
var userColumnPreferences = userConfig.UserColumnPreferences.Where(x => x.Tab == ImportMode.InspectionRecord);
|
||||
}
|
||||
<div class="row">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="d-flex align-items-center flex-wrap">
|
||||
<span class="ms-2 badge bg-success" data-aggregate-type="count">@($"{translator.Translate(userLanguage,"# of Inspection Records")}: {Model.Count()}")</span>
|
||||
<span class="ms-2 badge bg-primary" data-aggregate-type="sum">@($"{translator.Translate(userLanguage, "Total")}: {Model.Sum(x => x.Cost).ToString("C")}")</span>
|
||||
@foreach (string recordTag in recordTags)
|
||||
{
|
||||
<span onclick="filterTable('inspection-tab-pane', this)" class="user-select-none ms-2 rounded-pill badge bg-secondary tagfilter" style="cursor:pointer;">@recordTag</span>
|
||||
}
|
||||
<datalist id="tagList">
|
||||
@foreach (string recordTag in recordTags)
|
||||
{
|
||||
<!option value="@recordTag"></!option>
|
||||
}
|
||||
</datalist>
|
||||
</div>
|
||||
<div>
|
||||
@if (enableCsvImports)
|
||||
{
|
||||
<div class="btn-group">
|
||||
<button onclick="showInspectionRecordTemplateSelectorModal()" class="btn btn-primary btn-md mt-1 mb-1"><i class="bi bi-pencil-square me-2"></i>@translator.Translate(userLanguage, "Add Inspection 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="printTab()">@translator.Translate(userLanguage, "Print")</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="searchTableRows('inspection-tab-pane')">@translator.Translate(userLanguage, "Search")</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li>
|
||||
<div class="list-group-item">
|
||||
<input class="btn-check" type="checkbox" id="chkSelectMode">
|
||||
<label class="dropdown-item" for="chkSelectMode">@translator.Translate(userLanguage, "Select Mode")</label>
|
||||
</div>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
||||
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('InspectionRecord')">
|
||||
<div class="list-group-item">
|
||||
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'InspectionRecord')" type="checkbox" id="chkCol_Date" checked>
|
||||
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
||||
</div>
|
||||
</li>
|
||||
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('InspectionRecord')">
|
||||
<div class="list-group-item">
|
||||
<input class="form-check-input col-visible-toggle" data-column-toggle='odometer' onChange="showTableColumns(this, 'InspectionRecord')" type="checkbox" id="chkCol_Odometer" checked>
|
||||
<label class="form-check-label stretched-link" for="chkCol_Odometer">@translator.Translate(userLanguage, "Odometer")</label>
|
||||
</div>
|
||||
</li>
|
||||
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('InspectionRecord')">
|
||||
<div class="list-group-item">
|
||||
<input class="form-check-input col-visible-toggle" data-column-toggle='description' onChange="showTableColumns(this, 'InspectionRecord')" type="checkbox" id="chkCol_Description" checked>
|
||||
<label class="form-check-label stretched-link" for="chkCol_Description">@translator.Translate(userLanguage, "Description")</label>
|
||||
</div>
|
||||
</li>
|
||||
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('InspectionRecord')">
|
||||
<div class="list-group-item">
|
||||
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'InspectionRecord')" type="checkbox" id="chkCol_Cost" checked>
|
||||
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
||||
</div>
|
||||
</li>
|
||||
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('InspectionRecord')">
|
||||
<div class="list-group-item">
|
||||
<input class="form-check-input col-visible-toggle" data-column-toggle='result' onChange="showTableColumns(this, 'InspectionRecord')" type="checkbox" id="chkCol_Result" checked>
|
||||
<label class="form-check-label stretched-link" for="chkCol_Result">@translator.Translate(userLanguage, "Result")</label>
|
||||
</div>
|
||||
</li>
|
||||
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('InspectionRecord')">
|
||||
<div class="list-group-item">
|
||||
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'InspectionRecord')" type="checkbox" id="chkCol_Attachment">
|
||||
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button onclick="showInspectionRecordTemplateSelectorModal()" class="btn btn-primary btn-md mt-1 mb-1"><i class="bi bi-pencil-square me-2"></i>@translator.Translate(userLanguage, "Add Inspection Record")</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row vehicleDetailTabContainer">
|
||||
<div class="col-12">
|
||||
<div class="row mt-2 showOnPrint">
|
||||
<div class="d-flex">
|
||||
<img src="@config.GetLogoUrl()" class="lubelogger-logo" />
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<thead class="sticky-top">
|
||||
<tr class="d-flex">
|
||||
<th scope="col" class="col-2 col-xl-1 flex-grow-1 text-truncate" data-column="date">@translator.Translate(userLanguage, "Date")</th>
|
||||
<th scope="col" class="col-2 flex-grow-1 flex-shrink-1 text-truncate" data-column="odometer">@translator.Translate(userLanguage, "Odometer")</th>
|
||||
<th scope="col" class="col-3 col-xl-4 flex-grow-1 flex-shrink-1 text-truncate" data-column="description">@translator.Translate(userLanguage, "Description")</th>
|
||||
<th scope="col" class="col-2 flex-grow-1 flex-shrink-1 text-truncate" data-column="cost" onclick="toggleSort('inspection-tab-pane', this)" style="cursor:pointer;">@translator.Translate(userLanguage, "Cost")</th>
|
||||
<th scope="col" class="col-2 flex-grow-1 flex-shrink-1 text-truncate" data-column="result">@translator.Translate(userLanguage, "Result")</th>
|
||||
<th scope="col" class="col-1 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="attachments">@translator.Translate(userLanguage, "Attachments")</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (InspectionRecord inspectionRecord in Model)
|
||||
{
|
||||
<tr class="d-flex user-select-none" style="cursor:pointer;" onmouseup="stopEvent()" ontouchstart="detectRowLongTouch(this)" ontouchend="detectRowTouchEndPremature(this)" data-rowId="@inspectionRecord.Id" oncontextmenu="showTableContextMenu(this)" onmousemove="rangeMouseMove(this)" onclick="handleTableRowClick(this, showEditInspectionRecordModal,@inspectionRecord.Id)" data-tags='@string.Join(" ", inspectionRecord.Tags)'>
|
||||
<td class="col-2 col-xl-1 flex-grow-1 text-truncate" data-column="date" data-date="@StaticHelper.GetEpochFromDateTime(inspectionRecord.Date)">@inspectionRecord.Date.ToShortDateString()</td>
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" data-column="odometer">@(inspectionRecord.Mileage == default ? "---" : inspectionRecord.Mileage.ToString())</td>
|
||||
<td class="col-3 col-xl-4 flex-grow-1 flex-shrink-1 text-truncate" data-column="description">@inspectionRecord.Description</td>
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" data-column="cost" data-record-type="cost">@(StaticHelper.HideZeroCost(inspectionRecord.Cost, hideZero))</td>
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" data-column="result">@(inspectionRecord.Failed ? translator.Translate(userLanguage, "Fail") : translator.Translate(userLanguage, "Pass"))</td>
|
||||
<td class="col-1 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="attachments">@await Html.PartialAsync("_AttachmentColumn", inspectionRecord.Files)</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="d-flex">
|
||||
<td class="col-12 showOnPrint lubelogger-report-banner">
|
||||
@StaticHelper.ReportNote
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal fade" data-bs-focus="false" id="inspectionRecordModal" tabindex="-1" role="dialog" aria-hidden="true" onpaste="handleModalPaste(event)">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content" id="inspectionRecordModalContent">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" data-bs-focus="false" id="inspectionRecordTemplateModal" tabindex="-1" role="dialog" aria-hidden="true" onpaste="handleModalPaste(event)">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content" id="inspectionRecordTemplateModalContent">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" data-bs-focus="false" id="inspectionRecordTemplateEditModal" tabindex="-1" role="dialog" aria-hidden="true" onpaste="handleModalPaste(event)">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content" id="inspectionRecordTemplateEditModalContent">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="table-context-menu dropdown-menu" style="display:none;">
|
||||
<li><a class="context-menu-multiple context-menu-select-all dropdown-item" href="#" onclick="selectAllRows()"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Select All")</span><i class="bi bi-check-square"></i></div></a></li>
|
||||
<li><a class="context-menu-multiple context-menu-deselect-all dropdown-item" href="#" onclick="clearSelectedRows()"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Deselect All")</span><i class="bi bi-x-square"></i></div></a></li>
|
||||
<li><hr class="context-menu-multiple dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="printTabStickers(selectedRow, 'InspectionRecord')"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Print")</span><i class="bi bi-printer"></i></div></a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item text-danger" href="#" onclick="deleteRecords(selectedRow, 'InspectionRecord')"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Delete")</span><i class="bi bi-trash"></i></div></a></li>
|
||||
</ul>
|
||||
@if (userColumnPreferences.Any())
|
||||
{
|
||||
@await Html.PartialAsync("_UserColumnPreferences", userColumnPreferences)
|
||||
}
|
||||
@ -86,7 +86,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if(years.Count() > 5)
|
||||
@if(years.Where(x => x != default).Count() > 5)
|
||||
{
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary btn-costdata-prev"><i class="bi bi-caret-left-fill"></i></button>
|
||||
|
||||
@ -146,7 +146,7 @@
|
||||
@if (Model.CustomWidgetsConfigured)
|
||||
{
|
||||
<div class="d-grid">
|
||||
<button onclick="loadCustomWidgets()" class="btn btn-secondary btn-md mt-1 mb-1">@translator.Translate(userLanguage, "Additional Widgets")<i class="bi ms-2 bi-box-arrow-in-up-right"></i></button>
|
||||
<button onclick="showCustomWidgets()" class="btn btn-secondary btn-md mt-1 mb-1">@translator.Translate(userLanguage, "Additional Widgets")<i class="bi ms-2 bi-box-arrow-in-up-right"></i></button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@ -167,6 +167,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>loadCustomWidgets()</script>
|
||||
}
|
||||
|
||||
<script>
|
||||
|
||||
@ -274,4 +274,116 @@
|
||||
</div>
|
||||
}
|
||||
<script>setMarkDownStickerNotes()</script>
|
||||
}
|
||||
} else if (Model.InspectionRecords.Any())
|
||||
{
|
||||
@foreach (InspectionRecord inspectionRecord in Model.InspectionRecords)
|
||||
{
|
||||
var resultFields = inspectionRecord.Results.Where(x => x.FieldType == InspectionFieldType.Check || x.FieldType == InspectionFieldType.Radio);
|
||||
var textFields = inspectionRecord.Results.Where(x => x.FieldType == InspectionFieldType.Text);
|
||||
<div style="page-break-after: always;">
|
||||
<div class="d-flex">
|
||||
<img src="@config.GetLogoUrl()" class="lubelogger-logo" />
|
||||
</div>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<span class="display-6">@($"{Model.VehicleData.Year} {Model.VehicleData.Make} {Model.VehicleData.Model}")</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span class="lead">@($"{StaticHelper.GetVehicleIdentifier(Model.VehicleData)}")</span>
|
||||
</li>
|
||||
@foreach (ExtraField extraField in Model.VehicleData.ExtraFields)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(extraField.Value))
|
||||
{
|
||||
<li class="list-group-item">
|
||||
<span class="lead">@($"{extraField.Name}: {extraField.Value}")</span>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
@($"{translator.Translate(userLanguage, "Description")}: {inspectionRecord.Description}")
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
@($"{translator.Translate(userLanguage, "Result")}: {translator.Translate(userLanguage, inspectionRecord.Failed ? "Fail" : "Pass")}")
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
@($"{translator.Translate(userLanguage, "Date")}: {inspectionRecord.Date.ToShortDateString()}")
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
@($"{translator.Translate(userLanguage, "Odometer")}: {inspectionRecord.Mileage}")
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
@($"{translator.Translate(userLanguage, "Cost")}: {inspectionRecord.Cost.ToString("C")}")
|
||||
</li>
|
||||
@foreach (InspectionRecordResult textResult in textFields)
|
||||
{
|
||||
<li class="list-group-item">
|
||||
@($"{textResult.Description}: {textResult.Values?.FirstOrDefault(x => x.IsSelected)?.Description}")
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@if (resultFields.Any())
|
||||
{
|
||||
<table class="table table-hover">
|
||||
<thead class="sticky-top">
|
||||
<tr class="d-flex">
|
||||
<th scope="col" class="col-9 flex-grow-1 flex-shrink-1 text-truncate">@translator.Translate(userLanguage, "Description")</th>
|
||||
<th scope="col" class="col-3 flex-grow-1 flex-shrink-1 text-truncate">@translator.Translate(userLanguage, "Result")</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (InspectionRecordResult fieldResult in resultFields)
|
||||
{
|
||||
<tr class="d-flex user-select-none">
|
||||
<td class="col-9 flex-grow-1 flex-shrink-1 text-truncate">
|
||||
@fieldResult.Description
|
||||
<div class="d-flex flex-wrap">
|
||||
@foreach (InspectionRecordResultValue fieldValue in fieldResult.Values)
|
||||
{
|
||||
if (fieldResult.FieldType == InspectionFieldType.Radio)
|
||||
{
|
||||
<span class="inspection-value me-2 @(fieldValue.IsFail && fieldValue.IsSelected ? "inspection-value-fail text-danger" : "") @(fieldValue.IsSelected ? "inspection-value-selected" : "")">@fieldValue.Description</span>
|
||||
}
|
||||
else if (fieldResult.FieldType == InspectionFieldType.Check)
|
||||
{
|
||||
<span class="inspection-value me-2 @(fieldValue.IsFail && !fieldValue.IsSelected ? "text-danger" : "")"><i class="bi @(fieldValue.IsSelected ? "bi-check-lg" : "bi-x-lg") me-2"></i>@fieldValue.Description</span>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
<td class="col-3 flex-grow-1 flex-shrink-1 text-truncate">
|
||||
@(fieldResult.Failed? translator.Translate(userLanguage, "Fail") : translator.Translate(userLanguage, "Pass"))
|
||||
</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrWhiteSpace(fieldResult.Notes))
|
||||
{
|
||||
<tr class="d-flex user-select-none">
|
||||
<td class="col-12 flex-grow-1 flex-shrink-1 flex-wrap">
|
||||
<div class="stickerNote ms-1 me-1 p-1">
|
||||
@(fieldResult.Notes)
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<script>setMarkDownStickerNotes()</script>
|
||||
}
|
||||
@ -33,7 +33,7 @@
|
||||
"PreferredGasUnit": "",
|
||||
"UserLanguage": "en_US",
|
||||
"VisibleTabs": [ 0, 1, 4, 2, 3, 6, 5, 8 ],
|
||||
"TabOrder": [ 8, 9, 10, 0, 1, 4, 2, 7, 3, 6, 5 ],
|
||||
"TabOrder": [ 8, 9, 10, 0, 1, 4, 2, 7, 3, 6, 12, 5 ],
|
||||
"DefaultTab": 8,
|
||||
"UserNameHash": "",
|
||||
"UserPasswordHash": "",
|
||||
|
||||
@ -647,4 +647,17 @@ html[data-bs-theme="light"] .frosted {
|
||||
}
|
||||
.garage-item.garage-active .card {
|
||||
border-color: #6ea8fe;
|
||||
}
|
||||
}
|
||||
.inspection-value {
|
||||
padding: 0.35em 0.65em;
|
||||
text-align: center;
|
||||
vertical-align: baseline;
|
||||
white-space: nowrap;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
.inspection-value.inspection-value-selected{
|
||||
border: 1px solid;
|
||||
}
|
||||
.inspection-value.inspection-value-selected.inspection-value-fail {
|
||||
border-color: #dc3545;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
452
wwwroot/js/inspectionrecord.js
Normal file
452
wwwroot/js/inspectionrecord.js
Normal file
@ -0,0 +1,452 @@
|
||||
function showInspectionRecordTemplateSelectorModal() {
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
$.get(`/Vehicle/GetInspectionRecordTemplatesByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
$("#inspectionRecordTemplateModalContent").html(data);
|
||||
$('#inspectionRecordTemplateModal').modal('show');
|
||||
clearModalContentOnHide($('#inspectionRecordTemplateModal'));
|
||||
}
|
||||
});
|
||||
}
|
||||
function hideInspectionRecordTemplateSelectorModal() {
|
||||
$('#inspectionRecordTemplateModal').modal('hide');
|
||||
}
|
||||
function showAddInspectionRecordTemplateModal() {
|
||||
$.get('/Vehicle/GetAddInspectionRecordTemplatePartialView', function (data) {
|
||||
if (data) {
|
||||
$("#inspectionRecordTemplateEditModalContent").html(data);
|
||||
//initiate tag selector
|
||||
initTagSelector($("#inspectionRecordTemplateTag"));
|
||||
hideInspectionRecordTemplateSelectorModal();
|
||||
$('#inspectionRecordTemplateEditModal').modal('show');
|
||||
clearModalContentOnHide($('#inspectionRecordTemplateEditModal'));
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditInspectionRecordTemplateModal(inspectionRecordTemplateId) {
|
||||
$.get(`/Vehicle/GetEditInspectionRecordTemplatePartialView?inspectionRecordTemplateId=${inspectionRecordTemplateId}`, function (data) {
|
||||
if (data) {
|
||||
$("#inspectionRecordTemplateEditModalContent").html(data);
|
||||
//initiate tag selector
|
||||
initTagSelector($("#inspectionRecordTemplateTag"));
|
||||
hideInspectionRecordTemplateSelectorModal();
|
||||
$('#inspectionRecordTemplateEditModal').modal('show');
|
||||
clearModalContentOnHide($('#inspectionRecordTemplateEditModal'));
|
||||
}
|
||||
});
|
||||
}
|
||||
function hideInspectionRecordTemplateModal() {
|
||||
$('#inspectionRecordTemplateEditModal').modal('hide');
|
||||
showInspectionRecordTemplateSelectorModal();
|
||||
}
|
||||
function addInspectionRecordField() {
|
||||
$.get('/Vehicle/GetAddInspectionRecordFieldPartialView', function (data) {
|
||||
$("#inspectionRecordFields").append(data);
|
||||
});
|
||||
}
|
||||
function deleteInspectionRecordField(e) {
|
||||
$(e).closest('[data-type="field"]').remove();
|
||||
}
|
||||
function duplicateInspectionRecordField(e) {
|
||||
let currentField = $(e).closest('[data-type="field"]');
|
||||
let clonedField = currentField.clone();
|
||||
//$("#inspectionRecordFields").append(clonedField);
|
||||
clonedField.insertAfter(currentField);
|
||||
}
|
||||
function setDropDownOptionSelected(dropDownElem) {
|
||||
let selectedVal = $(dropDownElem).val();
|
||||
$(dropDownElem).find('option').removeAttr('selected');
|
||||
$(dropDownElem).find(`option[value="${selectedVal}"]`).attr('selected', '');
|
||||
}
|
||||
function handleInspectionRecordFieldTypeChange(e) {
|
||||
setDropDownOptionSelected(e);
|
||||
let selectedVal = $(e).val();
|
||||
switch (selectedVal) {
|
||||
case 'Radio':
|
||||
case 'Check':
|
||||
$.get('/Vehicle/GetAddInspectionRecordFieldOptionsPartialView', function (data) {
|
||||
$(e).closest('[data-type="field"]').find('[data-type="fieldOptions"]').html(data);
|
||||
});
|
||||
$(e).closest('[data-type="field"]').find('[data-type="fieldActionItem"]').show();
|
||||
break;
|
||||
case 'Text':
|
||||
$(e).closest('[data-type="field"]').find('[data-type="fieldOptions"]').html("");
|
||||
$(e).closest('[data-type="field"]').find('[data-type="fieldActionItem"]').hide();
|
||||
break;
|
||||
}
|
||||
}
|
||||
function handleInspectionRecordFieldHasActionItemChange(e) {
|
||||
if ($(e).is(":checked")) {
|
||||
$(e).closest('[data-type="field"]').find('[data-type="fieldActionItemContainer"]').collapse('show');
|
||||
} else {
|
||||
$(e).closest('[data-type="field"]').find('[data-type="fieldActionItemContainer"]').collapse('hide');
|
||||
}
|
||||
}
|
||||
function addInspectionRecordFieldOption(e) {
|
||||
$.get('/Vehicle/GetAddInspectionRecordFieldOptionPartialView', function (data) {
|
||||
$(e).closest('[data-type="field"]').find('[data-type="fieldOptions"]').append(data);
|
||||
});
|
||||
}
|
||||
function deleteInspectionRecordFieldOption(e) {
|
||||
$(e).closest('[data-type="fieldOption"]').remove();
|
||||
}
|
||||
function getAndValidateInspectionRecordTemplate() {
|
||||
let hasError = false;
|
||||
let inspectionDescription = $("#inspectionRecordDescription").val();
|
||||
if (inspectionDescription.trim() == '') {
|
||||
hasError = true;
|
||||
$("#inspectionRecordDescription").addClass("is-invalid");
|
||||
} else {
|
||||
$("#inspectionRecordDescription").removeClass("is-invalid");
|
||||
}
|
||||
let inspectionTags = $("#inspectionRecordTemplateTag").val();
|
||||
let inspectionRecordId = getInspectionRecordModelData().id;
|
||||
let vehicleId = GetVehicleId().vehicleId;
|
||||
let inspectionRecordTemplateData = {
|
||||
id: inspectionRecordId,
|
||||
vehicleId: vehicleId,
|
||||
description: inspectionDescription,
|
||||
tags: inspectionTags,
|
||||
reminderRecordId: recurringReminderRecordId
|
||||
}
|
||||
let templateFields = [];
|
||||
//process fields
|
||||
$('#inspectionRecordFields > [data-type="field"]').map((index, elem) => {
|
||||
let fieldElem = $(elem);
|
||||
let hasActionItem = fieldElem.find('[data-type="fieldHasActionItem"]').is(":checked");
|
||||
let fieldType = fieldElem.find('[data-type="fieldType"]').val();
|
||||
let fieldDescriptionElem = fieldElem.find('[data-type="fieldDescription"]');
|
||||
if (fieldDescriptionElem.val().trim() == '') {
|
||||
hasError = true;
|
||||
fieldDescriptionElem.addClass('is-invalid');
|
||||
} else {
|
||||
fieldDescriptionElem.removeClass('is-invalid');
|
||||
}
|
||||
let fieldData = {
|
||||
description: fieldDescriptionElem.val(),
|
||||
fieldType: fieldType,
|
||||
hasNotes: fieldElem.find('[data-type="fieldHasNotes"]').is(":checked"),
|
||||
hasActionItem: hasActionItem
|
||||
};
|
||||
if (hasActionItem) {
|
||||
fieldData["actionItemType"] = fieldElem.find('[data-type="fieldActionItemType"]').val();
|
||||
fieldData["actionItemPriority"] = fieldElem.find('[data-type="fieldActionItemPriority"]').val();
|
||||
let actionItemDescriptionElem = fieldElem.find('[data-type="fieldActionItemDescription"]');
|
||||
fieldData["actionItemDescription"] = actionItemDescriptionElem.val();
|
||||
if (actionItemDescriptionElem.val().trim() == '') {
|
||||
hasError = true;
|
||||
actionItemDescriptionElem.addClass('is-invalid');
|
||||
} else {
|
||||
actionItemDescriptionElem.removeClass('is-invalid');
|
||||
}
|
||||
}
|
||||
if (fieldType != 'Text') {
|
||||
let fieldOptions = [];
|
||||
fieldElem.find('[data-type="fieldOptions"]').find('[data-type="fieldOption"]').map((optionIndex, optionElem) => {
|
||||
let fieldOptionElem = $(optionElem);
|
||||
let fieldOptionTextElem = fieldOptionElem.find('[data-type="fieldOptionText"]');
|
||||
if (fieldOptionTextElem.val().trim() == '') {
|
||||
hasError = true;
|
||||
fieldOptionTextElem.addClass('is-invalid');
|
||||
} else {
|
||||
fieldOptionTextElem.removeClass('is-invalid');
|
||||
}
|
||||
fieldOptions.push({
|
||||
description: fieldOptionTextElem.val(),
|
||||
isFail: fieldOptionElem.find('[data-type="fieldOptionIsFail"]').is(":checked")
|
||||
});
|
||||
});
|
||||
fieldData["options"] = fieldOptions;
|
||||
if (fieldOptions.length == 0) {
|
||||
//user has not supplied any options
|
||||
fieldElem.find('[data-type="fieldType"]').addClass('is-invalid');
|
||||
hasError = true;
|
||||
} else {
|
||||
fieldElem.find('[data-type="fieldType"]').removeClass('is-invalid');
|
||||
}
|
||||
}
|
||||
else {
|
||||
fieldElem.find('[data-type="fieldType"]').removeClass('is-invalid');
|
||||
}
|
||||
templateFields.push(fieldData);
|
||||
});
|
||||
inspectionRecordTemplateData["fields"] = templateFields;
|
||||
inspectionRecordTemplateData["hasError"] = hasError;
|
||||
return inspectionRecordTemplateData;
|
||||
}
|
||||
function saveInspectionRecordTemplateToVehicle(isEdit) {
|
||||
let formValues = getAndValidateInspectionRecordTemplate();
|
||||
if (formValues.hasError) {
|
||||
errorToast("Please check the form data");
|
||||
return;
|
||||
}
|
||||
$.post('/Vehicle/SaveInspectionRecordTemplateToVehicleId', { inspectionRecordTemplate: formValues }, function (data) {
|
||||
if (data) {
|
||||
successToast(isEdit ? "Inspection Record Template Updated" : "Inspection Record Template Added.");
|
||||
hideInspectionRecordTemplateModal();
|
||||
getVehicleCollisionRecords(formValues.vehicleId);
|
||||
} else {
|
||||
errorToast(genericErrorMessage());
|
||||
}
|
||||
})
|
||||
}
|
||||
function deleteInspectionRecordTemplate(inspectionRecordTemplateId) {
|
||||
$("#workAroundInput").show();
|
||||
Swal.fire({
|
||||
title: "Confirm Deletion?",
|
||||
text: "Deleted Inspection Templates cannot be restored.",
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Delete",
|
||||
confirmButtonColor: "#dc3545"
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
$.post(`/Vehicle/DeleteInspectionRecordTemplateById?inspectionRecordTemplateId=${inspectionRecordTemplateId}`, function (data) {
|
||||
$("#workAroundInput").hide();
|
||||
if (data) {
|
||||
successToast("Inspection Template Deleted");
|
||||
hideInspectionRecordTemplateModal();
|
||||
} else {
|
||||
errorToast(genericErrorMessage());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$("#workAroundInput").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
function useInspectionRecordTemplate(inspectionRecordTemplateId) {
|
||||
$.get(`/Vehicle/GetAddInspectionRecordPartialView?inspectionRecordTemplateId=${inspectionRecordTemplateId}`, function (data) {
|
||||
if (data) {
|
||||
$("#inspectionRecordModalContent").html(data);
|
||||
hideInspectionRecordTemplateSelectorModal();
|
||||
//initiate datepicker
|
||||
initDatePicker($('#inspectionRecordDate'));
|
||||
initTagSelector($("#inspectionRecordTag"));
|
||||
$("#inspectionRecordModal").modal('show');
|
||||
clearModalContentOnHide($("#inspectionRecordModal"));
|
||||
} else {
|
||||
errorToast(genericErrorMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
function hideAddInspectionRecordModal(showSelector) {
|
||||
$("#inspectionRecordModalContent").html('');
|
||||
$("#inspectionRecordModal").modal('hide');
|
||||
if (showSelector) {
|
||||
showInspectionRecordTemplateSelectorModal();
|
||||
}
|
||||
}
|
||||
function getAndValidateInspectionRecord() {
|
||||
let hasError = false;
|
||||
let inspectionDescription = $("#inspectionRecordDescription").val();
|
||||
let inspectionDate = $("#inspectionRecordDate").val();
|
||||
let inspectionMileage = $("#inspectionRecordMileage").val();
|
||||
let inspectionCost = $("#inspectionRecordCost").val();
|
||||
let inspectionTags = $("#inspectionRecordTag").val();
|
||||
let inspectionRecordId = 0;
|
||||
var addReminderRecord = $("#addReminderCheck").is(":checked");
|
||||
let vehicleId = GetVehicleId().vehicleId;
|
||||
//Odometer Adjustments
|
||||
if (isNaN(inspectionMileage) && GetVehicleId().odometerOptional) {
|
||||
inspectionMileage = '0';
|
||||
}
|
||||
inspectionMileage = GetAdjustedOdometer(inspectionRecordId, inspectionMileage);
|
||||
//validations
|
||||
if (inspectionDescription.trim() == '') {
|
||||
hasError = true;
|
||||
$("#inspectionRecordDescription").addClass("is-invalid");
|
||||
} else {
|
||||
$("#inspectionRecordDescription").removeClass("is-invalid");
|
||||
}
|
||||
if (inspectionDate.trim() == '') { //eliminates whitespace.
|
||||
hasError = true;
|
||||
$("#inspectionRecordDate").addClass("is-invalid");
|
||||
} else {
|
||||
$("#inspectionRecordDate").removeClass("is-invalid");
|
||||
}
|
||||
if (inspectionMileage.trim() == '' || isNaN(inspectionMileage) || parseInt(inspectionMileage) < 0) {
|
||||
hasError = true;
|
||||
$("#inspectionRecordMileage").addClass("is-invalid");
|
||||
} else {
|
||||
$("#inspectionRecordMileage").removeClass("is-invalid");
|
||||
}
|
||||
if (inspectionCost.trim() == '' || !isValidMoney(inspectionCost)) {
|
||||
hasError = true;
|
||||
$("#inspectionRecordCost").addClass("is-invalid");
|
||||
} else {
|
||||
$("#inspectionRecordCost").removeClass("is-invalid");
|
||||
}
|
||||
let inspectionRecordData = {
|
||||
id: inspectionRecordId,
|
||||
vehicleId: vehicleId,
|
||||
date: inspectionDate,
|
||||
mileage: inspectionMileage,
|
||||
cost: inspectionCost,
|
||||
description: inspectionDescription,
|
||||
tags: inspectionTags,
|
||||
reminderRecordId: recurringReminderRecordId,
|
||||
files: uploadedFiles,
|
||||
addReminderRecord: addReminderRecord
|
||||
}
|
||||
let recordFields = [];
|
||||
//process fields
|
||||
$('#inspectionRecordFields > [data-type="field"]').map((index, elem) => {
|
||||
let fieldElem = $(elem);
|
||||
let hasActionItem = fieldElem.find('[data-type="fieldActionItemContainer"]').length > 0;
|
||||
let hasNotes = fieldElem.find('[data-type="fieldNotes"]').length > 0;
|
||||
let fieldType = fieldElem.attr('data-fieldtype');
|
||||
let fieldData = {
|
||||
description: fieldElem.find('[data-type="fieldDescription"]').text(),
|
||||
fieldType: fieldType,
|
||||
hasNotes: hasNotes,
|
||||
hasActionItem: hasActionItem
|
||||
};
|
||||
if (hasActionItem) {
|
||||
fieldData["actionItemDescription"] = fieldElem.find('[data-type="fieldActionItemDescription"]').val();
|
||||
fieldData["actionItemType"] = fieldElem.find('[data-type="fieldActionItemType"]').val();
|
||||
fieldData["actionItemPriority"] = fieldElem.find('[data-type="fieldActionItemPriority"]').val();
|
||||
}
|
||||
if (hasNotes) {
|
||||
let fieldNoteElem = fieldElem.find('[data-type="fieldNotes"]');
|
||||
fieldData["notes"] = fieldNoteElem.val();
|
||||
if (fieldNoteElem.val().trim() == '') {
|
||||
hasError = true;
|
||||
fieldNoteElem.addClass('is-invalid');
|
||||
} else {
|
||||
fieldNoteElem.removeClass('is-invalid');
|
||||
}
|
||||
}
|
||||
if (fieldType != 'Text') {
|
||||
let fieldOptions = [];
|
||||
fieldElem.find('[data-type="fieldOptions"]').find('[data-type="fieldOption"]').map((optionIndex, optionElem) => {
|
||||
let fieldOptionElem = $(optionElem);
|
||||
fieldOptions.push({
|
||||
description: fieldOptionElem.closest('[data-type="fieldOptionContainer"]').find('[data-type="fieldOptionText"]').text(),
|
||||
isSelected: fieldOptionElem.is(":checked"),
|
||||
isFail: fieldOptionElem.attr('data-field') == 'fail'
|
||||
});
|
||||
});
|
||||
fieldData["options"] = fieldOptions;
|
||||
//user must select at least one option for radio fields
|
||||
if (fieldType == 'Radio' && fieldOptions.filter(x=>x.isSelected).length == 0) {
|
||||
fieldElem.find('[data-type="fieldOptions"]').find('[data-type="fieldOption"]').addClass('is-invalid');
|
||||
hasError = true;
|
||||
} else {
|
||||
fieldElem.find('[data-type="fieldOptions"]').find('[data-type="fieldOption"]').removeClass('is-invalid');
|
||||
}
|
||||
} else {
|
||||
//handle text field
|
||||
let fieldOptions = [];
|
||||
let fieldTextOptionElem = fieldElem.find('[data-type="fieldOptions"]').find('[data-type="fieldOption"]');
|
||||
if (fieldTextOptionElem.val().trim() == '') {
|
||||
hasError = true;
|
||||
fieldTextOptionElem.addClass('is-invalid');
|
||||
} else {
|
||||
fieldTextOptionElem.removeClass('is-invalid');
|
||||
}
|
||||
fieldOptions.push({
|
||||
description: fieldTextOptionElem.val(),
|
||||
isSelected: true,
|
||||
isFail: false
|
||||
});
|
||||
fieldData["options"] = fieldOptions;
|
||||
}
|
||||
recordFields.push(fieldData);
|
||||
});
|
||||
inspectionRecordData["fields"] = recordFields;
|
||||
inspectionRecordData["hasError"] = hasError;
|
||||
return inspectionRecordData;
|
||||
}
|
||||
function saveinspectionRecordToVehicle() {
|
||||
//get values
|
||||
var formValues = getAndValidateInspectionRecord();
|
||||
//validate
|
||||
if (formValues.hasError) {
|
||||
errorToast("Please check the form data");
|
||||
return;
|
||||
}
|
||||
$.post('/Vehicle/SaveInspectionRecordToVehicleId', { inspectionRecord: formValues }, function (data) {
|
||||
if (data) {
|
||||
successToast("Inspection Record Added.");
|
||||
hideAddInspectionRecordModal();
|
||||
saveScrollPosition();
|
||||
getVehicleInspectionRecords(formValues.vehicleId);
|
||||
if (formValues.addReminderRecord) {
|
||||
setTimeout(function () { showAddReminderModal(formValues); }, 500);
|
||||
}
|
||||
} else {
|
||||
errorToast(genericErrorMessage());
|
||||
}
|
||||
})
|
||||
}
|
||||
function updateInspectionRecordTag(recordId) {
|
||||
let inspectionTags = $("#inspectionRecordTag").val();
|
||||
let vehicleId = GetVehicleId().vehicleId;
|
||||
$.post('/Vehicle/UpdateInspectionRecordTags', { inspectionRecordId: recordId, tags: inspectionTags }, function (data) {
|
||||
if (data) {
|
||||
successToast("Inspection Record Updated.");
|
||||
hideAddInspectionRecordModal();
|
||||
saveScrollPosition();
|
||||
getVehicleInspectionRecords(vehicleId);
|
||||
} else {
|
||||
errorToast(genericErrorMessage());
|
||||
}
|
||||
})
|
||||
}
|
||||
function showEditInspectionRecordModal(inspectionRecordId) {
|
||||
$.get(`/Vehicle/GetViewInspectionRecordPartialView?inspectionRecordId=${inspectionRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#inspectionRecordModalContent").html(data);
|
||||
//initiate tag selector
|
||||
initTagSelector($("#inspectionRecordTag"));
|
||||
$("#inspectionRecordModal").modal('show');
|
||||
clearModalContentOnHide($("#inspectionRecordModal"));
|
||||
} else {
|
||||
errorToast(genericErrorMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
function deleteInspectionRecord(inspectionRecordId) {
|
||||
$("#workAroundInput").show();
|
||||
Swal.fire({
|
||||
title: "Confirm Deletion?",
|
||||
text: "Deleted Inspection Records cannot be restored.",
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Delete",
|
||||
confirmButtonColor: "#dc3545"
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
$.post(`/Vehicle/DeleteInspectionRecordById?inspectionRecordId=${inspectionRecordId}`, function (data) {
|
||||
if (data) {
|
||||
hideAddInspectionRecordModal();
|
||||
successToast("Inspection Record Deleted");
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
getVehicleInspectionRecords(vehicleId);
|
||||
} else {
|
||||
errorToast(genericErrorMessage());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$("#workAroundInput").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
function moveInspectionRecordField(e, isDown) {
|
||||
let currentField = $(e).closest('[data-type="field"]');
|
||||
if (isDown) {
|
||||
let nextField = currentField.next('[data-type="field"]');
|
||||
if (nextField.length != 0) {
|
||||
currentField.insertAfter(nextField);
|
||||
}
|
||||
} else {
|
||||
let prevField = currentField.prev('[data-type="field"]');
|
||||
if (prevField.length != 0) {
|
||||
currentField.insertBefore(prevField);
|
||||
}
|
||||
}
|
||||
}
|
||||
function duplicateInspectionRecordTemplateToVehicle() {
|
||||
let inspectionRecordsIds = [];
|
||||
inspectionRecordsIds.push(getInspectionRecordModelData().id);
|
||||
duplicateRecordsToOtherVehicles(inspectionRecordsIds, 'InspectionRecord');
|
||||
}
|
||||
@ -412,10 +412,17 @@ function loadMapSearchResult(id, recordType) {
|
||||
hideDataTable();
|
||||
loadGlobalSearchResult(id, recordType);
|
||||
}
|
||||
function loadRecordAttachment(id, recordType) {
|
||||
closeAttachmentPreview();
|
||||
$(".modal.show").modal('hide');
|
||||
loadGlobalSearchResult(id, recordType);
|
||||
}
|
||||
function showCustomWidgets() {
|
||||
$("#vehicleCustomWidgetsModal").modal('show');
|
||||
}
|
||||
function loadCustomWidgets() {
|
||||
$.get('/Vehicle/GetAdditionalWidgets', function (data) {
|
||||
$("#vehicleCustomWidgetsModalContent").html(data);
|
||||
$("#vehicleCustomWidgetsModal").modal('show');
|
||||
})
|
||||
}
|
||||
function hideCustomWidgetsModal() {
|
||||
|
||||
@ -915,6 +915,9 @@ function deleteRecords(ids, source) {
|
||||
friendlySource = "Fuel Records";
|
||||
refreshDataCallBack = getVehicleGasRecords;
|
||||
break;
|
||||
case "InspectionRecord":
|
||||
friendlySource = "Inspection Records";
|
||||
refreshDataCallBack = getVehicleInspectionRecords;
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
@ -1061,6 +1064,9 @@ function duplicateRecordsToOtherVehicles(ids, source) {
|
||||
friendlySource = "Plan";
|
||||
refreshDataCallBack = getVehiclePlanRecords;
|
||||
break;
|
||||
case "InspectionRecord":
|
||||
friendlySource = "Inspection Records";
|
||||
refreshDataCallBack = getVehicleInspectionRecords;
|
||||
}
|
||||
|
||||
$.get(`/Home/GetVehicleSelector?vehicleId=${GetVehicleId().vehicleId}`, function (data) {
|
||||
@ -1783,4 +1789,17 @@ function getTabNameFromURL(defaultValue) {
|
||||
} else {
|
||||
return `${currentTab}-tab`;
|
||||
}
|
||||
}
|
||||
function stretchedLinkClick(e) {
|
||||
let closestCheckElem = $(e).closest('.form-check').find('.form-check-input');
|
||||
if (closestCheckElem.prop('checked')) {
|
||||
closestCheckElem.prop('checked', false).trigger('change');
|
||||
} else {
|
||||
closestCheckElem.prop('checked', true).trigger('change');
|
||||
}
|
||||
}
|
||||
function clearModalContentOnHide(modalElem) {
|
||||
modalElem.off('hidden.bs.modal').on('hidden.bs.modal', () => {
|
||||
modalElem.find('.modal-content').html('');
|
||||
});
|
||||
}
|
||||
@ -36,6 +36,9 @@
|
||||
case "odometer-tab":
|
||||
getVehicleOdometerRecords(vehicleId);
|
||||
break;
|
||||
case "inspection-tab":
|
||||
getVehicleInspectionRecords(vehicleId);
|
||||
break;
|
||||
}
|
||||
$(`.lubelogger-tab #${e.target.id}`).addClass('active');
|
||||
$(`.lubelogger-mobile-nav #${e.target.id}`).addClass('active');
|
||||
@ -74,6 +77,9 @@
|
||||
case "odometer-tab":
|
||||
$("#odometer-tab-pane").html("");
|
||||
break;
|
||||
case "inspection-tab":
|
||||
$("#inspection-tab-pane").html("");
|
||||
break;
|
||||
}
|
||||
$(`.lubelogger-tab #${e.relatedTarget.id}`).removeClass('active');
|
||||
$(`.lubelogger-mobile-nav #${e.relatedTarget.id}`).removeClass('active');
|
||||
@ -159,6 +165,7 @@ function getVehicleTaxRecords(vehicleId) {
|
||||
if (data) {
|
||||
$("#tax-tab-pane").html(data);
|
||||
restoreScrollPosition();
|
||||
getVehicleHaveImportantReminders(vehicleId);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -171,6 +178,15 @@ function getVehicleReminders(vehicleId) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function getVehicleInspectionRecords(vehicleId) {
|
||||
$.get(`/Vehicle/GetInspectionRecordsByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
$("#inspection-tab-pane").html(data);
|
||||
restoreScrollPosition();
|
||||
getVehicleHaveImportantReminders(vehicleId);
|
||||
}
|
||||
});
|
||||
}
|
||||
function getVehicleReport(vehicleId) {
|
||||
$.get(`/Vehicle/GetReportPartialView?vehicleId=${vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
@ -301,6 +317,21 @@ function moveRecord(recordId, source, dest) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function loadSelectedRecurringReminder() {
|
||||
if (recurringReminderRecordId != undefined && recurringReminderRecordId.length > 0) {
|
||||
if (recurringReminderRecordId.length > 1) {
|
||||
//multiple reminders
|
||||
$('#multipleRemindersCheck').prop('checked', true);
|
||||
$('#multipleRemindersCheck').trigger('change');
|
||||
recurringReminderRecordId.map(x => {
|
||||
$(`#recurringReminder_${x}`).prop('checked', true);
|
||||
});
|
||||
}
|
||||
else if (recurringReminderRecordId.length == 1) {
|
||||
$("#recurringReminderInput").val(recurringReminderRecordId[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
function showRecurringReminderSelector(descriptionFieldName, noteFieldName) {
|
||||
$.get(`/Vehicle/GetRecurringReminderRecordsByVehicleId?vehicleId=${GetVehicleId().vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
@ -310,6 +341,9 @@ function showRecurringReminderSelector(descriptionFieldName, noteFieldName) {
|
||||
html: data,
|
||||
confirmButtonText: 'Select',
|
||||
focusConfirm: false,
|
||||
didRender: () => {
|
||||
loadSelectedRecurringReminder();
|
||||
},
|
||||
preConfirm: () => {
|
||||
//validate
|
||||
var selectedRecurringReminderData = getAndValidateSelectedRecurringReminder();
|
||||
@ -671,48 +705,101 @@ function handleGlobalSearchKeyPress(event) {
|
||||
|
||||
function loadGlobalSearchResult(recordId, recordType) {
|
||||
hideGlobalSearch();
|
||||
switch (recordType) {
|
||||
case "ServiceRecord":
|
||||
$('#servicerecord-tab').tab('show');
|
||||
waitForElement('#serviceRecordModalContent', showEditServiceRecordModal, recordId);
|
||||
break;
|
||||
case "RepairRecord":
|
||||
$('#accident-tab').tab('show');
|
||||
waitForElement('#collisionRecordModalContent', showEditCollisionRecordModal, recordId);
|
||||
break;
|
||||
case "UpgradeRecord":
|
||||
$('#upgrade-tab').tab('show');
|
||||
waitForElement('#upgradeRecordModalContent', showEditUpgradeRecordModal, recordId);
|
||||
break;
|
||||
case "TaxRecord":
|
||||
$('#tax-tab').tab('show');
|
||||
waitForElement('#taxRecordModalContent', showEditTaxRecordModal, recordId);
|
||||
break;
|
||||
case "SupplyRecord":
|
||||
$('#supply-tab').tab('show');
|
||||
waitForElement('#supplyRecordModalContent', showEditSupplyRecordModal, recordId);
|
||||
break;
|
||||
case "NoteRecord":
|
||||
$('#notes-tab').tab('show');
|
||||
waitForElement('#noteModalContent', showEditNoteModal, recordId);
|
||||
break;
|
||||
case "OdometerRecord":
|
||||
$('#odometer-tab').tab('show');
|
||||
waitForElement('#odometerRecordModalContent', showEditOdometerRecordModal, recordId);
|
||||
break;
|
||||
case "ReminderRecord":
|
||||
$('#reminder-tab').tab('show');
|
||||
waitForElement('#reminderRecordModalContent', showEditReminderRecordModal, recordId);
|
||||
break;
|
||||
case "GasRecord":
|
||||
$('#gas-tab').tab('show');
|
||||
waitForElement('#gasRecordModalContent', showEditGasRecordModal, recordId);
|
||||
break;
|
||||
case "PlanRecord":
|
||||
$('#plan-tab').tab('show');
|
||||
waitForElement('#planRecordModalContent', showEditPlanRecordModal, recordId);
|
||||
break;
|
||||
}
|
||||
$.post(`/Vehicle/CheckRecordExist?vehicleId=${GetVehicleId().vehicleId}&importMode=${recordType}&recordId=${recordId}`, function (data) {
|
||||
if (data.success) {
|
||||
switch (recordType) {
|
||||
case "ServiceRecord":
|
||||
if ($('#servicerecord-tab').hasClass('d-none')) {
|
||||
errorToast(`${recordType} Tab Not Enabled`);
|
||||
return;
|
||||
}
|
||||
$('#servicerecord-tab').tab('show');
|
||||
waitForElement('#serviceRecordModalContent', showEditServiceRecordModal, recordId);
|
||||
break;
|
||||
case "RepairRecord":
|
||||
if ($('#accident-tab').hasClass('d-none')) {
|
||||
errorToast(`${recordType} Tab Not Enabled`);
|
||||
return;
|
||||
}
|
||||
$('#accident-tab').tab('show');
|
||||
waitForElement('#collisionRecordModalContent', showEditCollisionRecordModal, recordId);
|
||||
break;
|
||||
case "UpgradeRecord":
|
||||
if ($('#upgrade-tab').hasClass('d-none')) {
|
||||
errorToast(`${recordType} Tab Not Enabled`);
|
||||
return;
|
||||
}
|
||||
$('#upgrade-tab').tab('show');
|
||||
waitForElement('#upgradeRecordModalContent', showEditUpgradeRecordModal, recordId);
|
||||
break;
|
||||
case "TaxRecord":
|
||||
if ($('#tax-tab').hasClass('d-none')) {
|
||||
errorToast(`${recordType} Tab Not Enabled`);
|
||||
return;
|
||||
}
|
||||
$('#tax-tab').tab('show');
|
||||
waitForElement('#taxRecordModalContent', showEditTaxRecordModal, recordId);
|
||||
break;
|
||||
case "SupplyRecord":
|
||||
if ($('#supply-tab').hasClass('d-none')) {
|
||||
errorToast(`${recordType} Tab Not Enabled`);
|
||||
return;
|
||||
}
|
||||
$('#supply-tab').tab('show');
|
||||
waitForElement('#supplyRecordModalContent', showEditSupplyRecordModal, recordId);
|
||||
break;
|
||||
case "NoteRecord":
|
||||
if ($('#notes-tab').hasClass('d-none')) {
|
||||
errorToast(`${recordType} Tab Not Enabled`);
|
||||
return;
|
||||
}
|
||||
$('#notes-tab').tab('show');
|
||||
waitForElement('#noteModalContent', showEditNoteModal, recordId);
|
||||
break;
|
||||
case "OdometerRecord":
|
||||
if ($('#odometer-tab').hasClass('d-none')) {
|
||||
errorToast(`${recordType} Tab Not Enabled`);
|
||||
return;
|
||||
}
|
||||
$('#odometer-tab').tab('show');
|
||||
waitForElement('#odometerRecordModalContent', showEditOdometerRecordModal, recordId);
|
||||
break;
|
||||
case "ReminderRecord":
|
||||
if ($('#reminder-tab').hasClass('d-none')) {
|
||||
errorToast(`${recordType} Tab Not Enabled`);
|
||||
return;
|
||||
}
|
||||
$('#reminder-tab').tab('show');
|
||||
waitForElement('#reminderRecordModalContent', showEditReminderRecordModal, recordId);
|
||||
break;
|
||||
case "GasRecord":
|
||||
if ($('#gas-tab').hasClass('d-none')) {
|
||||
errorToast(`${recordType} Tab Not Enabled`);
|
||||
return;
|
||||
}
|
||||
$('#gas-tab').tab('show');
|
||||
waitForElement('#gasRecordModalContent', showEditGasRecordModal, recordId);
|
||||
break;
|
||||
case "PlanRecord":
|
||||
if ($('#plan-tab').hasClass('d-none')) {
|
||||
errorToast(`${recordType} Tab Not Enabled`);
|
||||
return;
|
||||
}
|
||||
$('#plan-tab').tab('show');
|
||||
waitForElement('#planRecordModalContent', showEditPlanRecordModal, recordId);
|
||||
break;
|
||||
case "InspectionRecord":
|
||||
if ($('#inspection-tab').hasClass('d-none')) {
|
||||
errorToast(`${recordType} Tab Not Enabled`);
|
||||
return;
|
||||
}
|
||||
$('#inspection-tab').tab('show');
|
||||
waitForElement("#inspectionRecordModalContent", showEditInspectionRecordModal, recordId);
|
||||
}
|
||||
} else {
|
||||
errorToast(data.message);
|
||||
}
|
||||
})
|
||||
}
|
||||
function loadDefaultTab() {
|
||||
//check if tab param exists
|
||||
@ -756,5 +843,8 @@ function getDefaultTabName() {
|
||||
case "OdometerRecord":
|
||||
return 'odometer';
|
||||
break;
|
||||
case "InspectionRecord":
|
||||
return 'inspection';
|
||||
break;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user