Compare commits

...

106 Commits

Author SHA1 Message Date
Hargata Softworks
0707b515ab Merge pull request #525 from hargata/Hargata/sponsor.tiers
Updated Sponsors File Path
2024-05-21 15:42:58 -06:00
DESKTOP-T0O5CDB\DESK-555BD
78ae71fc46 Updated Sponsors File Path 2024-05-21 15:41:05 -06:00
Hargata Softworks
3f62cd40e7 Merge pull request #524 from hargata/Hargata/sponsor.tiers
Add Sponsor Section
2024-05-21 15:32:20 -06:00
DESKTOP-T0O5CDB\DESK-555BD
47657c0093 Added sponsor section. 2024-05-21 15:29:46 -06:00
Hargata Softworks
a5b0fde4b6 Merge pull request #522 from hargata/Hargata/swal.uncensored
Hargata/swal.uncensored
2024-05-20 12:26:10 -06:00
DESKTOP-T0O5CDB\DESK-555BD
78cc0b34b1 Updated version number 2024-05-20 12:25:07 -06:00
Hargata Softworks
e3017e986b Merge pull request #520 from hargata/Hargata/license.change
Removed commercial license restrictions from license.
2024-05-20 12:22:21 -06:00
DESKTOP-T0O5CDB\DESK-555BD
e12cd876db removed unused files 2024-05-20 12:21:54 -06:00
DESKTOP-T0O5CDB\DESK-555BD
5292e4b814 utilize uncensored version of sweet alert 2024-05-20 12:16:10 -06:00
DESKTOP-T0O5CDB\DESK-555BD
dbdd16ab89 Removed commercial license restrictions from license. 2024-05-14 08:46:47 -06:00
Hargata Softworks
ddc3c2e1b5 Merge pull request #503 from hargata/Hargata/null.mail.config
null check for mail config
2024-04-25 12:45:36 -06:00
DESKTOP-T0O5CDB\DESK-555BD
49184b287b null check for mail config 2024-04-25 12:45:21 -06:00
Hargata Softworks
f6139bda0d Merge pull request #502 from hargata/Hargata/mailkit.upgrade
fix inefficiencies
2024-04-25 11:33:14 -06:00
DESKTOP-T0O5CDB\DESK-555BD
a6471b823b fix inefficiencies 2024-04-25 11:11:54 -06:00
Hargata Softworks
7c34003647 Merge pull request #501 from hargata/Hargata/mailkit.upgrade
MailKit Upgrade
2024-04-25 10:46:53 -06:00
DESKTOP-T0O5CDB\DESK-555BD
1aa21f9980 Uprgade from .NET SMTPClient to MailKit as the default smtpclient does not support modern protocols. 2024-04-25 10:45:55 -06:00
Hargata Softworks
ce4ca50939 Merge pull request #499 from hargata/Hargata/persist.metric.bug
fix getyear method
2024-04-23 23:50:31 -06:00
DESKTOP-T0O5CDB\DESK-555BD
fb28260c4a fix getyear method 2024-04-23 23:50:06 -06:00
Hargata Softworks
626a904747 Merge pull request #498 from hargata/Hargata/persist.metric.bug
Minor bug fix
2024-04-23 23:43:18 -06:00
DESKTOP-T0O5CDB\DESK-555BD
893cdafdc5 Fixes a very minor bug where the persisted year metric blanks out when viewing a different car that doesn't have that specific year. 2024-04-23 23:42:09 -06:00
Hargata Softworks
dbfb7d7d9c Merge pull request #493 from hargata/Hargata/persist.dashboard
check against null instead of undefined,
2024-04-15 08:42:43 -06:00
DESKTOP-GENO133\IvanPlex
a66538a7db check against null instead of undefined, 2024-04-15 08:41:53 -06:00
Hargata Softworks
2f77d87d4f Merge pull request #492 from hargata/Hargata/persist.dashboard
temporarily persist dashboard metrics in sessionStorage
2024-04-15 08:25:54 -06:00
DESKTOP-GENO133\IvanPlex
de85ba984c temporarily persist dashboard metrics in sessionStorage 2024-04-15 08:20:37 -06:00
Hargata Softworks
caac1a05ae Merge pull request #480 from hargata/Hargata/fix.link.color
fix donation link colors
2024-04-12 08:04:44 -06:00
Hargata Softworks
eb5793b819 Merge pull request #490 from hargata/Hargata/fix.alt.fuel
Fix Alternate Fuel Mileage Bug
2024-04-12 08:04:28 -06:00
DESKTOP-GENO133\IvanPlex
5ef3e1e2ce updated version number 2024-04-12 08:04:04 -06:00
DESKTOP-GENO133\IvanPlex
d8b459e5ee persist regional formatting when viewing record statistics. 2024-04-12 08:01:25 -06:00
DESKTOP-GENO133\IvanPlex
7b40d58aa1 fix alternate fuel mileage auto converting to NA decimal format bug. 2024-04-12 07:54:10 -06:00
DESKTOP-T0O5CDB\DESK-555BD
809e9b838e fix donation link colors 2024-04-09 21:29:19 -06:00
Hargata Softworks
23ae36ebd9 Merge pull request #475 from hargata/Hargata/update.readme
check if function exists.
2024-04-07 21:03:31 -06:00
DESKTOP-GENO133\IvanPlex
9c3f7d20f5 fix plans not updating when deleted. 2024-04-07 21:01:06 -06:00
DESKTOP-GENO133\IvanPlex
083298303c check if function exists. 2024-04-07 20:51:55 -06:00
Hargata Softworks
224970a07e Merge pull request #474 from hargata/Hargata/update.readme
Fix the problem with time.
2024-04-07 19:15:41 -06:00
DESKTOP-GENO133\IvanPlex
86d039e5b0 Fix the problem with time. 2024-04-07 17:59:08 -06:00
Hargata Softworks
6a8038aac9 Merge pull request #473 from hargata/Hargata/update.readme
update readme
2024-04-07 13:59:02 -06:00
DESKTOP-GENO133\IvanPlex
e748f08a8e update readme 2024-04-07 13:58:32 -06:00
Hargata Softworks
3580963e9f Merge pull request #472 from hargata/Hargata/planner.improvement.part2
Improved UI UX For Planner Edit
2024-04-07 12:51:28 -06:00
DESKTOP-GENO133\IvanPlex
b008ce2ab8 Improved UI UX 2024-04-07 12:50:28 -06:00
Hargata Softworks
ea0c2c7061 Merge pull request #471 from hargata/Hargata/transl
Updated translation
2024-04-07 11:26:35 -06:00
DESKTOP-GENO133\IvanPlex
0926220933 Updated translation 2024-04-07 11:26:12 -06:00
Hargata Softworks
ca975bbdd3 Merge pull request #470 from hargata/Hargata/planner.template.edit
updated translation
2024-04-07 11:22:20 -06:00
DESKTOP-GENO133\IvanPlex
b16c5c5302 updated translation 2024-04-07 11:21:43 -06:00
Hargata Softworks
cad05fe5d9 Merge pull request #466 from hargata/Hargata/planner.improvement
Moved template modal outside of add modal.
2024-04-07 11:20:42 -06:00
Hargata Softworks
a7cd466d9c Merge pull request #469 from hargata/Hargata/planner.template.edit
Add functionality to let users edit plan record templates
2024-04-07 11:20:28 -06:00
DESKTOP-GENO133\IvanPlex
4472a67ec0 fixed label function 2024-04-07 11:19:52 -06:00
DESKTOP-GENO133\IvanPlex
c84a4029ec basic functionality to edit templates 2024-04-07 11:09:05 -06:00
DESKTOP-GENO133\IvanPlex
d7d9ab505e Add functionality to let users edit plan record templates 2024-04-07 08:31:17 -06:00
DESKTOP-GENO133\IvanPlex
c582f5f5c7 Moved template modal outside of add modal. 2024-04-05 19:36:26 -06:00
Hargata Softworks
4c30939339 Merge pull request #465 from hargata/Hargata/unused.translation.key
Updated translation file and unsaved changes label color.
2024-04-05 18:50:02 -06:00
DESKTOP-GENO133\IvanPlex
cecd6a1d2b Updated translation file and unsaved changes label color. 2024-04-05 18:48:54 -06:00
Hargata Softworks
853dcbb364 Merge pull request #464 from hargata/Hargata/unused.translation.key
removed cached translation key
2024-04-05 07:18:08 -06:00
DESKTOP-GENO133\IvanPlex
ae327ed26d removed cached translation key 2024-04-05 07:17:49 -06:00
DESKTOP-GENO133\IvanPlex
3e416aa255 Revert "removed unused translation key"
This reverts commit ab98d02106faceaca1c6c76b8f0de7bf3e28cebe.
2024-04-05 07:16:11 -06:00
DESKTOP-GENO133\IvanPlex
61c2c3fc83 removed unused translation key 2024-04-05 07:16:10 -06:00
Hargata Softworks
ca749aaf1e Merge pull request #463 from hargata/Hargata/unsaved.changes
updated cached view to only show when there are unsaved changes present.
2024-04-05 07:11:50 -06:00
DESKTOP-GENO133\IvanPlex
2a2cb3bd0c updated cached view to only show when there are unsaved changes present. 2024-04-05 07:10:09 -06:00
Hargata Softworks
44e3d19844 Merge pull request #462 from hargata/Hargata/global.search
added incremental search
2024-04-04 19:16:22 -06:00
DESKTOP-GENO133\IvanPlex
1e25fffc70 added incremental search 2024-04-04 19:14:49 -06:00
Hargata Softworks
44645ed23d Merge pull request #461 from hargata/Hargata/global.search
added global search
2024-04-04 10:48:57 -06:00
DESKTOP-GENO133\IvanPlex
fa557e5f76 added global search 2024-04-04 10:46:43 -06:00
Hargata Softworks
7202fda38e Merge pull request #458 from hargata/Hargata/cached.records
Cached Record.
2024-04-02 21:53:46 -06:00
DESKTOP-GENO133\IvanPlex
d05afe41d6 Cache the record the user was viewing if they didn't save, delete, or move it. 2024-04-02 21:51:02 -06:00
Hargata Softworks
bfc0b58728 Merge pull request #453 from hargata/Hargata/bring.back.modal
Allow users to bring back modal window they accidentally closed.
2024-04-02 07:39:25 -06:00
DESKTOP-GENO133\IvanPlex
22e8aaca81 Allow users to bring back modal window they accidentally closed. 2024-04-02 07:29:16 -06:00
Hargata Softworks
5cb1247fb2 Merge pull request #452 from hargata/Hargata/odometer.increment
Odometer Increments
2024-04-01 18:31:27 -06:00
DESKTOP-GENO133\IvanPlex
17a6d99703 Allow users to increment for last reported odometer reading when creating new records. 2024-04-01 18:25:20 -06:00
Hargata Softworks
3e7917f767 Create FUNDING.yml 2024-04-01 09:14:46 -06:00
Hargata Softworks
e9277d4dd9 Merge pull request #443 from hargata/Hargata/reminder.icons
reminders will now display urgency in icons instead of a full badge w…
2024-03-29 09:35:17 -06:00
DESKTOP-GENO133\IvanPlex
058edd8af6 reminders will now display urgency in icons instead of a full badge when viewed in small screens. 2024-03-29 08:15:55 -06:00
Hargata Softworks
8ed7dcb9ff Merge pull request #441 from hargata/Hargata/reminder.mobile
Improved Reminder page usability on mobile
2024-03-28 19:15:49 -06:00
DESKTOP-GENO133\IvanPlex
1f4827abc0 Improved Reminder page usabilty on mobile 2024-03-28 19:13:19 -06:00
Hargata Softworks
9715a0fcf7 Merge pull request #440 from hargata/Hargata/vehicle.garage.tags
Added status tags
2024-03-27 20:22:44 -06:00
DESKTOP-GENO133\IvanPlex
9bf475c352 Added status tags 2024-03-27 20:16:56 -06:00
Hargata Softworks
c2aeb4bca0 Merge pull request #438 from hargata/Hargata/garage.status
Hargata/garage.status
2024-03-27 11:41:43 -06:00
DESKTOP-GENO133\IvanPlex
07b3020999 use current mileage and date when renewing reminders. 2024-03-27 11:39:30 -06:00
DESKTOP-GENO133\IvanPlex
c2a7f39025 add depreciation calculation 2024-03-27 09:24:33 -06:00
DESKTOP-GENO133\IvanPlex
a92d422972 add purchase and sold price 2024-03-27 08:21:02 -06:00
Hargata Softworks
345eb65c3a Merge pull request #437 from hargata/Hargata/copy.supplies.attachments
Option to copy supplies attachments into records.
2024-03-26 18:33:15 -06:00
DESKTOP-GENO133\IvanPlex
a459973983 Add functionality to copy over attachments from supplies to records that are utilizing them. 2024-03-26 18:23:16 -06:00
Hargata Softworks
470dd4d78a Merge pull request #435 from hargata/Hargata/reminder.tag
Reminder Tags
2024-03-26 08:47:14 -06:00
DESKTOP-GENO133\IvanPlex
e4cb183140 improve readability on urgent reminder labels, filtering by tag now updates aggregate counts. 2024-03-26 08:40:30 -06:00
DESKTOP-GENO133\IvanPlex
6455af96bf Add tag functionality to reminders. 2024-03-26 08:11:14 -06:00
Hargata Softworks
42afa87464 Merge pull request #432 from hargata/Hargata/multiple.reminders
added translation layer
2024-03-25 06:46:59 -06:00
DESKTOP-GENO133\IvanPlex
97466eeff2 added translation layer 2024-03-25 06:45:15 -06:00
Hargata Softworks
bcbfd4ba9c Merge pull request #426 from hargata/Hargata/multiple.reminders
Select Multiple Reminders when creating new record.
2024-03-23 20:55:04 -06:00
DESKTOP-GENO133\IvanPlex
cfa052fc31 Fix styling 2024-03-23 20:52:46 -06:00
DESKTOP-GENO133\IvanPlex
3f71f6a8d8 Updated version number. 2024-03-23 20:35:41 -06:00
DESKTOP-GENO133\IvanPlex
b70e442ca3 Allow users to select multiple reminders to push back when creating new record. 2024-03-23 20:32:23 -06:00
Hargata Softworks
1f60b2aadc Merge pull request #422 from hargata/Hargata/auto.oidc
Enable auto login via OIDC
2024-03-20 14:55:14 -06:00
DESKTOP-GENO133\IvanPlex
3d2117ddaf Enable auto login via OIDC 2024-03-20 14:53:51 -06:00
Hargata Softworks
bcff18ea58 Merge pull request #421 from hargata/Hargata/extrafield.links
Add URL parser to extra fields.
2024-03-20 14:35:12 -06:00
DESKTOP-GENO133\IvanPlex
2e9821402f Add URL parser to extra fields. 2024-03-20 13:54:51 -06:00
Hargata Softworks
8914c5cd51 Merge pull request #420 from hargata/Hargata/litedb.concurrency
Hargata/litedb.concurrency
2024-03-20 13:14:24 -06:00
DESKTOP-GENO133\IvanPlex
0b240498f9 Renamed LiteDBInjection to LiteDBHelper 2024-03-20 13:13:24 -06:00
DESKTOP-GENO133\IvanPlex
16f66364cf fix backup breaking error. 2024-03-20 13:04:15 -06:00
Hargata Softworks
f2b0cec427 Merge pull request #419 from hargata/Hargata/litedb.concurrency
Added DB Checkpoint for WAL
2024-03-20 11:44:23 -06:00
DESKTOP-GENO133\IvanPlex
fac05ff5c0 Added DB Checkpoint records. 2024-03-20 11:40:55 -06:00
Hargata Softworks
1ac6dfd2a6 Merge pull request #418 from hargata/Hargata/litedb.concurrency
LiteDB Concurrency
2024-03-20 10:44:39 -06:00
DESKTOP-GENO133\IvanPlex
8bcac7344f removed unused using. 2024-03-20 10:40:53 -06:00
DESKTOP-GENO133\IvanPlex
300c986abb Replaced LiteDB's initialization with every DB call with Dependency Injection instead. 2024-03-20 10:38:32 -06:00
Hargata Softworks
91a5f92df6 Merge pull request #415 from hargata/Hargata/cleanup
Fix security vulnerability with hosted files being accessible by unau…
2024-03-18 10:10:28 -06:00
DESKTOP-GENO133\IvanPlex
d60a09d48f Fix security vulnerability with hosted files being accessible by unauthorized users.
Note that this is a retrospecitve commit to credit the user with finding the vulnerability.

