Compare commits
139 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cf733b9c6 | ||
|
|
1eb6e2cedf | ||
|
|
ef4deaba8f | ||
|
|
e8c196c2fa | ||
|
|
f7c9db6353 | ||
|
|
4ce720ff97 | ||
|
|
a96011629b | ||
|
|
9dcdcf97e8 | ||
|
|
5148338f52 | ||
|
|
0d3c04d8f8 | ||
|
|
15328a14b4 | ||
|
|
2d092f722a | ||
|
|
8825cb9b9b | ||
|
|
2f17e303ab | ||
|
|
4b56c8a343 | ||
|
|
7b6b62c623 | ||
|
|
07f5e66491 | ||
|
|
fe633f3220 | ||
|
|
af1090553f | ||
|
|
92c2e66660 | ||
|
|
08372f9dcb | ||
|
|
64ea0e2eee | ||
|
|
7ab476a88f | ||
|
|
de41ca911d | ||
|
|
dde9688f96 | ||
|
|
c1ca63edc0 | ||
|
|
cbc430499f | ||
|
|
4da9fa4802 | ||
|
|
42586d9556 | ||
|
|
ea4387d4ab | ||
|
|
0707b515ab | ||
|
|
78ae71fc46 | ||
|
|
3f62cd40e7 | ||
|
|
47657c0093 | ||
|
|
a5b0fde4b6 | ||
|
|
78cc0b34b1 | ||
|
|
e3017e986b | ||
|
|
e12cd876db | ||
|
|
5292e4b814 | ||
|
|
dbdd16ab89 | ||
|
|
61c2600286 | ||
|
|
163a33ae3a | ||
|
|
37d064aa62 | ||
|
|
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 |
1
.env
1
.env
@@ -2,7 +2,6 @@ LC_ALL=en_US.UTF-8
|
||||
LANG=en_US.UTF-8
|
||||
MailConfig__EmailServer=""
|
||||
MailConfig__EmailFrom=""
|
||||
MailConfig__UseSSL="false"
|
||||
MailConfig__Port=587
|
||||
MailConfig__Username=""
|
||||
MailConfig__Password=""
|
||||
|
||||
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,7 +13,8 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CsvHelper" Version="30.0.1" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.17" />
|
||||
<PackageReference Include="Npgsql" Version="8.0.2" />
|
||||
<PackageReference Include="MailKit" Version="4.5.0" />
|
||||
<PackageReference Include="Npgsql" Version="8.0.3" />
|
||||
<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]
|
||||
@@ -190,6 +219,13 @@ namespace CarCareTracker.Controllers
|
||||
var userName = User.Identity.Name;
|
||||
return PartialView("_AccountModal", new UserData() { EmailAddress = emailAddress, UserName = userName });
|
||||
}
|
||||
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||
[HttpGet]
|
||||
public IActionResult GetRootAccountInformationModal()
|
||||
{
|
||||
var userName = User.Identity.Name;
|
||||
return PartialView("_RootAccountModal", new UserData() { UserName = userName });
|
||||
}
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
@@ -208,7 +220,7 @@ namespace CarCareTracker.Controllers
|
||||
var result = _loginLogic.ResetPasswordByUser(credentials);
|
||||
return Json(result);
|
||||
}
|
||||
[Authorize] //User must already be logged in to do this.
|
||||
[Authorize(Roles = nameof(UserData.IsRootUser))] //User must already be logged in as root user to do this.
|
||||
[HttpPost]
|
||||
public IActionResult CreateLoginCreds(LoginModel credentials)
|
||||
{
|
||||
@@ -223,7 +235,7 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
return Json(false);
|
||||
}
|
||||
[Authorize]
|
||||
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||
[HttpPost]
|
||||
public IActionResult DestroyLoginCreds()
|
||||
{
|
||||
@@ -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;
|
||||
}
|
||||
@@ -436,7 +439,8 @@ namespace CarCareTracker.Controllers
|
||||
Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)),
|
||||
Gallons = decimal.Parse(importModel.FuelConsumed, NumberStyles.Any),
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value }).ToList() : new List<ExtraField>()
|
||||
};
|
||||
if (string.IsNullOrWhiteSpace(importModel.Cost) && !string.IsNullOrWhiteSpace(importModel.Price))
|
||||
{
|
||||
@@ -492,7 +496,8 @@ namespace CarCareTracker.Controllers
|
||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Service Record on {importModel.Date}" : importModel.Description,
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value }).ToList() : new List<ExtraField>()
|
||||
};
|
||||
_serviceRecordDataAccess.SaveServiceRecordToVehicle(convertedRecord);
|
||||
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
@@ -515,7 +520,8 @@ namespace CarCareTracker.Controllers
|
||||
InitialMileage = string.IsNullOrWhiteSpace(importModel.InitialOdometer) ? 0 : decimal.ToInt32(decimal.Parse(importModel.InitialOdometer, NumberStyles.Any)),
|
||||
Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)),
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value }).ToList() : new List<ExtraField>()
|
||||
};
|
||||
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(convertedRecord);
|
||||
}
|
||||
@@ -534,7 +540,8 @@ namespace CarCareTracker.Controllers
|
||||
Priority = parsedPriority,
|
||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Plan Record on {importModel.DateCreated}" : importModel.Description,
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any)
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value }).ToList() : new List<ExtraField>()
|
||||
};
|
||||
_planRecordDataAccess.SavePlanRecordToVehicle(convertedRecord);
|
||||
}
|
||||
@@ -548,7 +555,8 @@ namespace CarCareTracker.Controllers
|
||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Repair Record on {importModel.Date}" : importModel.Description,
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value }).ToList() : new List<ExtraField>()
|
||||
};
|
||||
_collisionRecordDataAccess.SaveCollisionRecordToVehicle(convertedRecord);
|
||||
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
@@ -572,7 +580,8 @@ namespace CarCareTracker.Controllers
|
||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Upgrade Record on {importModel.Date}" : importModel.Description,
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value }).ToList() : new List<ExtraField>()
|
||||
};
|
||||
_upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(convertedRecord);
|
||||
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||
@@ -598,7 +607,8 @@ namespace CarCareTracker.Controllers
|
||||
Description = importModel.Description,
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||
Notes = importModel.Notes,
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value }).ToList() : new List<ExtraField>()
|
||||
};
|
||||
_supplyRecordDataAccess.SaveSupplyRecordToVehicle(convertedRecord);
|
||||
}
|
||||
@@ -611,7 +621,8 @@ namespace CarCareTracker.Controllers
|
||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Tax Record on {importModel.Date}" : importModel.Description,
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value }).ToList() : new List<ExtraField>()
|
||||
};
|
||||
_taxRecordDataAccess.SaveTaxRecordToVehicle(convertedRecord);
|
||||
}
|
||||
@@ -823,11 +834,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 +926,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 +1046,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 +1161,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 +1345,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 +1532,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 +1554,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 +1566,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 +1595,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 +1667,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 +1718,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 +1863,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 +1925,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 +1971,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 +2050,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 +2067,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 +2121,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 +2157,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 +2170,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 +2186,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 +2202,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 +2216,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 +2390,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.5";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,18 @@ namespace CarCareTracker.MapProfile
|
||||
Map(m => m.Type).Name(["type"]);
|
||||
Map(m => m.Priority).Name(["priority"]);
|
||||
Map(m => m.Tags).Name(["tags"]);
|
||||
Map(m => m.ExtraFields).Convert(row =>
|
||||
{
|
||||
var attributes = new Dictionary<string, string>();
|
||||
foreach (var header in row.Row.HeaderRecord)
|
||||
{
|
||||
if (header.ToLower().StartsWith("extrafield_"))
|
||||
{
|
||||
attributes.Add(header.Substring(11), row.Row.GetField(header));
|
||||
}
|
||||
}
|
||||
return attributes;
|
||||
}); ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
{
|
||||
public string EmailServer { get; set; }
|
||||
public string EmailFrom { get; set; }
|
||||
public bool UseSSL { get; set; }
|
||||
public int Port { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
public string PartSupplier { get; set; }
|
||||
public string PartQuantity { get; set; }
|
||||
public string Tags { get; set; }
|
||||
public Dictionary<string,string> ExtraFields {get;set;}
|
||||
}
|
||||
|
||||
public class SupplyRecordExportModel
|
||||
|
||||
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)
|
||||
@@ -41,7 +41,12 @@
|
||||
<a class="dropdown-item" href="/Admin"><span class="display-3 ms-2"><i class="bi bi-people me-2"></i>@translator.Translate(userLanguage,"Admin Panel")</span></a>
|
||||
</li>
|
||||
}
|
||||
@if (!User.IsInRole(nameof(UserData.IsRootUser)))
|
||||
@if (User.IsInRole(nameof(UserData.IsRootUser)))
|
||||
{
|
||||
<li>
|
||||
<button class="nav-link" onclick="showRootAccountInformationModal()"><span class="display-3 ms-2"><i class="bi bi-person-gear me-2"></i>@translator.Translate(userLanguage, "Profile")</span></button>
|
||||
</li>
|
||||
} else
|
||||
{
|
||||
<li>
|
||||
<button class="nav-link" onclick="showAccountInformationModal()"><span class="display-3 ms-2"><i class="bi bi-person-gear me-2"></i>@translator.Translate(userLanguage, "Profile")</span></button>
|
||||
@@ -90,7 +95,12 @@
|
||||
<a class="dropdown-item" href="/Admin"><i class="bi bi-people me-2"></i>@translator.Translate(userLanguage,"Admin Panel")</a>
|
||||
</li>
|
||||
}
|
||||
@if (!User.IsInRole(nameof(UserData.IsRootUser)))
|
||||
@if (User.IsInRole(nameof(UserData.IsRootUser)))
|
||||
{
|
||||
<li>
|
||||
<button class="dropdown-item" onclick="showRootAccountInformationModal()"><i class="bi bi-person-gear me-2"></i>@translator.Translate(userLanguage, "Profile")</button>
|
||||
</li>
|
||||
} else
|
||||
{
|
||||
<li>
|
||||
<button class="dropdown-item" onclick="showAccountInformationModal()"><i class="bi bi-person-gear me-2"></i>@translator.Translate(userLanguage, "Profile")</button>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="addVehicleModalLabel">@translator.Translate(userLanguage, "Update Profile")</h5>
|
||||
<h5 class="modal-title" id="updateAccountModalLabel">@translator.Translate(userLanguage, "Update Profile")</h5>
|
||||
<button type="button" class="btn-close" onclick="hideAccountInformationModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
@@ -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>
|
||||
|
||||
26
Views/Home/_RootAccountModal.cshtml
Normal file
26
Views/Home/_RootAccountModal.cshtml
Normal file
@@ -0,0 +1,26 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@inject ITranslationHelper translator
|
||||
@model UserData
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
var userLanguage = userConfig.UserLanguage;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="updateRootAccountModalLabel">@translator.Translate(userLanguage, "Update Profile")</h5>
|
||||
<button type="button" class="btn-close" onclick="hideAccountInformationModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-inline">
|
||||
<div class="form-group">
|
||||
<label for="inputUsername">@translator.Translate(userLanguage, "Username")</label>
|
||||
<input type="text" id="inputUsername" class="form-control" placeholder="@translator.Translate(userLanguage, "Account Username")" value="@Model.UserName">
|
||||
<label for="inputPassword">@translator.Translate(userLanguage, "Password")</label>
|
||||
<input type="password" id="inputPassword" class="form-control" placeholder="@translator.Translate(userLanguage, "Password")" value="">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" onclick="hideAccountInformationModal()">@translator.Translate(userLanguage, "Cancel")</button>
|
||||
<button type="button" onclick="validateAndSaveRootUserAccount()" class="btn btn-primary">@translator.Translate(userLanguage, "Update")</button>
|
||||
</div>
|
||||
@@ -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')"><i class="bi bi-plus"></i></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')"><i class="bi bi-plus"></i></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">
|
||||
@@ -23,9 +23,25 @@
|
||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||
</div>
|
||||
<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)">
|
||||
<div class="input-group">
|
||||
<input type="number" inputmode="numeric" id="initialOdometerRecordMileage" @(Model.InitialMileage != default ? "disabled" : "") class="form-control" placeholder="@translator.Translate(userLanguage,"Initial Odometer reading")" value="@(Model.InitialMileage)">
|
||||
@if (Model.InitialMileage != default)
|
||||
{
|
||||
<div class="input-group-text">
|
||||
<button type="button" class="btn btn-sm btn-secondary zero-y-padding" onclick="toggleInitialOdometerEnabled()"><i class="bi bi-pencil"></i></button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<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')"><i class="bi bi-plus"></i></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>
|
||||
@@ -21,7 +21,7 @@
|
||||
<input type="text" id="reminderDescription" class="form-control" placeholder="@translator.Translate(userLanguage,"Reminder Description")" value="@Model.Description">
|
||||
<label>@translator.Translate(userLanguage,"Remind me on")</label>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="reminderMetricOptions" id="reminderMetricDate" value="@(ReminderMetric.Date)" checked="@(Model.Metric == ReminderMetric.Date)">
|
||||
<input class="form-check-input" onclick="enableRecurring()" type="radio" name="reminderMetricOptions" id="reminderMetricDate" value="@(ReminderMetric.Date)" checked="@(Model.Metric == ReminderMetric.Date)">
|
||||
<label class="form-check-label" for="reminderMetricDate">@translator.Translate(userLanguage,"Date")</label>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
@@ -29,19 +29,30 @@
|
||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="radio" name="reminderMetricOptions" id="reminderMetricOdometer" value="@(ReminderMetric.Odometer)" checked="@(Model.Metric == ReminderMetric.Odometer)">
|
||||
<input class="form-check-input" onclick="enableRecurring()" type="radio" name="reminderMetricOptions" id="reminderMetricOdometer" value="@(ReminderMetric.Odometer)" checked="@(Model.Metric == ReminderMetric.Odometer)">
|
||||
<label class="form-check-label" for="reminderMetricOdometer">@translator.Translate(userLanguage,"Odometer")</label>
|
||||
</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')"><i class="bi bi-plus"></i></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)">
|
||||
<input class="form-check-input" onclick="enableRecurring()" 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>
|
||||
@@ -51,7 +62,7 @@
|
||||
<label class="form-check-label" for="reminderIsRecurring">@translator.Translate(userLanguage,"Is Recurring")</label>
|
||||
</div>
|
||||
<label for="reminderRecurringMileage">@translator.Translate(userLanguage,"Odometer")</label>
|
||||
<select class="form-select" onchange="checkCustomMileageInterval()" id="reminderRecurringMileage" @(Model.IsRecurring ? "" : "disabled")>
|
||||
<select class="form-select" onchange="checkCustomMileageInterval()" id="reminderRecurringMileage" @(Model.IsRecurring && (Model.Metric == ReminderMetric.Odometer || Model.Metric == ReminderMetric.Both) ? "" : "disabled")>
|
||||
<!option value="Other" @(Model.ReminderMileageInterval == ReminderMileageInterval.Other ? "selected" : "")>@(Model.ReminderMileageInterval == ReminderMileageInterval.Other && Model.CustomMileageInterval > 0 ? $"{translator.Translate(userLanguage, "Other")}: {Model.CustomMileageInterval}" : $"{translator.Translate(userLanguage, "Other")}") </!option>
|
||||
<!option value="FiftyMiles" @(Model.ReminderMileageInterval == ReminderMileageInterval.FiftyMiles ? "selected" : "")>50 mi. / Km</!option>
|
||||
<!option value="OneHundredMiles" @(Model.ReminderMileageInterval == ReminderMileageInterval.OneHundredMiles ? "selected" : "")>100 mi. / Km</!option>
|
||||
@@ -72,7 +83,7 @@
|
||||
<!option value="OneHundredFiftyThousandMiles" @(Model.ReminderMileageInterval == ReminderMileageInterval.OneHundredFiftyThousandMiles ? "selected" : "")>150000 mi. / Km</!option>
|
||||
</select>
|
||||
<label for="reminderRecurringMonth">Month</label>
|
||||
<select class="form-select" onchange="checkCustomMonthInterval()" id="reminderRecurringMonth" @(Model.IsRecurring ? "" : "disabled")>
|
||||
<select class="form-select" onchange="checkCustomMonthInterval()" id="reminderRecurringMonth" @(Model.IsRecurring && (Model.Metric == ReminderMetric.Date || Model.Metric == ReminderMetric.Both) ? "" : "disabled")>
|
||||
<!option value="Other" @(Model.ReminderMonthInterval == ReminderMonthInterval.Other ? "selected" : "")>@(Model.ReminderMonthInterval == ReminderMonthInterval.Other && Model.CustomMonthInterval > 0 ? $"{translator.Translate(userLanguage, "Other")}: {Model.CustomMonthInterval}" : $"{translator.Translate(userLanguage, "Other")}") </!option>
|
||||
<!option value="OneMonth" @(Model.ReminderMonthInterval == ReminderMonthInterval.OneMonth ? "selected" : "")>@translator.Translate(userLanguage, "1 Month")</!option>
|
||||
<!option value="ThreeMonths" @(Model.ReminderMonthInterval == ReminderMonthInterval.ThreeMonths || isNew ? "selected" : "")>@translator.Translate(userLanguage,"3 Months")</!option>
|
||||
|
||||
@@ -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')"><i class="bi bi-plus"></i></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">
|
||||
@@ -34,7 +34,7 @@
|
||||
<div class="input-group">
|
||||
<input type="text" inputmode="decimal" id="supplyRecordQuantity" class="form-control" placeholder="@translator.Translate(userLanguage,"Quantity")" value="@(isNew ? "1" : Model.Quantity)">
|
||||
<div class="input-group-text">
|
||||
<button type="button" class="btn btn-sm zero-y-padding btn-primary" onclick="replenishSupplies()">+</button>
|
||||
<button type="button" class="btn btn-sm zero-y-padding btn-primary" onclick="replenishSupplies()"><i class="bi bi-plus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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')"><i class="bi bi-plus"></i></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)
|
||||
|
||||
@@ -30,6 +30,7 @@ services:
|
||||
POSTGRES_PASSWORD: "lubepass"
|
||||
POSTGRES_DB: "lubelogger"
|
||||
volumes:
|
||||
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
- postgres:/var/lib/postgresql/data
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
|
||||
|
||||
6
init.sql
Normal file
6
init.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'app') THEN
|
||||
CREATE SCHEMA app;
|
||||
END IF;
|
||||
END $$;
|
||||
@@ -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
BIN
wwwroot/defaults/lubelogger_maskable_icon_128.png
Normal file
BIN
wwwroot/defaults/lubelogger_maskable_icon_128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
BIN
wwwroot/defaults/lubelogger_maskable_icon_192.png
Normal file
BIN
wwwroot/defaults/lubelogger_maskable_icon_192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
wwwroot/defaults/lubelogger_maskable_icon_72.png
Normal file
BIN
wwwroot/defaults/lubelogger_maskable_icon_72.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
@@ -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;
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -341,6 +341,47 @@ function showAccountInformationModal() {
|
||||
$('#accountInformationModal').modal('show');
|
||||
})
|
||||
}
|
||||
|
||||
function showRootAccountInformationModal() {
|
||||
$.get('/Home/GetRootAccountInformationModal', function (data) {
|
||||
$('#accountInformationModalContent').html(data);
|
||||
$('#accountInformationModal').modal('show');
|
||||
})
|
||||
}
|
||||
function validateAndSaveRootUserAccount() {
|
||||
var hasError = false;
|
||||
if ($('#inputUsername').val().trim() == '') {
|
||||
$('#inputUsername').addClass("is-invalid");
|
||||
hasError = true;
|
||||
} else {
|
||||
$('#inputUsername').removeClass("is-invalid");
|
||||
}
|
||||
if ($('#inputPassword').val().trim() == '') {
|
||||
$('#inputPassword').addClass("is-invalid");
|
||||
hasError = true;
|
||||
} else {
|
||||
$('#inputPassword').removeClass("is-invalid");
|
||||
}
|
||||
if (hasError) {
|
||||
errorToast("Please check the form data");
|
||||
return;
|
||||
}
|
||||
var userAccountInfo = {
|
||||
userName: $('#inputUsername').val(),
|
||||
password: $('#inputPassword').val()
|
||||
}
|
||||
$.post('/Login/CreateLoginCreds', { credentials: userAccountInfo }, function (data) {
|
||||
if (data) {
|
||||
//hide modal
|
||||
hideAccountInformationModal();
|
||||
successToast('Root Account Updated');
|
||||
performLogOut();
|
||||
} else {
|
||||
errorToast(data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function hideAccountInformationModal() {
|
||||
$('#accountInformationModal').modal('hide');
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user