Compare commits
115 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64ea0e2eee | ||
|
|
7ab476a88f | ||
|
|
de41ca911d | ||
|
|
dde9688f96 | ||
|
|
c1ca63edc0 | ||
|
|
cbc430499f | ||
|
|
4da9fa4802 | ||
|
|
42586d9556 | ||
|
|
ea4387d4ab | ||
|
|
0707b515ab | ||
|
|
78ae71fc46 | ||
|
|
3f62cd40e7 | ||
|
|
47657c0093 | ||
|
|
a5b0fde4b6 | ||
|
|
78cc0b34b1 | ||
|
|
e3017e986b | ||
|
|
e12cd876db | ||
|
|
5292e4b814 | ||
|
|
dbdd16ab89 | ||
|
|
ddc3c2e1b5 | ||
|
|
49184b287b | ||
|
|
f6139bda0d | ||
|
|
a6471b823b | ||
|
|
7c34003647 | ||
|
|
1aa21f9980 | ||
|
|
ce4ca50939 | ||
|
|
fb28260c4a | ||
|
|
626a904747 | ||
|
|
893cdafdc5 | ||
|
|
dbfb7d7d9c | ||
|
|
a66538a7db | ||
|
|
2f77d87d4f | ||
|
|
de85ba984c | ||
|
|
caac1a05ae | ||
|
|
eb5793b819 | ||
|
|
5ef3e1e2ce | ||
|
|
d8b459e5ee | ||
|
|
7b40d58aa1 | ||
|
|
809e9b838e | ||
|
|
23ae36ebd9 | ||
|
|
9c3f7d20f5 | ||
|
|
083298303c | ||
|
|
224970a07e | ||
|
|
86d039e5b0 | ||
|
|
6a8038aac9 | ||
|
|
e748f08a8e | ||
|
|
3580963e9f | ||
|
|
b008ce2ab8 | ||
|
|
ea0c2c7061 | ||
|
|
0926220933 | ||
|
|
ca975bbdd3 | ||
|
|
b16c5c5302 | ||
|
|
cad05fe5d9 | ||
|
|
a7cd466d9c | ||
|
|
4472a67ec0 | ||
|
|
c84a4029ec | ||
|
|
d7d9ab505e | ||
|
|
c582f5f5c7 | ||
|
|
4c30939339 | ||
|
|
cecd6a1d2b | ||
|
|
853dcbb364 | ||
|
|
ae327ed26d | ||
|
|
3e416aa255 | ||
|
|
61c2c3fc83 | ||
|
|
ca749aaf1e | ||
|
|
2a2cb3bd0c | ||
|
|
44e3d19844 | ||
|
|
1e25fffc70 | ||
|
|
44645ed23d | ||
|
|
fa557e5f76 | ||
|
|
7202fda38e | ||
|
|
d05afe41d6 | ||
|
|
bfc0b58728 | ||
|
|
22e8aaca81 | ||
|
|
5cb1247fb2 | ||
|
|
17a6d99703 | ||
|
|
3e7917f767 | ||
|
|
e9277d4dd9 | ||
|
|
058edd8af6 | ||
|
|
8ed7dcb9ff | ||
|
|
1f4827abc0 | ||
|
|
9715a0fcf7 | ||
|
|
9bf475c352 | ||
|
|
c2aeb4bca0 | ||
|
|
07b3020999 | ||
|
|
c2a7f39025 | ||
|
|
a92d422972 | ||
|
|
345eb65c3a | ||
|
|
a459973983 | ||
|
|
470dd4d78a | ||
|
|
e4cb183140 | ||
|
|
6455af96bf | ||
|
|
42afa87464 | ||
|
|
97466eeff2 | ||
|
|
bcbfd4ba9c | ||
|
|
cfa052fc31 | ||
|
|
3f71f6a8d8 | ||
|
|
b70e442ca3 | ||
|
|
1f60b2aadc | ||
|
|
3d2117ddaf | ||
|
|
bcff18ea58 | ||
|
|
2e9821402f | ||
|
|
8914c5cd51 | ||
|
|
0b240498f9 | ||
|
|
16f66364cf | ||
|
|
f2b0cec427 | ||
|
|
fac05ff5c0 | ||
|
|
1ac6dfd2a6 | ||
|
|
8bcac7344f | ||
|
|
300c986abb | ||
|
|
91a5f92df6 | ||
|
|
d60a09d48f | ||
|
|
b22bb7c7ad | ||
|
|
63cddc4ab0 | ||
|
|
790061d5c4 |
14
.github/FUNDING.yml
vendored
Normal file
14
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: lubelogger
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
polar: # Replace with a single Polar username
|
||||
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@ wwwroot/translations/
|
||||
config/userConfig.json
|
||||
CarCareTracker.csproj.user
|
||||
Properties/launchSettings.json
|
||||
data/cartracker-log.db
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CsvHelper" Version="30.0.1" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.17" />
|
||||
<PackageReference Include="MailKit" Version="4.5.0" />
|
||||
<PackageReference Include="Npgsql" Version="8.0.2" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using CarCareTracker.External.Implementations;
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Filter;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Logic;
|
||||
@@ -27,6 +26,7 @@ namespace CarCareTracker.Controllers
|
||||
private readonly IReminderHelper _reminderHelper;
|
||||
private readonly IGasHelper _gasHelper;
|
||||
private readonly IUserLogic _userLogic;
|
||||
private readonly IVehicleLogic _vehicleLogic;
|
||||
private readonly IOdometerLogic _odometerLogic;
|
||||
private readonly IFileHelper _fileHelper;
|
||||
private readonly IMailHelper _mailHelper;
|
||||
@@ -48,6 +48,7 @@ namespace CarCareTracker.Controllers
|
||||
IFileHelper fileHelper,
|
||||
IConfigHelper config,
|
||||
IUserLogic userLogic,
|
||||
IVehicleLogic vehicleLogic,
|
||||
IOdometerLogic odometerLogic)
|
||||
{
|
||||
_dataAccess = dataAccess;
|
||||
@@ -66,6 +67,7 @@ namespace CarCareTracker.Controllers
|
||||
_reminderHelper = reminderHelper;
|
||||
_userLogic = userLogic;
|
||||
_odometerLogic = odometerLogic;
|
||||
_vehicleLogic = vehicleLogic;
|
||||
_fileHelper = fileHelper;
|
||||
_config = config;
|
||||
}
|
||||
@@ -351,7 +353,7 @@ namespace CarCareTracker.Controllers
|
||||
[Route("/api/vehicle/odometerrecords/latest")]
|
||||
public IActionResult LastOdometer(int vehicleId)
|
||||
{
|
||||
var result = GetMaxMileage(vehicleId);
|
||||
var result = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||
return Json(result);
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
@@ -500,7 +502,7 @@ namespace CarCareTracker.Controllers
|
||||
[Route("/api/vehicle/reminders")]
|
||||
public IActionResult Reminders(int vehicleId)
|
||||
{
|
||||
var currentMileage = GetMaxMileage(vehicleId);
|
||||
var currentMileage = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
||||
var results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, DateTime.Now).Select(x=> new ReminderExportModel { Description = x.Description, Urgency = x.Urgency.ToString(), Metric = x.Metric.ToString(), Notes = x.Notes});
|
||||
return Json(results);
|
||||
@@ -516,7 +518,7 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
var vehicleId = vehicle.Id;
|
||||
//get reminders
|
||||
var currentMileage = GetMaxMileage(vehicleId);
|
||||
var currentMileage = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||
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));
|
||||
@@ -566,35 +568,5 @@ namespace CarCareTracker.Controllers
|
||||
var result = _fileHelper.RestoreBackup("/defaults/demo_default.zip", true);
|
||||
return Json(result);
|
||||
}
|
||||
private int GetMaxMileage(int vehicleId)
|
||||
{
|
||||
var numbersArray = new List<int>();
|
||||
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
||||
if (serviceRecords.Any())
|
||||
{
|
||||
numbersArray.Add(serviceRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var repairRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
|
||||
if (repairRecords.Any())
|
||||
{
|
||||
numbersArray.Add(repairRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
|
||||
if (gasRecords.Any())
|
||||
{
|
||||
numbersArray.Add(gasRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
||||
if (upgradeRecords.Any())
|
||||
{
|
||||
numbersArray.Add(upgradeRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||
if (odometerRecords.Any())
|
||||
{
|
||||
numbersArray.Add(odometerRecords.Max(x => x.Mileage));
|
||||
}
|
||||
return numbersArray.Any() ? numbersArray.Max() : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace CarCareTracker.Controllers
|
||||
private readonly IVehicleDataAccess _dataAccess;
|
||||
private readonly IUserLogic _userLogic;
|
||||
private readonly ILoginLogic _loginLogic;
|
||||
private readonly IVehicleLogic _vehicleLogic;
|
||||
private readonly IFileHelper _fileHelper;
|
||||
private readonly IConfigHelper _config;
|
||||
private readonly IExtraFieldDataAccess _extraFieldDataAccess;
|
||||
@@ -25,6 +26,7 @@ namespace CarCareTracker.Controllers
|
||||
IVehicleDataAccess dataAccess,
|
||||
IUserLogic userLogic,
|
||||
ILoginLogic loginLogic,
|
||||
IVehicleLogic vehicleLogic,
|
||||
IConfigHelper configuration,
|
||||
IFileHelper fileHelper,
|
||||
IExtraFieldDataAccess extraFieldDataAccess,
|
||||
@@ -40,6 +42,7 @@ namespace CarCareTracker.Controllers
|
||||
_reminderRecordDataAccess = reminderRecordDataAccess;
|
||||
_reminderHelper = reminderHelper;
|
||||
_loginLogic = loginLogic;
|
||||
_vehicleLogic = vehicleLogic;
|
||||
}
|
||||
private int GetUserID()
|
||||
{
|
||||
@@ -56,7 +59,23 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
vehiclesStored = _userLogic.FilterUserVehicles(vehiclesStored, GetUserID());
|
||||
}
|
||||
return PartialView("_GarageDisplay", vehiclesStored);
|
||||
var vehicleViewModels = vehiclesStored.Select(x => new VehicleViewModel
|
||||
{
|
||||
Id = x.Id,
|
||||
ImageLocation = x.ImageLocation,
|
||||
Year = x.Year,
|
||||
Make = x.Make,
|
||||
Model = x.Model,
|
||||
LicensePlate = x.LicensePlate,
|
||||
SoldDate = x.SoldDate,
|
||||
IsElectric = x.IsElectric,
|
||||
UseHours = x.UseHours,
|
||||
ExtraFields = x.ExtraFields,
|
||||
Tags = x.Tags,
|
||||
LastReportedMileage = _vehicleLogic.GetMaxMileage(x.Id),
|
||||
HasReminders = _vehicleLogic.GetVehicleHasUrgentOrPastDueReminders(x.Id)
|
||||
}).ToList();
|
||||
return PartialView("_GarageDisplay", vehicleViewModels);
|
||||
}
|
||||
public IActionResult Calendar()
|
||||
{
|
||||
@@ -86,7 +105,7 @@ namespace CarCareTracker.Controllers
|
||||
var reminderUrgency = _reminderHelper.GetReminderRecordViewModels(new List<ReminderRecord> { reminder }, 0, DateTime.Now).FirstOrDefault();
|
||||
return PartialView("_ReminderRecordCalendarModal", reminderUrgency);
|
||||
}
|
||||
public IActionResult Settings()
|
||||
public async Task<IActionResult> Settings()
|
||||
{
|
||||
var userConfig = _config.GetUserConfig(User);
|
||||
var languages = _fileHelper.GetLanguages();
|
||||
@@ -95,6 +114,16 @@ namespace CarCareTracker.Controllers
|
||||
UserConfig = userConfig,
|
||||
UILanguages = languages
|
||||
};
|
||||
try
|
||||
{
|
||||
var httpClient = new HttpClient();
|
||||
var sponsorsData = await httpClient.GetFromJsonAsync<Sponsors>(StaticHelper.SponsorsPath) ?? new Sponsors();
|
||||
viewModel.Sponsors = sponsorsData;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError($"Unable to retrieve sponsors: {ex.Message}");
|
||||
}
|
||||
return PartialView("_Settings", viewModel);
|
||||
}
|
||||
[HttpPost]
|
||||
|
||||
@@ -29,6 +29,18 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
public IActionResult Index(string redirectURL = "")
|
||||
{
|
||||
var remoteAuthConfig = _config.GetOpenIDConfig();
|
||||
if (remoteAuthConfig.DisableRegularLogin && !string.IsNullOrWhiteSpace(remoteAuthConfig.LogOutURL))
|
||||
{
|
||||
var generatedState = Guid.NewGuid().ToString().Substring(0, 8);
|
||||
remoteAuthConfig.State = generatedState;
|
||||
if (remoteAuthConfig.ValidateState)
|
||||
{
|
||||
Response.Cookies.Append("OIDC_STATE", remoteAuthConfig.State, new CookieOptions { Expires = new DateTimeOffset(DateTime.Now.AddMinutes(5)) });
|
||||
}
|
||||
var remoteAuthURL = remoteAuthConfig.RemoteAuthURL;
|
||||
return Redirect(remoteAuthURL);
|
||||
}
|
||||
return View(model: redirectURL);
|
||||
}
|
||||
public IActionResult Registration()
|
||||
@@ -248,7 +260,12 @@ namespace CarCareTracker.Controllers
|
||||
public IActionResult LogOut()
|
||||
{
|
||||
Response.Cookies.Delete("ACCESS_TOKEN");
|
||||
return Json(true);
|
||||
var remoteAuthConfig = _config.GetOpenIDConfig();
|
||||
if (remoteAuthConfig.DisableRegularLogin && !string.IsNullOrWhiteSpace(remoteAuthConfig.LogOutURL))
|
||||
{
|
||||
return Json(remoteAuthConfig.LogOutURL);
|
||||
}
|
||||
return Json("/Login");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Models;
|
||||
using LiteDB;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using CarCareTracker.Helper;
|
||||
using CsvHelper;
|
||||
@@ -10,6 +9,7 @@ using CarCareTracker.MapProfile;
|
||||
using System.Security.Claims;
|
||||
using CarCareTracker.Logic;
|
||||
using CarCareTracker.Filter;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace CarCareTracker.Controllers
|
||||
{
|
||||
@@ -37,6 +37,7 @@ namespace CarCareTracker.Controllers
|
||||
private readonly IReportHelper _reportHelper;
|
||||
private readonly IUserLogic _userLogic;
|
||||
private readonly IOdometerLogic _odometerLogic;
|
||||
private readonly IVehicleLogic _vehicleLogic;
|
||||
private readonly IExtraFieldDataAccess _extraFieldDataAccess;
|
||||
|
||||
public VehicleController(ILogger<VehicleController> logger,
|
||||
@@ -59,6 +60,7 @@ namespace CarCareTracker.Controllers
|
||||
IExtraFieldDataAccess extraFieldDataAccess,
|
||||
IUserLogic userLogic,
|
||||
IOdometerLogic odometerLogic,
|
||||
IVehicleLogic vehicleLogic,
|
||||
IWebHostEnvironment webEnv,
|
||||
IConfigHelper config)
|
||||
{
|
||||
@@ -82,6 +84,7 @@ namespace CarCareTracker.Controllers
|
||||
_extraFieldDataAccess = extraFieldDataAccess;
|
||||
_userLogic = userLogic;
|
||||
_odometerLogic = odometerLogic;
|
||||
_vehicleLogic = vehicleLogic;
|
||||
_webEnv = webEnv;
|
||||
_config = config;
|
||||
}
|
||||
@@ -823,11 +826,18 @@ namespace CarCareTracker.Controllers
|
||||
if (serviceRecord.Supplies.Any())
|
||||
{
|
||||
serviceRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(serviceRecord.Supplies, DateTime.Parse(serviceRecord.Date), serviceRecord.Description);
|
||||
if (serviceRecord.CopySuppliesAttachment)
|
||||
{
|
||||
serviceRecord.Files.AddRange(GetSuppliesAttachments(serviceRecord.Supplies));
|
||||
}
|
||||
}
|
||||
//push back any reminders
|
||||
if (serviceRecord.ReminderRecordId != default)
|
||||
if (serviceRecord.ReminderRecordId.Any())
|
||||
{
|
||||
PushbackRecurringReminderRecordWithChecks(serviceRecord.ReminderRecordId);
|
||||
foreach(int reminderRecordId in serviceRecord.ReminderRecordId)
|
||||
{
|
||||
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(serviceRecord.Date), serviceRecord.Mileage);
|
||||
}
|
||||
}
|
||||
var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord());
|
||||
if (result)
|
||||
@@ -908,11 +918,18 @@ namespace CarCareTracker.Controllers
|
||||
if (collisionRecord.Supplies.Any())
|
||||
{
|
||||
collisionRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(collisionRecord.Supplies, DateTime.Parse(collisionRecord.Date), collisionRecord.Description);
|
||||
if (collisionRecord.CopySuppliesAttachment)
|
||||
{
|
||||
collisionRecord.Files.AddRange(GetSuppliesAttachments(collisionRecord.Supplies));
|
||||
}
|
||||
}
|
||||
//push back any reminders
|
||||
if (collisionRecord.ReminderRecordId != default)
|
||||
if (collisionRecord.ReminderRecordId.Any())
|
||||
{
|
||||
PushbackRecurringReminderRecordWithChecks(collisionRecord.ReminderRecordId);
|
||||
foreach (int reminderRecordId in collisionRecord.ReminderRecordId)
|
||||
{
|
||||
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(collisionRecord.Date), collisionRecord.Mileage);
|
||||
}
|
||||
}
|
||||
var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord());
|
||||
if (result)
|
||||
@@ -1021,9 +1038,12 @@ namespace CarCareTracker.Controllers
|
||||
//move files from temp.
|
||||
taxRecord.Files = taxRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||
//push back any reminders
|
||||
if (taxRecord.ReminderRecordId != default)
|
||||
if (taxRecord.ReminderRecordId.Any())
|
||||
{
|
||||
PushbackRecurringReminderRecordWithChecks(taxRecord.ReminderRecordId);
|
||||
foreach (int reminderRecordId in taxRecord.ReminderRecordId)
|
||||
{
|
||||
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(taxRecord.Date), null);
|
||||
}
|
||||
}
|
||||
var result = _taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord.ToTaxRecord());
|
||||
if (result)
|
||||
@@ -1133,6 +1153,10 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
numbersArray.Add(upgradeRecords.Min(x => x.Date.Year));
|
||||
}
|
||||
if (odometerRecords.Any())
|
||||
{
|
||||
numbersArray.Add(odometerRecords.Min(x => x.Date.Year));
|
||||
}
|
||||
var minYear = numbersArray.Any() ? numbersArray.Min() : DateTime.Now.AddYears(-5).Year;
|
||||
var yearDifference = DateTime.Now.Year - minYear + 1;
|
||||
for (int i = 0; i < yearDifference; i++)
|
||||
@@ -1313,26 +1337,43 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
var vehicleHistory = new VehicleHistoryViewModel();
|
||||
vehicleHistory.VehicleData = _dataAccess.GetVehicleById(vehicleId);
|
||||
var maxMileage = GetMaxMileage(vehicleId);
|
||||
var maxMileage = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||
vehicleHistory.Odometer = maxMileage.ToString("N0");
|
||||
var minMileage = GetMinMileage(vehicleId);
|
||||
var minMileage = _vehicleLogic.GetMinMileage(vehicleId);
|
||||
var distanceTraveled = maxMileage - minMileage;
|
||||
if (!string.IsNullOrWhiteSpace(vehicleHistory.VehicleData.PurchaseDate))
|
||||
{
|
||||
var endDate = vehicleHistory.VehicleData.SoldDate;
|
||||
int daysOwned = 0;
|
||||
if (string.IsNullOrWhiteSpace(endDate))
|
||||
{
|
||||
endDate = DateTime.Now.ToShortDateString();
|
||||
}
|
||||
try
|
||||
{
|
||||
vehicleHistory.DaysOwned = (DateTime.Parse(endDate) - DateTime.Parse(vehicleHistory.VehicleData.PurchaseDate)).Days.ToString("N0");
|
||||
daysOwned = (DateTime.Parse(endDate) - DateTime.Parse(vehicleHistory.VehicleData.PurchaseDate)).Days;
|
||||
vehicleHistory.DaysOwned = daysOwned.ToString("N0");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
vehicleHistory.DaysOwned = string.Empty;
|
||||
}
|
||||
//calculate depreciation
|
||||
var totalDepreciation = vehicleHistory.VehicleData.PurchasePrice - vehicleHistory.VehicleData.SoldPrice;
|
||||
//we only calculate depreciation if a sold price is provided.
|
||||
if (totalDepreciation != default && vehicleHistory.VehicleData.SoldPrice != default)
|
||||
{
|
||||
vehicleHistory.TotalDepreciation = totalDepreciation;
|
||||
if (daysOwned != default)
|
||||
{
|
||||
vehicleHistory.DepreciationPerDay = Math.Abs(totalDepreciation / daysOwned);
|
||||
}
|
||||
if (distanceTraveled != default)
|
||||
{
|
||||
vehicleHistory.DepreciationPerMile = Math.Abs(totalDepreciation / distanceTraveled);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<GenericReportModel> reportData = new List<GenericReportModel>();
|
||||
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
||||
@@ -1483,78 +1524,14 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
#endregion
|
||||
#region "Reminders"
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
private int GetMaxMileage(int vehicleId)
|
||||
{
|
||||
var numbersArray = new List<int>();
|
||||
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
||||
if (serviceRecords.Any())
|
||||
{
|
||||
numbersArray.Add(serviceRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var repairRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
|
||||
if (repairRecords.Any())
|
||||
{
|
||||
numbersArray.Add(repairRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
|
||||
if (gasRecords.Any())
|
||||
{
|
||||
numbersArray.Add(gasRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
||||
if (upgradeRecords.Any())
|
||||
{
|
||||
numbersArray.Add(upgradeRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||
if (odometerRecords.Any())
|
||||
{
|
||||
numbersArray.Add(odometerRecords.Max(x => x.Mileage));
|
||||
}
|
||||
return numbersArray.Any() ? numbersArray.Max() : 0;
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
private int GetMinMileage(int vehicleId)
|
||||
{
|
||||
var numbersArray = new List<int>();
|
||||
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
|
||||
if (serviceRecords.Any())
|
||||
{
|
||||
numbersArray.Add(serviceRecords.Min(x => x.Mileage));
|
||||
}
|
||||
var repairRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
|
||||
if (repairRecords.Any())
|
||||
{
|
||||
numbersArray.Add(repairRecords.Min(x => x.Mileage));
|
||||
}
|
||||
var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
|
||||
if (gasRecords.Any())
|
||||
{
|
||||
numbersArray.Add(gasRecords.Min(x => x.Mileage));
|
||||
}
|
||||
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
|
||||
if (upgradeRecords.Any())
|
||||
{
|
||||
numbersArray.Add(upgradeRecords.Min(x => x.Mileage));
|
||||
}
|
||||
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
|
||||
if (odometerRecords.Any())
|
||||
{
|
||||
numbersArray.Add(odometerRecords.Min(x => x.Mileage));
|
||||
}
|
||||
return numbersArray.Any() ? numbersArray.Min() : 0;
|
||||
}
|
||||
private List<ReminderRecordViewModel> GetRemindersAndUrgency(int vehicleId, DateTime dateCompare)
|
||||
{
|
||||
var currentMileage = GetMaxMileage(vehicleId);
|
||||
var currentMileage = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
||||
List<ReminderRecordViewModel> results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, dateCompare);
|
||||
return results;
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
[HttpGet]
|
||||
public IActionResult GetVehicleHaveUrgentOrPastDueReminders(int vehicleId)
|
||||
private bool GetAndUpdateVehicleUrgentOrPastDueReminders(int vehicleId)
|
||||
{
|
||||
var result = GetRemindersAndUrgency(vehicleId, DateTime.Now);
|
||||
//check if user wants auto-refresh past-due reminders
|
||||
@@ -1569,7 +1546,7 @@ namespace CarCareTracker.Controllers
|
||||
//update based on recurring intervals.
|
||||
//pull reminderRecord based on ID
|
||||
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecord.Id);
|
||||
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder);
|
||||
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder, null, null);
|
||||
//save to db.
|
||||
_reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
|
||||
//set urgency to not urgent so it gets excluded in count.
|
||||
@@ -1581,9 +1558,16 @@ namespace CarCareTracker.Controllers
|
||||
var pastDueAndUrgentReminders = result.Where(x => x.Urgency == ReminderUrgency.VeryUrgent || x.Urgency == ReminderUrgency.PastDue);
|
||||
if (pastDueAndUrgentReminders.Any())
|
||||
{
|
||||
return Json(true);
|
||||
return true;
|
||||
}
|
||||
return Json(false);
|
||||
return false;
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
[HttpGet]
|
||||
public IActionResult GetVehicleHaveUrgentOrPastDueReminders(int vehicleId)
|
||||
{
|
||||
var result = GetAndUpdateVehicleUrgentOrPastDueReminders(vehicleId);
|
||||
return Json(result);
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
[HttpGet]
|
||||
@@ -1603,17 +1587,17 @@ namespace CarCareTracker.Controllers
|
||||
[HttpPost]
|
||||
public IActionResult PushbackRecurringReminderRecord(int reminderRecordId)
|
||||
{
|
||||
var result = PushbackRecurringReminderRecordWithChecks(reminderRecordId);
|
||||
var result = PushbackRecurringReminderRecordWithChecks(reminderRecordId, null, null);
|
||||
return Json(result);
|
||||
}
|
||||
private bool PushbackRecurringReminderRecordWithChecks(int reminderRecordId)
|
||||
private bool PushbackRecurringReminderRecordWithChecks(int reminderRecordId, DateTime? currentDate, int? currentMileage)
|
||||
{
|
||||
try
|
||||
{
|
||||
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecordId);
|
||||
if (existingReminder is not null && existingReminder.Id != default && existingReminder.IsRecurring)
|
||||
{
|
||||
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder);
|
||||
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder, currentDate, currentMileage);
|
||||
//save to db.
|
||||
var reminderUpdateResult = _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
|
||||
if (!reminderUpdateResult)
|
||||
@@ -1675,7 +1659,8 @@ namespace CarCareTracker.Controllers
|
||||
ReminderMileageInterval = result.ReminderMileageInterval,
|
||||
ReminderMonthInterval = result.ReminderMonthInterval,
|
||||
CustomMileageInterval = result.CustomMileageInterval,
|
||||
CustomMonthInterval = result.CustomMonthInterval
|
||||
CustomMonthInterval = result.CustomMonthInterval,
|
||||
Tags = result.Tags
|
||||
};
|
||||
return PartialView("_ReminderRecordModal", convertedResult);
|
||||
}
|
||||
@@ -1725,11 +1710,18 @@ namespace CarCareTracker.Controllers
|
||||
if (upgradeRecord.Supplies.Any())
|
||||
{
|
||||
upgradeRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(upgradeRecord.Supplies, DateTime.Parse(upgradeRecord.Date), upgradeRecord.Description);
|
||||
if (upgradeRecord.CopySuppliesAttachment)
|
||||
{
|
||||
upgradeRecord.Files.AddRange(GetSuppliesAttachments(upgradeRecord.Supplies));
|
||||
}
|
||||
}
|
||||
//push back any reminders
|
||||
if (upgradeRecord.ReminderRecordId != default)
|
||||
if (upgradeRecord.ReminderRecordId.Any())
|
||||
{
|
||||
PushbackRecurringReminderRecordWithChecks(upgradeRecord.ReminderRecordId);
|
||||
foreach (int reminderRecordId in upgradeRecord.ReminderRecordId)
|
||||
{
|
||||
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(upgradeRecord.Date), upgradeRecord.Mileage);
|
||||
}
|
||||
}
|
||||
var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord.ToUpgradeRecord());
|
||||
if (result)
|
||||
@@ -1863,6 +1855,16 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private List<UploadedFiles> GetSuppliesAttachments(List<SupplyUsage> supplyUsage)
|
||||
{
|
||||
List<UploadedFiles> results = new List<UploadedFiles>();
|
||||
foreach(SupplyUsage supply in supplyUsage)
|
||||
{
|
||||
var result = _supplyRecordDataAccess.GetSupplyRecordById(supply.SupplyId);
|
||||
results.AddRange(result.Files);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
private List<SupplyUsageHistory> RequisitionSupplyRecordsByUsage(List<SupplyUsage> supplyUsage, DateTime dateRequisitioned, string usageDescription)
|
||||
{
|
||||
List<SupplyUsageHistory> results = new List<SupplyUsageHistory>();
|
||||
@@ -1915,6 +1917,33 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
return PartialView("_SupplyRecords", result);
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetSupplyRecordsForPlanRecordTemplate(int planRecordTemplateId)
|
||||
{
|
||||
var viewModel = new SupplyUsageViewModel();
|
||||
var planRecordTemplate = _planRecordTemplateDataAccess.GetPlanRecordTemplateById(planRecordTemplateId);
|
||||
if (planRecordTemplate != default && planRecordTemplate.VehicleId != default)
|
||||
{
|
||||
var supplies = _supplyRecordDataAccess.GetSupplyRecordsByVehicleId(planRecordTemplate.VehicleId);
|
||||
if (_config.GetServerEnableShopSupplies())
|
||||
{
|
||||
supplies.AddRange(_supplyRecordDataAccess.GetSupplyRecordsByVehicleId(0)); // add shop supplies
|
||||
}
|
||||
supplies.RemoveAll(x => x.Quantity <= 0);
|
||||
bool _useDescending = _config.GetUserConfig(User).UseDescending;
|
||||
if (_useDescending)
|
||||
{
|
||||
supplies = supplies.OrderByDescending(x => x.Date).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
supplies = supplies.OrderBy(x => x.Date).ToList();
|
||||
}
|
||||
viewModel.Supplies = supplies;
|
||||
viewModel.Usage = planRecordTemplate.Supplies;
|
||||
}
|
||||
return PartialView("_SupplyUsage", viewModel);
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
[HttpGet]
|
||||
public IActionResult GetSupplyRecordsForRecordsByVehicleId(int vehicleId)
|
||||
@@ -1934,7 +1963,11 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
result = result.OrderBy(x => x.Date).ToList();
|
||||
}
|
||||
return PartialView("_SupplyUsage", result);
|
||||
var viewModel = new SupplyUsageViewModel
|
||||
{
|
||||
Supplies = result
|
||||
};
|
||||
return PartialView("_SupplyUsage", viewModel);
|
||||
}
|
||||
[HttpPost]
|
||||
public IActionResult SaveSupplyRecordToVehicleId(SupplyRecordInput supplyRecord)
|
||||
@@ -2009,6 +2042,10 @@ namespace CarCareTracker.Controllers
|
||||
if (planRecord.Supplies.Any())
|
||||
{
|
||||
planRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(planRecord.Supplies, DateTime.Parse(planRecord.DateCreated), planRecord.Description);
|
||||
if (planRecord.CopySuppliesAttachment)
|
||||
{
|
||||
planRecord.Files.AddRange(GetSuppliesAttachments(planRecord.Supplies));
|
||||
}
|
||||
}
|
||||
var result = _planRecordDataAccess.SavePlanRecordToVehicle(planRecord.ToPlanRecord());
|
||||
if (result)
|
||||
@@ -2022,7 +2059,7 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
//check if template name already taken.
|
||||
var existingRecord = _planRecordTemplateDataAccess.GetPlanRecordTemplatesByVehicleId(planRecord.VehicleId).Where(x => x.Description == planRecord.Description).Any();
|
||||
if (existingRecord)
|
||||
if (planRecord.Id == default && existingRecord)
|
||||
{
|
||||
return Json(new OperationResponse { Success = false, Message = "A template with that description already exists for this vehicle" });
|
||||
}
|
||||
@@ -2076,6 +2113,10 @@ namespace CarCareTracker.Controllers
|
||||
if (existingRecord.Supplies.Any())
|
||||
{
|
||||
existingRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(existingRecord.Supplies, DateTime.Parse(existingRecord.DateCreated), existingRecord.Description);
|
||||
if (existingRecord.CopySuppliesAttachment)
|
||||
{
|
||||
existingRecord.Files.AddRange(GetSuppliesAttachments(existingRecord.Supplies));
|
||||
}
|
||||
}
|
||||
var result = _planRecordDataAccess.SavePlanRecordToVehicle(existingRecord.ToPlanRecord());
|
||||
return Json(new OperationResponse { Success = result, Message = result ? "Plan Record Added" : StaticHelper.GenericErrorMessage });
|
||||
@@ -2108,7 +2149,7 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||
{
|
||||
Date = DateTime.Now,
|
||||
Date = DateTime.Now.Date,
|
||||
VehicleId = existingRecord.VehicleId,
|
||||
Mileage = odometer,
|
||||
Notes = $"Auto Insert From Plan Record: {existingRecord.Description}",
|
||||
@@ -2121,7 +2162,7 @@ namespace CarCareTracker.Controllers
|
||||
var newRecord = new ServiceRecord()
|
||||
{
|
||||
VehicleId = existingRecord.VehicleId,
|
||||
Date = DateTime.Now,
|
||||
Date = DateTime.Now.Date,
|
||||
Mileage = odometer,
|
||||
Description = existingRecord.Description,
|
||||
Cost = existingRecord.Cost,
|
||||
@@ -2137,7 +2178,7 @@ namespace CarCareTracker.Controllers
|
||||
var newRecord = new CollisionRecord()
|
||||
{
|
||||
VehicleId = existingRecord.VehicleId,
|
||||
Date = DateTime.Now,
|
||||
Date = DateTime.Now.Date,
|
||||
Mileage = odometer,
|
||||
Description = existingRecord.Description,
|
||||
Cost = existingRecord.Cost,
|
||||
@@ -2153,7 +2194,7 @@ namespace CarCareTracker.Controllers
|
||||
var newRecord = new UpgradeRecord()
|
||||
{
|
||||
VehicleId = existingRecord.VehicleId,
|
||||
Date = DateTime.Now,
|
||||
Date = DateTime.Now.Date,
|
||||
Mileage = odometer,
|
||||
Description = existingRecord.Description,
|
||||
Cost = existingRecord.Cost,
|
||||
@@ -2167,12 +2208,18 @@ namespace CarCareTracker.Controllers
|
||||
//push back any reminders
|
||||
if (existingRecord.ReminderRecordId != default)
|
||||
{
|
||||
PushbackRecurringReminderRecordWithChecks(existingRecord.ReminderRecordId);
|
||||
PushbackRecurringReminderRecordWithChecks(existingRecord.ReminderRecordId, DateTime.Now, odometer);
|
||||
}
|
||||
}
|
||||
return Json(result);
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetPlanRecordTemplateForEditById(int planRecordTemplateId)
|
||||
{
|
||||
var result = _planRecordTemplateDataAccess.GetPlanRecordTemplateById(planRecordTemplateId);
|
||||
return PartialView("_PlanRecordTemplateEditModal", result);
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetPlanRecordForEditById(int planRecordId)
|
||||
{
|
||||
var result = _planRecordDataAccess.GetPlanRecordById(planRecordId);
|
||||
@@ -2335,6 +2382,89 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
#endregion
|
||||
#region "Shared Methods"
|
||||
[HttpPost]
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
public IActionResult SearchRecords(int vehicleId, string searchQuery)
|
||||
{
|
||||
List<SearchResult> searchResults = new List<SearchResult>();
|
||||
if (string.IsNullOrWhiteSpace(searchQuery))
|
||||
{
|
||||
return Json(searchResults);
|
||||
}
|
||||
foreach(ImportMode visibleTab in _config.GetUserConfig(User).VisibleTabs)
|
||||
{
|
||||
switch (visibleTab)
|
||||
{
|
||||
case ImportMode.ServiceRecord:
|
||||
{
|
||||
var results = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.ServiceRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
|
||||
}
|
||||
break;
|
||||
case ImportMode.RepairRecord:
|
||||
{
|
||||
var results = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.RepairRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
|
||||
}
|
||||
break;
|
||||
case ImportMode.UpgradeRecord:
|
||||
{
|
||||
var results = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.UpgradeRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
|
||||
}
|
||||
break;
|
||||
case ImportMode.TaxRecord:
|
||||
{
|
||||
var results = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.TaxRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
|
||||
}
|
||||
break;
|
||||
case ImportMode.SupplyRecord:
|
||||
{
|
||||
var results = _supplyRecordDataAccess.GetSupplyRecordsByVehicleId(vehicleId);
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.SupplyRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
|
||||
}
|
||||
break;
|
||||
case ImportMode.PlanRecord:
|
||||
{
|
||||
var results = _planRecordDataAccess.GetPlanRecordsByVehicleId(vehicleId);
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.PlanRecord, Description = $"{x.DateCreated.ToShortDateString()} - {x.Description}" }));
|
||||
}
|
||||
break;
|
||||
case ImportMode.OdometerRecord:
|
||||
{
|
||||
var results = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.OdometerRecord, Description = $"{x.Date.ToShortDateString()} - {x.Mileage}" }));
|
||||
}
|
||||
break;
|
||||
case ImportMode.GasRecord:
|
||||
{
|
||||
var results = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.GasRecord, Description = $"{x.Date.ToShortDateString()} - {x.Mileage}" }));
|
||||
}
|
||||
break;
|
||||
case ImportMode.NoteRecord:
|
||||
{
|
||||
var results = _noteDataAccess.GetNotesByVehicleId(vehicleId);
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.NoteRecord, Description = $"{x.Description}" }));
|
||||
}
|
||||
break;
|
||||
case ImportMode.ReminderRecord:
|
||||
{
|
||||
var results = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
||||
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.ReminderRecord, Description = $"{x.Description}" }));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return PartialView("_GlobalSearchResult", searchResults);
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
public IActionResult GetMaxMileage(int vehicleId)
|
||||
{
|
||||
var result = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||
return Json(result);
|
||||
}
|
||||
public IActionResult MoveRecord(int recordId, ImportMode source, ImportMode destination)
|
||||
{
|
||||
var genericRecord = new GenericRecord();
|
||||
|
||||
@@ -7,51 +7,48 @@ namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class CollisionRecordDataAccess : ICollisionRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "collisionrecords";
|
||||
public CollisionRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<CollisionRecord> GetCollisionRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||
var collisionRecords = table.Find(Query.EQ(nameof(CollisionRecord.VehicleId), vehicleId));
|
||||
return collisionRecords.ToList() ?? new List<CollisionRecord>();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||
var collisionRecords = table.Find(Query.EQ(nameof(CollisionRecord.VehicleId), vehicleId));
|
||||
return collisionRecords.ToList() ?? new List<CollisionRecord>();
|
||||
}
|
||||
public CollisionRecord GetCollisionRecordById(int collisionRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||
return table.FindById(collisionRecordId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||
return table.FindById(collisionRecordId);
|
||||
}
|
||||
public bool DeleteCollisionRecordById(int collisionRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||
table.Delete(collisionRecordId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||
table.Delete(collisionRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SaveCollisionRecordToVehicle(CollisionRecord collisionRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||
table.Upsert(collisionRecord);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||
table.Upsert(collisionRecord);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllCollisionRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||
var collisionRecords = table.DeleteMany(Query.EQ(nameof(CollisionRecord.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||
var collisionRecords = table.DeleteMany(Query.EQ(nameof(CollisionRecord.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class ExtraFieldDataAccess: IExtraFieldDataAccess
|
||||
public class ExtraFieldDataAccess : IExtraFieldDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "extrafields";
|
||||
public ExtraFieldDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public RecordExtraField GetExtraFieldsById(int importMode)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<RecordExtraField>(tableName);
|
||||
return table.FindById(importMode) ?? new RecordExtraField();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<RecordExtraField>(tableName);
|
||||
return table.FindById(importMode) ?? new RecordExtraField();
|
||||
}
|
||||
public bool SaveExtraFields(RecordExtraField record)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<RecordExtraField>(tableName);
|
||||
table.Upsert(record);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<RecordExtraField>(tableName);
|
||||
table.Upsert(record);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,53 +5,50 @@ using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class GasRecordDataAccess: IGasRecordDataAccess
|
||||
public class GasRecordDataAccess : IGasRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "gasrecords";
|
||||
public GasRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<GasRecord> GetGasRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<GasRecord>(tableName);
|
||||
var gasRecords = table.Find(Query.EQ(nameof(GasRecord.VehicleId), vehicleId));
|
||||
return gasRecords.ToList() ?? new List<GasRecord>();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<GasRecord>(tableName);
|
||||
var gasRecords = table.Find(Query.EQ(nameof(GasRecord.VehicleId), vehicleId));
|
||||
return gasRecords.ToList() ?? new List<GasRecord>();
|
||||
}
|
||||
public GasRecord GetGasRecordById(int gasRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<GasRecord>(tableName);
|
||||
return table.FindById(gasRecordId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<GasRecord>(tableName);
|
||||
return table.FindById(gasRecordId);
|
||||
}
|
||||
public bool DeleteGasRecordById(int gasRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<GasRecord>(tableName);
|
||||
table.Delete(gasRecordId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<GasRecord>(tableName);
|
||||
table.Delete(gasRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SaveGasRecordToVehicle(GasRecord gasRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<GasRecord>(tableName);
|
||||
table.Upsert(gasRecord);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<GasRecord>(tableName);
|
||||
table.Upsert(gasRecord);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllGasRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<GasRecord>(tableName);
|
||||
var gasRecords = table.DeleteMany(Query.EQ(nameof(GasRecord.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<GasRecord>(tableName);
|
||||
var gasRecords = table.DeleteMany(Query.EQ(nameof(GasRecord.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +1,54 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using CarCareTracker.Helper;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class NoteDataAccess: INoteDataAccess
|
||||
public class NoteDataAccess : INoteDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "notes";
|
||||
public NoteDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<Note> GetNotesByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Note>(tableName);
|
||||
var noteToReturn = table.Find(Query.EQ(nameof(Note.VehicleId), vehicleId));
|
||||
return noteToReturn.ToList() ?? new List<Note>();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Note>(tableName);
|
||||
var noteToReturn = table.Find(Query.EQ(nameof(Note.VehicleId), vehicleId));
|
||||
return noteToReturn.ToList() ?? new List<Note>();
|
||||
}
|
||||
public Note GetNoteById(int noteId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Note>(tableName);
|
||||
return table.FindById(noteId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Note>(tableName);
|
||||
return table.FindById(noteId);
|
||||
}
|
||||
public bool SaveNoteToVehicle(Note note)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Note>(tableName);
|
||||
table.Upsert(note);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Note>(tableName);
|
||||
table.Upsert(note);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteNoteById(int noteId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Note>(tableName);
|
||||
table.Delete(noteId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Note>(tableName);
|
||||
table.Delete(noteId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllNotesByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Note>(tableName);
|
||||
var notes = table.DeleteMany(Query.EQ(nameof(Note.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Note>(tableName);
|
||||
var notes = table.DeleteMany(Query.EQ(nameof(Note.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +1,54 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using CarCareTracker.Helper;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class OdometerRecordDataAccess : IOdometerRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "odometerrecords";
|
||||
public OdometerRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<OdometerRecord> GetOdometerRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
var odometerRecords = table.Find(Query.EQ(nameof(OdometerRecord.VehicleId), vehicleId));
|
||||
return odometerRecords.ToList() ?? new List<OdometerRecord>();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
var odometerRecords = table.Find(Query.EQ(nameof(OdometerRecord.VehicleId), vehicleId));
|
||||
return odometerRecords.ToList() ?? new List<OdometerRecord>();
|
||||
}
|
||||
public OdometerRecord GetOdometerRecordById(int odometerRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
return table.FindById(odometerRecordId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
return table.FindById(odometerRecordId);
|
||||
}
|
||||
public bool DeleteOdometerRecordById(int odometerRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
table.Delete(odometerRecordId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
table.Delete(odometerRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SaveOdometerRecordToVehicle(OdometerRecord odometerRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
table.Upsert(odometerRecord);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
table.Upsert(odometerRecord);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllOdometerRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
var odometerRecords = table.DeleteMany(Query.EQ(nameof(OdometerRecord.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
var odometerRecords = table.DeleteMany(Query.EQ(nameof(OdometerRecord.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +1,54 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using CarCareTracker.Helper;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class PlanRecordDataAccess : IPlanRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "planrecords";
|
||||
public PlanRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<PlanRecord> GetPlanRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
var planRecords = table.Find(Query.EQ(nameof(PlanRecord.VehicleId), vehicleId));
|
||||
return planRecords.ToList() ?? new List<PlanRecord>();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
var planRecords = table.Find(Query.EQ(nameof(PlanRecord.VehicleId), vehicleId));
|
||||
return planRecords.ToList() ?? new List<PlanRecord>();
|
||||
}
|
||||
public PlanRecord GetPlanRecordById(int planRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
return table.FindById(planRecordId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
return table.FindById(planRecordId);
|
||||
}
|
||||
public bool DeletePlanRecordById(int planRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
table.Delete(planRecordId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
table.Delete(planRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SavePlanRecordToVehicle(PlanRecord planRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
table.Upsert(planRecord);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
table.Upsert(planRecord);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllPlanRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
var planRecords = table.DeleteMany(Query.EQ(nameof(PlanRecord.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
var planRecords = table.DeleteMany(Query.EQ(nameof(PlanRecord.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +1,54 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using CarCareTracker.Helper;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class PlanRecordTemplateDataAccess : IPlanRecordTemplateDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "planrecordtemplates";
|
||||
public PlanRecordTemplateDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<PlanRecordInput> GetPlanRecordTemplatesByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||
var planRecords = table.Find(Query.EQ(nameof(PlanRecordInput.VehicleId), vehicleId));
|
||||
return planRecords.ToList() ?? new List<PlanRecordInput>();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||
var planRecords = table.Find(Query.EQ(nameof(PlanRecordInput.VehicleId), vehicleId));
|
||||
return planRecords.ToList() ?? new List<PlanRecordInput>();
|
||||
}
|
||||
public PlanRecordInput GetPlanRecordTemplateById(int planRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||
return table.FindById(planRecordId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||
return table.FindById(planRecordId);
|
||||
}
|
||||
public bool DeletePlanRecordTemplateById(int planRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||
table.Delete(planRecordId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||
table.Delete(planRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SavePlanRecordTemplateToVehicle(PlanRecordInput planRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||
table.Upsert(planRecord);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||
table.Upsert(planRecord);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllPlanRecordTemplatesByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
var planRecords = table.DeleteMany(Query.EQ(nameof(PlanRecordInput.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<PlanRecord>(tableName);
|
||||
var planRecords = table.DeleteMany(Query.EQ(nameof(PlanRecordInput.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +1,54 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using CarCareTracker.Helper;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class ReminderRecordDataAccess : IReminderRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "reminderrecords";
|
||||
public ReminderRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<ReminderRecord> GetReminderRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||
var reminderRecords = table.Find(Query.EQ(nameof(ReminderRecord.VehicleId), vehicleId));
|
||||
return reminderRecords.ToList() ?? new List<ReminderRecord>();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||
var reminderRecords = table.Find(Query.EQ(nameof(ReminderRecord.VehicleId), vehicleId));
|
||||
return reminderRecords.ToList() ?? new List<ReminderRecord>();
|
||||
}
|
||||
public ReminderRecord GetReminderRecordById(int reminderRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||
return table.FindById(reminderRecordId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||
return table.FindById(reminderRecordId);
|
||||
}
|
||||
public bool DeleteReminderRecordById(int reminderRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||
table.Delete(reminderRecordId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||
table.Delete(reminderRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SaveReminderRecordToVehicle(ReminderRecord reminderRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||
table.Upsert(reminderRecord);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||
table.Upsert(reminderRecord);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllReminderRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||
var reminderRecords = table.DeleteMany(Query.EQ(nameof(ReminderRecord.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||
var reminderRecords = table.DeleteMany(Query.EQ(nameof(ReminderRecord.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +1,54 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using CarCareTracker.Helper;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class ServiceRecordDataAccess: IServiceRecordDataAccess
|
||||
public class ServiceRecordDataAccess : IServiceRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "servicerecords";
|
||||
public ServiceRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<ServiceRecord> GetServiceRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||
var serviceRecords = table.Find(Query.EQ(nameof(ServiceRecord.VehicleId), vehicleId));
|
||||
return serviceRecords.ToList() ?? new List<ServiceRecord>();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||
var serviceRecords = table.Find(Query.EQ(nameof(ServiceRecord.VehicleId), vehicleId));
|
||||
return serviceRecords.ToList() ?? new List<ServiceRecord>();
|
||||
}
|
||||
public ServiceRecord GetServiceRecordById(int serviceRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||
return table.FindById(serviceRecordId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||
return table.FindById(serviceRecordId);
|
||||
}
|
||||
public bool DeleteServiceRecordById(int serviceRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||
table.Delete(serviceRecordId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||
table.Delete(serviceRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SaveServiceRecordToVehicle(ServiceRecord serviceRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||
table.Upsert(serviceRecord);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||
table.Upsert(serviceRecord);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllServiceRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||
var serviceRecords = table.DeleteMany(Query.EQ(nameof(ServiceRecord.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||
var serviceRecords = table.DeleteMany(Query.EQ(nameof(ServiceRecord.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,51 +7,48 @@ namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class SupplyRecordDataAccess : ISupplyRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "supplyrecords";
|
||||
public SupplyRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<SupplyRecord> GetSupplyRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
var supplyRecords = table.Find(Query.EQ(nameof(SupplyRecord.VehicleId), vehicleId));
|
||||
return supplyRecords.ToList() ?? new List<SupplyRecord>();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
var supplyRecords = table.Find(Query.EQ(nameof(SupplyRecord.VehicleId), vehicleId));
|
||||
return supplyRecords.ToList() ?? new List<SupplyRecord>();
|
||||
}
|
||||
public SupplyRecord GetSupplyRecordById(int supplyRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
return table.FindById(supplyRecordId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
return table.FindById(supplyRecordId);
|
||||
}
|
||||
public bool DeleteSupplyRecordById(int supplyRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
table.Delete(supplyRecordId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
table.Delete(supplyRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SaveSupplyRecordToVehicle(SupplyRecord supplyRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
table.Upsert(supplyRecord);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
table.Upsert(supplyRecord);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllSupplyRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
var supplyRecords = table.DeleteMany(Query.EQ(nameof(SupplyRecord.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
var supplyRecords = table.DeleteMany(Query.EQ(nameof(SupplyRecord.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +1,54 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using CarCareTracker.Helper;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class TaxRecordDataAccess : ITaxRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "taxrecords";
|
||||
public TaxRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<TaxRecord> GetTaxRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<TaxRecord>(tableName);
|
||||
var taxRecords = table.Find(Query.EQ(nameof(TaxRecord.VehicleId), vehicleId));
|
||||
return taxRecords.ToList() ?? new List<TaxRecord>();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<TaxRecord>(tableName);
|
||||
var taxRecords = table.Find(Query.EQ(nameof(TaxRecord.VehicleId), vehicleId));
|
||||
return taxRecords.ToList() ?? new List<TaxRecord>();
|
||||
}
|
||||
public TaxRecord GetTaxRecordById(int taxRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<TaxRecord>(tableName);
|
||||
return table.FindById(taxRecordId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<TaxRecord>(tableName);
|
||||
return table.FindById(taxRecordId);
|
||||
}
|
||||
public bool DeleteTaxRecordById(int taxRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<TaxRecord>(tableName);
|
||||
table.Delete(taxRecordId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<TaxRecord>(tableName);
|
||||
table.Delete(taxRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SaveTaxRecordToVehicle(TaxRecord taxRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<TaxRecord>(tableName);
|
||||
table.Upsert(taxRecord);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<TaxRecord>(tableName);
|
||||
table.Upsert(taxRecord);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllTaxRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<TaxRecord>(tableName);
|
||||
var taxRecords = table.DeleteMany(Query.EQ(nameof(TaxRecord.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<TaxRecord>(tableName);
|
||||
var taxRecords = table.DeleteMany(Query.EQ(nameof(TaxRecord.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,51 +7,47 @@ namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class TokenRecordDataAccess : ITokenRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "tokenrecords";
|
||||
public TokenRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<Token> GetTokens()
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Token>(tableName);
|
||||
return table.FindAll().ToList();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Token>(tableName);
|
||||
return table.FindAll().ToList();
|
||||
}
|
||||
public Token GetTokenRecordByBody(string tokenBody)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Token>(tableName);
|
||||
var tokenRecord = table.FindOne(Query.EQ(nameof(Token.Body), tokenBody));
|
||||
return tokenRecord ?? new Token();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Token>(tableName);
|
||||
var tokenRecord = table.FindOne(Query.EQ(nameof(Token.Body), tokenBody));
|
||||
return tokenRecord ?? new Token();
|
||||
}
|
||||
public Token GetTokenRecordByEmailAddress(string emailAddress)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Token>(tableName);
|
||||
var tokenRecord = table.FindOne(Query.EQ(nameof(Token.EmailAddress), emailAddress));
|
||||
return tokenRecord ?? new Token();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Token>(tableName);
|
||||
var tokenRecord = table.FindOne(Query.EQ(nameof(Token.EmailAddress), emailAddress));
|
||||
return tokenRecord ?? new Token();
|
||||
}
|
||||
public bool CreateNewToken(Token token)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Token>(tableName);
|
||||
table.Insert(token);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Token>(tableName);
|
||||
table.Insert(token);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteToken(int tokenId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Token>(tableName);
|
||||
table.Delete(tokenId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Token>(tableName);
|
||||
table.Delete(tokenId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,51 +7,48 @@ namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class UpgradeRecordDataAccess : IUpgradeRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
public UpgradeRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
private static string tableName = "upgraderecords";
|
||||
public List<UpgradeRecord> GetUpgradeRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||
var upgradeRecords = table.Find(Query.EQ(nameof(UpgradeRecord.VehicleId), vehicleId));
|
||||
return upgradeRecords.ToList() ?? new List<UpgradeRecord>();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||
var upgradeRecords = table.Find(Query.EQ(nameof(UpgradeRecord.VehicleId), vehicleId));
|
||||
return upgradeRecords.ToList() ?? new List<UpgradeRecord>();
|
||||
}
|
||||
public UpgradeRecord GetUpgradeRecordById(int upgradeRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||
return table.FindById(upgradeRecordId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||
return table.FindById(upgradeRecordId);
|
||||
}
|
||||
public bool DeleteUpgradeRecordById(int upgradeRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||
table.Delete(upgradeRecordId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||
table.Delete(upgradeRecordId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool SaveUpgradeRecordToVehicle(UpgradeRecord upgradeRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||
table.Upsert(upgradeRecord);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||
table.Upsert(upgradeRecord);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteAllUpgradeRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||
var upgradeRecords = table.DeleteMany(Query.EQ(nameof(UpgradeRecord.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||
var upgradeRecords = table.DeleteMany(Query.EQ(nameof(UpgradeRecord.VehicleId), vehicleId));
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,12 @@ namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class UserAccessDataAccess : IUserAccessDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "useraccessrecords";
|
||||
public UserAccessDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets a list of vehicles user have access to.
|
||||
/// </summary>
|
||||
@@ -16,45 +20,37 @@ namespace CarCareTracker.External.Implementations
|
||||
/// <returns></returns>
|
||||
public List<UserAccess> GetUserAccessByUserId(int userId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
return table.Find(x=>x.Id.UserId == userId).ToList();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
return table.Find(x => x.Id.UserId == userId).ToList();
|
||||
}
|
||||
public UserAccess GetUserAccessByVehicleAndUserId(int userId, int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
return table.Find(x => x.Id.UserId == userId && x.Id.VehicleId == vehicleId).FirstOrDefault();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
return table.Find(x => x.Id.UserId == userId && x.Id.VehicleId == vehicleId).FirstOrDefault();
|
||||
}
|
||||
public List<UserAccess> GetUserAccessByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
return table.Find(x => x.Id.VehicleId == vehicleId).ToList();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
return table.Find(x => x.Id.VehicleId == vehicleId).ToList();
|
||||
}
|
||||
public bool SaveUserAccess(UserAccess userAccess)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
table.Upsert(userAccess);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
table.Upsert(userAccess);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteUserAccess(int userId, int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
table.DeleteMany(x => x.Id.UserId == userId && x.Id.VehicleId == vehicleId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
table.DeleteMany(x => x.Id.UserId == userId && x.Id.VehicleId == vehicleId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// Delete all access records when a vehicle is deleted.
|
||||
@@ -63,12 +59,11 @@ namespace CarCareTracker.External.Implementations
|
||||
/// <returns></returns>
|
||||
public bool DeleteAllAccessRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
table.DeleteMany(x=>x.Id.VehicleId == vehicleId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
table.DeleteMany(x => x.Id.VehicleId == vehicleId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// Delee all access records when a user is deleted.
|
||||
@@ -77,12 +72,11 @@ namespace CarCareTracker.External.Implementations
|
||||
/// <returns></returns>
|
||||
public bool DeleteAllAccessRecordsByUserId(int userId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
table.DeleteMany(x => x.Id.UserId == userId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserAccess>(tableName);
|
||||
table.DeleteMany(x => x.Id.UserId == userId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,38 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using LiteDB;
|
||||
using CarCareTracker.Helper;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class UserConfigDataAccess: IUserConfigDataAccess
|
||||
public class UserConfigDataAccess : IUserConfigDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "userconfigrecords";
|
||||
public UserConfigDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public UserConfigData GetUserConfig(int userId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserConfigData>(tableName);
|
||||
return table.FindById(userId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserConfigData>(tableName);
|
||||
return table.FindById(userId);
|
||||
}
|
||||
public bool SaveUserConfig(UserConfigData userConfigData)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserConfigData>(tableName);
|
||||
table.Upsert(userConfigData);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserConfigData>(tableName);
|
||||
table.Upsert(userConfigData);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteUserConfig(int userId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserConfigData>(tableName);
|
||||
table.Delete(userId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserConfigData>(tableName);
|
||||
table.Delete(userId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +1,60 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using LiteDB;
|
||||
using CarCareTracker.Helper;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class UserRecordDataAccess : IUserRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "userrecords";
|
||||
public UserRecordDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<UserData> GetUsers()
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
return table.FindAll().ToList();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
return table.FindAll().ToList();
|
||||
}
|
||||
public UserData GetUserRecordByUserName(string userName)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
var userRecord = table.FindOne(Query.EQ(nameof(UserData.UserName), userName));
|
||||
return userRecord ?? new UserData();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
var userRecord = table.FindOne(Query.EQ(nameof(UserData.UserName), userName));
|
||||
return userRecord ?? new UserData();
|
||||
}
|
||||
public UserData GetUserRecordByEmailAddress(string emailAddress)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
var userRecord = table.FindOne(Query.EQ(nameof(UserData.EmailAddress), emailAddress));
|
||||
return userRecord ?? new UserData();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
var userRecord = table.FindOne(Query.EQ(nameof(UserData.EmailAddress), emailAddress));
|
||||
return userRecord ?? new UserData();
|
||||
}
|
||||
public UserData GetUserRecordById(int userId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
var userRecord = table.FindById(userId);
|
||||
return userRecord ?? new UserData();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
var userRecord = table.FindById(userId);
|
||||
return userRecord ?? new UserData();
|
||||
}
|
||||
public bool SaveUserRecord(UserData userRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
table.Upsert(userRecord);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
table.Upsert(userRecord);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteUserRecord(int userId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
table.Delete(userId);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<UserData>(tableName);
|
||||
table.Delete(userId);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,42 +5,41 @@ using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class VehicleDataAccess: IVehicleDataAccess
|
||||
public class VehicleDataAccess : IVehicleDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private ILiteDBHelper _liteDB { get; set; }
|
||||
private static string tableName = "vehicles";
|
||||
public VehicleDataAccess(ILiteDBHelper liteDB)
|
||||
{
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public bool SaveVehicle(Vehicle vehicle)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Vehicle>(tableName);
|
||||
var result = table.Upsert(vehicle);
|
||||
return true;
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Vehicle>(tableName);
|
||||
var result = table.Upsert(vehicle);
|
||||
db.Checkpoint();
|
||||
return true;
|
||||
}
|
||||
public bool DeleteVehicle(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Vehicle>(tableName);
|
||||
return table.Delete(vehicleId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Vehicle>(tableName);
|
||||
var result = table.Delete(vehicleId);
|
||||
db.Checkpoint();
|
||||
return result;
|
||||
}
|
||||
public List<Vehicle> GetVehicles()
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Vehicle>(tableName);
|
||||
return table.FindAll().ToList();
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Vehicle>(tableName);
|
||||
return table.FindAll().ToList();
|
||||
}
|
||||
public Vehicle GetVehicleById(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<Vehicle>(tableName);
|
||||
return table.FindById(vehicleId);
|
||||
};
|
||||
var db = _liteDB.GetLiteDB();
|
||||
var table = db.GetCollection<Vehicle>(tableName);
|
||||
return table.FindById(vehicleId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,12 @@ namespace CarCareTracker.Helper
|
||||
{
|
||||
private readonly IWebHostEnvironment _webEnv;
|
||||
private readonly ILogger<IFileHelper> _logger;
|
||||
public FileHelper(IWebHostEnvironment webEnv, ILogger<IFileHelper> logger)
|
||||
private ILiteDBHelper _liteDB;
|
||||
public FileHelper(IWebHostEnvironment webEnv, ILogger<IFileHelper> logger, ILiteDBHelper liteDB)
|
||||
{
|
||||
_webEnv = webEnv;
|
||||
_logger = logger;
|
||||
_liteDB = liteDB;
|
||||
}
|
||||
public List<string> GetLanguages()
|
||||
{
|
||||
@@ -164,6 +166,8 @@ namespace CarCareTracker.Helper
|
||||
}
|
||||
if (File.Exists(dataPath))
|
||||
{
|
||||
//Relinquish current DB file lock
|
||||
_liteDB.DisposeLiteDB();
|
||||
//data path will always exist as it is created on startup if not.
|
||||
File.Move(dataPath, StaticHelper.DbName, true);
|
||||
}
|
||||
|
||||
36
Helper/LiteDBHelper.cs
Normal file
36
Helper/LiteDBHelper.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.Helper;
|
||||
|
||||
public interface ILiteDBHelper
|
||||
{
|
||||
LiteDatabase GetLiteDB();
|
||||
void DisposeLiteDB();
|
||||
}
|
||||
public class LiteDBHelper: ILiteDBHelper
|
||||
{
|
||||
public LiteDatabase db { get; set; }
|
||||
public LiteDBHelper()
|
||||
{
|
||||
if (db == null)
|
||||
{
|
||||
db = new LiteDatabase(StaticHelper.DbName);
|
||||
}
|
||||
}
|
||||
public LiteDatabase GetLiteDB()
|
||||
{
|
||||
if (db == null)
|
||||
{
|
||||
db = new LiteDatabase(StaticHelper.DbName);
|
||||
}
|
||||
return db;
|
||||
}
|
||||
public void DisposeLiteDB()
|
||||
{
|
||||
if (db != null)
|
||||
{
|
||||
db.Dispose();
|
||||
db = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using CarCareTracker.Models;
|
||||
using System.Net.Mail;
|
||||
using System.Net;
|
||||
using MimeKit;
|
||||
using MailKit.Net.Smtp;
|
||||
|
||||
namespace CarCareTracker.Helper
|
||||
{
|
||||
@@ -15,13 +15,16 @@ namespace CarCareTracker.Helper
|
||||
{
|
||||
private readonly MailConfig mailConfig;
|
||||
private readonly IFileHelper _fileHelper;
|
||||
private readonly ILogger<MailHelper> _logger;
|
||||
public MailHelper(
|
||||
IConfiguration config,
|
||||
IFileHelper fileHelper
|
||||
IFileHelper fileHelper,
|
||||
ILogger<MailHelper> logger
|
||||
) {
|
||||
//load mailConfig from Configuration
|
||||
mailConfig = config.GetSection("MailConfig").Get<MailConfig>();
|
||||
mailConfig = config.GetSection("MailConfig").Get<MailConfig>() ?? new MailConfig();
|
||||
_fileHelper = fileHelper;
|
||||
_logger = logger;
|
||||
}
|
||||
public OperationResponse NotifyUserForRegistration(string emailAddress, string token)
|
||||
{
|
||||
@@ -34,7 +37,7 @@ namespace CarCareTracker.Helper
|
||||
}
|
||||
string emailSubject = "Your Registration Token for LubeLogger";
|
||||
string emailBody = $"A token has been generated on your behalf, please complete your registration for LubeLogger using the token: {token}";
|
||||
var result = SendEmail(emailAddress, emailSubject, emailBody);
|
||||
var result = SendEmail(new List<string> { emailAddress }, emailSubject, emailBody);
|
||||
if (result)
|
||||
{
|
||||
return new OperationResponse { Success = true, Message = "Email Sent!" };
|
||||
@@ -55,7 +58,7 @@ namespace CarCareTracker.Helper
|
||||
}
|
||||
string emailSubject = "Your Password Reset Token for LubeLogger";
|
||||
string emailBody = $"A token has been generated on your behalf, please reset your password for LubeLogger using the token: {token}";
|
||||
var result = SendEmail(emailAddress, emailSubject, emailBody);
|
||||
var result = SendEmail(new List<string> { emailAddress }, emailSubject, emailBody);
|
||||
if (result)
|
||||
{
|
||||
return new OperationResponse { Success = true, Message = "Email Sent!" };
|
||||
@@ -77,7 +80,7 @@ namespace CarCareTracker.Helper
|
||||
}
|
||||
string emailSubject = "Your User Account Update Token for LubeLogger";
|
||||
string emailBody = $"A token has been generated on your behalf, please update your account for LubeLogger using the token: {token}";
|
||||
var result = SendEmail(emailAddress, emailSubject, emailBody);
|
||||
var result = SendEmail(new List<string> { emailAddress}, emailSubject, emailBody);
|
||||
if (result)
|
||||
{
|
||||
return new OperationResponse { Success = true, Message = "Email Sent!" };
|
||||
@@ -116,43 +119,48 @@ namespace CarCareTracker.Helper
|
||||
emailBody = emailBody.Replace("{TableBody}", tableBody);
|
||||
try
|
||||
{
|
||||
foreach (string emailAddress in emailAddresses)
|
||||
{
|
||||
SendEmail(emailAddress, emailSubject, emailBody, true, true);
|
||||
}
|
||||
SendEmail(emailAddresses, emailSubject, emailBody);
|
||||
return new OperationResponse { Success = true, Message = "Email Sent!" };
|
||||
} catch (Exception ex)
|
||||
{
|
||||
return new OperationResponse { Success = false, Message = ex.Message };
|
||||
}
|
||||
}
|
||||
private bool SendEmail(string emailTo, string emailSubject, string emailBody, bool isBodyHtml = false, bool useAsync = false) {
|
||||
string to = emailTo;
|
||||
private bool SendEmail(List<string> emailTo, string emailSubject, string emailBody) {
|
||||
string from = mailConfig.EmailFrom;
|
||||
var server = mailConfig.EmailServer;
|
||||
MailMessage message = new MailMessage(from, to);
|
||||
message.Subject = emailSubject;
|
||||
message.Body = emailBody;
|
||||
message.IsBodyHtml = isBodyHtml;
|
||||
SmtpClient client = new SmtpClient(server);
|
||||
client.EnableSsl = mailConfig.UseSSL;
|
||||
client.Port = mailConfig.Port;
|
||||
client.Credentials = new NetworkCredential(mailConfig.Username, mailConfig.Password);
|
||||
try
|
||||
var message = new MimeMessage();
|
||||
message.From.Add(new MailboxAddress(from, from));
|
||||
foreach(string emailRecipient in emailTo)
|
||||
{
|
||||
if (useAsync)
|
||||
{
|
||||
client.SendMailAsync(message, new CancellationToken());
|
||||
message.To.Add(new MailboxAddress(emailRecipient, emailRecipient));
|
||||
}
|
||||
message.Subject = emailSubject;
|
||||
|
||||
var builder = new BodyBuilder();
|
||||
|
||||
builder.HtmlBody = emailBody;
|
||||
|
||||
message.Body = builder.ToMessageBody();
|
||||
|
||||
using (var client = new SmtpClient())
|
||||
{
|
||||
client.Connect(server, mailConfig.Port, MailKit.Security.SecureSocketOptions.Auto);
|
||||
//perform authentication if either username or password is provided.
|
||||
//do not perform authentication if neither are provided.
|
||||
if (!string.IsNullOrWhiteSpace(mailConfig.Username) || !string.IsNullOrWhiteSpace(mailConfig.Password)) {
|
||||
client.Authenticate(mailConfig.Username, mailConfig.Password);
|
||||
}
|
||||
else
|
||||
try
|
||||
{
|
||||
client.Send(message);
|
||||
client.Disconnect(true);
|
||||
return true;
|
||||
} catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace CarCareTracker.Helper
|
||||
{
|
||||
public interface IReminderHelper
|
||||
{
|
||||
ReminderRecord GetUpdatedRecurringReminderRecord(ReminderRecord existingReminder);
|
||||
ReminderRecord GetUpdatedRecurringReminderRecord(ReminderRecord existingReminder, DateTime? currentDate, int? currentMileage);
|
||||
List<ReminderRecordViewModel> GetReminderRecordViewModels(List<ReminderRecord> reminders, int currentMileage, DateTime dateCompare);
|
||||
}
|
||||
public class ReminderHelper: IReminderHelper
|
||||
@@ -14,46 +14,48 @@ namespace CarCareTracker.Helper
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
public ReminderRecord GetUpdatedRecurringReminderRecord(ReminderRecord existingReminder)
|
||||
public ReminderRecord GetUpdatedRecurringReminderRecord(ReminderRecord existingReminder, DateTime? currentDate, int? currentMileage)
|
||||
{
|
||||
var newDate = currentDate ?? existingReminder.Date;
|
||||
var newMileage = currentMileage ?? existingReminder.Mileage;
|
||||
if (existingReminder.Metric == ReminderMetric.Both)
|
||||
{
|
||||
if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other)
|
||||
{
|
||||
existingReminder.Date = existingReminder.Date.AddMonths((int)existingReminder.ReminderMonthInterval);
|
||||
existingReminder.Date = newDate.AddMonths((int)existingReminder.ReminderMonthInterval);
|
||||
} else
|
||||
{
|
||||
existingReminder.Date = existingReminder.Date.AddMonths(existingReminder.CustomMonthInterval);
|
||||
existingReminder.Date = newDate.Date.AddMonths(existingReminder.CustomMonthInterval);
|
||||
}
|
||||
|
||||
if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other)
|
||||
{
|
||||
existingReminder.Mileage += (int)existingReminder.ReminderMileageInterval;
|
||||
existingReminder.Mileage = newMileage + (int)existingReminder.ReminderMileageInterval;
|
||||
}
|
||||
else
|
||||
{
|
||||
existingReminder.Mileage += existingReminder.CustomMileageInterval;
|
||||
existingReminder.Mileage = newMileage + existingReminder.CustomMileageInterval;
|
||||
}
|
||||
}
|
||||
else if (existingReminder.Metric == ReminderMetric.Odometer)
|
||||
{
|
||||
if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other)
|
||||
{
|
||||
existingReminder.Mileage += (int)existingReminder.ReminderMileageInterval;
|
||||
existingReminder.Mileage = newMileage + (int)existingReminder.ReminderMileageInterval;
|
||||
} else
|
||||
{
|
||||
existingReminder.Mileage += existingReminder.CustomMileageInterval;
|
||||
existingReminder.Mileage = newMileage + existingReminder.CustomMileageInterval;
|
||||
}
|
||||
}
|
||||
else if (existingReminder.Metric == ReminderMetric.Date)
|
||||
{
|
||||
if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other)
|
||||
{
|
||||
existingReminder.Date = existingReminder.Date.AddMonths((int)existingReminder.ReminderMonthInterval);
|
||||
existingReminder.Date = newDate.AddMonths((int)existingReminder.ReminderMonthInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
existingReminder.Date = existingReminder.Date.AddMonths(existingReminder.CustomMonthInterval);
|
||||
existingReminder.Date = newDate.AddMonths(existingReminder.CustomMonthInterval);
|
||||
}
|
||||
}
|
||||
return existingReminder;
|
||||
@@ -73,7 +75,8 @@ namespace CarCareTracker.Helper
|
||||
Description = reminder.Description,
|
||||
Notes = reminder.Notes,
|
||||
Metric = reminder.Metric,
|
||||
IsRecurring = reminder.IsRecurring
|
||||
IsRecurring = reminder.IsRecurring,
|
||||
Tags = reminder.Tags
|
||||
};
|
||||
if (reminder.Metric == ReminderMetric.Both)
|
||||
{
|
||||
|
||||
@@ -8,13 +8,13 @@ namespace CarCareTracker.Helper
|
||||
/// </summary>
|
||||
public static class StaticHelper
|
||||
{
|
||||
public static string VersionNumber = "1.2.7";
|
||||
public static string VersionNumber = "1.3.4";
|
||||
public static string DbName = "data/cartracker.db";
|
||||
public static string UserConfigPath = "config/userConfig.json";
|
||||
public static string GenericErrorMessage = "An error occurred, please try again later";
|
||||
public static string ReminderEmailTemplate = "defaults/reminderemailtemplate.txt";
|
||||
public static string DefaultAllowedFileExtensions = ".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx";
|
||||
|
||||
public static string SponsorsPath = "https://hargata.github.io/hargata/sponsors.json";
|
||||
public static string GetTitleCaseReminderUrgency(ReminderUrgency input)
|
||||
{
|
||||
switch (input)
|
||||
@@ -259,5 +259,33 @@ namespace CarCareTracker.Helper
|
||||
};
|
||||
httpClient.PostAsJsonAsync(webhookURL, httpParams);
|
||||
}
|
||||
public static string GetImportModeIcon(ImportMode importMode)
|
||||
{
|
||||
switch (importMode)
|
||||
{
|
||||
case ImportMode.ServiceRecord:
|
||||
return "bi-card-checklist";
|
||||
case ImportMode.RepairRecord:
|
||||
return "bi-exclamation-octagon";
|
||||
case ImportMode.UpgradeRecord:
|
||||
return "bi-wrench-adjustable";
|
||||
case ImportMode.TaxRecord:
|
||||
return "bi-currency-dollar";
|
||||
case ImportMode.SupplyRecord:
|
||||
return "bi-shop";
|
||||
case ImportMode.PlanRecord:
|
||||
return "bi-bar-chart-steps";
|
||||
case ImportMode.OdometerRecord:
|
||||
return "bi-speedometer";
|
||||
case ImportMode.GasRecord:
|
||||
return "bi-fuel-pump";
|
||||
case ImportMode.NoteRecord:
|
||||
return "bi-journal-bookmark";
|
||||
case ImportMode.ReminderRecord:
|
||||
return "bi-bell";
|
||||
default:
|
||||
return "bi-file-bar-graph";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
7
LICENSE
7
LICENSE
@@ -1,11 +1,6 @@
|
||||
LubeLogger by Hargata Softworks is licensed under the MIT License for individual
|
||||
and personal use. Commercial users and/or corporate entities are required
|
||||
to maintain an active subscription in order to continue using LubeLogger.
|
||||
For pricing information please contact us at hargatasoftworks@gmail.com
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Hargata Softworks
|
||||
Copyright (c) 2024 Hargata Softworks
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
107
Logic/VehicleLogic.cs
Normal file
107
Logic/VehicleLogic.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
|
||||
namespace CarCareTracker.Logic
|
||||
{
|
||||
public interface IVehicleLogic
|
||||
{
|
||||
int GetMaxMileage(int vehicleId);
|
||||
int GetMinMileage(int vehicleId);
|
||||
bool GetVehicleHasUrgentOrPastDueReminders(int vehicleId);
|
||||
}
|
||||
public class VehicleLogic: IVehicleLogic
|
||||
{
|
||||
private readonly IServiceRecordDataAccess _serviceRecordDataAccess;
|
||||
private readonly IGasRecordDataAccess _gasRecordDataAccess;
|
||||
private readonly ICollisionRecordDataAccess _collisionRecordDataAccess;
|
||||
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
|
||||
private readonly IOdometerRecordDataAccess _odometerRecordDataAccess;
|
||||
private readonly IReminderRecordDataAccess _reminderRecordDataAccess;
|
||||
private readonly IReminderHelper _reminderHelper;
|
||||
public VehicleLogic(
|
||||
IServiceRecordDataAccess serviceRecordDataAccess,
|
||||
IGasRecordDataAccess gasRecordDataAccess,
|
||||
ICollisionRecordDataAccess collisionRecordDataAccess,
|
||||
IUpgradeRecordDataAccess upgradeRecordDataAccess,
|
||||
IOdometerRecordDataAccess odometerRecordDataAccess,
|
||||
IReminderRecordDataAccess reminderRecordDataAccess,
|
||||
IReminderHelper reminderHelper
|
||||
) {
|
||||
_serviceRecordDataAccess = serviceRecordDataAccess;
|
||||
_gasRecordDataAccess = gasRecordDataAccess;
|
||||
_collisionRecordDataAccess = collisionRecordDataAccess;
|
||||
_upgradeRecordDataAccess = upgradeRecordDataAccess;
|
||||
_odometerRecordDataAccess = odometerRecordDataAccess;
|
||||
_reminderRecordDataAccess = reminderRecordDataAccess;
|
||||
_reminderHelper = reminderHelper;
|
||||
}
|
||||
public int GetMaxMileage(int vehicleId)
|
||||
{
|
||||
var numbersArray = new List<int>();
|
||||
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
||||
if (serviceRecords.Any())
|
||||
{
|
||||
numbersArray.Add(serviceRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var repairRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
|
||||
if (repairRecords.Any())
|
||||
{
|
||||
numbersArray.Add(repairRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
|
||||
if (gasRecords.Any())
|
||||
{
|
||||
numbersArray.Add(gasRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
||||
if (upgradeRecords.Any())
|
||||
{
|
||||
numbersArray.Add(upgradeRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||
if (odometerRecords.Any())
|
||||
{
|
||||
numbersArray.Add(odometerRecords.Max(x => x.Mileage));
|
||||
}
|
||||
return numbersArray.Any() ? numbersArray.Max() : 0;
|
||||
}
|
||||
public int GetMinMileage(int vehicleId)
|
||||
{
|
||||
var numbersArray = new List<int>();
|
||||
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
|
||||
if (serviceRecords.Any())
|
||||
{
|
||||
numbersArray.Add(serviceRecords.Min(x => x.Mileage));
|
||||
}
|
||||
var repairRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
|
||||
if (repairRecords.Any())
|
||||
{
|
||||
numbersArray.Add(repairRecords.Min(x => x.Mileage));
|
||||
}
|
||||
var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
|
||||
if (gasRecords.Any())
|
||||
{
|
||||
numbersArray.Add(gasRecords.Min(x => x.Mileage));
|
||||
}
|
||||
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
|
||||
if (upgradeRecords.Any())
|
||||
{
|
||||
numbersArray.Add(upgradeRecords.Min(x => x.Mileage));
|
||||
}
|
||||
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
|
||||
if (odometerRecords.Any())
|
||||
{
|
||||
numbersArray.Add(odometerRecords.Min(x => x.Mileage));
|
||||
}
|
||||
return numbersArray.Any() ? numbersArray.Min() : 0;
|
||||
}
|
||||
public bool GetVehicleHasUrgentOrPastDueReminders(int vehicleId)
|
||||
{
|
||||
var currentMileage = GetMaxMileage(vehicleId);
|
||||
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
||||
var results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, DateTime.Now);
|
||||
return results.Any(x => x.Urgency == ReminderUrgency.VeryUrgent || x.Urgency == ReminderUrgency.PastDue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int VehicleId { get; set; }
|
||||
public int ReminderRecordId { get; set; }
|
||||
public List<int> ReminderRecordId { get; set; } = new List<int>();
|
||||
public string Date { get; set; } = DateTime.Now.ToShortDateString();
|
||||
public int Mileage { get; set; }
|
||||
public string Description { get; set; }
|
||||
@@ -15,6 +15,7 @@
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
||||
public bool CopySuppliesAttachment { get; set; } = false;
|
||||
public CollisionRecord ToCollisionRecord() { return new CollisionRecord {
|
||||
Id = Id,
|
||||
VehicleId = VehicleId,
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
public string Scope { get; set; }
|
||||
public string State { get; set; }
|
||||
public bool ValidateState { get; set; } = false;
|
||||
public bool DisableRegularLogin { get; set; } = false;
|
||||
public string LogOutURL { get; set; } = "";
|
||||
public string RemoteAuthURL { get { return $"{AuthURL}?client_id={ClientId}&response_type=code&redirect_uri={RedirectURL}&scope={Scope}&state={State}"; } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
public decimal Cost { get; set; }
|
||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
||||
public bool CopySuppliesAttachment { get; set; } = false;
|
||||
public PlanRecord ToPlanRecord() { return new PlanRecord {
|
||||
Id = Id,
|
||||
VehicleId = VehicleId,
|
||||
|
||||
@@ -14,5 +14,6 @@
|
||||
public ReminderMileageInterval ReminderMileageInterval { get; set; } = ReminderMileageInterval.FiveThousandMiles;
|
||||
public ReminderMonthInterval ReminderMonthInterval { get; set; } = ReminderMonthInterval.OneYear;
|
||||
public ReminderMetric Metric { get; set; } = ReminderMetric.Date;
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
public ReminderMileageInterval ReminderMileageInterval { get; set; } = ReminderMileageInterval.FiveThousandMiles;
|
||||
public ReminderMonthInterval ReminderMonthInterval { get; set; } = ReminderMonthInterval.OneYear;
|
||||
public ReminderMetric Metric { get; set; } = ReminderMetric.Date;
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
public ReminderRecord ToReminderRecord()
|
||||
{
|
||||
return new ReminderRecord
|
||||
@@ -29,7 +30,8 @@
|
||||
ReminderMonthInterval = ReminderMonthInterval,
|
||||
CustomMileageInterval = CustomMileageInterval,
|
||||
CustomMonthInterval = CustomMonthInterval,
|
||||
Notes = Notes
|
||||
Notes = Notes,
|
||||
Tags = Tags
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,5 +17,6 @@
|
||||
/// Recurring Reminders
|
||||
/// </summary>
|
||||
public bool IsRecurring { get; set; } = false;
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,8 @@
|
||||
public decimal TotalCostPerMile { get; set; }
|
||||
public decimal TotalGasCostPerMile { get; set; }
|
||||
public string DistanceUnit { get; set; }
|
||||
public decimal TotalDepreciation { get; set; }
|
||||
public decimal DepreciationPerDay { get; set; }
|
||||
public decimal DepreciationPerMile { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
9
Models/SearchResult.cs
Normal file
9
Models/SearchResult.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class SearchResult
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public ImportMode RecordType { get; set; }
|
||||
public string Description { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int VehicleId { get; set; }
|
||||
public int ReminderRecordId { get; set; }
|
||||
public List<int> ReminderRecordId { get; set; } = new List<int>();
|
||||
public string Date { get; set; } = DateTime.Now.ToShortDateString();
|
||||
public int Mileage { get; set; }
|
||||
public string Description { get; set; }
|
||||
@@ -15,6 +15,7 @@
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
||||
public bool CopySuppliesAttachment { get; set; } = false;
|
||||
public ServiceRecord ToServiceRecord() { return new ServiceRecord {
|
||||
Id = Id,
|
||||
VehicleId = VehicleId,
|
||||
|
||||
@@ -4,5 +4,6 @@ namespace CarCareTracker.Models
|
||||
{
|
||||
public UserConfig UserConfig { get; set; }
|
||||
public List<string> UILanguages { get; set; }
|
||||
public Sponsors Sponsors { get; set; } = new Sponsors();
|
||||
}
|
||||
}
|
||||
|
||||
10
Models/Sponsors.cs
Normal file
10
Models/Sponsors.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class Sponsors
|
||||
{
|
||||
public List<string> LifeTime { get; set; } = new List<string>();
|
||||
public List<string> Bronze { get; set; } = new List<string>();
|
||||
public List<string> Silver { get; set; } = new List<string>();
|
||||
public List<string> Gold { get; set; } = new List<string>();
|
||||
}
|
||||
}
|
||||
8
Models/Supply/SupplyUsageViewModel.cs
Normal file
8
Models/Supply/SupplyUsageViewModel.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class SupplyUsageViewModel
|
||||
{
|
||||
public List<SupplyRecord> Supplies { get; set; } = new List<SupplyRecord>();
|
||||
public List<SupplyUsage> Usage { get; set; } = new List<SupplyUsage>();
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int VehicleId { get; set; }
|
||||
public int ReminderRecordId { get; set; }
|
||||
public List<int> ReminderRecordId { get; set; } = new List<int>();
|
||||
public string Date { get; set; } = DateTime.Now.ToShortDateString();
|
||||
public string Description { get; set; }
|
||||
public decimal Cost { get; set; }
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int VehicleId { get; set; }
|
||||
public int ReminderRecordId { get; set; }
|
||||
public List<int> ReminderRecordId { get; set; } = new List<int>();
|
||||
public string Date { get; set; } = DateTime.Now.ToShortDateString();
|
||||
public int Mileage { get; set; }
|
||||
public string Description { get; set; }
|
||||
@@ -15,6 +15,7 @@
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
||||
public bool CopySuppliesAttachment { get; set; } = false;
|
||||
public UpgradeRecord ToUpgradeRecord() { return new UpgradeRecord {
|
||||
Id = Id,
|
||||
VehicleId = VehicleId,
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
public string LicensePlate { get; set; }
|
||||
public string PurchaseDate { get; set; }
|
||||
public string SoldDate { get; set; }
|
||||
public decimal PurchasePrice { get; set; }
|
||||
public decimal SoldPrice { get; set; }
|
||||
public bool IsElectric { get; set; } = false;
|
||||
public bool UseHours { get; set; } = false;
|
||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||
|
||||
19
Models/VehicleViewModel.cs
Normal file
19
Models/VehicleViewModel.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class VehicleViewModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string ImageLocation { get; set; } = "/defaults/noimage.png";
|
||||
public int Year { get; set; }
|
||||
public string Make { get; set; }
|
||||
public string Model { get; set; }
|
||||
public string LicensePlate { get; set; }
|
||||
public string SoldDate { get; set; }
|
||||
public bool IsElectric { get; set; } = false;
|
||||
public bool UseHours { get; set; } = false;
|
||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
public int LastReportedMileage;
|
||||
public bool HasReminders = false;
|
||||
}
|
||||
}
|
||||
20
Program.cs
20
Program.cs
@@ -16,6 +16,9 @@ StaticHelper.InitMessage(builder.Configuration);
|
||||
// Add services to the container.
|
||||
builder.Services.AddControllersWithViews();
|
||||
|
||||
//LiteDB is always injected even if user uses Postgres.
|
||||
builder.Services.AddSingleton<ILiteDBHelper, LiteDBHelper>();
|
||||
|
||||
//data access method
|
||||
if (!string.IsNullOrWhiteSpace(builder.Configuration["POSTGRES_CONNECTION"])){
|
||||
builder.Services.AddSingleton<IVehicleDataAccess, PGVehicleDataAccess>();
|
||||
@@ -70,6 +73,7 @@ builder.Services.AddSingleton<ITranslationHelper, TranslationHelper>();
|
||||
builder.Services.AddSingleton<ILoginLogic, LoginLogic>();
|
||||
builder.Services.AddSingleton<IUserLogic, UserLogic>();
|
||||
builder.Services.AddSingleton<IOdometerLogic, OdometerLogic>();
|
||||
builder.Services.AddSingleton<IVehicleLogic, VehicleLogic>();
|
||||
|
||||
if (!Directory.Exists("data"))
|
||||
{
|
||||
@@ -107,7 +111,21 @@ var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
app.UseExceptionHandler("/Home/Error");
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
OnPrepareResponse = ctx =>
|
||||
{
|
||||
if (ctx.Context.Request.Path.StartsWithSegments("/images") || ctx.Context.Request.Path.StartsWithSegments("/documents"))
|
||||
{
|
||||
ctx.Context.Response.Headers.Add("Cache-Control", "no-store");
|
||||
if (!ctx.Context.User.Identity.IsAuthenticated)
|
||||
{
|
||||
ctx.Context.Response.Redirect("/Login");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
|
||||
32
README.md
32
README.md
@@ -22,15 +22,6 @@ LubeLogger is available as both a Docker Image and a Windows Standalone Executab
|
||||
|
||||
Read this [Getting Started Guide](https://docs.lubelogger.com/Getting%20Started) on how to download either of them
|
||||
|
||||
### Docker Setup (Manual Build for Advanced Users)
|
||||
1. Install Docker
|
||||
2. Clone this repo
|
||||
3. CHECK culture in .env file, default is en_US, also setup SMTP for user management if you want that.
|
||||
4. Run `docker build -t lubelogger -f Dockerfile .`
|
||||
5. CHECK docker-compose.yml and make sure the mounting directories look correct.
|
||||
6. If using traefik, use docker-compose.traefik.yml
|
||||
7. Run `docker-compose up`
|
||||
|
||||
### Need Help?
|
||||
[Documentation](https://docs.lubelogger.com/)
|
||||
|
||||
@@ -39,19 +30,18 @@ Read this [Getting Started Guide](https://docs.lubelogger.com/Getting%20Started)
|
||||
[Search Existing Issues](https://github.com/hargata/lubelog/issues)
|
||||
|
||||
## Dependencies
|
||||
- Bootstrap
|
||||
- LiteDB
|
||||
- Npgsql
|
||||
- Bootstrap-DatePicker
|
||||
- SweetAlert2
|
||||
- CsvHelper
|
||||
- Chart.js
|
||||
- Drawdown
|
||||
- [Bootstrap](https://github.com/twbs/bootstrap)
|
||||
- [LiteDB](https://github.com/mbdavid/litedb)
|
||||
- [Npgsql](https://github.com/npgsql/npgsql)
|
||||
- [Bootstrap-DatePicker](https://github.com/uxsolutions/bootstrap-datepicker)
|
||||
- [SweetAlert2](https://github.com/sweetalert2/sweetalert2)
|
||||
- [CsvHelper](https://github.com/JoshClose/CsvHelper)
|
||||
- [Chart.js](https://github.com/chartjs/Chart.js)
|
||||
- [Drawdown](https://github.com/adamvleggett/drawdown)
|
||||
- [MailKit](https://github.com/jstedfast/MailKit)
|
||||
|
||||
## License
|
||||
LubeLogger utilizes a dual-licensing model, see [License](/LICENSE) for more information
|
||||
MIT
|
||||
|
||||
## Support
|
||||
Support this project by [Subscribing on Patreon](https://patreon.com/LubeLogger) or [Making a Donation](https://buy.stripe.com/aEU9Egc8DdMc9bO144)
|
||||
|
||||
Note: Commercial users are required to maintain an active Patreon subscripton to be compliant with our licensing model.
|
||||
Support this project by [Subscribing on Patreon](https://patreon.com/LubeLogger) or [Making a Donation](https://buy.stripe.com/aEU9Egc8DdMc9bO144)
|
||||
@@ -1,7 +1,7 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model List<Vehicle>
|
||||
@model List<VehicleViewModel>
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
<div class="row">
|
||||
<div class="row gy-3 align-items-stretch vehiclesContainer">
|
||||
@foreach (Vehicle vehicle in Model)
|
||||
@foreach (VehicleViewModel vehicle in Model)
|
||||
{
|
||||
@if (!(userConfig.HideSoldVehicles && !string.IsNullOrWhiteSpace(vehicle.SoldDate)))
|
||||
{
|
||||
@@ -36,6 +36,22 @@
|
||||
@if (!string.IsNullOrWhiteSpace(vehicle.SoldDate))
|
||||
{
|
||||
<div class="vehicle-sold-banner"><p class='display-6 mb-0'>@translator.Translate(userLanguage, "SOLD")</p></div>
|
||||
} else if (vehicle.LastReportedMileage != default)
|
||||
{
|
||||
<div class="vehicle-sold-banner">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>
|
||||
<span class="ms-2"><i class="bi bi-speedometer me-2"></i>@vehicle.LastReportedMileage.ToString("N0")</span>
|
||||
</div>
|
||||
@if (vehicle.HasReminders)
|
||||
{
|
||||
<div>
|
||||
<span class="me-2"><i class="bi bi bi-bell-fill text-warning"></i></span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<span></span>
|
||||
</div>
|
||||
}
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-truncate garage-item-year" data-unit="@vehicle.Year">@($"{vehicle.Year}")</h5>
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
</p>
|
||||
<p class="lead">
|
||||
If you enjoyed using this app, please consider spreading the good word.<br />
|
||||
If you are a commercial user, or if you just want to support the development of this project, consider subscribing to <a class="link-light link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover" href="https://www.patreon.com/LubeLogger" target="_blank">our Patreon</a> or make a <a class="link-light link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover" href="https://buy.stripe.com/aEU9Egc8DdMc9bO144" target="_blank">donation</a>
|
||||
If you want to support the development of this project, consider subscribing to <a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover" href="https://www.patreon.com/LubeLogger" target="_blank">our Patreon</a> or make a <a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover" href="https://buy.stripe.com/aEU9Egc8DdMc9bO144" target="_blank">donation</a>
|
||||
</p>
|
||||
<div class="d-flex justify-content-center">
|
||||
<h6 class="display-7 mt-2">Hometown Shoutout</h6>
|
||||
@@ -247,9 +247,11 @@
|
||||
<li class="list-group-item">CsvHelper</li>
|
||||
<li class="list-group-item">Chart.js</li>
|
||||
<li class="list-group-item">Drawdown</li>
|
||||
<li class="list-group-item">MailKit</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@await Html.PartialAsync("_Sponsors", Model.Sponsors)
|
||||
<div class="modal fade" data-bs-focus="false" id="extraFieldModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content" id="extraFieldModalContent">
|
||||
|
||||
73
Views/Home/_Sponsors.cshtml
Normal file
73
Views/Home/_Sponsors.cshtml
Normal file
@@ -0,0 +1,73 @@
|
||||
@using CarCareTracker.Helper
|
||||
@model Sponsors
|
||||
@inject ITranslationHelper translator
|
||||
@inject IConfigHelper config
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var enableAuth = userConfig.EnableAuth;
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="row">
|
||||
<div class="d-flex justify-content-center">
|
||||
<h6 class="display-6 mt-2">@translator.Translate(userLanguage, "Sponsors")</h6>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-center">
|
||||
<p><a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover" href="https://docs.lubelogger.com/Funding" target="_blank">Become a Sponsor</a></p>
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.LifeTime.Any())
|
||||
{
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-center">
|
||||
<h6 class="display-7 mt-2">Lifetime</h6>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<p class="lead">
|
||||
@string.Join(", ", Model.LifeTime)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (Model.Gold.Any())
|
||||
{
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-center">
|
||||
<h6 class="display-7 mt-2">Gold</h6>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<p class="lead">
|
||||
@string.Join(", ", Model.Gold)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (Model.Silver.Any())
|
||||
{
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-center">
|
||||
<h6 class="display-7 mt-2">Silver</h6>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<p class="lead">
|
||||
@string.Join(", ", Model.Silver)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (Model.Bronze.Any())
|
||||
{
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-center">
|
||||
<h6 class="display-7 mt-2">Bronze</h6>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<p class="lead">
|
||||
@string.Join(", ", Model.Bronze)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -70,8 +70,8 @@
|
||||
}
|
||||
function globalParseFloat(input){
|
||||
//remove thousands separator.
|
||||
var thousandSeparator = "@numberFormat.NumberGroupSeparator";
|
||||
var decimalSeparator = "@numberFormat.NumberDecimalSeparator";
|
||||
var thousandSeparator = decodeHTMLEntities("@numberFormat.NumberGroupSeparator");
|
||||
var decimalSeparator = decodeHTMLEntities("@numberFormat.NumberDecimalSeparator");
|
||||
var currencySymbol = decodeHTMLEntities("@numberFormat.CurrencySymbol");
|
||||
if (input == "---") {
|
||||
input = "0";
|
||||
@@ -85,13 +85,32 @@
|
||||
return parseFloat(input);
|
||||
}
|
||||
function globalFloatToString(input) {
|
||||
var decimalSeparator = "@numberFormat.NumberDecimalSeparator";
|
||||
var decimalSeparator = decodeHTMLEntities("@numberFormat.NumberDecimalSeparator");
|
||||
input = input.replace(".", decimalSeparator);
|
||||
return input;
|
||||
}
|
||||
function genericErrorMessage(){
|
||||
return decodeHTMLEntities('@translator.Translate(userLanguage, "An error has occurred, please try again later")');
|
||||
}
|
||||
function globalAppendCurrency(input){
|
||||
//check currency symbol position
|
||||
var currencySymbolPosition = "@numberFormat.CurrencyPositivePattern";
|
||||
var currencySymbol = decodeHTMLEntities("@numberFormat.CurrencySymbol");
|
||||
switch (currencySymbolPosition) {
|
||||
case "0":
|
||||
return `${currencySymbol}${input}`;
|
||||
break;
|
||||
case "1":
|
||||
return `${input}${currencySymbol}`;
|
||||
break;
|
||||
case "2":
|
||||
return `${currencySymbol} ${input}`;
|
||||
break;
|
||||
case "3":
|
||||
return `${input} ${currencySymbol}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@await RenderSectionAsync("Scripts", required: false)
|
||||
</head>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Repair Record") : translator.Translate(userLanguage,"Edit Repair Record"))</h5>
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Repair Record") : translator.Translate(userLanguage, "Edit Repair Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditCollisionRecordModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddCollisionRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@@ -17,14 +17,22 @@
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12">
|
||||
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
|
||||
<label for="collisionRecordDate">@translator.Translate(userLanguage,"Date")</label>
|
||||
<label for="collisionRecordDate">@translator.Translate(userLanguage, "Date")</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="collisionRecordDate" class="form-control" placeholder="@translator.Translate(userLanguage,"Date repair was performed")" value="@Model.Date">
|
||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||
</div>
|
||||
<label for="collisionRecordMileage">@translator.Translate(userLanguage,"Odometer")</label>
|
||||
<input type="number" inputmode="numeric" id="collisionRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when repaired")" value="@(isNew ? "" : Model.Mileage)">
|
||||
<label for="collisionRecordDescription">@translator.Translate(userLanguage,"Description")</label>
|
||||
<label for="collisionRecordMileage">@translator.Translate(userLanguage, "Odometer")</label>
|
||||
<div class="input-group">
|
||||
<input type="number" inputmode="numeric" id="collisionRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when repaired")" value="@(isNew ? "" : Model.Mileage)">
|
||||
@if (isNew)
|
||||
{
|
||||
<div class="input-group-text">
|
||||
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('collisionRecordMileage')">+</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<label for="collisionRecordDescription">@translator.Translate(userLanguage, "Description")</label>
|
||||
<input type="text" id="collisionRecordDescription" class="form-control" placeholder="@translator.Translate(userLanguage,"Description of item(s) repaired(i.e. Alternator)")" value="@Model.Description">
|
||||
@if (isNew)
|
||||
{
|
||||
@@ -34,13 +42,13 @@
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<label for="collisionRecordCost">@translator.Translate(userLanguage,"Cost")</label>
|
||||
<label for="collisionRecordCost">@translator.Translate(userLanguage, "Cost")</label>
|
||||
<input type="text" inputmode="decimal" id="collisionRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"Cost of the repair")" value="@(isNew ? "" : Model.Cost)">
|
||||
@if (isNew)
|
||||
{
|
||||
@await Html.PartialAsync("_SupplyStore", "RepairRecord")
|
||||
}
|
||||
<label for="collisionRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
|
||||
<label for="collisionRecordTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
|
||||
<select multiple class="form-select" id="collisionRecordTag">
|
||||
@foreach (string tag in Model.Tags)
|
||||
{
|
||||
@@ -57,15 +65,15 @@
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-6 col-12">
|
||||
<label for="collisionRecordNotes">@translator.Translate(userLanguage,"Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
||||
<label for="collisionRecordNotes">@translator.Translate(userLanguage, "Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
||||
<textarea id="collisionRecordNotes" class="form-control" rows="5">@Model.Notes</textarea>
|
||||
@if (Model.Files.Any())
|
||||
{
|
||||
<div>
|
||||
@await Html.PartialAsync("_UploadedFiles", Model.Files)
|
||||
<label for="collisionRecordFiles">@translator.Translate(userLanguage,"Upload more documents")</label>
|
||||
<label for="collisionRecordFiles">@translator.Translate(userLanguage, "Upload more documents")</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="collisionRecordFiles">
|
||||
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
|
||||
<br /><small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -75,13 +83,15 @@
|
||||
<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")
|
||||
@translator.Translate(userLanguage, "Add Reminder")
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
<label for="collisionRecordFiles">@translator.Translate(userLanguage,"Upload documents(optional)")</label>
|
||||
<label for="collisionRecordFiles">@translator.Translate(userLanguage, "Upload documents(optional)")</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="collisionRecordFiles">
|
||||
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
|
||||
<br />
|
||||
|
||||
<small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -96,39 +106,40 @@
|
||||
<button type="button" class="btn btn-warning" onclick="toggleSupplyUsageHistory()"><i class="bi bi-shop"></i></button>
|
||||
}
|
||||
<div class="btn-group" style="margin-right:auto;">
|
||||
<button type="button" class="btn btn-md mt-1 mb-1 btn-danger" onclick="deleteCollisionRecord(@Model.Id)">@translator.Translate(userLanguage,"Delete")</button>
|
||||
<button type="button" class="btn btn-md mt-1 mb-1 btn-danger" onclick="deleteCollisionRecord(@Model.Id)">@translator.Translate(userLanguage, "Delete")</button>
|
||||
<button type="button" class="btn btn-md btn-danger 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><h6 class="dropdown-header">@translator.Translate(userLanguage,"Move To")</h6></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'RepairRecord', 'ServiceRecord')">@translator.Translate(userLanguage,"Service Records")</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'RepairRecord', 'UpgradeRecord')">@translator.Translate(userLanguage,"Upgrades")</a></li>
|
||||
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Move To")</h6></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'RepairRecord', 'ServiceRecord')">@translator.Translate(userLanguage, "Service Records")</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'RepairRecord', 'UpgradeRecord')">@translator.Translate(userLanguage, "Upgrades")</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
<button type="button" class="btn btn-secondary" onclick="hideAddCollisionRecordModal()">@translator.Translate(userLanguage,"Cancel")</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="hideAddCollisionRecordModal()">@translator.Translate(userLanguage, "Cancel")</button>
|
||||
@if (isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" onclick="saveCollisionRecordToVehicle()">@translator.Translate(userLanguage,"Add New Repair Record")</button>
|
||||
<button type="button" class="btn btn-primary" onclick="saveCollisionRecordToVehicle()">@translator.Translate(userLanguage, "Add New Repair Record")</button>
|
||||
}
|
||||
else if (!isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" onclick="saveCollisionRecordToVehicle(true)">@translator.Translate(userLanguage,"Edit Repair Record")</button>
|
||||
<button type="button" class="btn btn-primary" onclick="saveCollisionRecordToVehicle(true)">@translator.Translate(userLanguage, "Edit Repair Record")</button>
|
||||
}
|
||||
</div>
|
||||
@await Html.PartialAsync("_SupplyRequisitionHistory", Model.RequisitionHistory)
|
||||
<script>
|
||||
var uploadedFiles = [];
|
||||
var selectedSupplies = [];
|
||||
var recurringReminderRecordId = 0;
|
||||
var copySuppliesAttachments = false;
|
||||
var recurringReminderRecordId = [];
|
||||
getUploadedFilesFromModel();
|
||||
function getUploadedFilesFromModel() {
|
||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||
{
|
||||
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
|
||||
}
|
||||
}
|
||||
}
|
||||
function getCollisionRecordModelData() {
|
||||
return { id: @Model.Id}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,19 @@
|
||||
<td class="col-3 flex-grow-1 flex-shrink-1 text-truncate" data-column="notes">@CarCareTracker.Helper.StaticHelper.TruncateStrings(collisionRecord.Notes)</td>
|
||||
@foreach (string extraFieldColumn in extraFields)
|
||||
{
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">@(collisionRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "")</td>
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">
|
||||
@{
|
||||
var extraFieldValue = collisionRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "";
|
||||
if (!string.IsNullOrWhiteSpace(extraFieldValue) && Uri.IsWellFormedUriString(extraFieldValue, UriKind.Absolute))
|
||||
{
|
||||
<a href="@extraFieldValue" onclick="noPropagation()" target="_blank">@CarCareTracker.Helper.StaticHelper.TruncateStrings(extraFieldValue)</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
@extraFieldValue
|
||||
}
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
|
||||
@@ -199,7 +199,19 @@
|
||||
<td class="col-3 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="notes">@StaticHelper.TruncateStrings(gasRecord.Notes)</td>
|
||||
@foreach (string extraFieldColumn in extraFields)
|
||||
{
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">@(gasRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "")</td>
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">
|
||||
@{
|
||||
var extraFieldValue = gasRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "";
|
||||
if (!string.IsNullOrWhiteSpace(extraFieldValue) && Uri.IsWellFormedUriString(extraFieldValue, UriKind.Absolute))
|
||||
{
|
||||
<a href="@extraFieldValue" onclick="noPropagation()" target="_blank">@CarCareTracker.Helper.StaticHelper.TruncateStrings(extraFieldValue)</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
@extraFieldValue
|
||||
}
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
|
||||
@@ -17,27 +17,27 @@
|
||||
consumptionUnit = "kWh";
|
||||
} else if (useUKMPG)
|
||||
{
|
||||
consumptionUnit = "liters";
|
||||
consumptionUnit = @translator.Translate(userLanguage, "liters");
|
||||
}
|
||||
else
|
||||
{
|
||||
consumptionUnit = useMPG ? "gallons" : "liters";
|
||||
consumptionUnit = useMPG ? @translator.Translate(userLanguage, "gallons") : @translator.Translate(userLanguage, "liters");
|
||||
}
|
||||
if (useHours)
|
||||
{
|
||||
distanceUnit = "hours";
|
||||
distanceUnit = @translator.Translate(userLanguage, "hours");
|
||||
}
|
||||
else if (useUKMPG)
|
||||
{
|
||||
distanceUnit = "miles";
|
||||
distanceUnit = @translator.Translate(userLanguage, "miles");
|
||||
}
|
||||
else
|
||||
{
|
||||
distanceUnit = useMPG ? "miles" : "kilometers";
|
||||
distanceUnit = useMPG ? @translator.Translate(userLanguage, "miles") : @translator.Translate(userLanguage, "kilometers");
|
||||
}
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Gas Record") : translator.Translate(userLanguage,"Edit Gas Record"))</h5>
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Gas Record") : translator.Translate(userLanguage, "Edit Gas Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditGasRecordModal({Model.GasRecord.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddGasRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@@ -52,7 +52,15 @@
|
||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||
</div>
|
||||
<label for="gasRecordMileage">@($"{translator.Translate(userLanguage,"Odometer Reading")}({distanceUnit})")</label>
|
||||
<input type="number" inputmode="numeric" id="gasRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when refueled")" value="@(isNew ? "" : Model.GasRecord.Mileage)">
|
||||
<div class="input-group">
|
||||
<input type="number" inputmode="numeric" id="gasRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when refueled")" value="@(isNew ? "" : Model.GasRecord.Mileage)">
|
||||
@if (isNew)
|
||||
{
|
||||
<div class="input-group-text">
|
||||
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('gasRecordMileage')">+</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<label for="gasRecordGallons">@($"{translator.Translate(userLanguage, "Fuel Consumption")}({consumptionUnit})")</label>
|
||||
<input type="text" inputmode="decimal" id="gasRecordGallons" class="form-control" placeholder="@translator.Translate(userLanguage,"Amount of gas refueled")" value="@(isNew ? "" : Model.GasRecord.Gallons)">
|
||||
<div class="form-check form-switch">
|
||||
|
||||
34
Views/Vehicle/_GlobalSearchResult.cshtml
Normal file
34
Views/Vehicle/_GlobalSearchResult.cshtml
Normal file
@@ -0,0 +1,34 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model List<SearchResult>
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div style="max-height:50vh; overflow-y:auto;">
|
||||
@if (Model.Any())
|
||||
{
|
||||
@foreach (SearchResult result in Model)
|
||||
{
|
||||
<div class="row border p-2 m-1" onclick="loadGlobalSearchResult(@result.Id, '@result.RecordType')" style="cursor:pointer;">
|
||||
<div class="col-1">
|
||||
<i class="bi @StaticHelper.GetImportModeIcon(result.RecordType)"></i>
|
||||
</div>
|
||||
<div class="col-11">
|
||||
@result.Description
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
} else
|
||||
{
|
||||
<div class="row border p-2 m-1">
|
||||
<div class="col-1">
|
||||
<i class="bi bi-ban"></i>
|
||||
</div>
|
||||
<div class="col-11">
|
||||
@translator.Translate(userLanguage, "No Data Found")
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -8,7 +8,7 @@
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Note") : translator.Translate(userLanguage, "Edit Note"))</h5>
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Note") : translator.Translate(userLanguage, "Edit Note"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditNoteModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddNoteModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Odometer Record") : translator.Translate(userLanguage,"Edit Odometer Record"))</h5>
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Odometer Record") : translator.Translate(userLanguage, "Edit Odometer Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditOdometerRecordModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddOdometerRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@@ -25,7 +25,15 @@
|
||||
<label for="initialOdometerRecordMileage">@translator.Translate(userLanguage, "Initial Odometer")</label>
|
||||
<input type="number" inputmode="numeric" id="initialOdometerRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Initial Odometer reading")" value="@(Model.InitialMileage)">
|
||||
<label for="odometerRecordMileage">@translator.Translate(userLanguage,"Odometer")</label>
|
||||
<input type="number" inputmode="numeric" id="odometerRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading")" value="@(isNew ? "" : Model.Mileage)">
|
||||
<div class="input-group">
|
||||
<input type="number" inputmode="numeric" id="odometerRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading")" value="@(isNew ? "" : Model.Mileage)">
|
||||
@if (isNew)
|
||||
{
|
||||
<div class="input-group-text">
|
||||
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('odometerRecordMileage')">+</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<label for="odometerRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
|
||||
<select multiple class="form-select" id="odometerRecordTag">
|
||||
@foreach (string tag in Model.Tags)
|
||||
|
||||
@@ -129,7 +129,19 @@
|
||||
<td class="col-2 col-xl-3 flex-grow-1 flex-shrink-1 text-truncate" data-column="notes">@CarCareTracker.Helper.StaticHelper.TruncateStrings(odometerRecord.Notes, 75)</td>
|
||||
@foreach (string extraFieldColumn in extraFields)
|
||||
{
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">@(odometerRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "")</td>
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">
|
||||
@{
|
||||
var extraFieldValue = odometerRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "";
|
||||
if (!string.IsNullOrWhiteSpace(extraFieldValue) && Uri.IsWellFormedUriString(extraFieldValue, UriKind.Absolute))
|
||||
{
|
||||
<a href="@extraFieldValue" onclick="noPropagation()" target="_blank">@CarCareTracker.Helper.StaticHelper.TruncateStrings(extraFieldValue)</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
@extraFieldValue
|
||||
}
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@model PlanRecord
|
||||
<div class="taskCard @(Model.Progress == PlanProgress.Done ? "nodrag" : "") text-dark user-select-none mt-2 mb-2" draggable="@(Model.Progress == PlanProgress.Done ? "false" : "true")" ondragstart="dragStart(event, @Model.Id)" onclick="@(Model.Progress == PlanProgress.Done ? $"deletePlanRecord({Model.Id})" : $"showEditPlanRecordModal({Model.Id})")">
|
||||
<div class="taskCard @(Model.Progress == PlanProgress.Done ? "nodrag" : "") text-dark user-select-none mt-2 mb-2" draggable="@(Model.Progress == PlanProgress.Done ? "false" : "true")" ondragstart="dragStart(event, @Model.Id)" onclick="@(Model.Progress == PlanProgress.Done ? $"deletePlanRecord({Model.Id}, true)" : $"showEditPlanRecordModal({Model.Id})")">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-8 text-truncate">
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Plan Record") : translator.Translate(userLanguage, "Edit Plan Record"))</h5>
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Plan Record") : translator.Translate(userLanguage, "Edit Plan Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditPlanRecordModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddPlanRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@@ -101,10 +101,6 @@
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" onclick="savePlanRecordTemplate()">@translator.Translate(userLanguage, "Save as Template")</a></li>
|
||||
@if (!Model.CreatedFromReminder)
|
||||
{
|
||||
<li><a class="dropdown-item" href="#" onclick="showPlanRecordTemplatesModal()">@translator.Translate(userLanguage, "View Templates")</a></li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
@@ -117,6 +113,7 @@
|
||||
<script>
|
||||
var uploadedFiles = [];
|
||||
var selectedSupplies = [];
|
||||
var copySuppliesAttachments = false;
|
||||
getUploadedFilesFromModel();
|
||||
function getUploadedFilesFromModel() {
|
||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||
@@ -129,7 +126,8 @@
|
||||
id: @Model.Id,
|
||||
dateCreated: decodeHTMLEntities('@(Model.DateCreated)'),
|
||||
reminderRecordId: decodeHTMLEntities('@Model.ReminderRecordId'),
|
||||
createdFromReminder: @Model.CreatedFromReminder.ToString().ToLower()
|
||||
createdFromReminder: @Model.CreatedFromReminder.ToString().ToLower(),
|
||||
isTemplate: false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
117
Views/Vehicle/_PlanRecordTemplateEditModal.cshtml
Normal file
117
Views/Vehicle/_PlanRecordTemplateEditModal.cshtml
Normal file
@@ -0,0 +1,117 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model PlanRecordInput
|
||||
@{
|
||||
var isNew = Model.Id == 0;
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@translator.Translate(userLanguage, "Edit Plan Record Template")<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditPlanRecordTemplateModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddPlanRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12">
|
||||
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
|
||||
<label for="planRecordDescription">@translator.Translate(userLanguage, "Description")</label>
|
||||
<input type="text" id="planRecordDescription" class="form-control" placeholder="@translator.Translate(userLanguage, "Describe the Plan")" value="@Model.Description">
|
||||
<label for="planRecordCost">@translator.Translate(userLanguage, "Cost")</label>
|
||||
<input type="text" inputmode="decimal" id="planRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage, "Cost of the Plan")" value="@Model.Cost">
|
||||
@await Html.PartialAsync("_SupplyStore", "PlanRecordTemplate")
|
||||
<label for="planRecordType">@translator.Translate(userLanguage, "Type")</label>
|
||||
<select class="form-select" id="planRecordType">
|
||||
<!option value="ServiceRecord" @(Model.ImportMode == ImportMode.ServiceRecord || isNew ? "selected" : "")>@translator.Translate(userLanguage, "Service")</!option>
|
||||
<!option value="RepairRecord" @(Model.ImportMode == ImportMode.RepairRecord ? "selected" : "")>@translator.Translate(userLanguage, "Repair")</!option>
|
||||
<!option value="UpgradeRecord" @(Model.ImportMode == ImportMode.UpgradeRecord ? "selected" : "")>@translator.Translate(userLanguage, "Upgrade")</!option>
|
||||
</select>
|
||||
<label for="planRecordPriority">@translator.Translate(userLanguage, "Priority")</label>
|
||||
<select class="form-select" id="planRecordPriority">
|
||||
<!option value="Critical" @(Model.Priority == PlanPriority.Critical ? "selected" : "")>@translator.Translate(userLanguage, "Critical")</!option>
|
||||
<!option value="Normal" @(Model.Priority == PlanPriority.Normal || isNew ? "selected" : "")>@translator.Translate(userLanguage, "Normal")</!option>
|
||||
<!option value="Low" @(Model.Priority == PlanPriority.Low ? "selected" : "")>@translator.Translate(userLanguage, "Low")</!option>
|
||||
</select>
|
||||
<label for="planRecordProgress">@translator.Translate(userLanguage, "Current Stage")</label>
|
||||
<select class="form-select" id="planRecordProgress">
|
||||
<!option value = "Backlog" @(Model.Progress == PlanProgress.Backlog || isNew ? "selected" : "")>@translator.Translate(userLanguage, "Planned")</!option>
|
||||
<!option value="InProgress" @(Model.Progress == PlanProgress.InProgress ? "selected" : "")>@translator.Translate(userLanguage, "Doing")</!option>
|
||||
<!option value = "Testing" @(Model.Progress == PlanProgress.Testing ? "selected" : "")>@translator.Translate(userLanguage, "Testing")</!option>
|
||||
</select>
|
||||
@foreach (ExtraField field in Model.ExtraFields)
|
||||
{
|
||||
var elementId = Guid.NewGuid();
|
||||
<div class="extra-field">
|
||||
<label for="@elementId">@field.Name</label>
|
||||
<input type="text" id="@elementId" class="form-control @(field.IsRequired ? "extra-field-required" : "")" placeholder="@field.Name" value="@field.Value">
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-6 col-12">
|
||||
<label for="planRecordNotes">@translator.Translate(userLanguage, "Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
||||
<textarea id="planRecordNotes" class="form-control" rows="5">@Model.Notes</textarea>
|
||||
@if (Model.Files.Any())
|
||||
{
|
||||
<div>
|
||||
@await Html.PartialAsync("_UploadedFiles", Model.Files)
|
||||
<label for="planRecordFiles">@translator.Translate(userLanguage, "Upload more documents")</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="planRecordFiles">
|
||||
<br /><small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<label for="planRecordFiles">@translator.Translate(userLanguage, "Upload documents(optional)")</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="planRecordFiles">
|
||||
<br />
|
||||
|
||||
<small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@if (!isNew)
|
||||
{
|
||||
@if (Model.RequisitionHistory.Any())
|
||||
{
|
||||
<button type="button" class="btn btn-warning" onclick="toggleSupplyUsageHistory()"><i class="bi bi-shop"></i></button>
|
||||
}
|
||||
<button type="button" class="btn btn-danger" onclick="deletePlannerRecordTemplate(@Model.Id)" style="margin-right:auto;">@translator.Translate(userLanguage, "Delete")</button>
|
||||
}
|
||||
<button type="button" class="btn btn-secondary" onclick="hideAddPlanRecordModal()">@translator.Translate(userLanguage, "Cancel")</button>
|
||||
<button type="button" class="btn btn-primary" onclick="savePlanRecordTemplate(true)">@translator.Translate(userLanguage, "Edit Plan Record Template")</button>
|
||||
</div>
|
||||
@await Html.PartialAsync("_SupplyRequisitionHistory", Model.RequisitionHistory)
|
||||
<script>
|
||||
var uploadedFiles = [];
|
||||
var selectedSupplies = [];
|
||||
var copySuppliesAttachments = @Model.CopySuppliesAttachment.ToString().ToLower();
|
||||
getUploadedFilesFromModel();
|
||||
getSelectedSuppliesFromModel();
|
||||
function getUploadedFilesFromModel() {
|
||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||
{
|
||||
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
|
||||
}
|
||||
}
|
||||
function getSelectedSuppliesFromModel() {
|
||||
@foreach(SupplyUsage supplyUsage in Model.Supplies)
|
||||
{
|
||||
@:selectedSupplies.push({supplyId: @supplyUsage.SupplyId, quantity: @supplyUsage.Quantity})
|
||||
}
|
||||
}
|
||||
function getPlanRecordModelData() {
|
||||
return {
|
||||
id: @Model.Id,
|
||||
dateCreated: decodeHTMLEntities('@(Model.DateCreated)'),
|
||||
reminderRecordId: decodeHTMLEntities('@Model.ReminderRecordId'),
|
||||
createdFromReminder: @Model.CreatedFromReminder.ToString().ToLower(),
|
||||
isTemplate: true
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -20,7 +20,7 @@
|
||||
<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, "Delete")</th>
|
||||
<th scope="col" class="col-2">@translator.Translate(userLanguage, "Edit")</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -67,7 +67,7 @@
|
||||
}
|
||||
</td>
|
||||
<td class="col-2"><button type="button" class="btn btn-primary" onclick="usePlannerRecordTemplate(@planRecordTemplate.Id)"><i class="bi bi-plus-square"></i></button></td>
|
||||
<td class="col-2"><button type="button" class="btn btn-danger" onclick="deletePlannerRecordTemplate(@planRecordTemplate.Id)"><i class="bi bi-trash"></i></button></td>
|
||||
<td class="col-2"><button type="button" class="btn btn-warning" onclick="showEditPlanRecordTemplateModal(@planRecordTemplate.Id)"><i class="bi bi-pencil-square"></i></button></td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" onclick="showBulkImportModal('PlanRecord')">@translator.Translate(userLanguage,"Import via CSV")</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="exportVehicleData('PlanRecord')">@translator.Translate(userLanguage,"Export to CSV")</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="showPlanRecordTemplatesModal()">@translator.Translate(userLanguage, "View Templates")</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
@@ -102,7 +104,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" data-bs-focus="false" id="planRecordTemplateModal" tabindex="-1" role="dialog" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
|
||||
<div class="modal fade" data-bs-focus="false" id="planRecordTemplateModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content" id="planRecordTemplateModalContent">
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
@model List<ReminderRecord>
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
@model List<ReminderRecord>
|
||||
@if (Model.Count() > 1)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" onchange="showMultipleRemindersSelector()" id="multipleRemindersCheck">
|
||||
<label class="form-check-label" for="multipleRemindersCheck">@translator.Translate(userLanguage, "Multiple")</label>
|
||||
</div>
|
||||
}
|
||||
<select class="form-select" id="recurringReminderInput">
|
||||
@if (Model.Any())
|
||||
{
|
||||
@@ -10,4 +24,15 @@
|
||||
{
|
||||
<!option value="0">No Recurring Reminders Found</!option>
|
||||
}
|
||||
</select>
|
||||
</select>
|
||||
<div id="recurringMultipleReminders" style="display:none;">
|
||||
<ul class="list-group">
|
||||
@foreach (ReminderRecord reminderRecord in Model)
|
||||
{
|
||||
<li class="list-group-item text-start">
|
||||
<input class="form-check-input" type="checkbox" value="@reminderRecord.Id" id="recurringReminder_@reminderRecord.Id">
|
||||
<label class="form-check-label stretched-link" for="recurringReminder_@reminderRecord.Id">@reminderRecord.Description</label>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
@@ -34,14 +34,25 @@
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input type="number" inputmode="numeric" id="reminderMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Future Odometer Reading")" value="@(isNew ? "" : Model.Mileage)">
|
||||
<div class="input-group-text">
|
||||
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="appendMileageToOdometer(500)">+500</button>
|
||||
</div>
|
||||
@if (isNew)
|
||||
{
|
||||
<div class="input-group-text">
|
||||
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('reminderMileage')">+</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="radio" name="reminderMetricOptions" id="reminderMetricBoth" value="@(ReminderMetric.Both)" checked="@(Model.Metric == ReminderMetric.Both)">
|
||||
<label class="form-check-label" for="reminderMetricBoth">@translator.Translate(userLanguage,"Whichever comes first")</label>
|
||||
</div>
|
||||
<div class="d-grid"></div>
|
||||
<label for="reminderRecordTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
|
||||
<select multiple class="form-select" id="reminderRecordTag">
|
||||
@foreach (string tag in Model.Tags)
|
||||
{
|
||||
<!option value="@tag">@tag</!option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 col-12">
|
||||
<label for="reminderNotes">@translator.Translate(userLanguage,"Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
||||
|
||||
@@ -6,15 +6,26 @@
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
var hasRefresh = Model.Where(x => (x.Urgency == ReminderUrgency.VeryUrgent || x.Urgency == ReminderUrgency.PastDue) && x.IsRecurring).Any();
|
||||
var recordTags = Model.SelectMany(x => x.Tags).Distinct();
|
||||
}
|
||||
<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">@($"{translator.Translate(userLanguage, "# of Reminders")}: {Model.Count()}")</span>
|
||||
<span class="ms-2 badge bg-secondary">@($"{translator.Translate(userLanguage, "Past Due")}: {Model.Where(x => x.Urgency == ReminderUrgency.PastDue).Count()}")</span>
|
||||
<span class="ms-2 badge bg-danger">@($"{translator.Translate(userLanguage, "Very Urgent")}: {Model.Where(x=>x.Urgency == ReminderUrgency.VeryUrgent).Count()}")</span>
|
||||
<span class="ms-2 badge bg-warning">@($"{translator.Translate(userLanguage, "Urgent")}: {Model.Where(x => x.Urgency == ReminderUrgency.Urgent).Count()}")</span>
|
||||
<span class="ms-2 badge bg-success">@($"{translator.Translate(userLanguage, "Not Urgent")}: {Model.Where(x => x.Urgency == ReminderUrgency.NotUrgent).Count()}")</span>
|
||||
<span class="ms-2 badge bg-success" data-aggregate-type="count">@($"{translator.Translate(userLanguage, "# of Reminders")}: {Model.Count()}")</span>
|
||||
<span class="ms-2 badge bg-secondary" data-aggregate-type="pastdue-count">@($"{translator.Translate(userLanguage, "Past Due")}: {Model.Where(x => x.Urgency == ReminderUrgency.PastDue).Count()}")</span>
|
||||
<span class="ms-2 badge bg-danger" data-aggregate-type="veryurgent-count">@($"{translator.Translate(userLanguage, "Very Urgent")}: {Model.Where(x => x.Urgency == ReminderUrgency.VeryUrgent).Count()}")</span>
|
||||
<span class="ms-2 badge text-bg-warning" data-aggregate-type="urgent-count">@($"{translator.Translate(userLanguage, "Urgent")}: {Model.Where(x => x.Urgency == ReminderUrgency.Urgent).Count()}")</span>
|
||||
<span class="ms-2 badge bg-success" data-aggregate-type="noturgent-count">@($"{translator.Translate(userLanguage, "Not Urgent")}: {Model.Where(x => x.Urgency == ReminderUrgency.NotUrgent).Count()}")</span>
|
||||
@foreach (string recordTag in recordTags)
|
||||
{
|
||||
<span onclick="filterReminderTable(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>
|
||||
<button onclick="showAddReminderModal()" class="btn btn-primary btn-md mt-1 mb-1"><i class="bi bi-pencil-square me-2"></i>@translator.Translate(userLanguage, "Add Reminder")</button>
|
||||
@@ -33,34 +44,34 @@
|
||||
<tr class="d-flex">
|
||||
<th scope="col" class="col-1">@translator.Translate(userLanguage, "Urgency")</th>
|
||||
<th scope="col" class="col-2">@translator.Translate(userLanguage, "Metric")</th>
|
||||
<th scope="col" class="@(hasRefresh ? "col-4" : "col-5")">@translator.Translate(userLanguage, "Description")</th>
|
||||
<th scope="col" class="col-3">@translator.Translate(userLanguage, "Notes")</th>
|
||||
<th scope="col" class="@(hasRefresh ? "col-3 col-md-4" : "col-5")">@translator.Translate(userLanguage, "Description")</th>
|
||||
<th scope="col" class="col-2 col-md-3">@translator.Translate(userLanguage, "Notes")</th>
|
||||
@if (hasRefresh)
|
||||
{
|
||||
<th scope="col" class="col-1">@translator.Translate(userLanguage, "Done")</th>
|
||||
<th scope="col" class="col-2 col-md-1">@translator.Translate(userLanguage, "Done")</th>
|
||||
}
|
||||
<th scope="col" class="col-1">@translator.Translate(userLanguage, "Delete")</th>
|
||||
<th scope="col" class="col-2 col-md-1">@translator.Translate(userLanguage, "Delete")</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (ReminderRecordViewModel reminderRecord in Model)
|
||||
{
|
||||
<tr class="d-flex user-select-none" style="cursor:pointer;" onmouseup="stopEvent()" ontouchstart="detectRowLongTouch(this)" ontouchend="detectRowTouchEndPremature(this)" data-rowId="@reminderRecord.Id" oncontextmenu="showTableContextMenu(this)" onmousemove="rangeMouseMove(this)" onclick="handleTableRowClick(this, showEditReminderRecordModal,@reminderRecord.Id)">
|
||||
<tr class="d-flex user-select-none" style="cursor:pointer;" onmouseup="stopEvent()" ontouchstart="detectRowLongTouch(this)" ontouchend="detectRowTouchEndPremature(this)" data-rowId="@reminderRecord.Id" oncontextmenu="showTableContextMenu(this)" onmousemove="rangeMouseMove(this)" onclick="handleTableRowClick(this, showEditReminderRecordModal,@reminderRecord.Id)" data-tags='@string.Join(" ", reminderRecord.Tags)'>
|
||||
@if (reminderRecord.Urgency == ReminderUrgency.VeryUrgent)
|
||||
{
|
||||
<td class="col-1"><span class="badge text-bg-danger">@translator.Translate(userLanguage, "Very Urgent")</span></td>
|
||||
<td class="col-1"><span class="text-danger d-inline-block d-md-none"><i class="bi bi-hourglass-split h3"></i></span><span class="badge text-bg-danger d-none d-md-inline-block">@translator.Translate(userLanguage, "Very Urgent")</span></td>
|
||||
}
|
||||
else if (reminderRecord.Urgency == ReminderUrgency.Urgent)
|
||||
{
|
||||
<td class="col-1"><span class="badge text-bg-warning">@translator.Translate(userLanguage, "Urgent")</span></td>
|
||||
<td class="col-1"><span class="text-warning d-inline-block d-md-none"><i class="bi bi-hourglass-split h3"></i></span><span class="badge text-bg-warning d-none d-md-inline-block">@translator.Translate(userLanguage, "Urgent")</span></td>
|
||||
}
|
||||
else if (reminderRecord.Urgency == ReminderUrgency.PastDue)
|
||||
{
|
||||
<td class="col-1"><span class="badge text-bg-secondary">@translator.Translate(userLanguage, "Past Due")</span></td>
|
||||
<td class="col-1"><span class="text-secondary d-inline-block d-md-none"><i class="bi bi-hourglass-bottom h3"></i></span><span class="badge text-bg-secondary d-none d-md-inline-block">@translator.Translate(userLanguage, "Past Due")</span></td>
|
||||
}
|
||||
else
|
||||
{
|
||||
<td class="col-1"><span class="badge text-bg-success">@translator.Translate(userLanguage, "Not Urgent")</span></td>
|
||||
<td class="col-1"><span class="text-success d-inline-block d-md-none"><i class="bi bi-hourglass-top h3"></i></span><span class="badge text-bg-success d-none d-md-inline-block">@translator.Translate(userLanguage, "Not Urgent")</span></td>
|
||||
}
|
||||
@if (reminderRecord.Metric == ReminderMetric.Date)
|
||||
{
|
||||
@@ -74,18 +85,18 @@
|
||||
{
|
||||
<td class="col-2">@reminderRecord.Metric</td>
|
||||
}
|
||||
<td class="@(hasRefresh ? "col-4" : "col-5")">@reminderRecord.Description</td>
|
||||
<td class="col-3 text-truncate">@CarCareTracker.Helper.StaticHelper.TruncateStrings(reminderRecord.Notes)</td>
|
||||
<td class="@(hasRefresh ? "col-3 col-md-4" : "col-5")" data-record-type='cost'>@reminderRecord.Description</td>
|
||||
<td class="col-2 col-md-3 text-truncate">@CarCareTracker.Helper.StaticHelper.TruncateStrings(reminderRecord.Notes)</td>
|
||||
@if (hasRefresh)
|
||||
{
|
||||
<td class="col-1 text-truncate">
|
||||
<td class="col-2 col-md-1 text-truncate">
|
||||
@if((reminderRecord.Urgency == ReminderUrgency.VeryUrgent || reminderRecord.Urgency == ReminderUrgency.PastDue) && reminderRecord.IsRecurring)
|
||||
{
|
||||
<button type="button" class="btn btn-secondary" onclick="markDoneReminderRecord(@reminderRecord.Id, this)"><i class="bi bi-check-lg"></i></button>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
<td class="col-1 text-truncate">
|
||||
<td class="col-2 col-md-1 text-truncate">
|
||||
<button type="button" class="btn btn-danger" onclick="deleteReminderRecord(@reminderRecord.Id, this)"><i class="bi bi-trash"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<select class="form-select" id="yearOption" onchange="yearUpdated()">
|
||||
<option value="0">All Time</option>
|
||||
<option value="0">@translator.Translate(userLanguage, "All Time")</option>
|
||||
@foreach (int year in Model.Years)
|
||||
{
|
||||
<option value="@year">@year</option>
|
||||
@@ -32,7 +32,7 @@
|
||||
<div class="col-12 col-md-10">
|
||||
<div class="dropdown d-grid dropdown-center">
|
||||
<button class="btn btn-outline-warning dropdown-toggle" type="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
|
||||
Metrics
|
||||
@translator.Translate(userLanguage, "Metrics")
|
||||
</button>
|
||||
<ul class="dropdown-menu" style="width:100%;">
|
||||
<li class="dropdown-item">
|
||||
@@ -117,6 +117,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-12 chartContainer">
|
||||
<div class="d-grid">
|
||||
<button onclick="showGlobalSearch()" class="btn btn-secondary btn-md mt-1 mb-1">@translator.Translate(userLanguage, "Search")<i class="bi ms-2 bi-search"></i></button>
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button onclick="generateVehicleHistoryReport()" class="btn btn-secondary btn-md mt-1 mb-1">@translator.Translate(userLanguage, "Vehicle Maintenance Report")<i class="bi ms-2 bi-box-arrow-in-up-right"></i></button>
|
||||
</div>
|
||||
@@ -126,4 +129,25 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="vehicleHistoryReport" class="showOnPrint"></div>
|
||||
<div class="modal fade" data-bs-focus="false" id="globalSearchModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content" id="globalSearchModalContent">
|
||||
<div class="modal-body">
|
||||
<div class="input-group input-group-lg">
|
||||
<input type="text" id="globalSearchInput" autocomplete="off" onkeyup="handleGlobalSearchKeyPress(event)" class="form-control" placeholder="@translator.Translate(userLanguage,"Search by Keyword(Case Sensitive)")">
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="performGlobalSearch()"><i class="bi bi-search"></i></button>
|
||||
</div>
|
||||
<div class="form-check form-switch mt-1">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="globalSearchAutoSearchCheck" checked>
|
||||
<label class="form-check-label" for="globalSearchAutoSearchCheck">@translator.Translate(userLanguage, "Incremental Search")</label>
|
||||
</div>
|
||||
<div id="globalSearchModalResults"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="vehicleHistoryReport" class="showOnPrint"></div>
|
||||
|
||||
<script>
|
||||
getSelectedMetrics();
|
||||
</script>
|
||||
@@ -8,7 +8,7 @@
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Service Record") : translator.Translate(userLanguage,"Edit Service Record"))</h5>
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Service Record") : translator.Translate(userLanguage, "Edit Service Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditServiceRecordModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddServiceRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@@ -22,8 +22,16 @@
|
||||
<input type="text" id="serviceRecordDate" class="form-control" placeholder="@translator.Translate(userLanguage,"Date service was performed")" value="@Model.Date">
|
||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||
</div>
|
||||
<label for="serviceRecordMileage">@translator.Translate(userLanguage,"Odometer")</label>
|
||||
<input type="number" inputmode="numeric" id="serviceRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when serviced")" value="@(isNew ? "" : Model.Mileage)">
|
||||
<label for="serviceRecordMileage">@translator.Translate(userLanguage, "Odometer")</label>
|
||||
<div class="input-group">
|
||||
<input type="number" inputmode="numeric" id="serviceRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when serviced")" value="@(isNew ? "" : Model.Mileage)">
|
||||
@if (isNew)
|
||||
{
|
||||
<div class="input-group-text">
|
||||
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('serviceRecordMileage')">+</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<label for="serviceRecordDescription">@translator.Translate(userLanguage,"Description")</label>
|
||||
<input type="text" id="serviceRecordDescription" class="form-control" placeholder="@translator.Translate(userLanguage,"Description of item(s) serviced(i.e. Oil Change)")" value="@Model.Description">
|
||||
@if (isNew)
|
||||
@@ -121,7 +129,8 @@
|
||||
<script>
|
||||
var uploadedFiles = [];
|
||||
var selectedSupplies = [];
|
||||
var recurringReminderRecordId = 0;
|
||||
var recurringReminderRecordId = [];
|
||||
var copySuppliesAttachments = false;
|
||||
getUploadedFilesFromModel();
|
||||
function getUploadedFilesFromModel() {
|
||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||
|
||||
@@ -129,7 +129,17 @@
|
||||
<td class="col-3 text-truncate flex-grow-1 flex-shrink-1" data-column="notes">@CarCareTracker.Helper.StaticHelper.TruncateStrings(serviceRecord.Notes)</td>
|
||||
@foreach (string extraFieldColumn in extraFields)
|
||||
{
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">@(serviceRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "")</td>
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">
|
||||
@{
|
||||
var extraFieldValue = serviceRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "";
|
||||
if (!string.IsNullOrWhiteSpace(extraFieldValue) && Uri.IsWellFormedUriString(extraFieldValue, UriKind.Absolute)){
|
||||
<a href="@extraFieldValue" onclick="noPropagation()" target="_blank">@CarCareTracker.Helper.StaticHelper.TruncateStrings(extraFieldValue)</a>
|
||||
} else
|
||||
{
|
||||
@extraFieldValue
|
||||
}
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Supply Record") : translator.Translate(userLanguage,"Edit Supply Record"))</h5>
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Supply Record") : translator.Translate(userLanguage, "Edit Supply Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditSupplyRecordModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddSupplyRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
@@ -145,7 +145,19 @@
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" data-column="notes">@CarCareTracker.Helper.StaticHelper.TruncateStrings(supplyRecord.Notes)</td>
|
||||
@foreach (string extraFieldColumn in extraFields)
|
||||
{
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">@(supplyRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "")</td>
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">
|
||||
@{
|
||||
var extraFieldValue = supplyRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "";
|
||||
if (!string.IsNullOrWhiteSpace(extraFieldValue) && Uri.IsWellFormedUriString(extraFieldValue, UriKind.Absolute))
|
||||
{
|
||||
<a href="@extraFieldValue" onclick="noPropagation()" target="_blank">@CarCareTracker.Helper.StaticHelper.TruncateStrings(extraFieldValue)</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
@extraFieldValue
|
||||
}
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
|
||||
@@ -33,10 +33,12 @@
|
||||
$('#upgradeRecordCost').val(selectedSupplyResult.totalSum);
|
||||
break;
|
||||
case "PlanRecord":
|
||||
case "PlanRecordTemplate":
|
||||
$('#planRecordCost').val(selectedSupplyResult.totalSum);
|
||||
break;
|
||||
}
|
||||
selectedSupplies = getSuppliesAndQuantity().selectedSupplies;
|
||||
copySuppliesAttachments = $("#inputCopySuppliesAttachments").is(':checked');
|
||||
hideSuppliesModal();
|
||||
}
|
||||
function hideParentModal(){
|
||||
@@ -52,6 +54,7 @@
|
||||
$('#upgradeRecordModal').modal('hide');
|
||||
break;
|
||||
case "PlanRecord":
|
||||
case "PlanRecordTemplate":
|
||||
$('#planRecordModal').modal('hide');
|
||||
break;
|
||||
}
|
||||
@@ -69,6 +72,7 @@
|
||||
$('#upgradeRecordModal').modal('show');
|
||||
break;
|
||||
case "PlanRecord":
|
||||
case "PlanRecordTemplate":
|
||||
$('#planRecordModal').modal('show');
|
||||
break;
|
||||
}
|
||||
@@ -82,14 +86,30 @@
|
||||
}
|
||||
}
|
||||
function getSupplies() {
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
$.get(`/Vehicle/GetSupplyRecordsForRecordsByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
hideParentModal();
|
||||
$("#inputSuppliesModalContent").html(data);
|
||||
$('#inputSuppliesModal').modal('show');
|
||||
}
|
||||
})
|
||||
var caller = GetCaller().tab;
|
||||
if (caller == 'PlanRecordTemplate') {
|
||||
var planRecordTemplateId = getPlanRecordModelData().id;
|
||||
$.get(`/Vehicle/GetSupplyRecordsForPlanRecordTemplate?planRecordTemplateId=${planRecordTemplateId}`, function (data) {
|
||||
if (data) {
|
||||
hideParentModal();
|
||||
$("#inputSuppliesModalContent").html(data);
|
||||
$('#inputSuppliesModal').modal('show');
|
||||
recalculateTotal();
|
||||
if (copySuppliesAttachments) {
|
||||
$('#inputCopySuppliesAttachments').attr('checked', true);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
$.get(`/Vehicle/GetSupplyRecordsForRecordsByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
hideParentModal();
|
||||
$("#inputSuppliesModalContent").html(data);
|
||||
$('#inputSuppliesModal').modal('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
function hideSuppliesModal() {
|
||||
$('#inputSuppliesModal').modal('hide');
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
var recordTags = Model.SelectMany(x => x.Tags).Distinct();
|
||||
var recordTags = Model.Supplies.SelectMany(x => x.Tags).Distinct();
|
||||
}
|
||||
@model List<SupplyRecord>
|
||||
@model SupplyUsageViewModel
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@translator.Translate(userLanguage,"Select Supplies")</h5>
|
||||
<button type="button" class="btn-close" onclick="hideSuppliesModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@if (Model.Any())
|
||||
@if (Model.Supplies.Any())
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-12" style="max-height:50vh; overflow-y:auto;" id="supplies-table">
|
||||
@@ -37,11 +37,12 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (SupplyRecord supplyRecord in Model)
|
||||
@foreach (SupplyRecord supplyRecord in Model.Supplies)
|
||||
{
|
||||
var supplyUsage = Model.Usage.Where(x => x.SupplyId == supplyRecord.Id).SingleOrDefault();
|
||||
<tr class="d-flex" id="supplyRows" data-tags='@string.Join(" ", supplyRecord.Tags)'>
|
||||
<td class="col-1"><input class="form-check-input" type="checkbox" onchange="toggleQuantityFieldDisabled(this)" value="@supplyRecord.Id"></td>
|
||||
<td class="col-2"><input type="text" inputmode="decimal" disabled onchange="recalculateTotal()" class="form-control"></td>
|
||||
<td class="col-1"><input class="form-check-input" type="checkbox" onchange="toggleQuantityFieldDisabled(this)" value="@supplyRecord.Id" @(supplyUsage == default ? "" : "checked")></td>
|
||||
<td class="col-2"><input type="text" inputmode="decimal" @(supplyUsage == default ? "disabled" : "") value="@(supplyUsage == default ? "" : supplyUsage.Quantity)" onchange="recalculateTotal()" class="form-control"></td>
|
||||
<td class="col-2 supplyquantity">@supplyRecord.Quantity</td>
|
||||
<td class="col-2 text-truncate">@StaticHelper.TruncateStrings(supplyRecord.PartNumber)</td>
|
||||
<td class="col-3 text-truncate">@StaticHelper.TruncateStrings(supplyRecord.Description)</td>
|
||||
@@ -66,6 +67,10 @@
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<span id="supplySumLabel" style="margin-right:auto;">Total: 0.00</span>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="inputCopySuppliesAttachments">
|
||||
<label class="form-check-label" for="inputCopySuppliesAttachments">@translator.Translate(userLanguage, "Copy Attachments")</label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-secondary" onclick="hideSuppliesModal()">@translator.Translate(userLanguage, "Cancel")</button>
|
||||
<button type="button" class="btn btn-primary" disabled id="selectSuppliesButton" onclick="selectSupplies()">@translator.Translate(userLanguage, "Select")</button>
|
||||
</div>
|
||||
@@ -105,7 +110,7 @@
|
||||
var inStockQuantity = globalParseFloat(inStock.text());
|
||||
var unitPrice = globalParseFloat(priceField.text());
|
||||
//validation
|
||||
if (isNaN(requestedQuantity) || requestedQuantity > inStockQuantity) {
|
||||
if (isNaN(requestedQuantity) || requestedQuantity > inStockQuantity || requestedQuantity <= 0) {
|
||||
textField.addClass("is-invalid");
|
||||
hasError = true;
|
||||
} else {
|
||||
@@ -126,7 +131,7 @@
|
||||
var parsedFloat = globalFloatToString(totalSum);
|
||||
$("#supplySumLabel").text(`Total: ${parsedFloat}`);
|
||||
}
|
||||
$("#selectSuppliesButton").attr('disabled', (hasError || totalSum == 0));
|
||||
$("#selectSuppliesButton").attr('disabled', (hasError || selectedSupplies.toArray().length == 0));
|
||||
if (!hasError) {
|
||||
return {
|
||||
totalSum: globalFloatToString(totalSum),
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Tax Record") : translator.Translate(userLanguage,"Edit Tax Record"))</h5>
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Tax Record") : translator.Translate(userLanguage, "Edit Tax Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditTaxRecordModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddTaxRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@@ -115,7 +115,7 @@
|
||||
<script>
|
||||
var uploadedFiles = [];
|
||||
var customMonthInterval = @Model.CustomMonthInterval;
|
||||
var recurringReminderRecordId = 0;
|
||||
var recurringReminderRecordId = [];
|
||||
getUploadedFilesFromModel();
|
||||
function getUploadedFilesFromModel() {
|
||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||
|
||||
@@ -121,7 +121,19 @@
|
||||
<td class="col-3 flex-grow-1 flex-shrink-1 text-truncate" data-column="notes">@CarCareTracker.Helper.StaticHelper.TruncateStrings(taxRecord.Notes)</td>
|
||||
@foreach (string extraFieldColumn in extraFields)
|
||||
{
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">@(taxRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "")</td>
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">
|
||||
@{
|
||||
var extraFieldValue = taxRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "";
|
||||
if (!string.IsNullOrWhiteSpace(extraFieldValue) && Uri.IsWellFormedUriString(extraFieldValue, UriKind.Absolute))
|
||||
{
|
||||
<a href="@extraFieldValue" onclick="noPropagation()" target="_blank">@CarCareTracker.Helper.StaticHelper.TruncateStrings(extraFieldValue)</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
@extraFieldValue
|
||||
}
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Upgrade Record") : translator.Translate(userLanguage,"Edit Upgrade Record"))</h5>
|
||||
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Upgrade Record") : translator.Translate(userLanguage, "Edit Upgrade Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditUpgradeRecordModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddUpgradeRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@@ -17,14 +17,22 @@
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12">
|
||||
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
|
||||
<label for="upgradeRecordDate">@translator.Translate(userLanguage,"Date")</label>
|
||||
<label for="upgradeRecordDate">@translator.Translate(userLanguage, "Date")</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="upgradeRecordDate" class="form-control" placeholder="@translator.Translate(userLanguage,"Date upgrade/mods was installed")" value="@Model.Date">
|
||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||
</div>
|
||||
<label for="upgradeRecordMileage">@translator.Translate(userLanguage,"Odometer")</label>
|
||||
<input type="number" inputmode="numeric" id="upgradeRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when upgraded/modded")" value="@(isNew ? "" : Model.Mileage)">
|
||||
<label for="upgradeRecordDescription">@translator.Translate(userLanguage,"Description")</label>
|
||||
<label for="upgradeRecordMileage">@translator.Translate(userLanguage, "Odometer")</label>
|
||||
<div class="input-group">
|
||||
<input type="number" inputmode="numeric" id="upgradeRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when upgraded/modded")" value="@(isNew ? "" : Model.Mileage)">
|
||||
@if (isNew)
|
||||
{
|
||||
<div class="input-group-text">
|
||||
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('upgradeRecordMileage')">+</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<label for="upgradeRecordDescription">@translator.Translate(userLanguage, "Description")</label>
|
||||
<input type="text" id="upgradeRecordDescription" class="form-control" placeholder="@translator.Translate(userLanguage,"Description of item(s) upgraded/modded")" value="@Model.Description">
|
||||
@if (isNew)
|
||||
{
|
||||
@@ -34,13 +42,13 @@
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<label for="upgradeRecordCost">@translator.Translate(userLanguage,"Cost")</label>
|
||||
<label for="upgradeRecordCost">@translator.Translate(userLanguage, "Cost")</label>
|
||||
<input type="text" inputmode="decimal" id="upgradeRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"Cost of the upgrade/mods")" value="@(isNew ? "" : Model.Cost)">
|
||||
@if (isNew)
|
||||
{
|
||||
@await Html.PartialAsync("_SupplyStore", "UpgradeRecord")
|
||||
}
|
||||
<label for="upgradeRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
|
||||
<label for="upgradeRecordTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
|
||||
<select multiple class="form-select" id="upgradeRecordTag">
|
||||
@foreach (string tag in Model.Tags)
|
||||
{
|
||||
@@ -57,15 +65,15 @@
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-6 col-12">
|
||||
<label for="upgradeRecordNotes">@translator.Translate(userLanguage,"Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
||||
<label for="upgradeRecordNotes">@translator.Translate(userLanguage, "Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
|
||||
<textarea id="upgradeRecordNotes" class="form-control" rows="5">@Model.Notes</textarea>
|
||||
@if (Model.Files.Any())
|
||||
{
|
||||
<div>
|
||||
@await Html.PartialAsync("_UploadedFiles", Model.Files)
|
||||
<label for="upgradeRecordFiles">@translator.Translate(userLanguage,"Upload more documents")</label>
|
||||
<label for="upgradeRecordFiles">@translator.Translate(userLanguage, "Upload more documents")</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="upgradeRecordFiles">
|
||||
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
|
||||
<br /><small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -75,13 +83,15 @@
|
||||
<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")
|
||||
@translator.Translate(userLanguage, "Add Reminder")
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
<label for="upgradeRecordFiles">Upload documents(optional)</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="upgradeRecordFiles">
|
||||
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
|
||||
<br />
|
||||
|
||||
<small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -96,39 +106,40 @@
|
||||
<button type="button" class="btn btn-warning" onclick="toggleSupplyUsageHistory()"><i class="bi bi-shop"></i></button>
|
||||
}
|
||||
<div class="btn-group" style="margin-right:auto;">
|
||||
<button type="button" class="btn btn-md mt-1 mb-1 btn-danger" onclick="deleteUpgradeRecord(@Model.Id)">@translator.Translate(userLanguage,"Delete")</button>
|
||||
<button type="button" class="btn btn-md mt-1 mb-1 btn-danger" onclick="deleteUpgradeRecord(@Model.Id)">@translator.Translate(userLanguage, "Delete")</button>
|
||||
<button type="button" class="btn btn-md btn-danger 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><h6 class="dropdown-header">@translator.Translate(userLanguage,"Move To")</h6></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'UpgradeRecord', 'ServiceRecord')">@translator.Translate(userLanguage,"Service Records")</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'UpgradeRecord', 'RepairRecord')">@translator.Translate(userLanguage,"Repairs")</a></li>
|
||||
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Move To")</h6></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'UpgradeRecord', 'ServiceRecord')">@translator.Translate(userLanguage, "Service Records")</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'UpgradeRecord', 'RepairRecord')">@translator.Translate(userLanguage, "Repairs")</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
<button type="button" class="btn btn-secondary" onclick="hideAddUpgradeRecordModal()">@translator.Translate(userLanguage,"Cancel")</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="hideAddUpgradeRecordModal()">@translator.Translate(userLanguage, "Cancel")</button>
|
||||
@if (isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" onclick="saveUpgradeRecordToVehicle()">@translator.Translate(userLanguage,"Add New Upgrade Record")</button>
|
||||
<button type="button" class="btn btn-primary" onclick="saveUpgradeRecordToVehicle()">@translator.Translate(userLanguage, "Add New Upgrade Record")</button>
|
||||
}
|
||||
else if (!isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" onclick="saveUpgradeRecordToVehicle(true)">@translator.Translate(userLanguage,"Edit Upgrade Record")</button>
|
||||
<button type="button" class="btn btn-primary" onclick="saveUpgradeRecordToVehicle(true)">@translator.Translate(userLanguage, "Edit Upgrade Record")</button>
|
||||
}
|
||||
</div>
|
||||
@await Html.PartialAsync("_SupplyRequisitionHistory", Model.RequisitionHistory)
|
||||
<script>
|
||||
var uploadedFiles = [];
|
||||
var selectedSupplies = [];
|
||||
var recurringReminderRecordId = 0;
|
||||
var recurringReminderRecordId = [];
|
||||
var copySuppliesAttachments = false;
|
||||
getUploadedFilesFromModel();
|
||||
function getUploadedFilesFromModel() {
|
||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||
{
|
||||
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
|
||||
}
|
||||
}
|
||||
}
|
||||
function getUpgradeRecordModelData() {
|
||||
return { id: @Model.Id}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,19 @@
|
||||
<td class="col-3 flex-grow-1 flex-shrink-1 text-truncate" data-column="notes">@CarCareTracker.Helper.StaticHelper.TruncateStrings(upgradeRecord.Notes)</td>
|
||||
@foreach (string extraFieldColumn in extraFields)
|
||||
{
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">@(upgradeRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "")</td>
|
||||
<td class="col-2 flex-grow-1 flex-shrink-1 text-truncate" style='display:none;' data-column="@extraFieldColumn">
|
||||
@{
|
||||
var extraFieldValue = upgradeRecord.ExtraFields.Where(x => x.Name == extraFieldColumn)?.FirstOrDefault()?.Value ?? "";
|
||||
if (!string.IsNullOrWhiteSpace(extraFieldValue) && Uri.IsWellFormedUriString(extraFieldValue, UriKind.Absolute))
|
||||
{
|
||||
<a href="@extraFieldValue" onclick="noPropagation()" target="_blank">@CarCareTracker.Helper.StaticHelper.TruncateStrings(extraFieldValue)</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
@extraFieldValue
|
||||
}
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
|
||||
@@ -62,6 +62,30 @@
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
@if (Model.TotalDepreciation != default)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
@(Model.TotalDepreciation > 0 ? translator.Translate(userLanguage, "Depreciation") : translator.Translate(userLanguage, "Appreciation"))
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<span><i class="bi @(Model.TotalDepreciation > 0 ? "bi-graph-down-arrow" : "bi-graph-up-arrow") me-2"></i>@Math.Abs(Model.TotalDepreciation).ToString("C")</span>
|
||||
</div>
|
||||
@if (Model.DepreciationPerDay != default)
|
||||
{
|
||||
<div class="col-3">
|
||||
<span><i class="bi bi-calendar-event me-2"></i>@($"{Model.DepreciationPerDay.ToString("C")}/{translator.Translate(userLanguage, "day")}")</span>
|
||||
</div>
|
||||
}
|
||||
@if (Model.DepreciationPerMile != default)
|
||||
{
|
||||
<div class="col-3">
|
||||
<span><i class="bi bi-speedometer me-2"></i>@($"{Model.DepreciationPerMile.ToString("C")}/{Model.DistanceUnit}")</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<hr />
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<table class="table table-hover">
|
||||
|
||||
@@ -46,10 +46,6 @@
|
||||
}
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<label for="inputPurchaseDate">@translator.Translate(userLanguage, "Purchased Date(optional)")</label>
|
||||
<input type="text" id="inputPurchaseDate" class="form-control" placeholder="@translator.Translate(userLanguage, "Purchased Date")" value="@Model.PurchaseDate">
|
||||
<label for="inputSoldDate">@translator.Translate(userLanguage, "Sold Date(optional)")</label>
|
||||
<input type="text" id="inputSoldDate" class="form-control" placeholder="@translator.Translate(userLanguage, "Sold Date")" value="@Model.SoldDate">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="inputIsElectric" checked="@Model.IsElectric">
|
||||
<label class="form-check-label" for="inputIsElectric">@translator.Translate(userLanguage, "Electric Vehicle")</label>
|
||||
@@ -70,6 +66,25 @@
|
||||
<input type="text" id="inputOdometerDifference" class="form-control" placeholder="@translator.Translate(userLanguage, "Odometer Difference")" value="@Model.OdometerDifference">
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion accordion-flush" id="vehicleModalAccordion">
|
||||
<div class="accordion-item">
|
||||
<div class="accordion-header">
|
||||
<button class="accordion-button skinny collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapsePurchaseInfo">
|
||||
@translator.Translate(userLanguage, "Purchase/Sold Information(optional)")
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapsePurchaseInfo" class="accordion-collapse collapse" data-bs-parent="#vehicleModalAccordion">
|
||||
<label for="inputPurchaseDate">@translator.Translate(userLanguage, "Purchased Date(optional)")</label>
|
||||
<input type="text" id="inputPurchaseDate" class="form-control" placeholder="@translator.Translate(userLanguage, "Purchased Date")" value="@Model.PurchaseDate">
|
||||
<label for="inputSoldDate">@translator.Translate(userLanguage, "Sold Date(optional)")</label>
|
||||
<input type="text" id="inputSoldDate" class="form-control" placeholder="@translator.Translate(userLanguage, "Sold Date")" value="@Model.SoldDate">
|
||||
<label for="inputPurchasePrice">@translator.Translate(userLanguage, "Purchased Price(optional)")</label>
|
||||
<input type="text" inputmode="decimal" id="inputPurchasePrice" class="form-control" placeholder="@translator.Translate(userLanguage, "Purchased Price")" value="@(Model.PurchasePrice == default ? "" : Model.PurchasePrice)">
|
||||
<label for="inputSoldPrice">@translator.Translate(userLanguage, "Sold Price(optional)")</label>
|
||||
<input type="text" inputmode="decimal" id="inputSoldPrice" class="form-control" placeholder="@translator.Translate(userLanguage, "Sold Price")" value="@(Model.SoldPrice == default ? "" : Model.SoldPrice)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label for="inputTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
|
||||
<select multiple class="form-select" id="inputTag">
|
||||
@foreach (string tag in Model.Tags)
|
||||
|
||||
@@ -373,4 +373,8 @@ input[type="file"] {
|
||||
}
|
||||
.copyable{
|
||||
cursor: pointer;
|
||||
}
|
||||
.accordion-button.skinny {
|
||||
padding: 0.438rem 0rem !important;
|
||||
background-color: inherit !important;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -9,7 +9,19 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditCollisionRecordModal(collisionRecordId) {
|
||||
function showEditCollisionRecordModal(collisionRecordId, nocache) {
|
||||
if (!nocache) {
|
||||
var existingContent = $("#collisionRecordModalContent").html();
|
||||
if (existingContent.trim() != '') {
|
||||
//check if id is same.
|
||||
var existingId = getCollisionRecordModelData().id;
|
||||
if (existingId == collisionRecordId && $('[data-changed=true]').length > 0) {
|
||||
$('#collisionRecordModal').modal('show');
|
||||
$('.cached-banner').show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$.get(`/Vehicle/GetCollisionRecordForEditById?collisionRecordId=${collisionRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#collisionRecordModalContent").html(data);
|
||||
@@ -17,6 +29,7 @@ function showEditCollisionRecordModal(collisionRecordId) {
|
||||
initDatePicker($('#collisionRecordDate'));
|
||||
initTagSelector($("#collisionRecordTag"));
|
||||
$('#collisionRecordModal').modal('show');
|
||||
bindModalInputChanges('collisionRecordModal');
|
||||
$('#collisionRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
|
||||
if (getGlobalConfig().useMarkDown) {
|
||||
toggleMarkDownOverlay("collisionRecordNotes");
|
||||
@@ -133,6 +146,7 @@ function getAndValidateCollisionRecordValues() {
|
||||
addReminderRecord: addReminderRecord,
|
||||
extraFields: extraFields.extraFields,
|
||||
requisitionHistory: supplyUsageHistory,
|
||||
reminderRecordId: recurringReminderRecordId
|
||||
reminderRecordId: recurringReminderRecordId,
|
||||
copySuppliesAttachment: copySuppliesAttachments
|
||||
}
|
||||
}
|
||||
@@ -91,7 +91,7 @@ function generateReminderItem(id, urgency, description) {
|
||||
case "PastDue":
|
||||
return `<p class="badge text-wrap bg-secondary reminder-calendar-item mb-2" onclick='showCalendarReminderModal(${id})'>${encodeHTMLInput(description)}</p>`;
|
||||
case "Urgent":
|
||||
return `<p class="badge text-wrap bg-warning reminder-calendar-item mb-2" onclick='showCalendarReminderModal(${id})'>${encodeHTMLInput(description)}</p>`;
|
||||
return `<p class="badge text-wrap text-bg-warning reminder-calendar-item mb-2" onclick='showCalendarReminderModal(${id})'>${encodeHTMLInput(description)}</p>`;
|
||||
case "NotUrgent":
|
||||
return `<p class="badge text-wrap bg-success reminder-calendar-item mb-2" onclick='showCalendarReminderModal(${id})'>${encodeHTMLInput(description)}</p>`;
|
||||
}
|
||||
@@ -167,7 +167,7 @@ function initCalendar() {
|
||||
function performLogOut() {
|
||||
$.post('/Login/LogOut', function (data) {
|
||||
if (data) {
|
||||
window.location.href = '/Login';
|
||||
window.location.href = data;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,7 +9,19 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditGasRecordModal(gasRecordId) {
|
||||
function showEditGasRecordModal(gasRecordId, nocache) {
|
||||
if (!nocache) {
|
||||
var existingContent = $("#gasRecordModalContent").html();
|
||||
if (existingContent.trim() != '') {
|
||||
//check if id is same.
|
||||
var existingId = getGasRecordModelData().id;
|
||||
if (existingId == gasRecordId && $('[data-changed=true]').length > 0) {
|
||||
$('#gasRecordModal').modal('show');
|
||||
$('.cached-banner').show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$.get(`/Vehicle/GetGasRecordForEditById?gasRecordId=${gasRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#gasRecordModalContent").html(data);
|
||||
@@ -17,6 +29,7 @@ function showEditGasRecordModal(gasRecordId) {
|
||||
initDatePicker($('#gasRecordDate'));
|
||||
initTagSelector($("#gasRecordTag"));
|
||||
$('#gasRecordModal').modal('show');
|
||||
bindModalInputChanges('gasRecordModal');
|
||||
$('#gasRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
|
||||
if (getGlobalConfig().useMarkDown) {
|
||||
toggleMarkDownOverlay("gasRecordNotes");
|
||||
@@ -162,28 +175,28 @@ function convertGasConsumptionUnits(currentUnit, destinationUnit, save) {
|
||||
case "l":
|
||||
$("[data-gas-type='consumption']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) * 3.785;
|
||||
elem.innerText = convertedAmount.toFixed(2);
|
||||
elem.innerText = globalFloatToString(convertedAmount.toFixed(2));
|
||||
sender.text(sender.text().replace(sender.attr("data-unit"), "l"));
|
||||
sender.attr("data-unit", "l");
|
||||
});
|
||||
$("[data-gas-type='unitcost']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) / 3.785;
|
||||
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
|
||||
elem.innerText = `${getGlobalConfig().currencySymbol}${convertedAmount.toFixed(decimalPoints)}`;
|
||||
elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
|
||||
});
|
||||
if (save) { setDebounce(saveUserGasTabPreferences); }
|
||||
break;
|
||||
case "imp gal":
|
||||
$("[data-gas-type='consumption']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) / 1.201;
|
||||
elem.innerText = convertedAmount.toFixed(2);
|
||||
elem.innerText = globalFloatToString(convertedAmount.toFixed(2));
|
||||
sender.text(sender.text().replace(sender.attr("data-unit"), "imp gal"));
|
||||
sender.attr("data-unit", "imp gal");
|
||||
});
|
||||
$("[data-gas-type='unitcost']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) * 1.201;
|
||||
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
|
||||
elem.innerText = `${getGlobalConfig().currencySymbol}${convertedAmount.toFixed(decimalPoints)}`;
|
||||
elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
|
||||
});
|
||||
if (save) { setDebounce(saveUserGasTabPreferences); }
|
||||
break;
|
||||
@@ -193,28 +206,28 @@ function convertGasConsumptionUnits(currentUnit, destinationUnit, save) {
|
||||
case "US gal":
|
||||
$("[data-gas-type='consumption']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) / 3.785;
|
||||
elem.innerText = convertedAmount.toFixed(2);
|
||||
elem.innerText = globalFloatToString(convertedAmount.toFixed(2));
|
||||
sender.text(sender.text().replace(sender.attr("data-unit"), "US gal"));
|
||||
sender.attr("data-unit", "US gal");
|
||||
});
|
||||
$("[data-gas-type='unitcost']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) * 3.785;
|
||||
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
|
||||
elem.innerText = `${getGlobalConfig().currencySymbol}${convertedAmount.toFixed(decimalPoints)}`;
|
||||
elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
|
||||
});
|
||||
if (save) { setDebounce(saveUserGasTabPreferences); }
|
||||
break;
|
||||
case "imp gal":
|
||||
$("[data-gas-type='consumption']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) / 4.546;
|
||||
elem.innerText = convertedAmount.toFixed(2);
|
||||
elem.innerText = globalFloatToString(convertedAmount.toFixed(2));
|
||||
sender.text(sender.text().replace(sender.attr("data-unit"), "imp gal"));
|
||||
sender.attr("data-unit", "imp gal");
|
||||
});
|
||||
$("[data-gas-type='unitcost']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) * 4.546;
|
||||
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
|
||||
elem.innerText = `${getGlobalConfig().currencySymbol}${convertedAmount.toFixed(decimalPoints)}`;
|
||||
elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
|
||||
});
|
||||
if (save) { setDebounce(saveUserGasTabPreferences); }
|
||||
break;
|
||||
@@ -224,28 +237,28 @@ function convertGasConsumptionUnits(currentUnit, destinationUnit, save) {
|
||||
case "US gal":
|
||||
$("[data-gas-type='consumption']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) * 1.201;
|
||||
elem.innerText = convertedAmount.toFixed(2);
|
||||
elem.innerText = globalFloatToString(convertedAmount.toFixed(2));
|
||||
sender.text(sender.text().replace(sender.attr("data-unit"), "US gal"));
|
||||
sender.attr("data-unit", "US gal");
|
||||
});
|
||||
$("[data-gas-type='unitcost']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) / 1.201;
|
||||
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
|
||||
elem.innerText = `${getGlobalConfig().currencySymbol}${convertedAmount.toFixed(decimalPoints)}`;
|
||||
elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
|
||||
});
|
||||
if (save) { setDebounce(saveUserGasTabPreferences); }
|
||||
break;
|
||||
case "l":
|
||||
$("[data-gas-type='consumption']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) * 4.546;
|
||||
elem.innerText = convertedAmount.toFixed(2);
|
||||
elem.innerText = globalFloatToString(convertedAmount.toFixed(2));
|
||||
sender.text(sender.text().replace(sender.attr("data-unit"), "l"));
|
||||
sender.attr("data-unit", "l");
|
||||
});
|
||||
$("[data-gas-type='unitcost']").map((index, elem) => {
|
||||
var convertedAmount = globalParseFloat(elem.innerText) / 4.546;
|
||||
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
|
||||
elem.innerText = `${getGlobalConfig().currencySymbol}${convertedAmount.toFixed(decimalPoints)}`;
|
||||
elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
|
||||
});
|
||||
if (save) { setDebounce(saveUserGasTabPreferences); }
|
||||
break;
|
||||
@@ -262,7 +275,7 @@ function convertFuelMileageUnits(currentUnit, destinationUnit, save) {
|
||||
var convertedAmount = globalParseFloat(elem.innerText);
|
||||
if (convertedAmount > 0) {
|
||||
convertedAmount = 100 / convertedAmount;
|
||||
elem.innerText = convertedAmount.toFixed(2);
|
||||
elem.innerText = globalFloatToString(convertedAmount.toFixed(2));
|
||||
}
|
||||
});
|
||||
//update labels up top.
|
||||
@@ -270,19 +283,19 @@ function convertFuelMileageUnits(currentUnit, destinationUnit, save) {
|
||||
if (newAverage > 0) {
|
||||
newAverage = 100 / newAverage;
|
||||
var averageLabel = $("#averageFuelMileageLabel");
|
||||
averageLabel.text(`${averageLabel.text().split(':')[0]}: ${newAverage.toFixed(2)}`);
|
||||
averageLabel.text(`${averageLabel.text().split(':')[0]}: ${globalFloatToString(newAverage.toFixed(2))}`);
|
||||
}
|
||||
var newMin = globalParseFloat($("#minFuelMileageLabel").text().split(":")[1].trim());
|
||||
if (newMin > 0) {
|
||||
newMin = 100 / newMin;
|
||||
var minLabel = $("#minFuelMileageLabel");
|
||||
minLabel.text(`${minLabel.text().split(':')[0]}: ${newMin.toFixed(2)}`);
|
||||
minLabel.text(`${minLabel.text().split(':')[0]}: ${globalFloatToString(newMin.toFixed(2))}`);
|
||||
}
|
||||
var newMax = globalParseFloat($("#maxFuelMileageLabel").text().split(":")[1].trim());
|
||||
if (newMax > 0) {
|
||||
newMax = 100 / newMax;
|
||||
var maxLabel = $("#maxFuelMileageLabel");
|
||||
maxLabel.text(`${maxLabel.text().split(':')[0]}: ${newMax.toFixed(2)}`);
|
||||
maxLabel.text(`${maxLabel.text().split(':')[0]}: ${globalFloatToString(newMax.toFixed(2))}`);
|
||||
}
|
||||
sender.text(sender.text().replace(sender.attr("data-unit"), "km/l"));
|
||||
sender.attr("data-unit", "km/l");
|
||||
@@ -296,27 +309,26 @@ function convertFuelMileageUnits(currentUnit, destinationUnit, save) {
|
||||
var convertedAmount = globalParseFloat(elem.innerText);
|
||||
if (convertedAmount > 0) {
|
||||
convertedAmount = 100 / convertedAmount;
|
||||
elem.innerText = convertedAmount.toFixed(2);
|
||||
elem.innerText = globalFloatToString(convertedAmount.toFixed(2));
|
||||
}
|
||||
});
|
||||
var newAverage = globalParseFloat($("#averageFuelMileageLabel").text().split(":")[1].trim());
|
||||
if (newAverage > 0) {
|
||||
newAverage = 100 / newAverage;
|
||||
|
||||
var averageLabel = $("#averageFuelMileageLabel");
|
||||
averageLabel.text(`${averageLabel.text().split(':')[0]}: ${newAverage.toFixed(2)}`);
|
||||
averageLabel.text(`${averageLabel.text().split(':')[0]}: ${globalFloatToString(newAverage.toFixed(2))}`);
|
||||
}
|
||||
var newMin = globalParseFloat($("#minFuelMileageLabel").text().split(":")[1].trim());
|
||||
if (newMin > 0) {
|
||||
newMin = 100 / newMin;
|
||||
var minLabel = $("#minFuelMileageLabel");
|
||||
minLabel.text(`${minLabel.text().split(':')[0]}: ${newMin.toFixed(2)}`);
|
||||
minLabel.text(`${minLabel.text().split(':')[0]}: ${globalFloatToString(newMin.toFixed(2))}`);
|
||||
}
|
||||
var newMax = globalParseFloat($("#maxFuelMileageLabel").text().split(":")[1].trim());
|
||||
if (newMax > 0) {
|
||||
newMax = 100 / newMax;
|
||||
var maxLabel = $("#maxFuelMileageLabel");
|
||||
maxLabel.text(`${maxLabel.text().split(':')[0]}: ${newMax.toFixed(2)}`);
|
||||
maxLabel.text(`${maxLabel.text().split(':')[0]}: ${globalFloatToString(newMax.toFixed(2))}`);
|
||||
}
|
||||
sender.text(sender.text().replace(sender.attr("data-unit"), "l/100km"));
|
||||
sender.attr("data-unit", "l/100km");
|
||||
@@ -345,17 +357,17 @@ function updateMPGLabels() {
|
||||
if (!getGlobalConfig().useMPG && $("[data-gas='fueleconomy']").attr("data-unit") != 'km/l' && averageMPG > 0) {
|
||||
averageMPG = 100 / averageMPG;
|
||||
}
|
||||
averageLabel.text(`${averageLabel.text().split(':')[0]}: ${averageMPG.toFixed(2)}`);
|
||||
averageLabel.text(`${averageLabel.text().split(':')[0]}: ${globalFloatToString(averageMPG.toFixed(2))}`);
|
||||
} else {
|
||||
averageLabel.text(`${averageLabel.text().split(':')[0]}: 0.00`);
|
||||
}
|
||||
if (!getGlobalConfig().useMPG && $("[data-gas='fueleconomy']").attr("data-unit") != 'km/l') {
|
||||
maxLabel.text(`${maxLabel.text().split(':')[0]}: ${minMPG.toFixed(2)}`);
|
||||
minLabel.text(`${minLabel.text().split(':')[0]}: ${maxMPG.toFixed(2)}`);
|
||||
maxLabel.text(`${maxLabel.text().split(':')[0]}: ${globalFloatToString(minMPG.toFixed(2))}`);
|
||||
minLabel.text(`${minLabel.text().split(':')[0]}: ${globalFloatToString(maxMPG.toFixed(2))}`);
|
||||
}
|
||||
else {
|
||||
minLabel.text(`${minLabel.text().split(':')[0]}: ${minMPG.toFixed(2)}`);
|
||||
maxLabel.text(`${maxLabel.text().split(':')[0]}: ${maxMPG.toFixed(2)}`);
|
||||
minLabel.text(`${minLabel.text().split(':')[0]}: ${globalFloatToString(minMPG.toFixed(2))}`);
|
||||
maxLabel.text(`${maxLabel.text().split(':')[0]}: ${globalFloatToString(maxMPG.toFixed(2))}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,25 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditNoteModal(noteId) {
|
||||
function showEditNoteModal(noteId, nocache) {
|
||||
if (!nocache) {
|
||||
var existingContent = $("#noteModalContent").html();
|
||||
if (existingContent.trim() != '') {
|
||||
//check if id is same.
|
||||
var existingId = getNoteModelData().id;
|
||||
if (existingId == noteId && $('[data-changed=true]').length > 0) {
|
||||
$('#noteModal').modal('show');
|
||||
$('.cached-banner').show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$.get(`/Vehicle/GetNoteForEditById?noteId=${noteId}`, function (data) {
|
||||
if (data) {
|
||||
$("#noteModalContent").html(data);
|
||||
initTagSelector($("#noteRecordTag"));
|
||||
$('#noteModal').modal('show');
|
||||
bindModalInputChanges('noteModal');
|
||||
$('#noteModal').off('shown.bs.modal').on('shown.bs.modal', function () {
|
||||
if (getGlobalConfig().useMarkDown) {
|
||||
toggleMarkDownOverlay("noteTextArea");
|
||||
|
||||
@@ -9,7 +9,19 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditOdometerRecordModal(odometerRecordId) {
|
||||
function showEditOdometerRecordModal(odometerRecordId, nocache) {
|
||||
if (!nocache) {
|
||||
var existingContent = $("#odometerRecordModalContent").html();
|
||||
if (existingContent.trim() != '') {
|
||||
//check if id is same.
|
||||
var existingId = getOdometerRecordModelData().id;
|
||||
if (existingId == odometerRecordId && $('[data-changed=true]').length > 0) {
|
||||
$('#odometerRecordModal').modal('show');
|
||||
$('.cached-banner').show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$.get(`/Vehicle/GetOdometerRecordForEditById?odometerRecordId=${odometerRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#odometerRecordModalContent").html(data);
|
||||
@@ -17,6 +29,7 @@ function showEditOdometerRecordModal(odometerRecordId) {
|
||||
initDatePicker($('#odometerRecordDate'));
|
||||
initTagSelector($("#odometerRecordTag"));
|
||||
$('#odometerRecordModal').modal('show');
|
||||
bindModalInputChanges('odometerRecordModal');
|
||||
$('#odometerRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
|
||||
if (getGlobalConfig().useMarkDown) {
|
||||
toggleMarkDownOverlay("odometerRecordNotes");
|
||||
|
||||
@@ -8,13 +8,57 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditPlanRecordModal(planRecordId) {
|
||||
function showEditPlanRecordModal(planRecordId, nocache) {
|
||||
if (!nocache) {
|
||||
var existingContent = $("#planRecordModalContent").html();
|
||||
if (existingContent.trim() != '') {
|
||||
//check if id is same.
|
||||
var existingId = getPlanRecordModelData().id;
|
||||
var isNotTemplate = !getPlanRecordModelData().isTemplate;
|
||||
if (existingId == planRecordId && isNotTemplate && $('[data-changed=true]').length > 0) {
|
||||
$('#planRecordModal').modal('show');
|
||||
$('.cached-banner').show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$.get(`/Vehicle/GetPlanRecordForEditById?planRecordId=${planRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#planRecordModalContent").html(data);
|
||||
//initiate datepicker
|
||||
initDatePicker($('#planRecordDate'));
|
||||
$('#planRecordModal').modal('show');
|
||||
bindModalInputChanges('planRecordModal');
|
||||
$('#planRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
|
||||
if (getGlobalConfig().useMarkDown) {
|
||||
toggleMarkDownOverlay("planRecordNotes");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditPlanRecordTemplateModal(planRecordTemplateId, nocache) {
|
||||
hidePlanRecordTemplatesModal();
|
||||
if (!nocache) {
|
||||
var existingContent = $("#planRecordModalContent").html();
|
||||
if (existingContent.trim() != '') {
|
||||
//check if id is same.
|
||||
var existingId = getPlanRecordModelData().id;
|
||||
var isTemplate = getPlanRecordModelData().isTemplate;
|
||||
if (existingId == planRecordTemplateId && isTemplate && $('[data-changed=true]').length > 0) {
|
||||
$('#planRecordModal').modal('show');
|
||||
$('.cached-banner').show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$.get(`/Vehicle/GetPlanRecordTemplateForEditById?planRecordTemplateId=${planRecordTemplateId}`, function (data) {
|
||||
if (data) {
|
||||
$("#planRecordModalContent").html(data);
|
||||
//initiate datepicker
|
||||
initDatePicker($('#planRecordDate'));
|
||||
$('#planRecordModal').modal('show');
|
||||
bindModalInputChanges('planRecordModal');
|
||||
$('#planRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
|
||||
if (getGlobalConfig().useMarkDown) {
|
||||
toggleMarkDownOverlay("planRecordNotes");
|
||||
@@ -25,12 +69,15 @@ function showEditPlanRecordModal(planRecordId) {
|
||||
}
|
||||
function hideAddPlanRecordModal() {
|
||||
$('#planRecordModal').modal('hide');
|
||||
if (getPlanRecordModelData().createdFromReminder) {
|
||||
//show reminder Modal
|
||||
$("#reminderRecordModal").modal("show");
|
||||
}
|
||||
if (getPlanRecordModelData().createdFromReminder) {
|
||||
//show reminder Modal
|
||||
$("#reminderRecordModal").modal("show");
|
||||
}
|
||||
if (getPlanRecordModelData().isTemplate) {
|
||||
showPlanRecordTemplatesModal();
|
||||
}
|
||||
}
|
||||
function deletePlanRecord(planRecordId) {
|
||||
function deletePlanRecord(planRecordId, noModal) {
|
||||
$("#workAroundInput").show();
|
||||
Swal.fire({
|
||||
title: "Confirm Deletion?",
|
||||
@@ -42,7 +89,9 @@ function deletePlanRecord(planRecordId) {
|
||||
if (result.isConfirmed) {
|
||||
$.post(`/Vehicle/DeletePlanRecordById?planRecordId=${planRecordId}`, function (data) {
|
||||
if (data) {
|
||||
hideAddPlanRecordModal();
|
||||
if (!noModal) {
|
||||
hideAddPlanRecordModal();
|
||||
}
|
||||
successToast("Plan Record Deleted");
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
getVehiclePlanRecords(vehicleId);
|
||||
@@ -85,22 +134,19 @@ function showPlanRecordTemplatesModal() {
|
||||
$.get(`/Vehicle/GetPlanRecordTemplatesForVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
$("#planRecordTemplateModalContent").html(data);
|
||||
hideAddPlanRecordModal();
|
||||
$('#planRecordTemplateModal').modal('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
function hidePlanRecordTemplatesModal() {
|
||||
$('#planRecordTemplateModal').modal('hide');
|
||||
$('#planRecordModal').modal('show');
|
||||
}
|
||||
function usePlannerRecordTemplate(planRecordTemplateId) {
|
||||
$.post(`/Vehicle/ConvertPlanRecordTemplateToPlanRecord?planRecordTemplateId=${planRecordTemplateId}`, function (data) {
|
||||
if (data.success) {
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
successToast(data.message);
|
||||
$('#planRecordTemplateModal').modal('hide');
|
||||
hideAddPlanRecordModal();
|
||||
hidePlanRecordTemplatesModal();
|
||||
saveScrollPosition();
|
||||
getVehiclePlanRecords(vehicleId);
|
||||
} else {
|
||||
@@ -122,8 +168,8 @@ function deletePlannerRecordTemplate(planRecordTemplateId) {
|
||||
$.post(`/Vehicle/DeletePlanRecordTemplateById?planRecordTemplateId=${planRecordTemplateId}`, function (data) {
|
||||
$("#workAroundInput").hide();
|
||||
if (data) {
|
||||
successToast("Template Deleted");
|
||||
hidePlanRecordTemplatesModal();
|
||||
successToast("Plan Template Deleted");
|
||||
hideAddPlanRecordModal();
|
||||
} else {
|
||||
errorToast(genericErrorMessage());
|
||||
}
|
||||
@@ -133,7 +179,7 @@ function deletePlannerRecordTemplate(planRecordTemplateId) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function savePlanRecordTemplate() {
|
||||
function savePlanRecordTemplate(isEdit) {
|
||||
//get values
|
||||
var formValues = getAndValidatePlanRecordValues();
|
||||
//validate
|
||||
@@ -144,7 +190,14 @@ function savePlanRecordTemplate() {
|
||||
//save to db.
|
||||
$.post('/Vehicle/SavePlanRecordTemplateToVehicleId', { planRecord: formValues }, function (data) {
|
||||
if (data.success) {
|
||||
successToast(data.message);
|
||||
if (isEdit) {
|
||||
hideAddPlanRecordModal();
|
||||
showPlanRecordTemplatesModal();
|
||||
$('[data-changed=true]').attr('data-changed', false)
|
||||
successToast('Plan Template Updated');
|
||||
} else {
|
||||
successToast('Plan Template Added');
|
||||
}
|
||||
} else {
|
||||
errorToast(data.message);
|
||||
}
|
||||
@@ -194,7 +247,8 @@ function getAndValidatePlanRecordValues() {
|
||||
importMode: planType,
|
||||
extraFields: extraFields.extraFields,
|
||||
requisitionHistory: supplyUsageHistory,
|
||||
reminderRecordId: reminderRecordId
|
||||
reminderRecordId: reminderRecordId,
|
||||
copySuppliesAttachment: copySuppliesAttachments
|
||||
}
|
||||
}
|
||||
//drag and drop stuff.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
if (data) {
|
||||
$("#reminderRecordModalContent").html(data);
|
||||
initDatePicker($('#reminderDate'), true);
|
||||
initTagSelector($("#reminderRecordTag"));
|
||||
$("#reminderRecordModal").modal("show");
|
||||
$('#reminderRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
|
||||
if (getGlobalConfig().useMarkDown) {
|
||||
@@ -166,6 +167,7 @@ function getAndValidateReminderRecordValues() {
|
||||
var reminderIsRecurring = $("#reminderIsRecurring").is(":checked");
|
||||
var reminderRecurringMonth = $("#reminderRecurringMonth").val();
|
||||
var reminderRecurringMileage = $("#reminderRecurringMileage").val();
|
||||
var reminderTags = $("#reminderRecordTag").val();
|
||||
var reminderCustomMileageInterval = customMileageInterval;
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
var reminderId = getReminderRecordModelData().id;
|
||||
@@ -215,7 +217,8 @@ function getAndValidateReminderRecordValues() {
|
||||
reminderMileageInterval: reminderRecurringMileage,
|
||||
reminderMonthInterval: reminderRecurringMonth,
|
||||
customMileageInterval: customMileageInterval,
|
||||
customMonthInterval: customMonthInterval
|
||||
customMonthInterval: customMonthInterval,
|
||||
tags: reminderTags
|
||||
}
|
||||
}
|
||||
function createPlanRecordFromReminder(reminderRecordId) {
|
||||
@@ -239,4 +242,55 @@ function createPlanRecordFromReminder(reminderRecordId) {
|
||||
$("#planRecordModalContent").html(data);
|
||||
$("#planRecordModal").modal("show");
|
||||
});
|
||||
}
|
||||
|
||||
function filterReminderTable(sender) {
|
||||
var rowData = $(`#reminder-tab-pane table tbody tr`);
|
||||
if (sender == undefined) {
|
||||
rowData.removeClass('override-hide');
|
||||
return;
|
||||
}
|
||||
var tagName = sender.textContent;
|
||||
//check for other applied filters
|
||||
if ($(sender).hasClass("bg-primary")) {
|
||||
rowData.removeClass('override-hide');
|
||||
$(sender).removeClass('bg-primary');
|
||||
$(sender).addClass('bg-secondary');
|
||||
updateReminderAggregateLabels();
|
||||
} else {
|
||||
//hide table rows.
|
||||
rowData.addClass('override-hide');
|
||||
$(`[data-tags~='${tagName}']`).removeClass('override-hide');
|
||||
updateReminderAggregateLabels();
|
||||
if ($(".tagfilter.bg-primary").length > 0) {
|
||||
//disabling other filters
|
||||
$(".tagfilter.bg-primary").addClass('bg-secondary');
|
||||
$(".tagfilter.bg-primary").removeClass('bg-primary');
|
||||
}
|
||||
$(sender).addClass('bg-primary');
|
||||
$(sender).removeClass('bg-secondary');
|
||||
}
|
||||
}
|
||||
function updateReminderAggregateLabels() {
|
||||
//update main count
|
||||
var newCount = $("[data-record-type='cost']").parent(":not('.override-hide')").length;
|
||||
var countLabel = $("[data-aggregate-type='count']");
|
||||
countLabel.text(`${countLabel.text().split(':')[0]}: ${newCount}`);
|
||||
//update labels
|
||||
//paste due
|
||||
var pastDueCount = $("tr td span.badge.text-bg-secondary").parents("tr:not('.override-hide')").length;
|
||||
var pastDueLabel = $('[data-aggregate-type="pastdue-count"]');
|
||||
pastDueLabel.text(`${pastDueLabel.text().split(':')[0]}: ${pastDueCount}`);
|
||||
//very urgent
|
||||
var veryUrgentCount = $("tr td span.badge.text-bg-danger").parents("tr:not('.override-hide')").length;
|
||||
var veryUrgentLabel = $('[data-aggregate-type="veryurgent-count"]');
|
||||
veryUrgentLabel.text(`${veryUrgentLabel.text().split(':')[0]}: ${veryUrgentCount}`);
|
||||
//urgent
|
||||
var urgentCount = $("tr td span.badge.text-bg-warning").parents("tr:not('.override-hide')").length;
|
||||
var urgentLabel = $('[data-aggregate-type="urgent-count"]');
|
||||
urgentLabel.text(`${urgentLabel.text().split(':')[0]}: ${urgentCount}`);
|
||||
//not urgent
|
||||
var notUrgentCount = $("tr td span.badge.text-bg-success").parents("tr:not('.override-hide')").length;
|
||||
var notUrgentLabel = $('[data-aggregate-type="noturgent-count"]');
|
||||
notUrgentLabel.text(`${notUrgentLabel.text().split(':')[0]}: ${notUrgentCount}`);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
function getYear() {
|
||||
return $("#yearOption").val();
|
||||
return $("#yearOption").val() ?? '0';
|
||||
}
|
||||
function generateVehicleHistoryReport() {
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
@@ -29,6 +29,43 @@ function refreshMPGChart() {
|
||||
$("#monthFuelMileageReportContent").html(data);
|
||||
})
|
||||
}
|
||||
function setSelectedMetrics() {
|
||||
var selectedMetricCheckBoxes = [];
|
||||
$(".reportCheckBox:checked").map((index, elem) => {
|
||||
selectedMetricCheckBoxes.push(elem.id);
|
||||
});
|
||||
var yearMetric = $('#yearOption').val();
|
||||
var reminderMetric = $("#reminderOption").val();
|
||||
sessionStorage.setItem("selectedMetricCheckBoxes", JSON.stringify(selectedMetricCheckBoxes));
|
||||
sessionStorage.setItem("yearMetric", yearMetric);
|
||||
sessionStorage.setItem("reminderMetric", reminderMetric);
|
||||
}
|
||||
function getSelectedMetrics() {
|
||||
var selectedMetricCheckBoxes = sessionStorage.getItem("selectedMetricCheckBoxes");
|
||||
var yearMetric = sessionStorage.getItem("yearMetric");
|
||||
var reminderMetric = sessionStorage.getItem("reminderMetric");
|
||||
if (selectedMetricCheckBoxes != null && yearMetric != null && reminderMetric != null) {
|
||||
selectedMetricCheckBoxes = JSON.parse(selectedMetricCheckBoxes);
|
||||
$(".reportCheckBox").prop('checked', false);
|
||||
$("#selectAllExpenseCheck").prop("checked", false);
|
||||
selectedMetricCheckBoxes.map(x => {
|
||||
$(`#${x}`).prop('checked', true);
|
||||
});
|
||||
if (selectedMetricCheckBoxes.length == 6) {
|
||||
$("#selectAllExpenseCheck").prop("checked", true);
|
||||
}
|
||||
//check if option is available
|
||||
if ($("#yearOption").has(`option[value=${yearMetric}]`).length > 0) {
|
||||
$('#yearOption').val(yearMetric);
|
||||
}
|
||||
$("#reminderOption").val(reminderMetric);
|
||||
//retrieve data.
|
||||
yearUpdated();
|
||||
updateReminderPie();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function refreshBarChart() {
|
||||
var selectedMetrics = [];
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
@@ -61,11 +98,13 @@ function refreshBarChart() {
|
||||
}, function (data) {
|
||||
$("#gasCostByMonthReportContent").html(data);
|
||||
refreshMPGChart();
|
||||
});
|
||||
});
|
||||
setSelectedMetrics();
|
||||
}
|
||||
function updateReminderPie() {
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
var daysToAdd = $("#reminderOption").val();
|
||||
setSelectedMetrics();
|
||||
$.get(`/Vehicle/GetReminderMakeUpByVehicle?vehicleId=${vehicleId}`, { daysToAdd: daysToAdd }, function (data) {
|
||||
$("#reminderMakeUpReportContent").html(data);
|
||||
});
|
||||
@@ -140,4 +179,74 @@ function exportAttachments() {
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
function showGlobalSearch() {
|
||||
$('#globalSearchModal').modal('show');
|
||||
}
|
||||
function hideGlobalSearch() {
|
||||
$('#globalSearchModal').modal('hide');
|
||||
}
|
||||
function performGlobalSearch() {
|
||||
var searchQuery = $('#globalSearchInput').val();
|
||||
if (searchQuery.trim() == '') {
|
||||
$('#globalSearchInput').addClass('is-invalid');
|
||||
} else {
|
||||
$('#globalSearchInput').removeClass('is-invalid');
|
||||
}
|
||||
$.post('/Vehicle/SearchRecords', { vehicleId: GetVehicleId().vehicleId, searchQuery: searchQuery }, function (data) {
|
||||
$('#globalSearchModalResults').html(data);
|
||||
});
|
||||
}
|
||||
function handleGlobalSearchKeyPress(event) {
|
||||
if ($('#globalSearchAutoSearchCheck').is(':checked')){
|
||||
setDebounce(performGlobalSearch);
|
||||
} else if (event.keyCode == 13) {
|
||||
performGlobalSearch();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,19 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditServiceRecordModal(serviceRecordId) {
|
||||
function showEditServiceRecordModal(serviceRecordId, nocache) {
|
||||
if (!nocache) {
|
||||
var existingContent = $("#serviceRecordModalContent").html();
|
||||
if (existingContent.trim() != '') {
|
||||
//check if id is same.
|
||||
var existingId = getServiceRecordModelData().id;
|
||||
if (existingId == serviceRecordId && $('[data-changed=true]').length > 0) {
|
||||
$('#serviceRecordModal').modal('show');
|
||||
$('.cached-banner').show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$.get(`/Vehicle/GetServiceRecordForEditById?serviceRecordId=${serviceRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#serviceRecordModalContent").html(data);
|
||||
@@ -17,6 +29,7 @@ function showEditServiceRecordModal(serviceRecordId) {
|
||||
initDatePicker($('#serviceRecordDate'));
|
||||
initTagSelector($("#serviceRecordTag"));
|
||||
$('#serviceRecordModal').modal('show');
|
||||
bindModalInputChanges('serviceRecordModal');
|
||||
$('#serviceRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
|
||||
if (getGlobalConfig().useMarkDown) {
|
||||
toggleMarkDownOverlay("serviceRecordNotes");
|
||||
@@ -133,6 +146,7 @@ function getAndValidateServiceRecordValues() {
|
||||
addReminderRecord: addReminderRecord,
|
||||
extraFields: extraFields.extraFields,
|
||||
requisitionHistory: supplyUsageHistory,
|
||||
reminderRecordId: recurringReminderRecordId
|
||||
reminderRecordId: recurringReminderRecordId,
|
||||
copySuppliesAttachment: copySuppliesAttachments
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,8 @@ function saveVehicle(isEdit) {
|
||||
var vehicleHasOdometerAdjustment = $("#inputHasOdometerAdjustment").is(':checked');
|
||||
var vehicleOdometerMultiplier = $("#inputOdometerMultiplier").val();
|
||||
var vehicleOdometerDifference = parseInt(globalParseFloat($("#inputOdometerDifference").val())).toString();
|
||||
var vehiclePurchasePrice = $("#inputPurchasePrice").val();
|
||||
var vehicleSoldPrice = $("#inputSoldPrice").val();
|
||||
var extraFields = getAndValidateExtraFields(true);
|
||||
//validate
|
||||
var hasError = false;
|
||||
@@ -92,6 +94,20 @@ function saveVehicle(isEdit) {
|
||||
$("#inputOdometerDifference").removeClass("is-invalid");
|
||||
}
|
||||
}
|
||||
if (vehiclePurchasePrice.trim() != '' && !isValidMoney(vehiclePurchasePrice)) {
|
||||
hasError = true;
|
||||
$("#inputPurchasePrice").addClass("is-invalid");
|
||||
$("#collapsePurchaseInfo").collapse('show');
|
||||
} else {
|
||||
$("#inputPurchasePrice").removeClass("is-invalid");
|
||||
}
|
||||
if (vehicleSoldPrice.trim() != '' && !isValidMoney(vehicleSoldPrice)) {
|
||||
hasError = true;
|
||||
$("#inputSoldPrice").addClass("is-invalid");
|
||||
$("#collapsePurchaseInfo").collapse('show');
|
||||
} else {
|
||||
$("#inputSoldPrice").removeClass("is-invalid");
|
||||
}
|
||||
if (hasError) {
|
||||
return;
|
||||
}
|
||||
@@ -110,7 +126,9 @@ function saveVehicle(isEdit) {
|
||||
soldDate: vehicleSoldDate,
|
||||
hasOdometerAdjustment: vehicleHasOdometerAdjustment,
|
||||
odometerMultiplier: vehicleOdometerMultiplier,
|
||||
odometerDifference: vehicleOdometerDifference
|
||||
odometerDifference: vehicleOdometerDifference,
|
||||
purchasePrice: vehiclePurchasePrice,
|
||||
soldPrice: vehicleSoldPrice
|
||||
}, function (data) {
|
||||
if (data) {
|
||||
if (!isEdit) {
|
||||
@@ -321,7 +339,7 @@ function updateAggregateLabels() {
|
||||
if (labelsToSum.length > 0) {
|
||||
newSum = labelsToSum.map(x => globalParseFloat(x.textContent)).reduce((a, b,) => a + b).toFixed(2);
|
||||
}
|
||||
sumLabel.text(`${sumLabel.text().split(':')[0]}: ${getGlobalConfig().currencySymbol}${newSum}`)
|
||||
sumLabel.text(`${sumLabel.text().split(':')[0]}: ${globalAppendCurrency(globalFloatToString(newSum))}`)
|
||||
}
|
||||
//Sum Distance
|
||||
var sumDistanceLabel = $("[data-aggregate-type='sum-distance']");
|
||||
@@ -336,7 +354,7 @@ function updateAggregateLabels() {
|
||||
//Count
|
||||
var newCount = $("[data-record-type='cost']").parent(":not('.override-hide')").length;
|
||||
var countLabel = $("[data-aggregate-type='count']");
|
||||
countLabel.text(`${countLabel.text().split(':')[0]}: ${newCount}`)
|
||||
countLabel.text(`${countLabel.text().split(':')[0]}: ${newCount}`);
|
||||
}
|
||||
|
||||
function uploadVehicleFilesAsync(event) {
|
||||
@@ -690,7 +708,10 @@ $(window).on('keydown', function (e) {
|
||||
selectAllRows();
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
function getCurrentTab() {
|
||||
return $(".tab-pane.active.show").attr('id');
|
||||
}
|
||||
function selectAllRows() {
|
||||
clearSelectedRows();
|
||||
$('.vehicleDetailTabContainer .table tbody tr:visible').addClass('table-active');
|
||||
@@ -1010,4 +1031,26 @@ function copyToClipboard(e) {
|
||||
var textToCopy = e.textContent.trim();
|
||||
navigator.clipboard.writeText(textToCopy);
|
||||
successToast("Copied to Clipboard");
|
||||
}
|
||||
function noPropagation() {
|
||||
event.stopPropagation();
|
||||
}
|
||||
var checkExist;
|
||||
|
||||
function waitForElement(element, callBack, callBackParameter) {
|
||||
checkExist = setInterval(function () {
|
||||
if ($(`${element}`).length) {
|
||||
callBack(callBackParameter);
|
||||
clearInterval(checkExist);
|
||||
}
|
||||
}, 100); // check every 100ms
|
||||
}
|
||||
function bindModalInputChanges(modalName) {
|
||||
//bind text inputs
|
||||
$(`#${modalName} input[type='text'], #${modalName} input[type='number'], #${modalName} textarea`).off('input').on('input', function (e) {
|
||||
$(e.currentTarget).attr('data-changed', true);
|
||||
});
|
||||
$(`#${modalName} select, #${modalName} input[type='checkbox']`).off('input').on('input', function (e) {
|
||||
$(e.currentTarget).attr('data-changed', true);
|
||||
});
|
||||
}
|
||||
@@ -9,7 +9,19 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditSupplyRecordModal(supplyRecordId) {
|
||||
function showEditSupplyRecordModal(supplyRecordId, nocache) {
|
||||
if (!nocache) {
|
||||
var existingContent = $("#supplyRecordModalContent").html();
|
||||
if (existingContent.trim() != '') {
|
||||
//check if id is same.
|
||||
var existingId = getSupplyRecordModelData().id;
|
||||
if (existingId == supplyRecordId && $('[data-changed=true]').length > 0) {
|
||||
$('#supplyRecordModal').modal('show');
|
||||
$('.cached-banner').show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$.get(`/Vehicle/GetSupplyRecordForEditById?supplyRecordId=${supplyRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#supplyRecordModalContent").html(data);
|
||||
@@ -17,6 +29,7 @@ function showEditSupplyRecordModal(supplyRecordId) {
|
||||
initDatePicker($('#supplyRecordDate'));
|
||||
initTagSelector($("#supplyRecordTag"));
|
||||
$('#supplyRecordModal').modal('show');
|
||||
bindModalInputChanges('supplyRecordModal');
|
||||
$('#supplyRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
|
||||
if (getGlobalConfig().useMarkDown) {
|
||||
toggleMarkDownOverlay("supplyRecordNotes");
|
||||
|
||||
@@ -9,7 +9,19 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditTaxRecordModal(taxRecordId) {
|
||||
function showEditTaxRecordModal(taxRecordId, nocache) {
|
||||
if (!nocache) {
|
||||
var existingContent = $("#taxRecordModalContent").html();
|
||||
if (existingContent.trim() != '') {
|
||||
//check if id is same.
|
||||
var existingId = getTaxRecordModelData().id;
|
||||
if (existingId == taxRecordId && $('[data-changed=true]').length > 0) {
|
||||
$('#taxRecordModal').modal('show');
|
||||
$('.cached-banner').show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$.get(`/Vehicle/GetTaxRecordForEditById?taxRecordId=${taxRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#taxRecordModalContent").html(data);
|
||||
@@ -17,6 +29,7 @@ function showEditTaxRecordModal(taxRecordId) {
|
||||
initDatePicker($('#taxRecordDate'));
|
||||
initTagSelector($("#taxRecordTag"));
|
||||
$('#taxRecordModal').modal('show');
|
||||
bindModalInputChanges('taxRecordModal');
|
||||
$('#taxRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
|
||||
if (getGlobalConfig().useMarkDown) {
|
||||
toggleMarkDownOverlay("taxRecordNotes");
|
||||
|
||||
@@ -9,7 +9,19 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditUpgradeRecordModal(upgradeRecordId) {
|
||||
function showEditUpgradeRecordModal(upgradeRecordId, nocache) {
|
||||
if (!nocache) {
|
||||
var existingContent = $("#upgradeRecordModalContent").html();
|
||||
if (existingContent.trim() != '') {
|
||||
//check if id is same.
|
||||
var existingId = getUpgradeRecordModelData().id;
|
||||
if (existingId == upgradeRecordId && $('[data-changed=true]').length > 0) {
|
||||
$('#upgradeRecordModal').modal('show');
|
||||
$('.cached-banner').show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$.get(`/Vehicle/GetUpgradeRecordForEditById?upgradeRecordId=${upgradeRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#upgradeRecordModalContent").html(data);
|
||||
@@ -17,6 +29,7 @@ function showEditUpgradeRecordModal(upgradeRecordId) {
|
||||
initDatePicker($('#upgradeRecordDate'));
|
||||
initTagSelector($("#upgradeRecordTag"));
|
||||
$('#upgradeRecordModal').modal('show');
|
||||
bindModalInputChanges('upgradeRecordModal');
|
||||
$('#upgradeRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
|
||||
if (getGlobalConfig().useMarkDown) {
|
||||
toggleMarkDownOverlay("upgradeRecordNotes");
|
||||
@@ -133,6 +146,7 @@ function getAndValidateUpgradeRecordValues() {
|
||||
addReminderRecord: addReminderRecord,
|
||||
extraFields: extraFields.extraFields,
|
||||
requisitionHistory: supplyUsageHistory,
|
||||
reminderRecordId: recurringReminderRecordId
|
||||
reminderRecordId: recurringReminderRecordId,
|
||||
copySuppliesAttachment: copySuppliesAttachments
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,10 @@ $(document).ready(function () {
|
||||
$("#odometer-tab-pane").html("");
|
||||
break;
|
||||
}
|
||||
$(`.lubelogger-tab #${e.target.id}`).addClass('active');
|
||||
$(`.lubelogger-mobile-nav #${e.target.id}`).addClass('active');
|
||||
$(`.lubelogger-tab #${e.relatedTarget.id}`).removeClass('active');
|
||||
$(`.lubelogger-mobile-nav #${e.relatedTarget.id}`).removeClass('active');
|
||||
});
|
||||
var defaultTab = GetDefaultTab().tab;
|
||||
switch (defaultTab) {
|
||||
@@ -246,12 +250,14 @@ function showAddReminderModal(reminderModalInput) {
|
||||
$.post('/Vehicle/GetAddReminderRecordPartialView', { reminderModel: reminderModalInput }, function (data) {
|
||||
$("#reminderRecordModalContent").html(data);
|
||||
initDatePicker($('#reminderDate'), true);
|
||||
initTagSelector($("#reminderRecordTag"));
|
||||
$("#reminderRecordModal").modal("show");
|
||||
});
|
||||
} else {
|
||||
$.post('/Vehicle/GetAddReminderRecordPartialView', function (data) {
|
||||
$("#reminderRecordModalContent").html(data);
|
||||
initDatePicker($('#reminderDate'), true);
|
||||
initTagSelector($("#reminderRecordTag"));
|
||||
$("#reminderRecordModal").modal("show");
|
||||
});
|
||||
}
|
||||
@@ -340,19 +346,19 @@ function showRecurringReminderSelector(descriptionFieldName) {
|
||||
confirmButtonText: 'Select',
|
||||
focusConfirm: false,
|
||||
preConfirm: () => {
|
||||
const selectedRecurringReminder = $("#recurringReminderInput").val();
|
||||
const selectedRecurringReminderText = $("#recurringReminderInput option:selected").text();
|
||||
if (!selectedRecurringReminder || parseInt(selectedRecurringReminder) == 0) {
|
||||
//validate
|
||||
var selectedRecurringReminderData = getAndValidateSelectedRecurringReminder();
|
||||
if (selectedRecurringReminderData.hasError) {
|
||||
Swal.showValidationMessage(`You must select a recurring reminder`);
|
||||
}
|
||||
return { selectedRecurringReminder, selectedRecurringReminderText }
|
||||
return { selectedRecurringReminderData }
|
||||
},
|
||||
}).then(function (result) {
|
||||
if (result.isConfirmed) {
|
||||
recurringReminderRecordId = result.value.selectedRecurringReminder;
|
||||
recurringReminderRecordId = result.value.selectedRecurringReminderData.ids;
|
||||
var descriptionField = $(`#${descriptionFieldName}`);
|
||||
if (descriptionField.length > 0) {
|
||||
descriptionField.val(result.value.selectedRecurringReminderText.trim());
|
||||
descriptionField.val(result.value.selectedRecurringReminderData.text);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -474,19 +480,19 @@ function getRecordsDeltaStats(recordIds) {
|
||||
var diffOdo = maxOdo - minOdo;
|
||||
var diffDate = maxDate - minDate;
|
||||
var divisibleCount = recordIds.length - 1;
|
||||
var averageOdo = diffOdo > 0 ? (diffOdo / divisibleCount).toFixed(2) : 0;
|
||||
var averageDays = diffDate > 0 ? Math.floor((diffDate / divisibleCount) / 8.64e7) : 0;
|
||||
var averageSum = costSum > 0 ? (costSum / recordIds.length).toFixed(2) : 0;
|
||||
var averageOdo = diffOdo > 0 ? (diffOdo / divisibleCount).toFixed(2) : '0';
|
||||
var averageDays = diffDate > 0 ? Math.floor((diffDate / divisibleCount) / 8.64e7) : '0';
|
||||
var averageSum = costSum > 0 ? (costSum / recordIds.length).toFixed(2) : '0';
|
||||
costSum = costSum.toFixed(2);
|
||||
Swal.fire({
|
||||
title: "Record Statistics",
|
||||
html: `<p>Average Distance Traveled between Records: ${averageOdo}</p>
|
||||
html: `<p>Average Distance Traveled between Records: ${globalFloatToString(averageOdo)}</p>
|
||||
<br />
|
||||
<p>Average Days between Records: ${averageDays}</p>
|
||||
<br />
|
||||
<p>Total Cost: ${getGlobalConfig().currencySymbol} ${costSum}</p>
|
||||
<p>Total Cost: ${globalAppendCurrency(globalFloatToString(costSum))}</p>
|
||||
<br />
|
||||
<p>Average Cost: ${getGlobalConfig().currencySymbol} ${averageSum}</p>`
|
||||
<p>Average Cost: ${globalAppendCurrency(globalFloatToString(averageSum))}</p>`
|
||||
,
|
||||
icon: "info"
|
||||
});
|
||||
@@ -554,4 +560,89 @@ function adjustRecordsOdometer(ids, source) {
|
||||
$("#workAroundInput").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
function showMultipleRemindersSelector() {
|
||||
if ($("#multipleRemindersCheck").is(":checked")) {
|
||||
$("#recurringMultipleReminders").show();
|
||||
$("#recurringReminderInput").hide();
|
||||
} else {
|
||||
$("#recurringMultipleReminders").hide();
|
||||
$("#recurringReminderInput").show();
|
||||
}
|
||||
}
|
||||
function getAndValidateSelectedRecurringReminder() {
|
||||
if ($("#multipleRemindersCheck").is(":checked")) {
|
||||
//validate multiple reminders
|
||||
var selectedRecurringRemindersArray = [];
|
||||
$("#recurringMultipleReminders :checked").map(function () {
|
||||
selectedRecurringRemindersArray.push({
|
||||
value: this.value,
|
||||
text: $(this).parent().find('.form-check-label').text()
|
||||
});
|
||||
});
|
||||
if (selectedRecurringRemindersArray.length == 0) {
|
||||
return {
|
||||
hasError: true,
|
||||
ids: [],
|
||||
text: ''
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
hasError: false,
|
||||
ids: selectedRecurringRemindersArray.map(x=>x.value),
|
||||
text: selectedRecurringRemindersArray.map(x=>x.text).join(', ')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//validate single reminder
|
||||
var selectedRecurringReminder = $("#recurringReminderInput").val();
|
||||
var selectedRecurringReminderText = $("#recurringReminderInput option:selected").text();
|
||||
if (!selectedRecurringReminder || parseInt(selectedRecurringReminder) == 0) {
|
||||
return {
|
||||
hasError: true,
|
||||
ids: [],
|
||||
text: ''
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
hasError: false,
|
||||
ids: [selectedRecurringReminder],
|
||||
text: selectedRecurringReminderText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function getLastOdometerReadingAndIncrement(odometerFieldName) {
|
||||
Swal.fire({
|
||||
title: 'Increment Last Reported Odometer Reading',
|
||||
html: `
|
||||
<input type="text" id="inputOdometerIncrement" class="swal2-input" placeholder="Increment">
|
||||
`,
|
||||
confirmButtonText: 'Add',
|
||||
focusConfirm: false,
|
||||
preConfirm: () => {
|
||||
const odometerIncrement = parseInt(globalParseFloat($("#inputOdometerIncrement").val()));
|
||||
if (isNaN(odometerIncrement) || odometerIncrement <= 0) {
|
||||
Swal.showValidationMessage(`Please enter a non-zero amount to increment`);
|
||||
}
|
||||
return { odometerIncrement }
|
||||
},
|
||||
}).then(function (result) {
|
||||
if (result.isConfirmed) {
|
||||
var amountToIncrement = result.value.odometerIncrement;
|
||||
$.get(`/Vehicle/GetMaxMileage?vehicleId=${GetVehicleId().vehicleId}`, function (data) {
|
||||
var newAmount = data + amountToIncrement;
|
||||
if (!isNaN(newAmount)) {
|
||||
var odometerField = $(`#${odometerFieldName}`);
|
||||
if (odometerField.length > 0) {
|
||||
odometerField.val(newAmount);
|
||||
} else {
|
||||
errorToast(genericErrorMessage());
|
||||
}
|
||||
} else {
|
||||
errorToast(genericErrorMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
4
wwwroot/sweetalert/sweetalert2.all.min.js
vendored
4
wwwroot/sweetalert/sweetalert2.all.min.js
vendored
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user