Co-authored-by: Julien Stebenne <julien.stebenne@gmail.com>
2024-03-18 10:08:34 -06:00
Hargata Softworks
b22bb7c7ad Merge pull request #414 from hargata/Hargata/cleanup
Hargata/cleanup
2024-03-18 09:21:56 -06:00
DESKTOP-GENO133\IvanPlex
63cddc4ab0 fixed security vulnerability. 2024-03-18 09:18:05 -06:00
DESKTOP-GENO133\IvanPlex
790061d5c4 cleaned up unused usings. 2024-03-17 18:33:05 -06:00
102 changed files with 2231 additions and 11309 deletions

14
.github/FUNDING.yml vendored Normal file
View 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
View File

@@ -11,3 +11,4 @@ wwwroot/translations/
config/userConfig.json
CarCareTracker.csproj.user
Properties/launchSettings.json
data/cartracker-log.db

View File

@@ -13,6 +13,7 @@
<ItemGroup>
<PackageReference Include="CsvHelper" Version="30.0.1" />
<PackageReference Include="LiteDB" Version="5.0.17" />
<PackageReference Include="MailKit" Version="4.5.0" />
<PackageReference Include="Npgsql" Version="8.0.2" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" />
</ItemGroup>

View File

@@ -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;
}
}
}

View File

@@ -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]

View File

@@ -29,6 +29,18 @@ namespace CarCareTracker.Controllers
}
public IActionResult Index(string redirectURL = "")
{
var remoteAuthConfig = _config.GetOpenIDConfig();
if (remoteAuthConfig.DisableRegularLogin && !string.IsNullOrWhiteSpace(remoteAuthConfig.LogOutURL))
{
var generatedState = Guid.NewGuid().ToString().Substring(0, 8);
remoteAuthConfig.State = generatedState;
if (remoteAuthConfig.ValidateState)
{
Response.Cookies.Append("OIDC_STATE", remoteAuthConfig.State, new CookieOptions { Expires = new DateTimeOffset(DateTime.Now.AddMinutes(5)) });
}
var remoteAuthURL = remoteAuthConfig.RemoteAuthURL;
return Redirect(remoteAuthURL);
}
return View(model: redirectURL);
}
public IActionResult Registration()
@@ -248,7 +260,12 @@ namespace CarCareTracker.Controllers
public IActionResult LogOut()
{
Response.Cookies.Delete("ACCESS_TOKEN");
return Json(true);
var remoteAuthConfig = _config.GetOpenIDConfig();
if (remoteAuthConfig.DisableRegularLogin && !string.IsNullOrWhiteSpace(remoteAuthConfig.LogOutURL))
{
return Json(remoteAuthConfig.LogOutURL);
}
return Json("/Login");
}
}
}

View File

@@ -1,6 +1,5 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using LiteDB;
using Microsoft.AspNetCore.Mvc;
using CarCareTracker.Helper;
using CsvHelper;
@@ -10,6 +9,7 @@ using CarCareTracker.MapProfile;
using System.Security.Claims;
using CarCareTracker.Logic;
using CarCareTracker.Filter;
using System.Text.Json;
namespace CarCareTracker.Controllers
{
@@ -37,6 +37,7 @@ namespace CarCareTracker.Controllers
private readonly IReportHelper _reportHelper;
private readonly IUserLogic _userLogic;
private readonly IOdometerLogic _odometerLogic;
private readonly IVehicleLogic _vehicleLogic;
private readonly IExtraFieldDataAccess _extraFieldDataAccess;
public VehicleController(ILogger<VehicleController> logger,
@@ -59,6 +60,7 @@ namespace CarCareTracker.Controllers
IExtraFieldDataAccess extraFieldDataAccess,
IUserLogic userLogic,
IOdometerLogic odometerLogic,
IVehicleLogic vehicleLogic,
IWebHostEnvironment webEnv,
IConfigHelper config)
{
@@ -82,6 +84,7 @@ namespace CarCareTracker.Controllers
_extraFieldDataAccess = extraFieldDataAccess;
_userLogic = userLogic;
_odometerLogic = odometerLogic;
_vehicleLogic = vehicleLogic;
_webEnv = webEnv;
_config = config;
}
@@ -823,11 +826,18 @@ namespace CarCareTracker.Controllers
if (serviceRecord.Supplies.Any())
{
serviceRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(serviceRecord.Supplies, DateTime.Parse(serviceRecord.Date), serviceRecord.Description);
if (serviceRecord.CopySuppliesAttachment)
{
serviceRecord.Files.AddRange(GetSuppliesAttachments(serviceRecord.Supplies));
}
}
//push back any reminders
if (serviceRecord.ReminderRecordId != default)
if (serviceRecord.ReminderRecordId.Any())
{
PushbackRecurringReminderRecordWithChecks(serviceRecord.ReminderRecordId);
foreach(int reminderRecordId in serviceRecord.ReminderRecordId)
{
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(serviceRecord.Date), serviceRecord.Mileage);
}
}
var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord());
if (result)
@@ -908,11 +918,18 @@ namespace CarCareTracker.Controllers
if (collisionRecord.Supplies.Any())
{
collisionRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(collisionRecord.Supplies, DateTime.Parse(collisionRecord.Date), collisionRecord.Description);
if (collisionRecord.CopySuppliesAttachment)
{
collisionRecord.Files.AddRange(GetSuppliesAttachments(collisionRecord.Supplies));
}
}
//push back any reminders
if (collisionRecord.ReminderRecordId != default)
if (collisionRecord.ReminderRecordId.Any())
{
PushbackRecurringReminderRecordWithChecks(collisionRecord.ReminderRecordId);
foreach (int reminderRecordId in collisionRecord.ReminderRecordId)
{
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(collisionRecord.Date), collisionRecord.Mileage);
}
}
var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord());
if (result)
@@ -1021,9 +1038,12 @@ namespace CarCareTracker.Controllers
//move files from temp.
taxRecord.Files = taxRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
//push back any reminders
if (taxRecord.ReminderRecordId != default)
if (taxRecord.ReminderRecordId.Any())
{
PushbackRecurringReminderRecordWithChecks(taxRecord.ReminderRecordId);
foreach (int reminderRecordId in taxRecord.ReminderRecordId)
{
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(taxRecord.Date), null);
}
}
var result = _taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord.ToTaxRecord());
if (result)
@@ -1133,6 +1153,10 @@ namespace CarCareTracker.Controllers
{
numbersArray.Add(upgradeRecords.Min(x => x.Date.Year));
}
if (odometerRecords.Any())
{
numbersArray.Add(odometerRecords.Min(x => x.Date.Year));
}
var minYear = numbersArray.Any() ? numbersArray.Min() : DateTime.Now.AddYears(-5).Year;
var yearDifference = DateTime.Now.Year - minYear + 1;
for (int i = 0; i < yearDifference; i++)
@@ -1313,26 +1337,43 @@ namespace CarCareTracker.Controllers
{
var vehicleHistory = new VehicleHistoryViewModel();
vehicleHistory.VehicleData = _dataAccess.GetVehicleById(vehicleId);
var maxMileage = GetMaxMileage(vehicleId);
var maxMileage = _vehicleLogic.GetMaxMileage(vehicleId);
vehicleHistory.Odometer = maxMileage.ToString("N0");
var minMileage = GetMinMileage(vehicleId);
var minMileage = _vehicleLogic.GetMinMileage(vehicleId);
var distanceTraveled = maxMileage - minMileage;
if (!string.IsNullOrWhiteSpace(vehicleHistory.VehicleData.PurchaseDate))
{
var endDate = vehicleHistory.VehicleData.SoldDate;
int daysOwned = 0;
if (string.IsNullOrWhiteSpace(endDate))
{
endDate = DateTime.Now.ToShortDateString();
}
try
{
vehicleHistory.DaysOwned = (DateTime.Parse(endDate) - DateTime.Parse(vehicleHistory.VehicleData.PurchaseDate)).Days.ToString("N0");
daysOwned = (DateTime.Parse(endDate) - DateTime.Parse(vehicleHistory.VehicleData.PurchaseDate)).Days;
vehicleHistory.DaysOwned = daysOwned.ToString("N0");
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
vehicleHistory.DaysOwned = string.Empty;
}
//calculate depreciation
var totalDepreciation = vehicleHistory.VehicleData.PurchasePrice - vehicleHistory.VehicleData.SoldPrice;
//we only calculate depreciation if a sold price is provided.
if (totalDepreciation != default && vehicleHistory.VehicleData.SoldPrice != default)
{
vehicleHistory.TotalDepreciation = totalDepreciation;
if (daysOwned != default)
{
vehicleHistory.DepreciationPerDay = Math.Abs(totalDepreciation / daysOwned);
}
if (distanceTraveled != default)
{
vehicleHistory.DepreciationPerMile = Math.Abs(totalDepreciation / distanceTraveled);
}
}
}
List<GenericReportModel> reportData = new List<GenericReportModel>();
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
@@ -1483,78 +1524,14 @@ namespace CarCareTracker.Controllers
}
#endregion
#region "Reminders"
[TypeFilter(typeof(CollaboratorFilter))]
private int GetMaxMileage(int vehicleId)
{
var numbersArray = new List<int>();
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
if (serviceRecords.Any())
{
numbersArray.Add(serviceRecords.Max(x => x.Mileage));
}
var repairRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
if (repairRecords.Any())
{
numbersArray.Add(repairRecords.Max(x => x.Mileage));
}
var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
if (gasRecords.Any())
{
numbersArray.Add(gasRecords.Max(x => x.Mileage));
}
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
if (upgradeRecords.Any())
{
numbersArray.Add(upgradeRecords.Max(x => x.Mileage));
}
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
if (odometerRecords.Any())
{
numbersArray.Add(odometerRecords.Max(x => x.Mileage));
}
return numbersArray.Any() ? numbersArray.Max() : 0;
}
[TypeFilter(typeof(CollaboratorFilter))]
private int GetMinMileage(int vehicleId)
{
var numbersArray = new List<int>();
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
if (serviceRecords.Any())
{
numbersArray.Add(serviceRecords.Min(x => x.Mileage));
}
var repairRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
if (repairRecords.Any())
{
numbersArray.Add(repairRecords.Min(x => x.Mileage));
}
var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
if (gasRecords.Any())
{
numbersArray.Add(gasRecords.Min(x => x.Mileage));
}
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
if (upgradeRecords.Any())
{
numbersArray.Add(upgradeRecords.Min(x => x.Mileage));
}
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId).Where(x => x.Mileage != default);
if (odometerRecords.Any())
{
numbersArray.Add(odometerRecords.Min(x => x.Mileage));
}
return numbersArray.Any() ? numbersArray.Min() : 0;
}
private List<ReminderRecordViewModel> GetRemindersAndUrgency(int vehicleId, DateTime dateCompare)
{
var currentMileage = GetMaxMileage(vehicleId);
var currentMileage = _vehicleLogic.GetMaxMileage(vehicleId);
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
List<ReminderRecordViewModel> results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, dateCompare);
return results;
}
[TypeFilter(typeof(CollaboratorFilter))]
[HttpGet]
public IActionResult GetVehicleHaveUrgentOrPastDueReminders(int vehicleId)
private bool GetAndUpdateVehicleUrgentOrPastDueReminders(int vehicleId)
{
var result = GetRemindersAndUrgency(vehicleId, DateTime.Now);
//check if user wants auto-refresh past-due reminders
@@ -1569,7 +1546,7 @@ namespace CarCareTracker.Controllers
//update based on recurring intervals.
//pull reminderRecord based on ID
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecord.Id);
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder);
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder, null, null);
//save to db.
_reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
//set urgency to not urgent so it gets excluded in count.
@@ -1581,9 +1558,16 @@ namespace CarCareTracker.Controllers
var pastDueAndUrgentReminders = result.Where(x => x.Urgency == ReminderUrgency.VeryUrgent || x.Urgency == ReminderUrgency.PastDue);
if (pastDueAndUrgentReminders.Any())
{
return Json(true);
return true;
}
return Json(false);
return false;
}
[TypeFilter(typeof(CollaboratorFilter))]
[HttpGet]
public IActionResult GetVehicleHaveUrgentOrPastDueReminders(int vehicleId)
{
var result = GetAndUpdateVehicleUrgentOrPastDueReminders(vehicleId);
return Json(result);
}
[TypeFilter(typeof(CollaboratorFilter))]
[HttpGet]
@@ -1603,17 +1587,17 @@ namespace CarCareTracker.Controllers
[HttpPost]
public IActionResult PushbackRecurringReminderRecord(int reminderRecordId)
{
var result = PushbackRecurringReminderRecordWithChecks(reminderRecordId);
var result = PushbackRecurringReminderRecordWithChecks(reminderRecordId, null, null);
return Json(result);
}
private bool PushbackRecurringReminderRecordWithChecks(int reminderRecordId)
private bool PushbackRecurringReminderRecordWithChecks(int reminderRecordId, DateTime? currentDate, int? currentMileage)
{
try
{
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecordId);
if (existingReminder is not null && existingReminder.Id != default && existingReminder.IsRecurring)
{
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder);
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder, currentDate, currentMileage);
//save to db.
var reminderUpdateResult = _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
if (!reminderUpdateResult)
@@ -1675,7 +1659,8 @@ namespace CarCareTracker.Controllers
ReminderMileageInterval = result.ReminderMileageInterval,
ReminderMonthInterval = result.ReminderMonthInterval,
CustomMileageInterval = result.CustomMileageInterval,
CustomMonthInterval = result.CustomMonthInterval
CustomMonthInterval = result.CustomMonthInterval,
Tags = result.Tags
};
return PartialView("_ReminderRecordModal", convertedResult);
}
@@ -1725,11 +1710,18 @@ namespace CarCareTracker.Controllers
if (upgradeRecord.Supplies.Any())
{
upgradeRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(upgradeRecord.Supplies, DateTime.Parse(upgradeRecord.Date), upgradeRecord.Description);
if (upgradeRecord.CopySuppliesAttachment)
{
upgradeRecord.Files.AddRange(GetSuppliesAttachments(upgradeRecord.Supplies));
}
}
//push back any reminders
if (upgradeRecord.ReminderRecordId != default)
if (upgradeRecord.ReminderRecordId.Any())
{
PushbackRecurringReminderRecordWithChecks(upgradeRecord.ReminderRecordId);
foreach (int reminderRecordId in upgradeRecord.ReminderRecordId)
{
PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(upgradeRecord.Date), upgradeRecord.Mileage);
}
}
var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord.ToUpgradeRecord());
if (result)
@@ -1863,6 +1855,16 @@ namespace CarCareTracker.Controllers
}
return result;
}
private List<UploadedFiles> GetSuppliesAttachments(List<SupplyUsage> supplyUsage)
{
List<UploadedFiles> results = new List<UploadedFiles>();
foreach(SupplyUsage supply in supplyUsage)
{
var result = _supplyRecordDataAccess.GetSupplyRecordById(supply.SupplyId);
results.AddRange(result.Files);
}
return results;
}
private List<SupplyUsageHistory> RequisitionSupplyRecordsByUsage(List<SupplyUsage> supplyUsage, DateTime dateRequisitioned, string usageDescription)
{
List<SupplyUsageHistory> results = new List<SupplyUsageHistory>();
@@ -1915,6 +1917,33 @@ namespace CarCareTracker.Controllers
}
return PartialView("_SupplyRecords", result);
}
[HttpGet]
public IActionResult GetSupplyRecordsForPlanRecordTemplate(int planRecordTemplateId)
{
var viewModel = new SupplyUsageViewModel();
var planRecordTemplate = _planRecordTemplateDataAccess.GetPlanRecordTemplateById(planRecordTemplateId);
if (planRecordTemplate != default && planRecordTemplate.VehicleId != default)
{
var supplies = _supplyRecordDataAccess.GetSupplyRecordsByVehicleId(planRecordTemplate.VehicleId);
if (_config.GetServerEnableShopSupplies())
{
supplies.AddRange(_supplyRecordDataAccess.GetSupplyRecordsByVehicleId(0)); // add shop supplies
}
supplies.RemoveAll(x => x.Quantity <= 0);
bool _useDescending = _config.GetUserConfig(User).UseDescending;
if (_useDescending)
{
supplies = supplies.OrderByDescending(x => x.Date).ToList();
}
else
{
supplies = supplies.OrderBy(x => x.Date).ToList();
}
viewModel.Supplies = supplies;
viewModel.Usage = planRecordTemplate.Supplies;
}
return PartialView("_SupplyUsage", viewModel);
}
[TypeFilter(typeof(CollaboratorFilter))]
[HttpGet]
public IActionResult GetSupplyRecordsForRecordsByVehicleId(int vehicleId)
@@ -1934,7 +1963,11 @@ namespace CarCareTracker.Controllers
{
result = result.OrderBy(x => x.Date).ToList();
}
return PartialView("_SupplyUsage", result);
var viewModel = new SupplyUsageViewModel
{
Supplies = result
};
return PartialView("_SupplyUsage", viewModel);
}
[HttpPost]
public IActionResult SaveSupplyRecordToVehicleId(SupplyRecordInput supplyRecord)
@@ -2009,6 +2042,10 @@ namespace CarCareTracker.Controllers
if (planRecord.Supplies.Any())
{
planRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(planRecord.Supplies, DateTime.Parse(planRecord.DateCreated), planRecord.Description);
if (planRecord.CopySuppliesAttachment)
{
planRecord.Files.AddRange(GetSuppliesAttachments(planRecord.Supplies));
}
}
var result = _planRecordDataAccess.SavePlanRecordToVehicle(planRecord.ToPlanRecord());
if (result)
@@ -2022,7 +2059,7 @@ namespace CarCareTracker.Controllers
{
//check if template name already taken.
var existingRecord = _planRecordTemplateDataAccess.GetPlanRecordTemplatesByVehicleId(planRecord.VehicleId).Where(x => x.Description == planRecord.Description).Any();
if (existingRecord)
if (planRecord.Id == default && existingRecord)
{
return Json(new OperationResponse { Success = false, Message = "A template with that description already exists for this vehicle" });
}
@@ -2076,6 +2113,10 @@ namespace CarCareTracker.Controllers
if (existingRecord.Supplies.Any())
{
existingRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(existingRecord.Supplies, DateTime.Parse(existingRecord.DateCreated), existingRecord.Description);
if (existingRecord.CopySuppliesAttachment)
{
existingRecord.Files.AddRange(GetSuppliesAttachments(existingRecord.Supplies));
}
}
var result = _planRecordDataAccess.SavePlanRecordToVehicle(existingRecord.ToPlanRecord());
return Json(new OperationResponse { Success = result, Message = result ? "Plan Record Added" : StaticHelper.GenericErrorMessage });
@@ -2108,7 +2149,7 @@ namespace CarCareTracker.Controllers
{
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
{
Date = DateTime.Now,
Date = DateTime.Now.Date,
VehicleId = existingRecord.VehicleId,
Mileage = odometer,
Notes = $"Auto Insert From Plan Record: {existingRecord.Description}",
@@ -2121,7 +2162,7 @@ namespace CarCareTracker.Controllers
var newRecord = new ServiceRecord()
{
VehicleId = existingRecord.VehicleId,
Date = DateTime.Now,
Date = DateTime.Now.Date,
Mileage = odometer,
Description = existingRecord.Description,
Cost = existingRecord.Cost,
@@ -2137,7 +2178,7 @@ namespace CarCareTracker.Controllers
var newRecord = new CollisionRecord()
{
VehicleId = existingRecord.VehicleId,
Date = DateTime.Now,
Date = DateTime.Now.Date,
Mileage = odometer,
Description = existingRecord.Description,
Cost = existingRecord.Cost,
@@ -2153,7 +2194,7 @@ namespace CarCareTracker.Controllers
var newRecord = new UpgradeRecord()
{
VehicleId = existingRecord.VehicleId,
Date = DateTime.Now,
Date = DateTime.Now.Date,
Mileage = odometer,
Description = existingRecord.Description,
Cost = existingRecord.Cost,
@@ -2167,12 +2208,18 @@ namespace CarCareTracker.Controllers
//push back any reminders
if (existingRecord.ReminderRecordId != default)
{
PushbackRecurringReminderRecordWithChecks(existingRecord.ReminderRecordId);
PushbackRecurringReminderRecordWithChecks(existingRecord.ReminderRecordId, DateTime.Now, odometer);
}
}
return Json(result);
}
[HttpGet]
public IActionResult GetPlanRecordTemplateForEditById(int planRecordTemplateId)
{
var result = _planRecordTemplateDataAccess.GetPlanRecordTemplateById(planRecordTemplateId);
return PartialView("_PlanRecordTemplateEditModal", result);
}
[HttpGet]
public IActionResult GetPlanRecordForEditById(int planRecordId)
{
var result = _planRecordDataAccess.GetPlanRecordById(planRecordId);
@@ -2335,6 +2382,89 @@ namespace CarCareTracker.Controllers
}
#endregion
#region "Shared Methods"
[HttpPost]
[TypeFilter(typeof(CollaboratorFilter))]
public IActionResult SearchRecords(int vehicleId, string searchQuery)
{
List<SearchResult> searchResults = new List<SearchResult>();
if (string.IsNullOrWhiteSpace(searchQuery))
{
return Json(searchResults);
}
foreach(ImportMode visibleTab in _config.GetUserConfig(User).VisibleTabs)
{
switch (visibleTab)
{
case ImportMode.ServiceRecord:
{
var results = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.ServiceRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
}
break;
case ImportMode.RepairRecord:
{
var results = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.RepairRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
}
break;
case ImportMode.UpgradeRecord:
{
var results = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.UpgradeRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
}
break;
case ImportMode.TaxRecord:
{
var results = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.TaxRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
}
break;
case ImportMode.SupplyRecord:
{
var results = _supplyRecordDataAccess.GetSupplyRecordsByVehicleId(vehicleId);
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.SupplyRecord, Description = $"{x.Date.ToShortDateString()} - {x.Description}" }));
}
break;
case ImportMode.PlanRecord:
{
var results = _planRecordDataAccess.GetPlanRecordsByVehicleId(vehicleId);
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.PlanRecord, Description = $"{x.DateCreated.ToShortDateString()} - {x.Description}" }));
}
break;
case ImportMode.OdometerRecord:
{
var results = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.OdometerRecord, Description = $"{x.Date.ToShortDateString()} - {x.Mileage}" }));
}
break;
case ImportMode.GasRecord:
{
var results = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.GasRecord, Description = $"{x.Date.ToShortDateString()} - {x.Mileage}" }));
}
break;
case ImportMode.NoteRecord:
{
var results = _noteDataAccess.GetNotesByVehicleId(vehicleId);
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.NoteRecord, Description = $"{x.Description}" }));
}
break;
case ImportMode.ReminderRecord:
{
var results = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
searchResults.AddRange(results.Where(x => JsonSerializer.Serialize(x).Contains(searchQuery)).Select(x => new SearchResult { Id = x.Id, RecordType = ImportMode.ReminderRecord, Description = $"{x.Description}" }));
}
break;
}
}
return PartialView("_GlobalSearchResult", searchResults);
}
[TypeFilter(typeof(CollaboratorFilter))]
public IActionResult GetMaxMileage(int vehicleId)
{
var result = _vehicleLogic.GetMaxMileage(vehicleId);
return Json(result);
}
public IActionResult MoveRecord(int recordId, ImportMode source, ImportMode destination)
{
var genericRecord = new GenericRecord();

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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
View 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;
}
}
}

View File

@@ -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,44 @@ 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());
}
else
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);
client.Authenticate(mailConfig.Username, mailConfig.Password);
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;
}
}
}

View File

@@ -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)
{

View File

@@ -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.3";
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";
}
}
}
}

View File

@@ -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
View 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);
}
}
}

View File

@@ -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,

View File

@@ -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}"; } }
}
}

View File

@@ -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,

View File

@@ -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>();
}
}

View File

@@ -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
};
}
}

View File

@@ -17,5 +17,6 @@
/// Recurring Reminders
/// </summary>
public bool IsRecurring { get; set; } = false;
public List<string> Tags { get; set; } = new List<string>();
}
}

View File

@@ -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
View 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; }
}
}

View File

@@ -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,

View File

@@ -4,5 +4,6 @@ namespace CarCareTracker.Models
{
public UserConfig UserConfig { get; set; }
public List<string> UILanguages { get; set; }
public Sponsors Sponsors { get; set; } = new Sponsors();
}
}

10
Models/Sponsors.cs Normal file
View 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>();
}
}

View 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>();
}
}

View File

@@ -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; }

View File

@@ -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,

View File

@@ -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>();

View 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;
}
}

View File

@@ -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();

View File

@@ -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)

View File

@@ -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>

View File

@@ -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">

View 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>

View File

@@ -8,7 +8,7 @@
var userLanguage = userConfig.UserLanguage;
}
<div class="modal-header">
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Repair Record") : translator.Translate(userLanguage,"Edit Repair Record"))</h5>
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Repair Record") : translator.Translate(userLanguage, "Edit Repair Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditCollisionRecordModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
<button type="button" class="btn-close" onclick="hideAddCollisionRecordModal()" aria-label="Close"></button>
</div>
<div class="modal-body">
@@ -17,14 +17,22 @@
<div class="row">
<div class="col-md-6 col-12">
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
<label for="collisionRecordDate">@translator.Translate(userLanguage,"Date")</label>
<label for="collisionRecordDate">@translator.Translate(userLanguage, "Date")</label>
<div class="input-group">
<input type="text" id="collisionRecordDate" class="form-control" placeholder="@translator.Translate(userLanguage,"Date repair was performed")" value="@Model.Date">
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
</div>
<label for="collisionRecordMileage">@translator.Translate(userLanguage,"Odometer")</label>
<input type="number" inputmode="numeric" id="collisionRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when repaired")" value="@(isNew ? "" : Model.Mileage)">
<label for="collisionRecordDescription">@translator.Translate(userLanguage,"Description")</label>
<label for="collisionRecordMileage">@translator.Translate(userLanguage, "Odometer")</label>
<div class="input-group">
<input type="number" inputmode="numeric" id="collisionRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when repaired")" value="@(isNew ? "" : Model.Mileage)">
@if (isNew)
{
<div class="input-group-text">
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('collisionRecordMileage')">+</button>
</div>
}
</div>
<label for="collisionRecordDescription">@translator.Translate(userLanguage, "Description")</label>
<input type="text" id="collisionRecordDescription" class="form-control" placeholder="@translator.Translate(userLanguage,"Description of item(s) repaired(i.e. Alternator)")" value="@Model.Description">
@if (isNew)
{
@@ -34,13 +42,13 @@
</div>
</div>
}
<label for="collisionRecordCost">@translator.Translate(userLanguage,"Cost")</label>
<label for="collisionRecordCost">@translator.Translate(userLanguage, "Cost")</label>
<input type="text" inputmode="decimal" id="collisionRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"Cost of the repair")" value="@(isNew ? "" : Model.Cost)">
@if (isNew)
{
@await Html.PartialAsync("_SupplyStore", "RepairRecord")
}
<label for="collisionRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
<label for="collisionRecordTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
<select multiple class="form-select" id="collisionRecordTag">
@foreach (string tag in Model.Tags)
{
@@ -57,15 +65,15 @@
}
</div>
<div class="col-md-6 col-12">
<label for="collisionRecordNotes">@translator.Translate(userLanguage,"Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
<label for="collisionRecordNotes">@translator.Translate(userLanguage, "Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
<textarea id="collisionRecordNotes" class="form-control" rows="5">@Model.Notes</textarea>
@if (Model.Files.Any())
{
<div>
@await Html.PartialAsync("_UploadedFiles", Model.Files)
<label for="collisionRecordFiles">@translator.Translate(userLanguage,"Upload more documents")</label>
<label for="collisionRecordFiles">@translator.Translate(userLanguage, "Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="collisionRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
<br /><small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
</div>
}
else
@@ -75,13 +83,15 @@
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="addReminderCheck">
<label class="form-check-label" for="addReminderCheck">
@translator.Translate(userLanguage,"Add Reminder")
@translator.Translate(userLanguage, "Add Reminder")
</label>
</div>
}
<label for="collisionRecordFiles">@translator.Translate(userLanguage,"Upload documents(optional)")</label>
<label for="collisionRecordFiles">@translator.Translate(userLanguage, "Upload documents(optional)")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="collisionRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
<br />
<small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
}
</div>
</div>
@@ -96,39 +106,40 @@
<button type="button" class="btn btn-warning" onclick="toggleSupplyUsageHistory()"><i class="bi bi-shop"></i></button>
}
<div class="btn-group" style="margin-right:auto;">
<button type="button" class="btn btn-md mt-1 mb-1 btn-danger" onclick="deleteCollisionRecord(@Model.Id)">@translator.Translate(userLanguage,"Delete")</button>
<button type="button" class="btn btn-md mt-1 mb-1 btn-danger" onclick="deleteCollisionRecord(@Model.Id)">@translator.Translate(userLanguage, "Delete")</button>
<button type="button" class="btn btn-md btn-danger btn-md mt-1 mb-1 dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li><h6 class="dropdown-header">@translator.Translate(userLanguage,"Move To")</h6></li>
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'RepairRecord', 'ServiceRecord')">@translator.Translate(userLanguage,"Service Records")</a></li>
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'RepairRecord', 'UpgradeRecord')">@translator.Translate(userLanguage,"Upgrades")</a></li>
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Move To")</h6></li>
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'RepairRecord', 'ServiceRecord')">@translator.Translate(userLanguage, "Service Records")</a></li>
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'RepairRecord', 'UpgradeRecord')">@translator.Translate(userLanguage, "Upgrades")</a></li>
</ul>
</div>
}
<button type="button" class="btn btn-secondary" onclick="hideAddCollisionRecordModal()">@translator.Translate(userLanguage,"Cancel")</button>
<button type="button" class="btn btn-secondary" onclick="hideAddCollisionRecordModal()">@translator.Translate(userLanguage, "Cancel")</button>
@if (isNew)
{
<button type="button" class="btn btn-primary" onclick="saveCollisionRecordToVehicle()">@translator.Translate(userLanguage,"Add New Repair Record")</button>
<button type="button" class="btn btn-primary" onclick="saveCollisionRecordToVehicle()">@translator.Translate(userLanguage, "Add New Repair Record")</button>
}
else if (!isNew)
{
<button type="button" class="btn btn-primary" onclick="saveCollisionRecordToVehicle(true)">@translator.Translate(userLanguage,"Edit Repair Record")</button>
<button type="button" class="btn btn-primary" onclick="saveCollisionRecordToVehicle(true)">@translator.Translate(userLanguage, "Edit Repair Record")</button>
}
</div>
@await Html.PartialAsync("_SupplyRequisitionHistory", Model.RequisitionHistory)
<script>
var uploadedFiles = [];
var selectedSupplies = [];
var recurringReminderRecordId = 0;
var copySuppliesAttachments = false;
var recurringReminderRecordId = [];
getUploadedFilesFromModel();
function getUploadedFilesFromModel() {
@foreach (UploadedFiles filesUploaded in Model.Files)
{
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
}
}
}
function getCollisionRecordModelData() {
return { id: @Model.Id}
}

View File

@@ -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>
}

View File

@@ -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>
}

View File

@@ -37,7 +37,7 @@
}
}
<div class="modal-header">
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Gas Record") : translator.Translate(userLanguage,"Edit Gas Record"))</h5>
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Gas Record") : translator.Translate(userLanguage, "Edit Gas Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditGasRecordModal({Model.GasRecord.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
<button type="button" class="btn-close" onclick="hideAddGasRecordModal()" aria-label="Close"></button>
</div>
<div class="modal-body">
@@ -52,7 +52,15 @@
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
</div>
<label for="gasRecordMileage">@($"{translator.Translate(userLanguage,"Odometer Reading")}({distanceUnit})")</label>
<input type="number" inputmode="numeric" id="gasRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when refueled")" value="@(isNew ? "" : Model.GasRecord.Mileage)">
<div class="input-group">
<input type="number" inputmode="numeric" id="gasRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when refueled")" value="@(isNew ? "" : Model.GasRecord.Mileage)">
@if (isNew)
{
<div class="input-group-text">
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('gasRecordMileage')">+</button>
</div>
}
</div>
<label for="gasRecordGallons">@($"{translator.Translate(userLanguage, "Fuel Consumption")}({consumptionUnit})")</label>
<input type="text" inputmode="decimal" id="gasRecordGallons" class="form-control" placeholder="@translator.Translate(userLanguage,"Amount of gas refueled")" value="@(isNew ? "" : Model.GasRecord.Gallons)">
<div class="form-check form-switch">

View 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>

View File

@@ -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">

View File

@@ -8,7 +8,7 @@
var userLanguage = userConfig.UserLanguage;
}
<div class="modal-header">
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Odometer Record") : translator.Translate(userLanguage,"Edit Odometer Record"))</h5>
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Odometer Record") : translator.Translate(userLanguage, "Edit Odometer Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditOdometerRecordModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
<button type="button" class="btn-close" onclick="hideAddOdometerRecordModal()" aria-label="Close"></button>
</div>
<div class="modal-body">
@@ -25,7 +25,15 @@
<label for="initialOdometerRecordMileage">@translator.Translate(userLanguage, "Initial Odometer")</label>
<input type="number" inputmode="numeric" id="initialOdometerRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Initial Odometer reading")" value="@(Model.InitialMileage)">
<label for="odometerRecordMileage">@translator.Translate(userLanguage,"Odometer")</label>
<input type="number" inputmode="numeric" id="odometerRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading")" value="@(isNew ? "" : Model.Mileage)">
<div class="input-group">
<input type="number" inputmode="numeric" id="odometerRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading")" value="@(isNew ? "" : Model.Mileage)">
@if (isNew)
{
<div class="input-group-text">
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('odometerRecordMileage')">+</button>
</div>
}
</div>
<label for="odometerRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
<select multiple class="form-select" id="odometerRecordTag">
@foreach (string tag in Model.Tags)

View File

@@ -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>
}

View File

@@ -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">

View File

@@ -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>

View 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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -34,14 +34,25 @@
</div>
<div class="input-group">
<input type="number" inputmode="numeric" id="reminderMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Future Odometer Reading")" value="@(isNew ? "" : Model.Mileage)">
<div class="input-group-text">
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="appendMileageToOdometer(500)">+500</button>
</div>
@if (isNew)
{
<div class="input-group-text">
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('reminderMileage')">+</button>
</div>
}
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="reminderMetricOptions" id="reminderMetricBoth" value="@(ReminderMetric.Both)" checked="@(Model.Metric == ReminderMetric.Both)">
<label class="form-check-label" for="reminderMetricBoth">@translator.Translate(userLanguage,"Whichever comes first")</label>
</div>
<div class="d-grid"></div>
<label for="reminderRecordTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
<select multiple class="form-select" id="reminderRecordTag">
@foreach (string tag in Model.Tags)
{
<!option value="@tag">@tag</!option>
}
</select>
</div>
<div class="col-md-6 col-12">
<label for="reminderNotes">@translator.Translate(userLanguage,"Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>

View File

@@ -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>

View File

@@ -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>

View File

@@ -8,7 +8,7 @@
var userLanguage = userConfig.UserLanguage;
}
<div class="modal-header">
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Service Record") : translator.Translate(userLanguage,"Edit Service Record"))</h5>
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Service Record") : translator.Translate(userLanguage, "Edit Service Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditServiceRecordModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
<button type="button" class="btn-close" onclick="hideAddServiceRecordModal()" aria-label="Close"></button>
</div>
<div class="modal-body">
@@ -22,8 +22,16 @@
<input type="text" id="serviceRecordDate" class="form-control" placeholder="@translator.Translate(userLanguage,"Date service was performed")" value="@Model.Date">
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
</div>
<label for="serviceRecordMileage">@translator.Translate(userLanguage,"Odometer")</label>
<input type="number" inputmode="numeric" id="serviceRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when serviced")" value="@(isNew ? "" : Model.Mileage)">
<label for="serviceRecordMileage">@translator.Translate(userLanguage, "Odometer")</label>
<div class="input-group">
<input type="number" inputmode="numeric" id="serviceRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when serviced")" value="@(isNew ? "" : Model.Mileage)">
@if (isNew)
{
<div class="input-group-text">
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('serviceRecordMileage')">+</button>
</div>
}
</div>
<label for="serviceRecordDescription">@translator.Translate(userLanguage,"Description")</label>
<input type="text" id="serviceRecordDescription" class="form-control" placeholder="@translator.Translate(userLanguage,"Description of item(s) serviced(i.e. Oil Change)")" value="@Model.Description">
@if (isNew)
@@ -121,7 +129,8 @@
<script>
var uploadedFiles = [];
var selectedSupplies = [];
var recurringReminderRecordId = 0;
var recurringReminderRecordId = [];
var copySuppliesAttachments = false;
getUploadedFilesFromModel();
function getUploadedFilesFromModel() {
@foreach (UploadedFiles filesUploaded in Model.Files)

View File

@@ -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>
}

View File

@@ -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">

View File

@@ -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>
}

View File

@@ -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');

View File

@@ -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>

View File

@@ -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)

View File

@@ -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>
}

View File

@@ -8,7 +8,7 @@
var userLanguage = userConfig.UserLanguage;
}
<div class="modal-header">
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage,"Add New Upgrade Record") : translator.Translate(userLanguage,"Edit Upgrade Record"))</h5>
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Upgrade Record") : translator.Translate(userLanguage, "Edit Upgrade Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditUpgradeRecordModal({Model.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
<button type="button" class="btn-close" onclick="hideAddUpgradeRecordModal()" aria-label="Close"></button>
</div>
<div class="modal-body">
@@ -17,14 +17,22 @@
<div class="row">
<div class="col-md-6 col-12">
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
<label for="upgradeRecordDate">@translator.Translate(userLanguage,"Date")</label>
<label for="upgradeRecordDate">@translator.Translate(userLanguage, "Date")</label>
<div class="input-group">
<input type="text" id="upgradeRecordDate" class="form-control" placeholder="@translator.Translate(userLanguage,"Date upgrade/mods was installed")" value="@Model.Date">
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
</div>
<label for="upgradeRecordMileage">@translator.Translate(userLanguage,"Odometer")</label>
<input type="number" inputmode="numeric" id="upgradeRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when upgraded/modded")" value="@(isNew ? "" : Model.Mileage)">
<label for="upgradeRecordDescription">@translator.Translate(userLanguage,"Description")</label>
<label for="upgradeRecordMileage">@translator.Translate(userLanguage, "Odometer")</label>
<div class="input-group">
<input type="number" inputmode="numeric" id="upgradeRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when upgraded/modded")" value="@(isNew ? "" : Model.Mileage)">
@if (isNew)
{
<div class="input-group-text">
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('upgradeRecordMileage')">+</button>
</div>
}
</div>
<label for="upgradeRecordDescription">@translator.Translate(userLanguage, "Description")</label>
<input type="text" id="upgradeRecordDescription" class="form-control" placeholder="@translator.Translate(userLanguage,"Description of item(s) upgraded/modded")" value="@Model.Description">
@if (isNew)
{
@@ -34,13 +42,13 @@
</div>
</div>
}
<label for="upgradeRecordCost">@translator.Translate(userLanguage,"Cost")</label>
<label for="upgradeRecordCost">@translator.Translate(userLanguage, "Cost")</label>
<input type="text" inputmode="decimal" id="upgradeRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"Cost of the upgrade/mods")" value="@(isNew ? "" : Model.Cost)">
@if (isNew)
{
@await Html.PartialAsync("_SupplyStore", "UpgradeRecord")
}
<label for="upgradeRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
<label for="upgradeRecordTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
<select multiple class="form-select" id="upgradeRecordTag">
@foreach (string tag in Model.Tags)
{
@@ -57,15 +65,15 @@
}
</div>
<div class="col-md-6 col-12">
<label for="upgradeRecordNotes">@translator.Translate(userLanguage,"Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
<label for="upgradeRecordNotes">@translator.Translate(userLanguage, "Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
<textarea id="upgradeRecordNotes" class="form-control" rows="5">@Model.Notes</textarea>
@if (Model.Files.Any())
{
<div>
@await Html.PartialAsync("_UploadedFiles", Model.Files)
<label for="upgradeRecordFiles">@translator.Translate(userLanguage,"Upload more documents")</label>
<label for="upgradeRecordFiles">@translator.Translate(userLanguage, "Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="upgradeRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
<br /><small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
</div>
}
else
@@ -75,13 +83,15 @@
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="addReminderCheck">
<label class="form-check-label" for="addReminderCheck">
@translator.Translate(userLanguage,"Add Reminder")
@translator.Translate(userLanguage, "Add Reminder")
</label>
</div>
}
<label for="upgradeRecordFiles">Upload documents(optional)</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="upgradeRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
<br />
<small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
}
</div>
</div>
@@ -96,39 +106,40 @@
<button type="button" class="btn btn-warning" onclick="toggleSupplyUsageHistory()"><i class="bi bi-shop"></i></button>
}
<div class="btn-group" style="margin-right:auto;">
<button type="button" class="btn btn-md mt-1 mb-1 btn-danger" onclick="deleteUpgradeRecord(@Model.Id)">@translator.Translate(userLanguage,"Delete")</button>
<button type="button" class="btn btn-md mt-1 mb-1 btn-danger" onclick="deleteUpgradeRecord(@Model.Id)">@translator.Translate(userLanguage, "Delete")</button>
<button type="button" class="btn btn-md btn-danger btn-md mt-1 mb-1 dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li><h6 class="dropdown-header">@translator.Translate(userLanguage,"Move To")</h6></li>
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'UpgradeRecord', 'ServiceRecord')">@translator.Translate(userLanguage,"Service Records")</a></li>
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'UpgradeRecord', 'RepairRecord')">@translator.Translate(userLanguage,"Repairs")</a></li>
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Move To")</h6></li>
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'UpgradeRecord', 'ServiceRecord')">@translator.Translate(userLanguage, "Service Records")</a></li>
<li><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'UpgradeRecord', 'RepairRecord')">@translator.Translate(userLanguage, "Repairs")</a></li>
</ul>
</div>
}
<button type="button" class="btn btn-secondary" onclick="hideAddUpgradeRecordModal()">@translator.Translate(userLanguage,"Cancel")</button>
<button type="button" class="btn btn-secondary" onclick="hideAddUpgradeRecordModal()">@translator.Translate(userLanguage, "Cancel")</button>
@if (isNew)
{
<button type="button" class="btn btn-primary" onclick="saveUpgradeRecordToVehicle()">@translator.Translate(userLanguage,"Add New Upgrade Record")</button>
<button type="button" class="btn btn-primary" onclick="saveUpgradeRecordToVehicle()">@translator.Translate(userLanguage, "Add New Upgrade Record")</button>
}
else if (!isNew)
{
<button type="button" class="btn btn-primary" onclick="saveUpgradeRecordToVehicle(true)">@translator.Translate(userLanguage,"Edit Upgrade Record")</button>
<button type="button" class="btn btn-primary" onclick="saveUpgradeRecordToVehicle(true)">@translator.Translate(userLanguage, "Edit Upgrade Record")</button>
}
</div>
@await Html.PartialAsync("_SupplyRequisitionHistory", Model.RequisitionHistory)
<script>
var uploadedFiles = [];
var selectedSupplies = [];
var recurringReminderRecordId = 0;
var recurringReminderRecordId = [];
var copySuppliesAttachments = false;
getUploadedFilesFromModel();
function getUploadedFilesFromModel() {
@foreach (UploadedFiles filesUploaded in Model.Files)
{
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
}
}
}
function getUpgradeRecordModelData() {
return { id: @Model.Id}
}

View File

@@ -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>
}

View File

@@ -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">

View File

@@ -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)

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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;
}
})
}

View File

@@ -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 = `${getGlobalConfig().currencySymbol}${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 = `${getGlobalConfig().currencySymbol}${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 = `${getGlobalConfig().currencySymbol}${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 = `${getGlobalConfig().currencySymbol}${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 = `${getGlobalConfig().currencySymbol}${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 = `${getGlobalConfig().currencySymbol}${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))}`);
}
}
}

View File

@@ -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");

View File

@@ -9,7 +9,19 @@
}
});
}
function showEditOdometerRecordModal(odometerRecordId) {
function showEditOdometerRecordModal(odometerRecordId, nocache) {
if (!nocache) {
var existingContent = $("#odometerRecordModalContent").html();
if (existingContent.trim() != '') {
//check if id is same.
var existingId = getOdometerRecordModelData().id;
if (existingId == odometerRecordId && $('[data-changed=true]').length > 0) {
$('#odometerRecordModal').modal('show');
$('.cached-banner').show();
return;
}
}
}
$.get(`/Vehicle/GetOdometerRecordForEditById?odometerRecordId=${odometerRecordId}`, function (data) {
if (data) {
$("#odometerRecordModalContent").html(data);
@@ -17,6 +29,7 @@ function showEditOdometerRecordModal(odometerRecordId) {
initDatePicker($('#odometerRecordDate'));
initTagSelector($("#odometerRecordTag"));
$('#odometerRecordModal').modal('show');
bindModalInputChanges('odometerRecordModal');
$('#odometerRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
if (getGlobalConfig().useMarkDown) {
toggleMarkDownOverlay("odometerRecordNotes");

View File

@@ -8,13 +8,57 @@
}
});
}
function showEditPlanRecordModal(planRecordId) {
function showEditPlanRecordModal(planRecordId, nocache) {
if (!nocache) {
var existingContent = $("#planRecordModalContent").html();
if (existingContent.trim() != '') {
//check if id is same.
var existingId = getPlanRecordModelData().id;
var isNotTemplate = !getPlanRecordModelData().isTemplate;
if (existingId == planRecordId && isNotTemplate && $('[data-changed=true]').length > 0) {
$('#planRecordModal').modal('show');
$('.cached-banner').show();
return;
}
}
}
$.get(`/Vehicle/GetPlanRecordForEditById?planRecordId=${planRecordId}`, function (data) {
if (data) {
$("#planRecordModalContent").html(data);
//initiate datepicker
initDatePicker($('#planRecordDate'));
$('#planRecordModal').modal('show');
bindModalInputChanges('planRecordModal');
$('#planRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
if (getGlobalConfig().useMarkDown) {
toggleMarkDownOverlay("planRecordNotes");
}
});
}
});
}
function showEditPlanRecordTemplateModal(planRecordTemplateId, nocache) {
hidePlanRecordTemplatesModal();
if (!nocache) {
var existingContent = $("#planRecordModalContent").html();
if (existingContent.trim() != '') {
//check if id is same.
var existingId = getPlanRecordModelData().id;
var isTemplate = getPlanRecordModelData().isTemplate;
if (existingId == planRecordTemplateId && isTemplate && $('[data-changed=true]').length > 0) {
$('#planRecordModal').modal('show');
$('.cached-banner').show();
return;
}
}
}
$.get(`/Vehicle/GetPlanRecordTemplateForEditById?planRecordTemplateId=${planRecordTemplateId}`, function (data) {
if (data) {
$("#planRecordModalContent").html(data);
//initiate datepicker
initDatePicker($('#planRecordDate'));
$('#planRecordModal').modal('show');
bindModalInputChanges('planRecordModal');
$('#planRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
if (getGlobalConfig().useMarkDown) {
toggleMarkDownOverlay("planRecordNotes");
@@ -25,12 +69,15 @@ function showEditPlanRecordModal(planRecordId) {
}
function hideAddPlanRecordModal() {
$('#planRecordModal').modal('hide');
if (getPlanRecordModelData().createdFromReminder) {
//show reminder Modal
$("#reminderRecordModal").modal("show");
}
if (getPlanRecordModelData().createdFromReminder) {
//show reminder Modal
$("#reminderRecordModal").modal("show");
}
if (getPlanRecordModelData().isTemplate) {
showPlanRecordTemplatesModal();
}
}
function deletePlanRecord(planRecordId) {
function deletePlanRecord(planRecordId, noModal) {
$("#workAroundInput").show();
Swal.fire({
title: "Confirm Deletion?",
@@ -42,7 +89,9 @@ function deletePlanRecord(planRecordId) {
if (result.isConfirmed) {
$.post(`/Vehicle/DeletePlanRecordById?planRecordId=${planRecordId}`, function (data) {
if (data) {
hideAddPlanRecordModal();
if (!noModal) {
hideAddPlanRecordModal();
}
successToast("Plan Record Deleted");
var vehicleId = GetVehicleId().vehicleId;
getVehiclePlanRecords(vehicleId);
@@ -85,22 +134,19 @@ function showPlanRecordTemplatesModal() {
$.get(`/Vehicle/GetPlanRecordTemplatesForVehicleId?vehicleId=${vehicleId}`, function (data) {
if (data) {
$("#planRecordTemplateModalContent").html(data);
hideAddPlanRecordModal();
$('#planRecordTemplateModal').modal('show');
}
});
}
function hidePlanRecordTemplatesModal() {
$('#planRecordTemplateModal').modal('hide');
$('#planRecordModal').modal('show');
}
function usePlannerRecordTemplate(planRecordTemplateId) {
$.post(`/Vehicle/ConvertPlanRecordTemplateToPlanRecord?planRecordTemplateId=${planRecordTemplateId}`, function (data) {
if (data.success) {
var vehicleId = GetVehicleId().vehicleId;
successToast(data.message);
$('#planRecordTemplateModal').modal('hide');
hideAddPlanRecordModal();
hidePlanRecordTemplatesModal();
saveScrollPosition();
getVehiclePlanRecords(vehicleId);
} else {
@@ -122,8 +168,8 @@ function deletePlannerRecordTemplate(planRecordTemplateId) {
$.post(`/Vehicle/DeletePlanRecordTemplateById?planRecordTemplateId=${planRecordTemplateId}`, function (data) {
$("#workAroundInput").hide();
if (data) {
successToast("Template Deleted");
hidePlanRecordTemplatesModal();
successToast("Plan Template Deleted");
hideAddPlanRecordModal();
} else {
errorToast(genericErrorMessage());
}
@@ -133,7 +179,7 @@ function deletePlannerRecordTemplate(planRecordTemplateId) {
}
});
}
function savePlanRecordTemplate() {
function savePlanRecordTemplate(isEdit) {
//get values
var formValues = getAndValidatePlanRecordValues();
//validate
@@ -144,7 +190,14 @@ function savePlanRecordTemplate() {
//save to db.
$.post('/Vehicle/SavePlanRecordTemplateToVehicleId', { planRecord: formValues }, function (data) {
if (data.success) {
successToast(data.message);
if (isEdit) {
hideAddPlanRecordModal();
showPlanRecordTemplatesModal();
$('[data-changed=true]').attr('data-changed', false)
successToast('Plan Template Updated');
} else {
successToast('Plan Template Added');
}
} else {
errorToast(data.message);
}
@@ -194,7 +247,8 @@ function getAndValidatePlanRecordValues() {
importMode: planType,
extraFields: extraFields.extraFields,
requisitionHistory: supplyUsageHistory,
reminderRecordId: reminderRecordId
reminderRecordId: reminderRecordId,
copySuppliesAttachment: copySuppliesAttachments
}
}
//drag and drop stuff.

View File

@@ -3,6 +3,7 @@
if (data) {
$("#reminderRecordModalContent").html(data);
initDatePicker($('#reminderDate'), true);
initTagSelector($("#reminderRecordTag"));
$("#reminderRecordModal").modal("show");
$('#reminderRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
if (getGlobalConfig().useMarkDown) {
@@ -166,6 +167,7 @@ function getAndValidateReminderRecordValues() {
var reminderIsRecurring = $("#reminderIsRecurring").is(":checked");
var reminderRecurringMonth = $("#reminderRecurringMonth").val();
var reminderRecurringMileage = $("#reminderRecurringMileage").val();
var reminderTags = $("#reminderRecordTag").val();
var reminderCustomMileageInterval = customMileageInterval;
var vehicleId = GetVehicleId().vehicleId;
var reminderId = getReminderRecordModelData().id;
@@ -215,7 +217,8 @@ function getAndValidateReminderRecordValues() {
reminderMileageInterval: reminderRecurringMileage,
reminderMonthInterval: reminderRecurringMonth,
customMileageInterval: customMileageInterval,
customMonthInterval: customMonthInterval
customMonthInterval: customMonthInterval,
tags: reminderTags
}
}
function createPlanRecordFromReminder(reminderRecordId) {
@@ -239,4 +242,55 @@ function createPlanRecordFromReminder(reminderRecordId) {
$("#planRecordModalContent").html(data);
$("#planRecordModal").modal("show");
});
}
function filterReminderTable(sender) {
var rowData = $(`#reminder-tab-pane table tbody tr`);
if (sender == undefined) {
rowData.removeClass('override-hide');
return;
}
var tagName = sender.textContent;
//check for other applied filters
if ($(sender).hasClass("bg-primary")) {
rowData.removeClass('override-hide');
$(sender).removeClass('bg-primary');
$(sender).addClass('bg-secondary');
updateReminderAggregateLabels();
} else {
//hide table rows.
rowData.addClass('override-hide');
$(`[data-tags~='${tagName}']`).removeClass('override-hide');
updateReminderAggregateLabels();
if ($(".tagfilter.bg-primary").length > 0) {
//disabling other filters
$(".tagfilter.bg-primary").addClass('bg-secondary');
$(".tagfilter.bg-primary").removeClass('bg-primary');
}
$(sender).addClass('bg-primary');
$(sender).removeClass('bg-secondary');
}
}
function updateReminderAggregateLabels() {
//update main count
var newCount = $("[data-record-type='cost']").parent(":not('.override-hide')").length;
var countLabel = $("[data-aggregate-type='count']");
countLabel.text(`${countLabel.text().split(':')[0]}: ${newCount}`);
//update labels
//paste due
var pastDueCount = $("tr td span.badge.text-bg-secondary").parents("tr:not('.override-hide')").length;
var pastDueLabel = $('[data-aggregate-type="pastdue-count"]');
pastDueLabel.text(`${pastDueLabel.text().split(':')[0]}: ${pastDueCount}`);
//very urgent
var veryUrgentCount = $("tr td span.badge.text-bg-danger").parents("tr:not('.override-hide')").length;
var veryUrgentLabel = $('[data-aggregate-type="veryurgent-count"]');
veryUrgentLabel.text(`${veryUrgentLabel.text().split(':')[0]}: ${veryUrgentCount}`);
//urgent
var urgentCount = $("tr td span.badge.text-bg-warning").parents("tr:not('.override-hide')").length;
var urgentLabel = $('[data-aggregate-type="urgent-count"]');
urgentLabel.text(`${urgentLabel.text().split(':')[0]}: ${urgentCount}`);
//not urgent
var notUrgentCount = $("tr td span.badge.text-bg-success").parents("tr:not('.override-hide')").length;
var notUrgentLabel = $('[data-aggregate-type="noturgent-count"]');
notUrgentLabel.text(`${notUrgentLabel.text().split(':')[0]}: ${notUrgentCount}`);
}

View File

@@ -1,5 +1,5 @@
function getYear() {
return $("#yearOption").val();
return $("#yearOption").val() ?? '0';
}
function generateVehicleHistoryReport() {
var vehicleId = GetVehicleId().vehicleId;
@@ -29,6 +29,43 @@ function refreshMPGChart() {
$("#monthFuelMileageReportContent").html(data);
})
}
function setSelectedMetrics() {
var selectedMetricCheckBoxes = [];
$(".reportCheckBox:checked").map((index, elem) => {
selectedMetricCheckBoxes.push(elem.id);
});
var yearMetric = $('#yearOption').val();
var reminderMetric = $("#reminderOption").val();
sessionStorage.setItem("selectedMetricCheckBoxes", JSON.stringify(selectedMetricCheckBoxes));
sessionStorage.setItem("yearMetric", yearMetric);
sessionStorage.setItem("reminderMetric", reminderMetric);
}
function getSelectedMetrics() {
var selectedMetricCheckBoxes = sessionStorage.getItem("selectedMetricCheckBoxes");
var yearMetric = sessionStorage.getItem("yearMetric");
var reminderMetric = sessionStorage.getItem("reminderMetric");
if (selectedMetricCheckBoxes != null && yearMetric != null && reminderMetric != null) {
selectedMetricCheckBoxes = JSON.parse(selectedMetricCheckBoxes);
$(".reportCheckBox").prop('checked', false);
$("#selectAllExpenseCheck").prop("checked", false);
selectedMetricCheckBoxes.map(x => {
$(`#${x}`).prop('checked', true);
});
if (selectedMetricCheckBoxes.length == 6) {
$("#selectAllExpenseCheck").prop("checked", true);
}
//check if option is available
if ($("#yearOption").has(`option[value=${yearMetric}]`).length > 0) {
$('#yearOption').val(yearMetric);
}
$("#reminderOption").val(reminderMetric);
//retrieve data.
yearUpdated();
updateReminderPie();
return true;
}
return false;
}
function refreshBarChart() {
var selectedMetrics = [];
var vehicleId = GetVehicleId().vehicleId;
@@ -61,11 +98,13 @@ function refreshBarChart() {
}, function (data) {
$("#gasCostByMonthReportContent").html(data);
refreshMPGChart();
});
});
setSelectedMetrics();
}
function updateReminderPie() {
var vehicleId = GetVehicleId().vehicleId;
var daysToAdd = $("#reminderOption").val();
setSelectedMetrics();
$.get(`/Vehicle/GetReminderMakeUpByVehicle?vehicleId=${vehicleId}`, { daysToAdd: daysToAdd }, function (data) {
$("#reminderMakeUpReportContent").html(data);
});
@@ -140,4 +179,74 @@ function exportAttachments() {
})
}
});
}
function showGlobalSearch() {
$('#globalSearchModal').modal('show');
}
function hideGlobalSearch() {
$('#globalSearchModal').modal('hide');
}
function performGlobalSearch() {
var searchQuery = $('#globalSearchInput').val();
if (searchQuery.trim() == '') {
$('#globalSearchInput').addClass('is-invalid');
} else {
$('#globalSearchInput').removeClass('is-invalid');
}
$.post('/Vehicle/SearchRecords', { vehicleId: GetVehicleId().vehicleId, searchQuery: searchQuery }, function (data) {
$('#globalSearchModalResults').html(data);
});
}
function handleGlobalSearchKeyPress(event) {
if ($('#globalSearchAutoSearchCheck').is(':checked')){
setDebounce(performGlobalSearch);
} else if (event.keyCode == 13) {
performGlobalSearch();
}
}
function loadGlobalSearchResult(recordId, recordType) {
hideGlobalSearch();
switch (recordType) {
case "ServiceRecord":
$('#servicerecord-tab').tab('show');
waitForElement('#serviceRecordModalContent', showEditServiceRecordModal, recordId);
break;
case "RepairRecord":
$('#accident-tab').tab('show');
waitForElement('#collisionRecordModalContent', showEditCollisionRecordModal, recordId);
break;
case "UpgradeRecord":
$('#upgrade-tab').tab('show');
waitForElement('#upgradeRecordModalContent', showEditUpgradeRecordModal, recordId);
break;
case "TaxRecord":
$('#tax-tab').tab('show');
waitForElement('#taxRecordModalContent', showEditTaxRecordModal, recordId);
break;
case "SupplyRecord":
$('#supply-tab').tab('show');
waitForElement('#supplyRecordModalContent', showEditSupplyRecordModal, recordId);
break;
case "NoteRecord":
$('#notes-tab').tab('show');
waitForElement('#noteModalContent', showEditNoteModal, recordId);
break;
case "OdometerRecord":
$('#odometer-tab').tab('show');
waitForElement('#odometerRecordModalContent', showEditOdometerRecordModal, recordId);
break;
case "ReminderRecord":
$('#reminder-tab').tab('show');
waitForElement('#reminderRecordModalContent', showEditReminderRecordModal, recordId);
break;
case "GasRecord":
$('#gas-tab').tab('show');
waitForElement('#gasRecordModalContent', showEditGasRecordModal, recordId);
break;
case "PlanRecord":
$('#plan-tab').tab('show');
waitForElement('#planRecordModalContent', showEditPlanRecordModal, recordId);
break;
}
}

View File

@@ -9,7 +9,19 @@
}
});
}
function showEditServiceRecordModal(serviceRecordId) {
function showEditServiceRecordModal(serviceRecordId, nocache) {
if (!nocache) {
var existingContent = $("#serviceRecordModalContent").html();
if (existingContent.trim() != '') {
//check if id is same.
var existingId = getServiceRecordModelData().id;
if (existingId == serviceRecordId && $('[data-changed=true]').length > 0) {
$('#serviceRecordModal').modal('show');
$('.cached-banner').show();
return;
}
}
}
$.get(`/Vehicle/GetServiceRecordForEditById?serviceRecordId=${serviceRecordId}`, function (data) {
if (data) {
$("#serviceRecordModalContent").html(data);
@@ -17,6 +29,7 @@ function showEditServiceRecordModal(serviceRecordId) {
initDatePicker($('#serviceRecordDate'));
initTagSelector($("#serviceRecordTag"));
$('#serviceRecordModal').modal('show');
bindModalInputChanges('serviceRecordModal');
$('#serviceRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
if (getGlobalConfig().useMarkDown) {
toggleMarkDownOverlay("serviceRecordNotes");
@@ -133,6 +146,7 @@ function getAndValidateServiceRecordValues() {
addReminderRecord: addReminderRecord,
extraFields: extraFields.extraFields,
requisitionHistory: supplyUsageHistory,
reminderRecordId: recurringReminderRecordId
reminderRecordId: recurringReminderRecordId,
copySuppliesAttachment: copySuppliesAttachments
}
}

View File

@@ -45,6 +45,8 @@ function saveVehicle(isEdit) {
var vehicleHasOdometerAdjustment = $("#inputHasOdometerAdjustment").is(':checked');
var vehicleOdometerMultiplier = $("#inputOdometerMultiplier").val();
var vehicleOdometerDifference = parseInt(globalParseFloat($("#inputOdometerDifference").val())).toString();
var vehiclePurchasePrice = $("#inputPurchasePrice").val();
var vehicleSoldPrice = $("#inputSoldPrice").val();
var extraFields = getAndValidateExtraFields(true);
//validate
var hasError = false;
@@ -92,6 +94,20 @@ function saveVehicle(isEdit) {
$("#inputOdometerDifference").removeClass("is-invalid");
}
}
if (vehiclePurchasePrice.trim() != '' && !isValidMoney(vehiclePurchasePrice)) {
hasError = true;
$("#inputPurchasePrice").addClass("is-invalid");
$("#collapsePurchaseInfo").collapse('show');
} else {
$("#inputPurchasePrice").removeClass("is-invalid");
}
if (vehicleSoldPrice.trim() != '' && !isValidMoney(vehicleSoldPrice)) {
hasError = true;
$("#inputSoldPrice").addClass("is-invalid");
$("#collapsePurchaseInfo").collapse('show');
} else {
$("#inputSoldPrice").removeClass("is-invalid");
}
if (hasError) {
return;
}
@@ -110,7 +126,9 @@ function saveVehicle(isEdit) {
soldDate: vehicleSoldDate,
hasOdometerAdjustment: vehicleHasOdometerAdjustment,
odometerMultiplier: vehicleOdometerMultiplier,
odometerDifference: vehicleOdometerDifference
odometerDifference: vehicleOdometerDifference,
purchasePrice: vehiclePurchasePrice,
soldPrice: vehicleSoldPrice
}, function (data) {
if (data) {
if (!isEdit) {
@@ -336,7 +354,7 @@ function updateAggregateLabels() {
//Count
var newCount = $("[data-record-type='cost']").parent(":not('.override-hide')").length;
var countLabel = $("[data-aggregate-type='count']");
countLabel.text(`${countLabel.text().split(':')[0]}: ${newCount}`)
countLabel.text(`${countLabel.text().split(':')[0]}: ${newCount}`);
}
function uploadVehicleFilesAsync(event) {
@@ -690,7 +708,10 @@ $(window).on('keydown', function (e) {
selectAllRows();
}
}
})
});
function getCurrentTab() {
return $(".tab-pane.active.show").attr('id');
}
function selectAllRows() {
clearSelectedRows();
$('.vehicleDetailTabContainer .table tbody tr:visible').addClass('table-active');
@@ -1010,4 +1031,26 @@ function copyToClipboard(e) {
var textToCopy = e.textContent.trim();
navigator.clipboard.writeText(textToCopy);
successToast("Copied to Clipboard");
}
function noPropagation() {
event.stopPropagation();
}
var checkExist;
function waitForElement(element, callBack, callBackParameter) {
checkExist = setInterval(function () {
if ($(`${element}`).length) {
callBack(callBackParameter);
clearInterval(checkExist);
}
}, 100); // check every 100ms
}
function bindModalInputChanges(modalName) {
//bind text inputs
$(`#${modalName} input[type='text'], #${modalName} input[type='number'], #${modalName} textarea`).off('input').on('input', function (e) {
$(e.currentTarget).attr('data-changed', true);
});
$(`#${modalName} select, #${modalName} input[type='checkbox']`).off('input').on('input', function (e) {
$(e.currentTarget).attr('data-changed', true);
});
}

View File

@@ -9,7 +9,19 @@
}
});
}
function showEditSupplyRecordModal(supplyRecordId) {
function showEditSupplyRecordModal(supplyRecordId, nocache) {
if (!nocache) {
var existingContent = $("#supplyRecordModalContent").html();
if (existingContent.trim() != '') {
//check if id is same.
var existingId = getSupplyRecordModelData().id;
if (existingId == supplyRecordId && $('[data-changed=true]').length > 0) {
$('#supplyRecordModal').modal('show');
$('.cached-banner').show();
return;
}
}
}
$.get(`/Vehicle/GetSupplyRecordForEditById?supplyRecordId=${supplyRecordId}`, function (data) {
if (data) {
$("#supplyRecordModalContent").html(data);
@@ -17,6 +29,7 @@ function showEditSupplyRecordModal(supplyRecordId) {
initDatePicker($('#supplyRecordDate'));
initTagSelector($("#supplyRecordTag"));
$('#supplyRecordModal').modal('show');
bindModalInputChanges('supplyRecordModal');
$('#supplyRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
if (getGlobalConfig().useMarkDown) {
toggleMarkDownOverlay("supplyRecordNotes");

View File

@@ -9,7 +9,19 @@
}
});
}
function showEditTaxRecordModal(taxRecordId) {
function showEditTaxRecordModal(taxRecordId, nocache) {
if (!nocache) {
var existingContent = $("#taxRecordModalContent").html();
if (existingContent.trim() != '') {
//check if id is same.
var existingId = getTaxRecordModelData().id;
if (existingId == taxRecordId && $('[data-changed=true]').length > 0) {
$('#taxRecordModal').modal('show');
$('.cached-banner').show();
return;
}
}
}
$.get(`/Vehicle/GetTaxRecordForEditById?taxRecordId=${taxRecordId}`, function (data) {
if (data) {
$("#taxRecordModalContent").html(data);
@@ -17,6 +29,7 @@ function showEditTaxRecordModal(taxRecordId) {
initDatePicker($('#taxRecordDate'));
initTagSelector($("#taxRecordTag"));
$('#taxRecordModal').modal('show');
bindModalInputChanges('taxRecordModal');
$('#taxRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
if (getGlobalConfig().useMarkDown) {
toggleMarkDownOverlay("taxRecordNotes");

View File

@@ -9,7 +9,19 @@
}
});
}
function showEditUpgradeRecordModal(upgradeRecordId) {
function showEditUpgradeRecordModal(upgradeRecordId, nocache) {
if (!nocache) {
var existingContent = $("#upgradeRecordModalContent").html();
if (existingContent.trim() != '') {
//check if id is same.
var existingId = getUpgradeRecordModelData().id;
if (existingId == upgradeRecordId && $('[data-changed=true]').length > 0) {
$('#upgradeRecordModal').modal('show');
$('.cached-banner').show();
return;
}
}
}
$.get(`/Vehicle/GetUpgradeRecordForEditById?upgradeRecordId=${upgradeRecordId}`, function (data) {
if (data) {
$("#upgradeRecordModalContent").html(data);
@@ -17,6 +29,7 @@ function showEditUpgradeRecordModal(upgradeRecordId) {
initDatePicker($('#upgradeRecordDate'));
initTagSelector($("#upgradeRecordTag"));
$('#upgradeRecordModal').modal('show');
bindModalInputChanges('upgradeRecordModal');
$('#upgradeRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
if (getGlobalConfig().useMarkDown) {
toggleMarkDownOverlay("upgradeRecordNotes");
@@ -133,6 +146,7 @@ function getAndValidateUpgradeRecordValues() {
addReminderRecord: addReminderRecord,
extraFields: extraFields.extraFields,
requisitionHistory: supplyUsageHistory,
reminderRecordId: recurringReminderRecordId
reminderRecordId: recurringReminderRecordId,
copySuppliesAttachment: copySuppliesAttachments
}
}

View File

@@ -75,6 +75,10 @@ $(document).ready(function () {
$("#odometer-tab-pane").html("");
break;
}
$(`.lubelogger-tab #${e.target.id}`).addClass('active');
$(`.lubelogger-mobile-nav #${e.target.id}`).addClass('active');
$(`.lubelogger-tab #${e.relatedTarget.id}`).removeClass('active');
$(`.lubelogger-mobile-nav #${e.relatedTarget.id}`).removeClass('active');
});
var defaultTab = GetDefaultTab().tab;
switch (defaultTab) {
@@ -246,12 +250,14 @@ function showAddReminderModal(reminderModalInput) {
$.post('/Vehicle/GetAddReminderRecordPartialView', { reminderModel: reminderModalInput }, function (data) {
$("#reminderRecordModalContent").html(data);
initDatePicker($('#reminderDate'), true);
initTagSelector($("#reminderRecordTag"));
$("#reminderRecordModal").modal("show");
});
} else {
$.post('/Vehicle/GetAddReminderRecordPartialView', function (data) {
$("#reminderRecordModalContent").html(data);
initDatePicker($('#reminderDate'), true);
initTagSelector($("#reminderRecordTag"));
$("#reminderRecordModal").modal("show");
});
}
@@ -340,19 +346,19 @@ function showRecurringReminderSelector(descriptionFieldName) {
confirmButtonText: 'Select',
focusConfirm: false,
preConfirm: () => {
const selectedRecurringReminder = $("#recurringReminderInput").val();
const selectedRecurringReminderText = $("#recurringReminderInput option:selected").text();
if (!selectedRecurringReminder || parseInt(selectedRecurringReminder) == 0) {
//validate
var selectedRecurringReminderData = getAndValidateSelectedRecurringReminder();
if (selectedRecurringReminderData.hasError) {
Swal.showValidationMessage(`You must select a recurring reminder`);
}
return { selectedRecurringReminder, selectedRecurringReminderText }
return { selectedRecurringReminderData }
},
}).then(function (result) {
if (result.isConfirmed) {
recurringReminderRecordId = result.value.selectedRecurringReminder;
recurringReminderRecordId = result.value.selectedRecurringReminderData.ids;
var descriptionField = $(`#${descriptionFieldName}`);
if (descriptionField.length > 0) {
descriptionField.val(result.value.selectedRecurringReminderText.trim());
descriptionField.val(result.value.selectedRecurringReminderData.text);
}
}
});
@@ -480,13 +486,13 @@ function getRecordsDeltaStats(recordIds) {
costSum = costSum.toFixed(2);
Swal.fire({
title: "Record Statistics",
html: `<p>Average Distance Traveled between Records: ${averageOdo}</p>
html: `<p>Average Distance Traveled between Records: ${globalFloatToString(averageOdo)}</p>
<br />
<p>Average Days between Records: ${averageDays}</p>
<br />
<p>Total Cost: ${getGlobalConfig().currencySymbol} ${costSum}</p>
<p>Total Cost: ${getGlobalConfig().currencySymbol} ${globalFloatToString(costSum)}</p>
<br />
<p>Average Cost: ${getGlobalConfig().currencySymbol} ${averageSum}</p>`
<p>Average Cost: ${getGlobalConfig().currencySymbol} ${globalFloatToString(averageSum)}</p>`
,
icon: "info"
});
@@ -554,4 +560,89 @@ function adjustRecordsOdometer(ids, source) {
$("#workAroundInput").hide();
}
});
}
function showMultipleRemindersSelector() {
if ($("#multipleRemindersCheck").is(":checked")) {
$("#recurringMultipleReminders").show();
$("#recurringReminderInput").hide();
} else {
$("#recurringMultipleReminders").hide();
$("#recurringReminderInput").show();
}
}
function getAndValidateSelectedRecurringReminder() {
if ($("#multipleRemindersCheck").is(":checked")) {
//validate multiple reminders
var selectedRecurringRemindersArray = [];
$("#recurringMultipleReminders :checked").map(function () {
selectedRecurringRemindersArray.push({
value: this.value,
text: $(this).parent().find('.form-check-label').text()
});
});
if (selectedRecurringRemindersArray.length == 0) {
return {
hasError: true,
ids: [],
text: ''
}
} else {
return {
hasError: false,
ids: selectedRecurringRemindersArray.map(x=>x.value),
text: selectedRecurringRemindersArray.map(x=>x.text).join(', ')
}
}
} else {
//validate single reminder
var selectedRecurringReminder = $("#recurringReminderInput").val();
var selectedRecurringReminderText = $("#recurringReminderInput option:selected").text();
if (!selectedRecurringReminder || parseInt(selectedRecurringReminder) == 0) {
return {
hasError: true,
ids: [],
text: ''
}
} else {
return {
hasError: false,
ids: [selectedRecurringReminder],
text: selectedRecurringReminderText
}
}
}
}
function getLastOdometerReadingAndIncrement(odometerFieldName) {
Swal.fire({
title: 'Increment Last Reported Odometer Reading',
html: `
<input type="text" id="inputOdometerIncrement" class="swal2-input" placeholder="Increment">
`,
confirmButtonText: 'Add',
focusConfirm: false,
preConfirm: () => {
const odometerIncrement = parseInt(globalParseFloat($("#inputOdometerIncrement").val()));
if (isNaN(odometerIncrement) || odometerIncrement <= 0) {
Swal.showValidationMessage(`Please enter a non-zero amount to increment`);
}
return { odometerIncrement }
},
}).then(function (result) {
if (result.isConfirmed) {
var amountToIncrement = result.value.odometerIncrement;
$.get(`/Vehicle/GetMaxMileage?vehicleId=${GetVehicleId().vehicleId}`, function (data) {
var newAmount = data + amountToIncrement;
if (!isNaN(newAmount)) {
var odometerField = $(`#${odometerFieldName}`);
if (odometerField.length > 0) {
odometerField.val(newAmount);
} else {
errorToast(genericErrorMessage());
}
} else {
errorToast(genericErrorMessage());
}
});
}
});
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More