Compare commits
223 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b69749b073 | ||
|
|
951eea844f | ||
|
|
f3e5aff0c9 | ||
|
|
ef3e450e4f | ||
|
|
8272fa20da | ||
|
|
9ef0a748a3 | ||
|
|
6de928aef4 | ||
|
|
34ff874949 | ||
|
|
a653f3ac7f | ||
|
|
dc96084406 | ||
|
|
e056aaa7dc | ||
|
|
73bb3c11b4 | ||
|
|
c88a040728 | ||
|
|
dfa56c2b12 | ||
|
|
104d4bab52 | ||
|
|
6916161e87 | ||
|
|
512852d217 | ||
|
|
a61c699417 | ||
|
|
1e832f014f | ||
|
|
e9a463e2e5 | ||
|
|
d0c19d0436 | ||
|
|
3428abf358 | ||
|
|
e6857331e2 | ||
|
|
1fd93d2efe | ||
|
|
84e44acbfe | ||
|
|
77014c71f2 | ||
|
|
2db01aa4ad | ||
|
|
6c3fa21cc5 | ||
|
|
26b7d101ab | ||
|
|
f3c3cdf0cb | ||
|
|
e62fa31485 | ||
|
|
5f283c1558 | ||
|
|
52163098d2 | ||
|
|
dfe27f0577 | ||
|
|
e415a3468f | ||
|
|
71302a52e4 | ||
|
|
762730eb0f | ||
|
|
3999a8a54d | ||
|
|
065291e146 | ||
|
|
99376aba1c | ||
|
|
698e8a0a95 | ||
|
|
b1b3a127dc | ||
|
|
ec55c95c71 | ||
|
|
e6eb2b473c | ||
|
|
a4b39820e4 | ||
|
|
4a20c81047 | ||
|
|
b72ab461e5 | ||
|
|
0be498d9bd | ||
|
|
00bad986e5 | ||
|
|
4710e84dcf | ||
|
|
ee55f8c884 | ||
|
|
3a74116e70 | ||
|
|
cfd83b5b4e | ||
|
|
e468261095 | ||
|
|
1362dc87df | ||
|
|
b89902bbdb | ||
|
|
f31b70a6dc | ||
|
|
47a1f0c4d5 | ||
|
|
3234b530d5 | ||
|
|
75d16544db | ||
|
|
7179b60116 | ||
|
|
7cb5d8254f | ||
|
|
6ab7ee6e4f | ||
|
|
a57ce55f8b | ||
|
|
190484762d | ||
|
|
78554ade5d | ||
|
|
364a13226a | ||
|
|
691813838c | ||
|
|
0defb0fadf | ||
|
|
08bf00ee37 | ||
|
|
522322ee2a | ||
|
|
062e3600e7 | ||
|
|
a92160f6d7 | ||
|
|
4adf967f7f | ||
|
|
fd6bd98a25 | ||
|
|
fe76f32778 | ||
|
|
897b4f2efe | ||
|
|
267f903ffe | ||
|
|
db884d0a6a | ||
|
|
d1190e7ddb | ||
|
|
dae8ab679e | ||
|
|
86ec9409c3 | ||
|
|
2c4ddb0c38 | ||
|
|
44d10f11ca | ||
|
|
6cf733b9c6 | ||
|
|
1eb6e2cedf | ||
|
|
ef4deaba8f | ||
|
|
e8c196c2fa | ||
|
|
f7c9db6353 | ||
|
|
4ce720ff97 | ||
|
|
a96011629b | ||
|
|
9dcdcf97e8 | ||
|
|
5148338f52 | ||
|
|
0d3c04d8f8 | ||
|
|
15328a14b4 | ||
|
|
2d092f722a | ||
|
|
8825cb9b9b | ||
|
|
2f17e303ab | ||
|
|
4b56c8a343 | ||
|
|
7b6b62c623 | ||
|
|
07f5e66491 | ||
|
|
fe633f3220 | ||
|
|
af1090553f | ||
|
|
92c2e66660 | ||
|
|
08372f9dcb | ||
|
|
64ea0e2eee | ||
|
|
7ab476a88f | ||
|
|
de41ca911d | ||
|
|
dde9688f96 | ||
|
|
c1ca63edc0 | ||
|
|
cbc430499f | ||
|
|
4da9fa4802 | ||
|
|
42586d9556 | ||
|
|
ea4387d4ab | ||
|
|
0707b515ab | ||
|
|
78ae71fc46 | ||
|
|
3f62cd40e7 | ||
|
|
47657c0093 | ||
|
|
a5b0fde4b6 | ||
|
|
78cc0b34b1 | ||
|
|
e3017e986b | ||
|
|
e12cd876db | ||
|
|
5292e4b814 | ||
|
|
dbdd16ab89 | ||
|
|
61c2600286 | ||
|
|
163a33ae3a | ||
|
|
37d064aa62 | ||
|
|
ddc3c2e1b5 | ||
|
|
49184b287b | ||
|
|
f6139bda0d | ||
|
|
a6471b823b | ||
|
|
7c34003647 | ||
|
|
1aa21f9980 | ||
|
|
ce4ca50939 | ||
|
|
fb28260c4a | ||
|
|
626a904747 | ||
|
|
893cdafdc5 | ||
|
|
dbfb7d7d9c | ||
|
|
a66538a7db | ||
|
|
2f77d87d4f | ||
|
|
de85ba984c | ||
|
|
caac1a05ae | ||
|
|
eb5793b819 | ||
|
|
5ef3e1e2ce | ||
|
|
d8b459e5ee | ||
|
|
7b40d58aa1 | ||
|
|
809e9b838e | ||
|
|
23ae36ebd9 | ||
|
|
9c3f7d20f5 | ||
|
|
083298303c | ||
|
|
224970a07e | ||
|
|
86d039e5b0 | ||
|
|
6a8038aac9 | ||
|
|
e748f08a8e | ||
|
|
3580963e9f | ||
|
|
b008ce2ab8 | ||
|
|
ea0c2c7061 | ||
|
|
0926220933 | ||
|
|
ca975bbdd3 | ||
|
|
b16c5c5302 | ||
|
|
cad05fe5d9 | ||
|
|
a7cd466d9c | ||
|
|
4472a67ec0 | ||
|
|
c84a4029ec | ||
|
|
d7d9ab505e | ||
|
|
c582f5f5c7 | ||
|
|
4c30939339 | ||
|
|
cecd6a1d2b | ||
|
|
853dcbb364 | ||
|
|
ae327ed26d | ||
|
|
3e416aa255 | ||
|
|
61c2c3fc83 | ||
|
|
ca749aaf1e | ||
|
|
2a2cb3bd0c | ||
|
|
44e3d19844 | ||
|
|
1e25fffc70 | ||
|
|
44645ed23d | ||
|
|
fa557e5f76 | ||
|
|
7202fda38e | ||
|
|
d05afe41d6 | ||
|
|
bfc0b58728 | ||
|
|
22e8aaca81 | ||
|
|
5cb1247fb2 | ||
|
|
17a6d99703 | ||
|
|
3e7917f767 | ||
|
|
e9277d4dd9 | ||
|
|
058edd8af6 | ||
|
|
8ed7dcb9ff | ||
|
|
1f4827abc0 | ||
|
|
9715a0fcf7 | ||
|
|
9bf475c352 | ||
|
|
c2aeb4bca0 | ||
|
|
07b3020999 | ||
|
|
c2a7f39025 | ||
|
|
a92d422972 | ||
|
|
345eb65c3a | ||
|
|
a459973983 | ||
|
|
470dd4d78a | ||
|
|
e4cb183140 | ||
|
|
6455af96bf | ||
|
|
42afa87464 | ||
|
|
97466eeff2 | ||
|
|
bcbfd4ba9c | ||
|
|
cfa052fc31 | ||
|
|
3f71f6a8d8 | ||
|
|
b70e442ca3 | ||
|
|
1f60b2aadc | ||
|
|
3d2117ddaf | ||
|
|
bcff18ea58 | ||
|
|
2e9821402f | ||
|
|
8914c5cd51 | ||
|
|
0b240498f9 | ||
|
|
16f66364cf | ||
|
|
f2b0cec427 | ||
|
|
fac05ff5c0 | ||
|
|
1ac6dfd2a6 | ||
|
|
8bcac7344f | ||
|
|
300c986abb | ||
|
|
91a5f92df6 | ||
|
|
d60a09d48f | ||
|
|
b22bb7c7ad | ||
|
|
63cddc4ab0 | ||
|
|
790061d5c4 |
1
.env
1
.env
@@ -2,7 +2,6 @@ LC_ALL=en_US.UTF-8
|
|||||||
LANG=en_US.UTF-8
|
LANG=en_US.UTF-8
|
||||||
MailConfig__EmailServer=""
|
MailConfig__EmailServer=""
|
||||||
MailConfig__EmailFrom=""
|
MailConfig__EmailFrom=""
|
||||||
MailConfig__UseSSL="false"
|
|
||||||
MailConfig__Port=587
|
MailConfig__Port=587
|
||||||
MailConfig__Username=""
|
MailConfig__Username=""
|
||||||
MailConfig__Password=""
|
MailConfig__Password=""
|
||||||
|
|||||||
14
.github/FUNDING.yml
vendored
Normal file
14
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
|
patreon: lubelogger
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||||
|
polar: # Replace with a single Polar username
|
||||||
|
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
||||||
|
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||||
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -10,7 +10,7 @@ assignees: ''
|
|||||||
**Checklist**
|
**Checklist**
|
||||||
Please make sure you have performed the following steps before opening a new bug ticket, change `[ ]` to `[x]` to mark it as done
|
Please make sure you have performed the following steps before opening a new bug ticket, change `[ ]` to `[x]` to mark it as done
|
||||||
|
|
||||||
- [ ] I have read and tried the steps outlined in the [Troubleshooting Guide](https://docs.lubelogger.com/Troubleshooting)
|
- [ ] I have read and tried the steps outlined in the [Troubleshooting Guide](https://docs.lubelogger.com/Installation/Troubleshooting)
|
||||||
- [ ] I have searched through existing issues.
|
- [ ] I have searched through existing issues.
|
||||||
|
|
||||||
**Description**
|
**Description**
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@ wwwroot/translations/
|
|||||||
config/userConfig.json
|
config/userConfig.json
|
||||||
CarCareTracker.csproj.user
|
CarCareTracker.csproj.user
|
||||||
Properties/launchSettings.json
|
Properties/launchSettings.json
|
||||||
|
data/cartracker-log.db
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CsvHelper" Version="30.0.1" />
|
<PackageReference Include="CsvHelper" Version="30.0.1" />
|
||||||
<PackageReference Include="LiteDB" Version="5.0.17" />
|
<PackageReference Include="LiteDB" Version="5.0.17" />
|
||||||
<PackageReference Include="Npgsql" Version="8.0.2" />
|
<PackageReference Include="MailKit" Version="4.5.0" />
|
||||||
|
<PackageReference Include="Npgsql" Version="8.0.3" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using CarCareTracker.External.Implementations;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.External.Interfaces;
|
|
||||||
using CarCareTracker.Filter;
|
using CarCareTracker.Filter;
|
||||||
using CarCareTracker.Helper;
|
using CarCareTracker.Helper;
|
||||||
using CarCareTracker.Logic;
|
using CarCareTracker.Logic;
|
||||||
@@ -22,11 +21,15 @@ namespace CarCareTracker.Controllers
|
|||||||
private readonly IReminderRecordDataAccess _reminderRecordDataAccess;
|
private readonly IReminderRecordDataAccess _reminderRecordDataAccess;
|
||||||
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
|
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
|
||||||
private readonly IOdometerRecordDataAccess _odometerRecordDataAccess;
|
private readonly IOdometerRecordDataAccess _odometerRecordDataAccess;
|
||||||
|
private readonly ISupplyRecordDataAccess _supplyRecordDataAccess;
|
||||||
|
private readonly IPlanRecordDataAccess _planRecordDataAccess;
|
||||||
|
private readonly IPlanRecordTemplateDataAccess _planRecordTemplateDataAccess;
|
||||||
private readonly IUserAccessDataAccess _userAccessDataAccess;
|
private readonly IUserAccessDataAccess _userAccessDataAccess;
|
||||||
private readonly IUserRecordDataAccess _userRecordDataAccess;
|
private readonly IUserRecordDataAccess _userRecordDataAccess;
|
||||||
private readonly IReminderHelper _reminderHelper;
|
private readonly IReminderHelper _reminderHelper;
|
||||||
private readonly IGasHelper _gasHelper;
|
private readonly IGasHelper _gasHelper;
|
||||||
private readonly IUserLogic _userLogic;
|
private readonly IUserLogic _userLogic;
|
||||||
|
private readonly IVehicleLogic _vehicleLogic;
|
||||||
private readonly IOdometerLogic _odometerLogic;
|
private readonly IOdometerLogic _odometerLogic;
|
||||||
private readonly IFileHelper _fileHelper;
|
private readonly IFileHelper _fileHelper;
|
||||||
private readonly IMailHelper _mailHelper;
|
private readonly IMailHelper _mailHelper;
|
||||||
@@ -42,12 +45,16 @@ namespace CarCareTracker.Controllers
|
|||||||
IReminderRecordDataAccess reminderRecordDataAccess,
|
IReminderRecordDataAccess reminderRecordDataAccess,
|
||||||
IUpgradeRecordDataAccess upgradeRecordDataAccess,
|
IUpgradeRecordDataAccess upgradeRecordDataAccess,
|
||||||
IOdometerRecordDataAccess odometerRecordDataAccess,
|
IOdometerRecordDataAccess odometerRecordDataAccess,
|
||||||
|
ISupplyRecordDataAccess supplyRecordDataAccess,
|
||||||
|
IPlanRecordDataAccess planRecordDataAccess,
|
||||||
|
IPlanRecordTemplateDataAccess planRecordTemplateDataAccess,
|
||||||
IUserAccessDataAccess userAccessDataAccess,
|
IUserAccessDataAccess userAccessDataAccess,
|
||||||
IUserRecordDataAccess userRecordDataAccess,
|
IUserRecordDataAccess userRecordDataAccess,
|
||||||
IMailHelper mailHelper,
|
IMailHelper mailHelper,
|
||||||
IFileHelper fileHelper,
|
IFileHelper fileHelper,
|
||||||
IConfigHelper config,
|
IConfigHelper config,
|
||||||
IUserLogic userLogic,
|
IUserLogic userLogic,
|
||||||
|
IVehicleLogic vehicleLogic,
|
||||||
IOdometerLogic odometerLogic)
|
IOdometerLogic odometerLogic)
|
||||||
{
|
{
|
||||||
_dataAccess = dataAccess;
|
_dataAccess = dataAccess;
|
||||||
@@ -59,6 +66,9 @@ namespace CarCareTracker.Controllers
|
|||||||
_reminderRecordDataAccess = reminderRecordDataAccess;
|
_reminderRecordDataAccess = reminderRecordDataAccess;
|
||||||
_upgradeRecordDataAccess = upgradeRecordDataAccess;
|
_upgradeRecordDataAccess = upgradeRecordDataAccess;
|
||||||
_odometerRecordDataAccess = odometerRecordDataAccess;
|
_odometerRecordDataAccess = odometerRecordDataAccess;
|
||||||
|
_supplyRecordDataAccess = supplyRecordDataAccess;
|
||||||
|
_planRecordDataAccess = planRecordDataAccess;
|
||||||
|
_planRecordTemplateDataAccess = planRecordTemplateDataAccess;
|
||||||
_userAccessDataAccess = userAccessDataAccess;
|
_userAccessDataAccess = userAccessDataAccess;
|
||||||
_userRecordDataAccess = userRecordDataAccess;
|
_userRecordDataAccess = userRecordDataAccess;
|
||||||
_mailHelper = mailHelper;
|
_mailHelper = mailHelper;
|
||||||
@@ -66,6 +76,7 @@ namespace CarCareTracker.Controllers
|
|||||||
_reminderHelper = reminderHelper;
|
_reminderHelper = reminderHelper;
|
||||||
_userLogic = userLogic;
|
_userLogic = userLogic;
|
||||||
_odometerLogic = odometerLogic;
|
_odometerLogic = odometerLogic;
|
||||||
|
_vehicleLogic = vehicleLogic;
|
||||||
_fileHelper = fileHelper;
|
_fileHelper = fileHelper;
|
||||||
_config = config;
|
_config = config;
|
||||||
}
|
}
|
||||||
@@ -88,19 +99,119 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[Route("/api/vehicle/info")]
|
||||||
|
public IActionResult VehicleInfo(int vehicleId)
|
||||||
|
{
|
||||||
|
//stats for a specific or all vehicles
|
||||||
|
List<Vehicle> vehicles = new List<Vehicle>();
|
||||||
|
if (vehicleId != default)
|
||||||
|
{
|
||||||
|
if (_userLogic.UserCanEditVehicle(GetUserID(), vehicleId))
|
||||||
|
{
|
||||||
|
vehicles.Add(_dataAccess.GetVehicleById(vehicleId));
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return new RedirectResult("/Error/Unauthorized");
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
var result = _dataAccess.GetVehicles();
|
||||||
|
if (!User.IsInRole(nameof(UserData.IsRootUser)))
|
||||||
|
{
|
||||||
|
result = _userLogic.FilterUserVehicles(result, GetUserID());
|
||||||
|
}
|
||||||
|
vehicles.AddRange(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<VehicleInfo> apiResult = new List<VehicleInfo>();
|
||||||
|
|
||||||
|
foreach(Vehicle vehicle in vehicles)
|
||||||
|
{
|
||||||
|
var currentMileage = _vehicleLogic.GetMaxMileage(vehicle.Id);
|
||||||
|
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicle.Id);
|
||||||
|
var results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, DateTime.Now);
|
||||||
|
|
||||||
|
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicle.Id);
|
||||||
|
var repairRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicle.Id);
|
||||||
|
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicle.Id);
|
||||||
|
var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicle.Id);
|
||||||
|
var taxRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicle.Id);
|
||||||
|
var planRecords = _planRecordDataAccess.GetPlanRecordsByVehicleId(vehicle.Id);
|
||||||
|
|
||||||
|
var resultToAdd = new VehicleInfo()
|
||||||
|
{
|
||||||
|
VehicleData = vehicle,
|
||||||
|
LastReportedOdometer = currentMileage,
|
||||||
|
ServiceRecordCount = serviceRecords.Count(),
|
||||||
|
ServiceRecordCost = serviceRecords.Sum(x=>x.Cost),
|
||||||
|
RepairRecordCount = repairRecords.Count(),
|
||||||
|
RepairRecordCost = repairRecords.Sum(x=>x.Cost),
|
||||||
|
UpgradeRecordCount = upgradeRecords.Count(),
|
||||||
|
UpgradeRecordCost = upgradeRecords.Sum(x=>x.Cost),
|
||||||
|
GasRecordCount = gasRecords.Count(),
|
||||||
|
GasRecordCost = gasRecords.Sum(x=>x.Cost),
|
||||||
|
TaxRecordCount = taxRecords.Count(),
|
||||||
|
TaxRecordCost = taxRecords.Sum(x=> x.Cost),
|
||||||
|
VeryUrgentReminderCount = results.Count(x => x.Urgency == ReminderUrgency.VeryUrgent),
|
||||||
|
PastDueReminderCount = results.Count(x => x.Urgency == ReminderUrgency.PastDue),
|
||||||
|
UrgentReminderCount = results.Count(x => x.Urgency == ReminderUrgency.Urgent),
|
||||||
|
NotUrgentReminderCount = results.Count(x => x.Urgency == ReminderUrgency.NotUrgent),
|
||||||
|
PlanRecordBackLogCount = planRecords.Count(x=>x.Progress == PlanProgress.Backlog),
|
||||||
|
PlanRecordInProgressCount = planRecords.Count(x=>x.Progress == PlanProgress.InProgress),
|
||||||
|
PlanRecordTestingCount = planRecords.Count(x=>x.Progress == PlanProgress.Testing),
|
||||||
|
PlanRecordDoneCount = planRecords.Count(x=>x.Progress == PlanProgress.Done)
|
||||||
|
};
|
||||||
|
//set next reminder
|
||||||
|
if (results.Any(x => (x.Metric == ReminderMetric.Date || x.Metric == ReminderMetric.Both) && x.Date >= DateTime.Now.Date))
|
||||||
|
{
|
||||||
|
resultToAdd.NextReminder = results.Where(x => x.Date >= DateTime.Now.Date).OrderBy(x => x.Date).Select(x => new ReminderExportModel { Description = x.Description, Urgency = x.Urgency.ToString(), Metric = x.Metric.ToString(), Notes = x.Notes, DueDate = x.Date.ToShortDateString(), DueOdometer = x.Mileage.ToString() }).First();
|
||||||
|
}
|
||||||
|
else if (results.Any(x => (x.Metric == ReminderMetric.Odometer || x.Metric == ReminderMetric.Both) && x.Mileage >= currentMileage))
|
||||||
|
{
|
||||||
|
resultToAdd.NextReminder = results.Where(x => x.Mileage >= currentMileage).OrderBy(x => x.Mileage).Select(x => new ReminderExportModel { Description = x.Description, Urgency = x.Urgency.ToString(), Metric = x.Metric.ToString(), Notes = x.Notes, DueDate = x.Date.ToShortDateString(), DueOdometer = x.Mileage.ToString() }).First();
|
||||||
|
}
|
||||||
|
apiResult.Add(resultToAdd);
|
||||||
|
}
|
||||||
|
return Json(apiResult);
|
||||||
|
}
|
||||||
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
|
[HttpGet]
|
||||||
|
[Route("/api/vehicle/adjustedodometer")]
|
||||||
|
public IActionResult AdjustedOdometer(int vehicleId, int odometer)
|
||||||
|
{
|
||||||
|
var vehicle = _dataAccess.GetVehicleById(vehicleId);
|
||||||
|
if (vehicle == null || !vehicle.HasOdometerAdjustment)
|
||||||
|
{
|
||||||
|
return Json(odometer);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
var convertedOdometer = (odometer + int.Parse(vehicle.OdometerDifference)) * int.Parse(vehicle.OdometerMultiplier);
|
||||||
|
return Json(convertedOdometer);
|
||||||
|
}
|
||||||
|
}
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("/api/vehicle/servicerecords")]
|
[Route("/api/vehicle/servicerecords")]
|
||||||
public IActionResult ServiceRecords(int vehicleId)
|
public IActionResult ServiceRecords(int vehicleId)
|
||||||
{
|
{
|
||||||
|
if (vehicleId == default)
|
||||||
|
{
|
||||||
|
var response = new OperationResponse();
|
||||||
|
response.Success = false;
|
||||||
|
response.Message = "Must provide a valid vehicle id";
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(response);
|
||||||
|
}
|
||||||
var vehicleRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
||||||
var result = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString() });
|
var result = vehicleRecords.Select(x => new GenericRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields });
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("/api/vehicle/servicerecords/add")]
|
[Route("/api/vehicle/servicerecords/add")]
|
||||||
public IActionResult AddServiceRecord(int vehicleId, ServiceRecordExportModel input)
|
public IActionResult AddServiceRecord(int vehicleId, GenericRecordExportModel input)
|
||||||
{
|
{
|
||||||
var response = new OperationResponse();
|
var response = new OperationResponse();
|
||||||
if (vehicleId == default)
|
if (vehicleId == default)
|
||||||
@@ -129,7 +240,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Mileage = int.Parse(input.Odometer),
|
Mileage = int.Parse(input.Odometer),
|
||||||
Description = input.Description,
|
Description = input.Description,
|
||||||
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||||
Cost = decimal.Parse(input.Cost)
|
Cost = decimal.Parse(input.Cost),
|
||||||
|
ExtraFields = input.ExtraFields
|
||||||
};
|
};
|
||||||
_serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord);
|
_serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord);
|
||||||
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||||
@@ -161,14 +273,22 @@ namespace CarCareTracker.Controllers
|
|||||||
[Route("/api/vehicle/repairrecords")]
|
[Route("/api/vehicle/repairrecords")]
|
||||||
public IActionResult RepairRecords(int vehicleId)
|
public IActionResult RepairRecords(int vehicleId)
|
||||||
{
|
{
|
||||||
|
if (vehicleId == default)
|
||||||
|
{
|
||||||
|
var response = new OperationResponse();
|
||||||
|
response.Success = false;
|
||||||
|
response.Message = "Must provide a valid vehicle id";
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(response);
|
||||||
|
}
|
||||||
var vehicleRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
|
||||||
var result = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString() });
|
var result = vehicleRecords.Select(x => new GenericRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields });
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("/api/vehicle/repairrecords/add")]
|
[Route("/api/vehicle/repairrecords/add")]
|
||||||
public IActionResult AddRepairRecord(int vehicleId, ServiceRecordExportModel input)
|
public IActionResult AddRepairRecord(int vehicleId, GenericRecordExportModel input)
|
||||||
{
|
{
|
||||||
var response = new OperationResponse();
|
var response = new OperationResponse();
|
||||||
if (vehicleId == default)
|
if (vehicleId == default)
|
||||||
@@ -197,7 +317,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Mileage = int.Parse(input.Odometer),
|
Mileage = int.Parse(input.Odometer),
|
||||||
Description = input.Description,
|
Description = input.Description,
|
||||||
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||||
Cost = decimal.Parse(input.Cost)
|
Cost = decimal.Parse(input.Cost),
|
||||||
|
ExtraFields = input.ExtraFields
|
||||||
};
|
};
|
||||||
_collisionRecordDataAccess.SaveCollisionRecordToVehicle(repairRecord);
|
_collisionRecordDataAccess.SaveCollisionRecordToVehicle(repairRecord);
|
||||||
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||||
@@ -229,14 +350,22 @@ namespace CarCareTracker.Controllers
|
|||||||
[Route("/api/vehicle/upgraderecords")]
|
[Route("/api/vehicle/upgraderecords")]
|
||||||
public IActionResult UpgradeRecords(int vehicleId)
|
public IActionResult UpgradeRecords(int vehicleId)
|
||||||
{
|
{
|
||||||
|
if (vehicleId == default)
|
||||||
|
{
|
||||||
|
var response = new OperationResponse();
|
||||||
|
response.Success = false;
|
||||||
|
response.Message = "Must provide a valid vehicle id";
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(response);
|
||||||
|
}
|
||||||
var vehicleRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
||||||
var result = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString() });
|
var result = vehicleRecords.Select(x => new GenericRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), ExtraFields = x.ExtraFields });
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("/api/vehicle/upgraderecords/add")]
|
[Route("/api/vehicle/upgraderecords/add")]
|
||||||
public IActionResult AddUpgradeRecord(int vehicleId, ServiceRecordExportModel input)
|
public IActionResult AddUpgradeRecord(int vehicleId, GenericRecordExportModel input)
|
||||||
{
|
{
|
||||||
var response = new OperationResponse();
|
var response = new OperationResponse();
|
||||||
if (vehicleId == default)
|
if (vehicleId == default)
|
||||||
@@ -265,7 +394,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Mileage = int.Parse(input.Odometer),
|
Mileage = int.Parse(input.Odometer),
|
||||||
Description = input.Description,
|
Description = input.Description,
|
||||||
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||||
Cost = decimal.Parse(input.Cost)
|
Cost = decimal.Parse(input.Cost),
|
||||||
|
ExtraFields = input.ExtraFields
|
||||||
};
|
};
|
||||||
_upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord);
|
_upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord);
|
||||||
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||||
@@ -297,7 +427,15 @@ namespace CarCareTracker.Controllers
|
|||||||
[Route("/api/vehicle/taxrecords")]
|
[Route("/api/vehicle/taxrecords")]
|
||||||
public IActionResult TaxRecords(int vehicleId)
|
public IActionResult TaxRecords(int vehicleId)
|
||||||
{
|
{
|
||||||
var result = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
|
if (vehicleId == default)
|
||||||
|
{
|
||||||
|
var response = new OperationResponse();
|
||||||
|
response.Success = false;
|
||||||
|
response.Message = "Must provide a valid vehicle id";
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(response);
|
||||||
|
}
|
||||||
|
var result = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId).Select(x => new TaxRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, ExtraFields = x.ExtraFields });
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
@@ -330,7 +468,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Date = DateTime.Parse(input.Date),
|
Date = DateTime.Parse(input.Date),
|
||||||
Description = input.Description,
|
Description = input.Description,
|
||||||
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||||
Cost = decimal.Parse(input.Cost)
|
Cost = decimal.Parse(input.Cost),
|
||||||
|
ExtraFields = input.ExtraFields
|
||||||
};
|
};
|
||||||
_taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord);
|
_taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord);
|
||||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleId, User.Identity.Name, $"Added Tax Record via API - Description: {taxRecord.Description}");
|
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleId, User.Identity.Name, $"Added Tax Record via API - Description: {taxRecord.Description}");
|
||||||
@@ -351,7 +490,15 @@ namespace CarCareTracker.Controllers
|
|||||||
[Route("/api/vehicle/odometerrecords/latest")]
|
[Route("/api/vehicle/odometerrecords/latest")]
|
||||||
public IActionResult LastOdometer(int vehicleId)
|
public IActionResult LastOdometer(int vehicleId)
|
||||||
{
|
{
|
||||||
var result = GetMaxMileage(vehicleId);
|
if (vehicleId == default)
|
||||||
|
{
|
||||||
|
var response = new OperationResponse();
|
||||||
|
response.Success = false;
|
||||||
|
response.Message = "Must provide a valid vehicle id";
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(response);
|
||||||
|
}
|
||||||
|
var result = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
@@ -359,13 +506,21 @@ namespace CarCareTracker.Controllers
|
|||||||
[Route("/api/vehicle/odometerrecords")]
|
[Route("/api/vehicle/odometerrecords")]
|
||||||
public IActionResult OdometerRecords(int vehicleId)
|
public IActionResult OdometerRecords(int vehicleId)
|
||||||
{
|
{
|
||||||
|
if (vehicleId == default)
|
||||||
|
{
|
||||||
|
var response = new OperationResponse();
|
||||||
|
response.Success = false;
|
||||||
|
response.Message = "Must provide a valid vehicle id";
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(response);
|
||||||
|
}
|
||||||
var vehicleRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||||
//determine if conversion is needed.
|
//determine if conversion is needed.
|
||||||
if (vehicleRecords.All(x => x.InitialMileage == default))
|
if (vehicleRecords.All(x => x.InitialMileage == default))
|
||||||
{
|
{
|
||||||
vehicleRecords = _odometerLogic.AutoConvertOdometerRecord(vehicleRecords);
|
vehicleRecords = _odometerLogic.AutoConvertOdometerRecord(vehicleRecords);
|
||||||
}
|
}
|
||||||
var result = vehicleRecords.Select(x => new OdometerRecordExportModel { Date = x.Date.ToShortDateString(), InitialOdometer = x.InitialMileage.ToString(), Odometer = x.Mileage.ToString(), Notes = x.Notes });
|
var result = vehicleRecords.Select(x => new OdometerRecordExportModel { Date = x.Date.ToShortDateString(), InitialOdometer = x.InitialMileage.ToString(), Odometer = x.Mileage.ToString(), Notes = x.Notes, ExtraFields = x.ExtraFields });
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
@@ -397,7 +552,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Date = DateTime.Parse(input.Date),
|
Date = DateTime.Parse(input.Date),
|
||||||
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||||
InitialMileage = (string.IsNullOrWhiteSpace(input.InitialOdometer) || int.Parse(input.InitialOdometer) == default) ? _odometerLogic.GetLastOdometerRecordMileage(vehicleId, new List<OdometerRecord>()) : int.Parse(input.InitialOdometer),
|
InitialMileage = (string.IsNullOrWhiteSpace(input.InitialOdometer) || int.Parse(input.InitialOdometer) == default) ? _odometerLogic.GetLastOdometerRecordMileage(vehicleId, new List<OdometerRecord>()) : int.Parse(input.InitialOdometer),
|
||||||
Mileage = int.Parse(input.Odometer)
|
Mileage = int.Parse(input.Odometer),
|
||||||
|
ExtraFields = input.ExtraFields
|
||||||
};
|
};
|
||||||
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord);
|
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord);
|
||||||
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleId, User.Identity.Name, $"Added Odometer Record via API - Mileage: {odometerRecord.Mileage.ToString()}");
|
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleId, User.Identity.Name, $"Added Odometer Record via API - Mileage: {odometerRecord.Mileage.ToString()}");
|
||||||
@@ -417,6 +573,14 @@ namespace CarCareTracker.Controllers
|
|||||||
[Route("/api/vehicle/gasrecords")]
|
[Route("/api/vehicle/gasrecords")]
|
||||||
public IActionResult GasRecords(int vehicleId, bool useMPG, bool useUKMPG)
|
public IActionResult GasRecords(int vehicleId, bool useMPG, bool useUKMPG)
|
||||||
{
|
{
|
||||||
|
if (vehicleId == default)
|
||||||
|
{
|
||||||
|
var response = new OperationResponse();
|
||||||
|
response.Success = false;
|
||||||
|
response.Message = "Must provide a valid vehicle id";
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(response);
|
||||||
|
}
|
||||||
var vehicleRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
|
||||||
var result = _gasHelper.GetGasRecordViewModels(vehicleRecords, useMPG, useUKMPG)
|
var result = _gasHelper.GetGasRecordViewModels(vehicleRecords, useMPG, useUKMPG)
|
||||||
.Select(x => new GasRecordExportModel {
|
.Select(x => new GasRecordExportModel {
|
||||||
@@ -427,7 +591,8 @@ namespace CarCareTracker.Controllers
|
|||||||
FuelEconomy = x.MilesPerGallon.ToString(),
|
FuelEconomy = x.MilesPerGallon.ToString(),
|
||||||
IsFillToFull = x.IsFillToFull.ToString(),
|
IsFillToFull = x.IsFillToFull.ToString(),
|
||||||
MissedFuelUp = x.MissedFuelUp.ToString(),
|
MissedFuelUp = x.MissedFuelUp.ToString(),
|
||||||
Notes = x.Notes
|
Notes = x.Notes,
|
||||||
|
ExtraFields = x.ExtraFields
|
||||||
});
|
});
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
@@ -468,7 +633,8 @@ namespace CarCareTracker.Controllers
|
|||||||
IsFillToFull = bool.Parse(input.IsFillToFull),
|
IsFillToFull = bool.Parse(input.IsFillToFull),
|
||||||
MissedFuelUp = bool.Parse(input.MissedFuelUp),
|
MissedFuelUp = bool.Parse(input.MissedFuelUp),
|
||||||
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||||
Cost = decimal.Parse(input.Cost)
|
Cost = decimal.Parse(input.Cost),
|
||||||
|
ExtraFields = input.ExtraFields
|
||||||
};
|
};
|
||||||
_gasRecordDataAccess.SaveGasRecordToVehicle(gasRecord);
|
_gasRecordDataAccess.SaveGasRecordToVehicle(gasRecord);
|
||||||
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||||
@@ -500,9 +666,17 @@ namespace CarCareTracker.Controllers
|
|||||||
[Route("/api/vehicle/reminders")]
|
[Route("/api/vehicle/reminders")]
|
||||||
public IActionResult Reminders(int vehicleId)
|
public IActionResult Reminders(int vehicleId)
|
||||||
{
|
{
|
||||||
var currentMileage = GetMaxMileage(vehicleId);
|
if (vehicleId == default)
|
||||||
|
{
|
||||||
|
var response = new OperationResponse();
|
||||||
|
response.Success = false;
|
||||||
|
response.Message = "Must provide a valid vehicle id";
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(response);
|
||||||
|
}
|
||||||
|
var currentMileage = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||||
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(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});
|
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, DueDate = x.Date.ToShortDateString(), DueOdometer = x.Mileage.ToString()});
|
||||||
return Json(results);
|
return Json(results);
|
||||||
}
|
}
|
||||||
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||||
@@ -512,11 +686,12 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
var vehicles = _dataAccess.GetVehicles();
|
var vehicles = _dataAccess.GetVehicles();
|
||||||
List<OperationResponse> operationResponses = new List<OperationResponse>();
|
List<OperationResponse> operationResponses = new List<OperationResponse>();
|
||||||
|
var defaultEmailAddress = _config.GetUserConfig(User).DefaultReminderEmail;
|
||||||
foreach(Vehicle vehicle in vehicles)
|
foreach(Vehicle vehicle in vehicles)
|
||||||
{
|
{
|
||||||
var vehicleId = vehicle.Id;
|
var vehicleId = vehicle.Id;
|
||||||
//get reminders
|
//get reminders
|
||||||
var currentMileage = GetMaxMileage(vehicleId);
|
var currentMileage = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||||
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
||||||
var results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, DateTime.Now).OrderByDescending(x => x.Urgency).ToList();
|
var results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, DateTime.Now).OrderByDescending(x => x.Urgency).ToList();
|
||||||
results.RemoveAll(x => !urgencies.Contains(x.Urgency));
|
results.RemoveAll(x => !urgencies.Contains(x.Urgency));
|
||||||
@@ -527,6 +702,10 @@ namespace CarCareTracker.Controllers
|
|||||||
//get list of recipients.
|
//get list of recipients.
|
||||||
var userIds = _userAccessDataAccess.GetUserAccessByVehicleId(vehicleId).Select(x => x.Id.UserId);
|
var userIds = _userAccessDataAccess.GetUserAccessByVehicleId(vehicleId).Select(x => x.Id.UserId);
|
||||||
List<string> emailRecipients = new List<string>();
|
List<string> emailRecipients = new List<string>();
|
||||||
|
if (!string.IsNullOrWhiteSpace(defaultEmailAddress))
|
||||||
|
{
|
||||||
|
emailRecipients.Add(defaultEmailAddress);
|
||||||
|
}
|
||||||
foreach (int userId in userIds)
|
foreach (int userId in userIds)
|
||||||
{
|
{
|
||||||
var userData = _userRecordDataAccess.GetUserRecordById(userId);
|
var userData = _userRecordDataAccess.GetUserRecordById(userId);
|
||||||
@@ -539,15 +718,19 @@ namespace CarCareTracker.Controllers
|
|||||||
var result = _mailHelper.NotifyUserForReminders(vehicle, emailRecipients, results);
|
var result = _mailHelper.NotifyUserForReminders(vehicle, emailRecipients, results);
|
||||||
operationResponses.Add(result);
|
operationResponses.Add(result);
|
||||||
}
|
}
|
||||||
if (operationResponses.All(x => x.Success))
|
if (!operationResponses.Any())
|
||||||
{
|
{
|
||||||
return Json(new OperationResponse { Success = true, Message = "Emails sent" });
|
return Json(new OperationResponse { Success = false, Message = "No Emails Sent, No Vehicles Available or No Recipients Configured" });
|
||||||
|
}
|
||||||
|
else if (operationResponses.All(x => x.Success))
|
||||||
|
{
|
||||||
|
return Json(new OperationResponse { Success = true, Message = $"Emails Sent({operationResponses.Count()})" });
|
||||||
} else if (operationResponses.All(x => !x.Success))
|
} else if (operationResponses.All(x => !x.Success))
|
||||||
{
|
{
|
||||||
return Json(new OperationResponse { Success = false, Message = "All emails failed, check SMTP settings" });
|
return Json(new OperationResponse { Success = false, Message = $"All Emails Failed({operationResponses.Count()}), Check SMTP Settings" });
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
return Json(new OperationResponse { Success = true, Message = "Some emails sent, some failed, check recipient settings" });
|
return Json(new OperationResponse { Success = true, Message = $"Emails Sent({operationResponses.Count(x => x.Success)}), Emails Failed({operationResponses.Count(x => !x.Success)}), Check Recipient Settings" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||||
@@ -560,41 +743,54 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
[Route("/api/cleanup")]
|
||||||
|
public IActionResult CleanUp(bool deepClean = false)
|
||||||
|
{
|
||||||
|
var jsonResponse = new Dictionary<string, string>();
|
||||||
|
//Clear out temp folder
|
||||||
|
var tempFilesDeleted = _fileHelper.ClearTempFolder();
|
||||||
|
jsonResponse.Add("temp_files_deleted", tempFilesDeleted.ToString());
|
||||||
|
if (deepClean)
|
||||||
|
{
|
||||||
|
//clear out unused vehicle thumbnails
|
||||||
|
var vehicles = _dataAccess.GetVehicles();
|
||||||
|
var vehicleImages = vehicles.Select(x => x.ImageLocation).Where(x => x.StartsWith("/images/")).Select(x=>Path.GetFileName(x)).ToList();
|
||||||
|
if (vehicleImages.Any())
|
||||||
|
{
|
||||||
|
var thumbnailsDeleted = _fileHelper.ClearUnlinkedThumbnails(vehicleImages);
|
||||||
|
jsonResponse.Add("unlinked_thumbnails_deleted", thumbnailsDeleted.ToString());
|
||||||
|
}
|
||||||
|
var vehicleDocuments = new List<string>();
|
||||||
|
foreach(Vehicle vehicle in vehicles)
|
||||||
|
{
|
||||||
|
vehicleDocuments.AddRange(_serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y=>Path.GetFileName(y.Location)));
|
||||||
|
vehicleDocuments.AddRange(_collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||||
|
vehicleDocuments.AddRange(_upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||||
|
vehicleDocuments.AddRange(_taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||||
|
vehicleDocuments.AddRange(_gasRecordDataAccess.GetGasRecordsByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||||
|
vehicleDocuments.AddRange(_noteDataAccess.GetNotesByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||||
|
vehicleDocuments.AddRange(_odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||||
|
vehicleDocuments.AddRange(_supplyRecordDataAccess.GetSupplyRecordsByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||||
|
vehicleDocuments.AddRange(_planRecordDataAccess.GetPlanRecordsByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||||
|
vehicleDocuments.AddRange(_planRecordTemplateDataAccess.GetPlanRecordTemplatesByVehicleId(vehicle.Id).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||||
|
}
|
||||||
|
//shop supplies
|
||||||
|
vehicleDocuments.AddRange(_supplyRecordDataAccess.GetSupplyRecordsByVehicleId(0).SelectMany(x => x.Files).Select(y => Path.GetFileName(y.Location)));
|
||||||
|
if (vehicleDocuments.Any())
|
||||||
|
{
|
||||||
|
var documentsDeleted = _fileHelper.ClearUnlinkedDocuments(vehicleDocuments);
|
||||||
|
jsonResponse.Add("unlinked_documents_deleted", documentsDeleted.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Json(jsonResponse);
|
||||||
|
}
|
||||||
|
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||||
|
[HttpGet]
|
||||||
[Route("/api/demo/restore")]
|
[Route("/api/demo/restore")]
|
||||||
public IActionResult RestoreDemo()
|
public IActionResult RestoreDemo()
|
||||||
{
|
{
|
||||||
var result = _fileHelper.RestoreBackup("/defaults/demo_default.zip", true);
|
var result = _fileHelper.RestoreBackup("/defaults/demo_default.zip", true);
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
private int GetMaxMileage(int vehicleId)
|
|
||||||
{
|
|
||||||
var numbersArray = new List<int>();
|
|
||||||
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
|
||||||
if (serviceRecords.Any())
|
|
||||||
{
|
|
||||||
numbersArray.Add(serviceRecords.Max(x => x.Mileage));
|
|
||||||
}
|
|
||||||
var repairRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
|
|
||||||
if (repairRecords.Any())
|
|
||||||
{
|
|
||||||
numbersArray.Add(repairRecords.Max(x => x.Mileage));
|
|
||||||
}
|
|
||||||
var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
|
|
||||||
if (gasRecords.Any())
|
|
||||||
{
|
|
||||||
numbersArray.Add(gasRecords.Max(x => x.Mileage));
|
|
||||||
}
|
|
||||||
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
|
||||||
if (upgradeRecords.Any())
|
|
||||||
{
|
|
||||||
numbersArray.Add(upgradeRecords.Max(x => x.Mileage));
|
|
||||||
}
|
|
||||||
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
|
||||||
if (odometerRecords.Any())
|
|
||||||
{
|
|
||||||
numbersArray.Add(odometerRecords.Max(x => x.Mileage));
|
|
||||||
}
|
|
||||||
return numbersArray.Any() ? numbersArray.Max() : 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ namespace CarCareTracker.Controllers
|
|||||||
private readonly IVehicleDataAccess _dataAccess;
|
private readonly IVehicleDataAccess _dataAccess;
|
||||||
private readonly IUserLogic _userLogic;
|
private readonly IUserLogic _userLogic;
|
||||||
private readonly ILoginLogic _loginLogic;
|
private readonly ILoginLogic _loginLogic;
|
||||||
|
private readonly IVehicleLogic _vehicleLogic;
|
||||||
private readonly IFileHelper _fileHelper;
|
private readonly IFileHelper _fileHelper;
|
||||||
private readonly IConfigHelper _config;
|
private readonly IConfigHelper _config;
|
||||||
private readonly IExtraFieldDataAccess _extraFieldDataAccess;
|
private readonly IExtraFieldDataAccess _extraFieldDataAccess;
|
||||||
@@ -25,6 +26,7 @@ namespace CarCareTracker.Controllers
|
|||||||
IVehicleDataAccess dataAccess,
|
IVehicleDataAccess dataAccess,
|
||||||
IUserLogic userLogic,
|
IUserLogic userLogic,
|
||||||
ILoginLogic loginLogic,
|
ILoginLogic loginLogic,
|
||||||
|
IVehicleLogic vehicleLogic,
|
||||||
IConfigHelper configuration,
|
IConfigHelper configuration,
|
||||||
IFileHelper fileHelper,
|
IFileHelper fileHelper,
|
||||||
IExtraFieldDataAccess extraFieldDataAccess,
|
IExtraFieldDataAccess extraFieldDataAccess,
|
||||||
@@ -40,6 +42,7 @@ namespace CarCareTracker.Controllers
|
|||||||
_reminderRecordDataAccess = reminderRecordDataAccess;
|
_reminderRecordDataAccess = reminderRecordDataAccess;
|
||||||
_reminderHelper = reminderHelper;
|
_reminderHelper = reminderHelper;
|
||||||
_loginLogic = loginLogic;
|
_loginLogic = loginLogic;
|
||||||
|
_vehicleLogic = vehicleLogic;
|
||||||
}
|
}
|
||||||
private int GetUserID()
|
private int GetUserID()
|
||||||
{
|
{
|
||||||
@@ -56,7 +59,52 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
vehiclesStored = _userLogic.FilterUserVehicles(vehiclesStored, GetUserID());
|
vehiclesStored = _userLogic.FilterUserVehicles(vehiclesStored, GetUserID());
|
||||||
}
|
}
|
||||||
return PartialView("_GarageDisplay", vehiclesStored);
|
var vehicleViewModels = vehiclesStored.Select(x => {
|
||||||
|
var vehicleVM = 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,
|
||||||
|
IsDiesel = x.IsDiesel,
|
||||||
|
UseHours = x.UseHours,
|
||||||
|
OdometerOptional = x.OdometerOptional,
|
||||||
|
ExtraFields = x.ExtraFields,
|
||||||
|
Tags = x.Tags,
|
||||||
|
DashboardMetrics = x.DashboardMetrics
|
||||||
|
};
|
||||||
|
//dashboard metrics
|
||||||
|
if (x.DashboardMetrics.Any())
|
||||||
|
{
|
||||||
|
var vehicleRecords = _vehicleLogic.GetVehicleRecords(x.Id);
|
||||||
|
var userConfig = _config.GetUserConfig(User);
|
||||||
|
var distanceUnit = x.UseHours ? "h" : userConfig.UseMPG ? "mi." : "km";
|
||||||
|
if (vehicleVM.DashboardMetrics.Contains(DashboardMetric.Default))
|
||||||
|
{
|
||||||
|
vehicleVM.LastReportedMileage = _vehicleLogic.GetMaxMileage(vehicleRecords);
|
||||||
|
vehicleVM.HasReminders = _vehicleLogic.GetVehicleHasUrgentOrPastDueReminders(x.Id, vehicleVM.LastReportedMileage);
|
||||||
|
}
|
||||||
|
if (vehicleVM.DashboardMetrics.Contains(DashboardMetric.CostPerMile))
|
||||||
|
{
|
||||||
|
var vehicleTotalCost = _vehicleLogic.GetVehicleTotalCost(vehicleRecords);
|
||||||
|
var maxMileage = _vehicleLogic.GetMaxMileage(vehicleRecords);
|
||||||
|
var minMileage = _vehicleLogic.GetMinMileage(vehicleRecords);
|
||||||
|
var totalDistance = maxMileage - minMileage;
|
||||||
|
vehicleVM.CostPerMile = totalDistance != default ? vehicleTotalCost / totalDistance : 0.00M;
|
||||||
|
vehicleVM.DistanceUnit = distanceUnit;
|
||||||
|
}
|
||||||
|
if (vehicleVM.DashboardMetrics.Contains(DashboardMetric.TotalCost))
|
||||||
|
{
|
||||||
|
vehicleVM.TotalCost = _vehicleLogic.GetVehicleTotalCost(vehicleRecords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vehicleVM;
|
||||||
|
}).ToList();
|
||||||
|
return PartialView("_GarageDisplay", vehicleViewModels);
|
||||||
}
|
}
|
||||||
public IActionResult Calendar()
|
public IActionResult Calendar()
|
||||||
{
|
{
|
||||||
@@ -86,7 +134,7 @@ namespace CarCareTracker.Controllers
|
|||||||
var reminderUrgency = _reminderHelper.GetReminderRecordViewModels(new List<ReminderRecord> { reminder }, 0, DateTime.Now).FirstOrDefault();
|
var reminderUrgency = _reminderHelper.GetReminderRecordViewModels(new List<ReminderRecord> { reminder }, 0, DateTime.Now).FirstOrDefault();
|
||||||
return PartialView("_ReminderRecordCalendarModal", reminderUrgency);
|
return PartialView("_ReminderRecordCalendarModal", reminderUrgency);
|
||||||
}
|
}
|
||||||
public IActionResult Settings()
|
public async Task<IActionResult> Settings()
|
||||||
{
|
{
|
||||||
var userConfig = _config.GetUserConfig(User);
|
var userConfig = _config.GetUserConfig(User);
|
||||||
var languages = _fileHelper.GetLanguages();
|
var languages = _fileHelper.GetLanguages();
|
||||||
@@ -95,6 +143,16 @@ namespace CarCareTracker.Controllers
|
|||||||
UserConfig = userConfig,
|
UserConfig = userConfig,
|
||||||
UILanguages = languages
|
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);
|
return PartialView("_Settings", viewModel);
|
||||||
}
|
}
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
@@ -190,6 +248,13 @@ namespace CarCareTracker.Controllers
|
|||||||
var userName = User.Identity.Name;
|
var userName = User.Identity.Name;
|
||||||
return PartialView("_AccountModal", new UserData() { EmailAddress = emailAddress, UserName = userName });
|
return PartialView("_AccountModal", new UserData() { EmailAddress = emailAddress, UserName = userName });
|
||||||
}
|
}
|
||||||
|
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult GetRootAccountInformationModal()
|
||||||
|
{
|
||||||
|
var userName = User.Identity.Name;
|
||||||
|
return PartialView("_RootAccountModal", new UserData() { UserName = userName });
|
||||||
|
}
|
||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
public IActionResult Error()
|
public IActionResult Error()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,10 +29,32 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
public IActionResult Index(string redirectURL = "")
|
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;
|
||||||
|
var pkceKeyPair = _loginLogic.GetPKCEChallengeCode();
|
||||||
|
remoteAuthConfig.CodeChallenge = pkceKeyPair.Value;
|
||||||
|
if (remoteAuthConfig.ValidateState)
|
||||||
|
{
|
||||||
|
Response.Cookies.Append("OIDC_STATE", remoteAuthConfig.State, new CookieOptions { Expires = new DateTimeOffset(DateTime.Now.AddMinutes(5)) });
|
||||||
|
}
|
||||||
|
if (remoteAuthConfig.UsePKCE)
|
||||||
|
{
|
||||||
|
Response.Cookies.Append("OIDC_VERIFIER", pkceKeyPair.Key, new CookieOptions { Expires = new DateTimeOffset(DateTime.Now.AddMinutes(5)) });
|
||||||
|
}
|
||||||
|
var remoteAuthURL = remoteAuthConfig.RemoteAuthURL;
|
||||||
|
return Redirect(remoteAuthURL);
|
||||||
|
}
|
||||||
return View(model: redirectURL);
|
return View(model: redirectURL);
|
||||||
}
|
}
|
||||||
public IActionResult Registration()
|
public IActionResult Registration()
|
||||||
{
|
{
|
||||||
|
if (_config.GetServerDisabledRegistration())
|
||||||
|
{
|
||||||
|
return RedirectToAction("Index");
|
||||||
|
}
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
public IActionResult ForgotPassword()
|
public IActionResult ForgotPassword()
|
||||||
@@ -48,10 +70,16 @@ namespace CarCareTracker.Controllers
|
|||||||
var remoteAuthConfig = _config.GetOpenIDConfig();
|
var remoteAuthConfig = _config.GetOpenIDConfig();
|
||||||
var generatedState = Guid.NewGuid().ToString().Substring(0, 8);
|
var generatedState = Guid.NewGuid().ToString().Substring(0, 8);
|
||||||
remoteAuthConfig.State = generatedState;
|
remoteAuthConfig.State = generatedState;
|
||||||
|
var pkceKeyPair = _loginLogic.GetPKCEChallengeCode();
|
||||||
|
remoteAuthConfig.CodeChallenge = pkceKeyPair.Value;
|
||||||
if (remoteAuthConfig.ValidateState)
|
if (remoteAuthConfig.ValidateState)
|
||||||
{
|
{
|
||||||
Response.Cookies.Append("OIDC_STATE", remoteAuthConfig.State, new CookieOptions { Expires = new DateTimeOffset(DateTime.Now.AddMinutes(5)) });
|
Response.Cookies.Append("OIDC_STATE", remoteAuthConfig.State, new CookieOptions { Expires = new DateTimeOffset(DateTime.Now.AddMinutes(5)) });
|
||||||
}
|
}
|
||||||
|
if (remoteAuthConfig.UsePKCE)
|
||||||
|
{
|
||||||
|
Response.Cookies.Append("OIDC_VERIFIER", pkceKeyPair.Key, new CookieOptions { Expires = new DateTimeOffset(DateTime.Now.AddMinutes(5)) });
|
||||||
|
}
|
||||||
var remoteAuthURL = remoteAuthConfig.RemoteAuthURL;
|
var remoteAuthURL = remoteAuthConfig.RemoteAuthURL;
|
||||||
return Json(remoteAuthURL);
|
return Json(remoteAuthURL);
|
||||||
}
|
}
|
||||||
@@ -87,6 +115,16 @@ namespace CarCareTracker.Controllers
|
|||||||
new KeyValuePair<string, string>("client_secret", openIdConfig.ClientSecret),
|
new KeyValuePair<string, string>("client_secret", openIdConfig.ClientSecret),
|
||||||
new KeyValuePair<string, string>("redirect_uri", openIdConfig.RedirectURL)
|
new KeyValuePair<string, string>("redirect_uri", openIdConfig.RedirectURL)
|
||||||
};
|
};
|
||||||
|
if (openIdConfig.UsePKCE)
|
||||||
|
{
|
||||||
|
//retrieve stored challenge verifier
|
||||||
|
var storedVerifier = Request.Cookies["OIDC_VERIFIER"];
|
||||||
|
if (!string.IsNullOrWhiteSpace(storedVerifier))
|
||||||
|
{
|
||||||
|
httpParams.Add(new KeyValuePair<string, string>("code_verifier", storedVerifier));
|
||||||
|
Response.Cookies.Delete("OIDC_VERIFIER");
|
||||||
|
}
|
||||||
|
}
|
||||||
var httpRequest = new HttpRequestMessage(HttpMethod.Post, openIdConfig.TokenURL)
|
var httpRequest = new HttpRequestMessage(HttpMethod.Post, openIdConfig.TokenURL)
|
||||||
{
|
{
|
||||||
Content = new FormUrlEncodedContent(httpParams)
|
Content = new FormUrlEncodedContent(httpParams)
|
||||||
@@ -125,6 +163,11 @@ namespace CarCareTracker.Controllers
|
|||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
_logger.LogInformation("OpenID Provider did not provide a valid id_token");
|
_logger.LogInformation("OpenID Provider did not provide a valid id_token");
|
||||||
|
if (!string.IsNullOrWhiteSpace(tokenResult))
|
||||||
|
{
|
||||||
|
//if something was returned from the IdP but it's invalid, we want to log it as an error.
|
||||||
|
_logger.LogError($"Expected id_token, received {tokenResult}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
@@ -208,7 +251,7 @@ namespace CarCareTracker.Controllers
|
|||||||
var result = _loginLogic.ResetPasswordByUser(credentials);
|
var result = _loginLogic.ResetPasswordByUser(credentials);
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
[Authorize] //User must already be logged in to do this.
|
[Authorize(Roles = nameof(UserData.IsRootUser))] //User must already be logged in as root user to do this.
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult CreateLoginCreds(LoginModel credentials)
|
public IActionResult CreateLoginCreds(LoginModel credentials)
|
||||||
{
|
{
|
||||||
@@ -223,7 +266,7 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
return Json(false);
|
return Json(false);
|
||||||
}
|
}
|
||||||
[Authorize]
|
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult DestroyLoginCreds()
|
public IActionResult DestroyLoginCreds()
|
||||||
{
|
{
|
||||||
@@ -248,7 +291,12 @@ namespace CarCareTracker.Controllers
|
|||||||
public IActionResult LogOut()
|
public IActionResult LogOut()
|
||||||
{
|
{
|
||||||
Response.Cookies.Delete("ACCESS_TOKEN");
|
Response.Cookies.Delete("ACCESS_TOKEN");
|
||||||
return Json(true);
|
var remoteAuthConfig = _config.GetOpenIDConfig();
|
||||||
|
if (remoteAuthConfig.DisableRegularLogin && !string.IsNullOrWhiteSpace(remoteAuthConfig.LogOutURL))
|
||||||
|
{
|
||||||
|
return Json(remoteAuthConfig.LogOutURL);
|
||||||
|
}
|
||||||
|
return Json("/Login");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using CarCareTracker.External.Interfaces;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
using LiteDB;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using CarCareTracker.Helper;
|
using CarCareTracker.Helper;
|
||||||
using CsvHelper;
|
using CsvHelper;
|
||||||
@@ -10,6 +9,7 @@ using CarCareTracker.MapProfile;
|
|||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using CarCareTracker.Logic;
|
using CarCareTracker.Logic;
|
||||||
using CarCareTracker.Filter;
|
using CarCareTracker.Filter;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace CarCareTracker.Controllers
|
namespace CarCareTracker.Controllers
|
||||||
{
|
{
|
||||||
@@ -37,6 +37,7 @@ namespace CarCareTracker.Controllers
|
|||||||
private readonly IReportHelper _reportHelper;
|
private readonly IReportHelper _reportHelper;
|
||||||
private readonly IUserLogic _userLogic;
|
private readonly IUserLogic _userLogic;
|
||||||
private readonly IOdometerLogic _odometerLogic;
|
private readonly IOdometerLogic _odometerLogic;
|
||||||
|
private readonly IVehicleLogic _vehicleLogic;
|
||||||
private readonly IExtraFieldDataAccess _extraFieldDataAccess;
|
private readonly IExtraFieldDataAccess _extraFieldDataAccess;
|
||||||
|
|
||||||
public VehicleController(ILogger<VehicleController> logger,
|
public VehicleController(ILogger<VehicleController> logger,
|
||||||
@@ -59,6 +60,7 @@ namespace CarCareTracker.Controllers
|
|||||||
IExtraFieldDataAccess extraFieldDataAccess,
|
IExtraFieldDataAccess extraFieldDataAccess,
|
||||||
IUserLogic userLogic,
|
IUserLogic userLogic,
|
||||||
IOdometerLogic odometerLogic,
|
IOdometerLogic odometerLogic,
|
||||||
|
IVehicleLogic vehicleLogic,
|
||||||
IWebHostEnvironment webEnv,
|
IWebHostEnvironment webEnv,
|
||||||
IConfigHelper config)
|
IConfigHelper config)
|
||||||
{
|
{
|
||||||
@@ -82,6 +84,7 @@ namespace CarCareTracker.Controllers
|
|||||||
_extraFieldDataAccess = extraFieldDataAccess;
|
_extraFieldDataAccess = extraFieldDataAccess;
|
||||||
_userLogic = userLogic;
|
_userLogic = userLogic;
|
||||||
_odometerLogic = odometerLogic;
|
_odometerLogic = odometerLogic;
|
||||||
|
_vehicleLogic = vehicleLogic;
|
||||||
_webEnv = webEnv;
|
_webEnv = webEnv;
|
||||||
_config = config;
|
_config = config;
|
||||||
}
|
}
|
||||||
@@ -216,37 +219,53 @@ namespace CarCareTracker.Controllers
|
|||||||
string uploadPath = Path.Combine(_webEnv.WebRootPath, uploadDirectory);
|
string uploadPath = Path.Combine(_webEnv.WebRootPath, uploadDirectory);
|
||||||
if (!Directory.Exists(uploadPath))
|
if (!Directory.Exists(uploadPath))
|
||||||
Directory.CreateDirectory(uploadPath);
|
Directory.CreateDirectory(uploadPath);
|
||||||
|
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
||||||
|
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
||||||
if (mode == ImportMode.ServiceRecord)
|
if (mode == ImportMode.ServiceRecord)
|
||||||
{
|
{
|
||||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
|
||||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
|
||||||
var vehicleRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
||||||
if (vehicleRecords.Any())
|
if (vehicleRecords.Any())
|
||||||
{
|
{
|
||||||
var exportData = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes, Odometer = x.Mileage.ToString(), Tags = string.Join(" ", x.Tags) });
|
var exportData = vehicleRecords.Select(x => new GenericRecordExportModel {
|
||||||
|
Date = x.Date.ToShortDateString(),
|
||||||
|
Description = x.Description,
|
||||||
|
Cost = x.Cost.ToString("C"),
|
||||||
|
Notes = x.Notes,
|
||||||
|
Odometer = x.Mileage.ToString(),
|
||||||
|
Tags = string.Join(" ", x.Tags),
|
||||||
|
ExtraFields = x.ExtraFields
|
||||||
|
});
|
||||||
using (var writer = new StreamWriter(fullExportFilePath))
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
{
|
{
|
||||||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
{
|
{
|
||||||
csv.WriteRecords(exportData);
|
//custom writer
|
||||||
|
StaticHelper.WriteGenericRecordExportModel(csv, exportData);
|
||||||
}
|
}
|
||||||
|
writer.Dispose();
|
||||||
}
|
}
|
||||||
return Json($"/{fileNameToExport}");
|
return Json($"/{fileNameToExport}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mode == ImportMode.RepairRecord)
|
else if (mode == ImportMode.RepairRecord)
|
||||||
{
|
{
|
||||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
|
||||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
|
||||||
var vehicleRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
|
||||||
if (vehicleRecords.Any())
|
if (vehicleRecords.Any())
|
||||||
{
|
{
|
||||||
var exportData = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes, Odometer = x.Mileage.ToString(), Tags = string.Join(" ", x.Tags) });
|
var exportData = vehicleRecords.Select(x => new GenericRecordExportModel {
|
||||||
|
Date = x.Date.ToShortDateString(),
|
||||||
|
Description = x.Description,
|
||||||
|
Cost = x.Cost.ToString("C"),
|
||||||
|
Notes = x.Notes,
|
||||||
|
Odometer = x.Mileage.ToString(),
|
||||||
|
Tags = string.Join(" ", x.Tags),
|
||||||
|
ExtraFields = x.ExtraFields
|
||||||
|
});
|
||||||
using (var writer = new StreamWriter(fullExportFilePath))
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
{
|
{
|
||||||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
{
|
{
|
||||||
csv.WriteRecords(exportData);
|
StaticHelper.WriteGenericRecordExportModel(csv, exportData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Json($"/{fileNameToExport}");
|
return Json($"/{fileNameToExport}");
|
||||||
@@ -254,17 +273,23 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
else if (mode == ImportMode.UpgradeRecord)
|
else if (mode == ImportMode.UpgradeRecord)
|
||||||
{
|
{
|
||||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
|
||||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
|
||||||
var vehicleRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
||||||
if (vehicleRecords.Any())
|
if (vehicleRecords.Any())
|
||||||
{
|
{
|
||||||
var exportData = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes, Odometer = x.Mileage.ToString(), Tags = string.Join(" ", x.Tags) });
|
var exportData = vehicleRecords.Select(x => new GenericRecordExportModel {
|
||||||
|
Date = x.Date.ToShortDateString(),
|
||||||
|
Description = x.Description,
|
||||||
|
Cost = x.Cost.ToString("C"),
|
||||||
|
Notes = x.Notes,
|
||||||
|
Odometer = x.Mileage.ToString(),
|
||||||
|
Tags = string.Join(" ", x.Tags),
|
||||||
|
ExtraFields = x.ExtraFields
|
||||||
|
});
|
||||||
using (var writer = new StreamWriter(fullExportFilePath))
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
{
|
{
|
||||||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
{
|
{
|
||||||
csv.WriteRecords(exportData);
|
StaticHelper.WriteGenericRecordExportModel(csv, exportData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Json($"/{fileNameToExport}");
|
return Json($"/{fileNameToExport}");
|
||||||
@@ -272,17 +297,22 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
else if (mode == ImportMode.OdometerRecord)
|
else if (mode == ImportMode.OdometerRecord)
|
||||||
{
|
{
|
||||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
|
||||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
|
||||||
var vehicleRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||||
if (vehicleRecords.Any())
|
if (vehicleRecords.Any())
|
||||||
{
|
{
|
||||||
var exportData = vehicleRecords.Select(x => new OdometerRecordExportModel { Date = x.Date.ToShortDateString(), Notes = x.Notes, InitialOdometer = x.InitialMileage.ToString(), Odometer = x.Mileage.ToString(), Tags = string.Join(" ", x.Tags) });
|
var exportData = vehicleRecords.Select(x => new OdometerRecordExportModel {
|
||||||
|
Date = x.Date.ToShortDateString(),
|
||||||
|
Notes = x.Notes,
|
||||||
|
InitialOdometer = x.InitialMileage.ToString(),
|
||||||
|
Odometer = x.Mileage.ToString(),
|
||||||
|
Tags = string.Join(" ", x.Tags),
|
||||||
|
ExtraFields = x.ExtraFields
|
||||||
|
});
|
||||||
using (var writer = new StreamWriter(fullExportFilePath))
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
{
|
{
|
||||||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
{
|
{
|
||||||
csv.WriteRecords(exportData);
|
StaticHelper.WriteOdometerRecordExportModel(csv, exportData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Json($"/{fileNameToExport}");
|
return Json($"/{fileNameToExport}");
|
||||||
@@ -290,8 +320,6 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
else if (mode == ImportMode.SupplyRecord)
|
else if (mode == ImportMode.SupplyRecord)
|
||||||
{
|
{
|
||||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
|
||||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
|
||||||
var vehicleRecords = _supplyRecordDataAccess.GetSupplyRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _supplyRecordDataAccess.GetSupplyRecordsByVehicleId(vehicleId);
|
||||||
if (vehicleRecords.Any())
|
if (vehicleRecords.Any())
|
||||||
{
|
{
|
||||||
@@ -304,13 +332,14 @@ namespace CarCareTracker.Controllers
|
|||||||
PartQuantity = x.Quantity.ToString(),
|
PartQuantity = x.Quantity.ToString(),
|
||||||
PartSupplier = x.PartSupplier,
|
PartSupplier = x.PartSupplier,
|
||||||
Notes = x.Notes,
|
Notes = x.Notes,
|
||||||
Tags = string.Join(" ", x.Tags)
|
Tags = string.Join(" ", x.Tags),
|
||||||
|
ExtraFields = x.ExtraFields
|
||||||
});
|
});
|
||||||
using (var writer = new StreamWriter(fullExportFilePath))
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
{
|
{
|
||||||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
{
|
{
|
||||||
csv.WriteRecords(exportData);
|
StaticHelper.WriteSupplyRecordExportModel(csv, exportData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Json($"/{fileNameToExport}");
|
return Json($"/{fileNameToExport}");
|
||||||
@@ -318,17 +347,22 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
else if (mode == ImportMode.TaxRecord)
|
else if (mode == ImportMode.TaxRecord)
|
||||||
{
|
{
|
||||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
|
||||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
|
||||||
var vehicleRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
|
||||||
if (vehicleRecords.Any())
|
if (vehicleRecords.Any())
|
||||||
{
|
{
|
||||||
var exportData = vehicleRecords.Select(x => new TaxRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes, Tags = string.Join(" ", x.Tags) });
|
var exportData = vehicleRecords.Select(x => new TaxRecordExportModel {
|
||||||
|
Date = x.Date.ToShortDateString(),
|
||||||
|
Description = x.Description,
|
||||||
|
Cost = x.Cost.ToString("C"),
|
||||||
|
Notes = x.Notes,
|
||||||
|
Tags = string.Join(" ", x.Tags),
|
||||||
|
ExtraFields = x.ExtraFields
|
||||||
|
});
|
||||||
using (var writer = new StreamWriter(fullExportFilePath))
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
{
|
{
|
||||||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
{
|
{
|
||||||
csv.WriteRecords(exportData);
|
StaticHelper.WriteTaxRecordExportModel(csv, exportData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Json($"/{fileNameToExport}");
|
return Json($"/{fileNameToExport}");
|
||||||
@@ -336,8 +370,6 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
else if (mode == ImportMode.PlanRecord)
|
else if (mode == ImportMode.PlanRecord)
|
||||||
{
|
{
|
||||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
|
||||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
|
||||||
var vehicleRecords = _planRecordDataAccess.GetPlanRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _planRecordDataAccess.GetPlanRecordsByVehicleId(vehicleId);
|
||||||
if (vehicleRecords.Any())
|
if (vehicleRecords.Any())
|
||||||
{
|
{
|
||||||
@@ -350,13 +382,14 @@ namespace CarCareTracker.Controllers
|
|||||||
Type = x.ImportMode.ToString(),
|
Type = x.ImportMode.ToString(),
|
||||||
Priority = x.Priority.ToString(),
|
Priority = x.Priority.ToString(),
|
||||||
Progress = x.Progress.ToString(),
|
Progress = x.Progress.ToString(),
|
||||||
Notes = x.Notes
|
Notes = x.Notes,
|
||||||
|
ExtraFields = x.ExtraFields
|
||||||
});
|
});
|
||||||
using (var writer = new StreamWriter(fullExportFilePath))
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
{
|
{
|
||||||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
{
|
{
|
||||||
csv.WriteRecords(exportData);
|
StaticHelper.WritePlanRecordExportModel(csv, exportData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Json($"/{fileNameToExport}");
|
return Json($"/{fileNameToExport}");
|
||||||
@@ -364,8 +397,6 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
else if (mode == ImportMode.GasRecord)
|
else if (mode == ImportMode.GasRecord)
|
||||||
{
|
{
|
||||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
|
||||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
|
||||||
var vehicleRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
|
var vehicleRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
|
||||||
bool useMPG = _config.GetUserConfig(User).UseMPG;
|
bool useMPG = _config.GetUserConfig(User).UseMPG;
|
||||||
bool useUKMPG = _config.GetUserConfig(User).UseUKMPG;
|
bool useUKMPG = _config.GetUserConfig(User).UseUKMPG;
|
||||||
@@ -380,13 +411,14 @@ namespace CarCareTracker.Controllers
|
|||||||
IsFillToFull = x.IsFillToFull.ToString(),
|
IsFillToFull = x.IsFillToFull.ToString(),
|
||||||
MissedFuelUp = x.MissedFuelUp.ToString(),
|
MissedFuelUp = x.MissedFuelUp.ToString(),
|
||||||
Notes = x.Notes,
|
Notes = x.Notes,
|
||||||
Tags = string.Join(" ", x.Tags)
|
Tags = string.Join(" ", x.Tags),
|
||||||
|
ExtraFields = x.ExtraFields
|
||||||
});
|
});
|
||||||
using (var writer = new StreamWriter(fullExportFilePath))
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
{
|
{
|
||||||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
{
|
{
|
||||||
csv.WriteRecords(exportData);
|
StaticHelper.WriteGasRecordExportModel(csv, exportData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Json($"/{fileNameToExport}");
|
return Json($"/{fileNameToExport}");
|
||||||
@@ -414,7 +446,7 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
using (var reader = new StreamReader(fullFileName))
|
using (var reader = new StreamReader(fullFileName))
|
||||||
{
|
{
|
||||||
var config = new CsvHelper.Configuration.CsvConfiguration(System.Globalization.CultureInfo.InvariantCulture);
|
var config = new CsvHelper.Configuration.CsvConfiguration(CultureInfo.InvariantCulture);
|
||||||
config.MissingFieldFound = null;
|
config.MissingFieldFound = null;
|
||||||
config.HeaderValidated = null;
|
config.HeaderValidated = null;
|
||||||
config.PrepareHeaderForMatch = args => { return args.Header.Trim().ToLower(); };
|
config.PrepareHeaderForMatch = args => { return args.Header.Trim().ToLower(); };
|
||||||
@@ -424,6 +456,7 @@ namespace CarCareTracker.Controllers
|
|||||||
var records = csv.GetRecords<ImportModel>().ToList();
|
var records = csv.GetRecords<ImportModel>().ToList();
|
||||||
if (records.Any())
|
if (records.Any())
|
||||||
{
|
{
|
||||||
|
var requiredExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)mode).ExtraFields.Where(x=>x.IsRequired).Select(y=>y.Name);
|
||||||
foreach (ImportModel importModel in records)
|
foreach (ImportModel importModel in records)
|
||||||
{
|
{
|
||||||
if (mode == ImportMode.GasRecord)
|
if (mode == ImportMode.GasRecord)
|
||||||
@@ -436,7 +469,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)),
|
Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)),
|
||||||
Gallons = decimal.Parse(importModel.FuelConsumed, NumberStyles.Any),
|
Gallons = decimal.Parse(importModel.FuelConsumed, NumberStyles.Any),
|
||||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||||
|
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value, IsRequired = requiredExtraFields.Contains(x.Key) }).ToList() : new List<ExtraField>()
|
||||||
};
|
};
|
||||||
if (string.IsNullOrWhiteSpace(importModel.Cost) && !string.IsNullOrWhiteSpace(importModel.Price))
|
if (string.IsNullOrWhiteSpace(importModel.Cost) && !string.IsNullOrWhiteSpace(importModel.Price))
|
||||||
{
|
{
|
||||||
@@ -492,7 +526,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Service Record on {importModel.Date}" : importModel.Description,
|
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Service Record on {importModel.Date}" : importModel.Description,
|
||||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||||
|
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value, IsRequired = requiredExtraFields.Contains(x.Key) }).ToList() : new List<ExtraField>()
|
||||||
};
|
};
|
||||||
_serviceRecordDataAccess.SaveServiceRecordToVehicle(convertedRecord);
|
_serviceRecordDataAccess.SaveServiceRecordToVehicle(convertedRecord);
|
||||||
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||||
@@ -515,7 +550,8 @@ namespace CarCareTracker.Controllers
|
|||||||
InitialMileage = string.IsNullOrWhiteSpace(importModel.InitialOdometer) ? 0 : decimal.ToInt32(decimal.Parse(importModel.InitialOdometer, NumberStyles.Any)),
|
InitialMileage = string.IsNullOrWhiteSpace(importModel.InitialOdometer) ? 0 : decimal.ToInt32(decimal.Parse(importModel.InitialOdometer, NumberStyles.Any)),
|
||||||
Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)),
|
Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)),
|
||||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||||
|
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value, IsRequired = requiredExtraFields.Contains(x.Key) }).ToList() : new List<ExtraField>()
|
||||||
};
|
};
|
||||||
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(convertedRecord);
|
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(convertedRecord);
|
||||||
}
|
}
|
||||||
@@ -534,7 +570,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Priority = parsedPriority,
|
Priority = parsedPriority,
|
||||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Plan Record on {importModel.DateCreated}" : importModel.Description,
|
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Plan Record on {importModel.DateCreated}" : importModel.Description,
|
||||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any)
|
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||||
|
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value, IsRequired = requiredExtraFields.Contains(x.Key) }).ToList() : new List<ExtraField>()
|
||||||
};
|
};
|
||||||
_planRecordDataAccess.SavePlanRecordToVehicle(convertedRecord);
|
_planRecordDataAccess.SavePlanRecordToVehicle(convertedRecord);
|
||||||
}
|
}
|
||||||
@@ -548,7 +585,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Repair Record on {importModel.Date}" : importModel.Description,
|
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Repair Record on {importModel.Date}" : importModel.Description,
|
||||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||||
|
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value, IsRequired = requiredExtraFields.Contains(x.Key) }).ToList() : new List<ExtraField>()
|
||||||
};
|
};
|
||||||
_collisionRecordDataAccess.SaveCollisionRecordToVehicle(convertedRecord);
|
_collisionRecordDataAccess.SaveCollisionRecordToVehicle(convertedRecord);
|
||||||
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||||
@@ -572,7 +610,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Upgrade Record on {importModel.Date}" : importModel.Description,
|
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Upgrade Record on {importModel.Date}" : importModel.Description,
|
||||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||||
|
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value, IsRequired = requiredExtraFields.Contains(x.Key) }).ToList() : new List<ExtraField>()
|
||||||
};
|
};
|
||||||
_upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(convertedRecord);
|
_upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(convertedRecord);
|
||||||
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
|
||||||
@@ -598,7 +637,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Description = importModel.Description,
|
Description = importModel.Description,
|
||||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||||
Notes = importModel.Notes,
|
Notes = importModel.Notes,
|
||||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||||
|
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value, IsRequired = requiredExtraFields.Contains(x.Key) }).ToList() : new List<ExtraField>()
|
||||||
};
|
};
|
||||||
_supplyRecordDataAccess.SaveSupplyRecordToVehicle(convertedRecord);
|
_supplyRecordDataAccess.SaveSupplyRecordToVehicle(convertedRecord);
|
||||||
}
|
}
|
||||||
@@ -611,7 +651,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Tax Record on {importModel.Date}" : importModel.Description,
|
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Tax Record on {importModel.Date}" : importModel.Description,
|
||||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||||
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
|
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList(),
|
||||||
|
ExtraFields = importModel.ExtraFields.Any() ? importModel.ExtraFields.Select(x => new ExtraField { Name = x.Key, Value = x.Value, IsRequired = requiredExtraFields.Contains(x.Key) }).ToList() : new List<ExtraField>()
|
||||||
};
|
};
|
||||||
_taxRecordDataAccess.SaveTaxRecordToVehicle(convertedRecord);
|
_taxRecordDataAccess.SaveTaxRecordToVehicle(convertedRecord);
|
||||||
}
|
}
|
||||||
@@ -823,11 +864,18 @@ namespace CarCareTracker.Controllers
|
|||||||
if (serviceRecord.Supplies.Any())
|
if (serviceRecord.Supplies.Any())
|
||||||
{
|
{
|
||||||
serviceRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(serviceRecord.Supplies, DateTime.Parse(serviceRecord.Date), serviceRecord.Description);
|
serviceRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(serviceRecord.Supplies, DateTime.Parse(serviceRecord.Date), serviceRecord.Description);
|
||||||
|
if (serviceRecord.CopySuppliesAttachment)
|
||||||
|
{
|
||||||
|
serviceRecord.Files.AddRange(GetSuppliesAttachments(serviceRecord.Supplies));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//push back any reminders
|
//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());
|
var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord());
|
||||||
if (result)
|
if (result)
|
||||||
@@ -908,11 +956,18 @@ namespace CarCareTracker.Controllers
|
|||||||
if (collisionRecord.Supplies.Any())
|
if (collisionRecord.Supplies.Any())
|
||||||
{
|
{
|
||||||
collisionRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(collisionRecord.Supplies, DateTime.Parse(collisionRecord.Date), collisionRecord.Description);
|
collisionRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(collisionRecord.Supplies, DateTime.Parse(collisionRecord.Date), collisionRecord.Description);
|
||||||
|
if (collisionRecord.CopySuppliesAttachment)
|
||||||
|
{
|
||||||
|
collisionRecord.Files.AddRange(GetSuppliesAttachments(collisionRecord.Supplies));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//push back any reminders
|
//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());
|
var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord());
|
||||||
if (result)
|
if (result)
|
||||||
@@ -1021,9 +1076,12 @@ namespace CarCareTracker.Controllers
|
|||||||
//move files from temp.
|
//move files from temp.
|
||||||
taxRecord.Files = taxRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
taxRecord.Files = taxRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||||
//push back any reminders
|
//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());
|
var result = _taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord.ToTaxRecord());
|
||||||
if (result)
|
if (result)
|
||||||
@@ -1082,6 +1140,7 @@ namespace CarCareTracker.Controllers
|
|||||||
var taxRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
|
var taxRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
|
||||||
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
||||||
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||||
|
var userConfig = _config.GetUserConfig(User);
|
||||||
var viewModel = new ReportViewModel();
|
var viewModel = new ReportViewModel();
|
||||||
//get totalCostMakeUp
|
//get totalCostMakeUp
|
||||||
viewModel.CostMakeUpForVehicle = new CostMakeUpForVehicle
|
viewModel.CostMakeUpForVehicle = new CostMakeUpForVehicle
|
||||||
@@ -1133,6 +1192,10 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
numbersArray.Add(upgradeRecords.Min(x => x.Date.Year));
|
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 minYear = numbersArray.Any() ? numbersArray.Min() : DateTime.Now.AddYears(-5).Year;
|
||||||
var yearDifference = DateTime.Now.Year - minYear + 1;
|
var yearDifference = DateTime.Now.Year - minYear + 1;
|
||||||
for (int i = 0; i < yearDifference; i++)
|
for (int i = 0; i < yearDifference; i++)
|
||||||
@@ -1143,7 +1206,6 @@ namespace CarCareTracker.Controllers
|
|||||||
var collaborators = _userLogic.GetCollaboratorsForVehicle(vehicleId);
|
var collaborators = _userLogic.GetCollaboratorsForVehicle(vehicleId);
|
||||||
viewModel.Collaborators = collaborators;
|
viewModel.Collaborators = collaborators;
|
||||||
//get MPG per month.
|
//get MPG per month.
|
||||||
var userConfig = _config.GetUserConfig(User);
|
|
||||||
var mileageData = _gasHelper.GetGasRecordViewModels(gasRecords, userConfig.UseMPG, userConfig.UseUKMPG);
|
var mileageData = _gasHelper.GetGasRecordViewModels(gasRecords, userConfig.UseMPG, userConfig.UseUKMPG);
|
||||||
mileageData.RemoveAll(x => x.MilesPerGallon == default);
|
mileageData.RemoveAll(x => x.MilesPerGallon == default);
|
||||||
var monthlyMileageData = StaticHelper.GetBaseLineCostsNoMonthName();
|
var monthlyMileageData = StaticHelper.GetBaseLineCostsNoMonthName();
|
||||||
@@ -1210,6 +1272,45 @@ namespace CarCareTracker.Controllers
|
|||||||
return PartialView("_CostMakeUpReport", viewModel);
|
return PartialView("_CostMakeUpReport", viewModel);
|
||||||
}
|
}
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult GetCostTableForVehicle(int vehicleId, int year = 0)
|
||||||
|
{
|
||||||
|
var vehicleRecords = _vehicleLogic.GetVehicleRecords(vehicleId);
|
||||||
|
var serviceRecords = vehicleRecords.ServiceRecords;
|
||||||
|
var gasRecords = vehicleRecords.GasRecords;
|
||||||
|
var collisionRecords = vehicleRecords.CollisionRecords;
|
||||||
|
var taxRecords = vehicleRecords.TaxRecords;
|
||||||
|
var upgradeRecords = vehicleRecords.UpgradeRecords;
|
||||||
|
var odometerRecords = vehicleRecords.OdometerRecords;
|
||||||
|
if (year != default)
|
||||||
|
{
|
||||||
|
serviceRecords.RemoveAll(x => x.Date.Year != year);
|
||||||
|
gasRecords.RemoveAll(x => x.Date.Year != year);
|
||||||
|
collisionRecords.RemoveAll(x => x.Date.Year != year);
|
||||||
|
taxRecords.RemoveAll(x => x.Date.Year != year);
|
||||||
|
upgradeRecords.RemoveAll(x => x.Date.Year != year);
|
||||||
|
odometerRecords.RemoveAll(x => x.Date.Year != year);
|
||||||
|
}
|
||||||
|
var maxMileage = _vehicleLogic.GetMaxMileage(vehicleRecords);
|
||||||
|
var minMileage = _vehicleLogic.GetMinMileage(vehicleRecords);
|
||||||
|
var vehicleData = _dataAccess.GetVehicleById(vehicleId);
|
||||||
|
var userConfig = _config.GetUserConfig(User);
|
||||||
|
var totalDistanceTraveled = maxMileage - minMileage;
|
||||||
|
var totalDays = _vehicleLogic.GetOwnershipDays(vehicleData.PurchaseDate, vehicleData.SoldDate, serviceRecords, collisionRecords, gasRecords, upgradeRecords, odometerRecords, taxRecords);
|
||||||
|
var viewModel = new CostTableForVehicle
|
||||||
|
{
|
||||||
|
ServiceRecordSum = serviceRecords.Sum(x => x.Cost),
|
||||||
|
GasRecordSum = gasRecords.Sum(x => x.Cost),
|
||||||
|
CollisionRecordSum = collisionRecords.Sum(x => x.Cost),
|
||||||
|
TaxRecordSum = taxRecords.Sum(x => x.Cost),
|
||||||
|
UpgradeRecordSum = upgradeRecords.Sum(x => x.Cost),
|
||||||
|
TotalDistance = totalDistanceTraveled,
|
||||||
|
DistanceUnit = vehicleData.UseHours ? "Cost Per Hour" : userConfig.UseMPG ? "Cost Per Mile" : "Cost Per Kilometer",
|
||||||
|
NumberOfDays = totalDays
|
||||||
|
};
|
||||||
|
return PartialView("_CostTableReport", viewModel);
|
||||||
|
}
|
||||||
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
public IActionResult GetReminderMakeUpByVehicle(int vehicleId, int daysToAdd)
|
public IActionResult GetReminderMakeUpByVehicle(int vehicleId, int daysToAdd)
|
||||||
{
|
{
|
||||||
var reminders = GetRemindersAndUrgency(vehicleId, DateTime.Now.AddDays(daysToAdd));
|
var reminders = GetRemindersAndUrgency(vehicleId, DateTime.Now.AddDays(daysToAdd));
|
||||||
@@ -1313,26 +1414,43 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
var vehicleHistory = new VehicleHistoryViewModel();
|
var vehicleHistory = new VehicleHistoryViewModel();
|
||||||
vehicleHistory.VehicleData = _dataAccess.GetVehicleById(vehicleId);
|
vehicleHistory.VehicleData = _dataAccess.GetVehicleById(vehicleId);
|
||||||
var maxMileage = GetMaxMileage(vehicleId);
|
var maxMileage = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||||
vehicleHistory.Odometer = maxMileage.ToString("N0");
|
vehicleHistory.Odometer = maxMileage.ToString("N0");
|
||||||
var minMileage = GetMinMileage(vehicleId);
|
var minMileage = _vehicleLogic.GetMinMileage(vehicleId);
|
||||||
var distanceTraveled = maxMileage - minMileage;
|
var distanceTraveled = maxMileage - minMileage;
|
||||||
if (!string.IsNullOrWhiteSpace(vehicleHistory.VehicleData.PurchaseDate))
|
if (!string.IsNullOrWhiteSpace(vehicleHistory.VehicleData.PurchaseDate))
|
||||||
{
|
{
|
||||||
var endDate = vehicleHistory.VehicleData.SoldDate;
|
var endDate = vehicleHistory.VehicleData.SoldDate;
|
||||||
|
int daysOwned = 0;
|
||||||
if (string.IsNullOrWhiteSpace(endDate))
|
if (string.IsNullOrWhiteSpace(endDate))
|
||||||
{
|
{
|
||||||
endDate = DateTime.Now.ToShortDateString();
|
endDate = DateTime.Now.ToShortDateString();
|
||||||
}
|
}
|
||||||
try
|
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)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex.Message);
|
_logger.LogError(ex.Message);
|
||||||
vehicleHistory.DaysOwned = string.Empty;
|
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>();
|
List<GenericReportModel> reportData = new List<GenericReportModel>();
|
||||||
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
|
||||||
@@ -1483,78 +1601,14 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#region "Reminders"
|
#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)
|
private List<ReminderRecordViewModel> GetRemindersAndUrgency(int vehicleId, DateTime dateCompare)
|
||||||
{
|
{
|
||||||
var currentMileage = GetMaxMileage(vehicleId);
|
var currentMileage = _vehicleLogic.GetMaxMileage(vehicleId);
|
||||||
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
||||||
List<ReminderRecordViewModel> results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, dateCompare);
|
List<ReminderRecordViewModel> results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, dateCompare);
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
private bool GetAndUpdateVehicleUrgentOrPastDueReminders(int vehicleId)
|
||||||
[HttpGet]
|
|
||||||
public IActionResult GetVehicleHaveUrgentOrPastDueReminders(int vehicleId)
|
|
||||||
{
|
{
|
||||||
var result = GetRemindersAndUrgency(vehicleId, DateTime.Now);
|
var result = GetRemindersAndUrgency(vehicleId, DateTime.Now);
|
||||||
//check if user wants auto-refresh past-due reminders
|
//check if user wants auto-refresh past-due reminders
|
||||||
@@ -1569,7 +1623,7 @@ namespace CarCareTracker.Controllers
|
|||||||
//update based on recurring intervals.
|
//update based on recurring intervals.
|
||||||
//pull reminderRecord based on ID
|
//pull reminderRecord based on ID
|
||||||
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecord.Id);
|
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecord.Id);
|
||||||
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder);
|
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder, null, null);
|
||||||
//save to db.
|
//save to db.
|
||||||
_reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
|
_reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
|
||||||
//set urgency to not urgent so it gets excluded in count.
|
//set urgency to not urgent so it gets excluded in count.
|
||||||
@@ -1581,9 +1635,16 @@ namespace CarCareTracker.Controllers
|
|||||||
var pastDueAndUrgentReminders = result.Where(x => x.Urgency == ReminderUrgency.VeryUrgent || x.Urgency == ReminderUrgency.PastDue);
|
var pastDueAndUrgentReminders = result.Where(x => x.Urgency == ReminderUrgency.VeryUrgent || x.Urgency == ReminderUrgency.PastDue);
|
||||||
if (pastDueAndUrgentReminders.Any())
|
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))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
@@ -1603,17 +1664,17 @@ namespace CarCareTracker.Controllers
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult PushbackRecurringReminderRecord(int reminderRecordId)
|
public IActionResult PushbackRecurringReminderRecord(int reminderRecordId)
|
||||||
{
|
{
|
||||||
var result = PushbackRecurringReminderRecordWithChecks(reminderRecordId);
|
var result = PushbackRecurringReminderRecordWithChecks(reminderRecordId, null, null);
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
private bool PushbackRecurringReminderRecordWithChecks(int reminderRecordId)
|
private bool PushbackRecurringReminderRecordWithChecks(int reminderRecordId, DateTime? currentDate, int? currentMileage)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecordId);
|
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecordId);
|
||||||
if (existingReminder is not null && existingReminder.Id != default && existingReminder.IsRecurring)
|
if (existingReminder is not null && existingReminder.Id != default && existingReminder.IsRecurring)
|
||||||
{
|
{
|
||||||
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder);
|
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder, currentDate, currentMileage);
|
||||||
//save to db.
|
//save to db.
|
||||||
var reminderUpdateResult = _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
|
var reminderUpdateResult = _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
|
||||||
if (!reminderUpdateResult)
|
if (!reminderUpdateResult)
|
||||||
@@ -1672,10 +1733,13 @@ namespace CarCareTracker.Controllers
|
|||||||
Mileage = result.Mileage,
|
Mileage = result.Mileage,
|
||||||
Metric = result.Metric,
|
Metric = result.Metric,
|
||||||
IsRecurring = result.IsRecurring,
|
IsRecurring = result.IsRecurring,
|
||||||
|
UseCustomThresholds = result.UseCustomThresholds,
|
||||||
|
CustomThresholds = result.CustomThresholds,
|
||||||
ReminderMileageInterval = result.ReminderMileageInterval,
|
ReminderMileageInterval = result.ReminderMileageInterval,
|
||||||
ReminderMonthInterval = result.ReminderMonthInterval,
|
ReminderMonthInterval = result.ReminderMonthInterval,
|
||||||
CustomMileageInterval = result.CustomMileageInterval,
|
CustomMileageInterval = result.CustomMileageInterval,
|
||||||
CustomMonthInterval = result.CustomMonthInterval
|
CustomMonthInterval = result.CustomMonthInterval,
|
||||||
|
Tags = result.Tags
|
||||||
};
|
};
|
||||||
return PartialView("_ReminderRecordModal", convertedResult);
|
return PartialView("_ReminderRecordModal", convertedResult);
|
||||||
}
|
}
|
||||||
@@ -1725,11 +1789,18 @@ namespace CarCareTracker.Controllers
|
|||||||
if (upgradeRecord.Supplies.Any())
|
if (upgradeRecord.Supplies.Any())
|
||||||
{
|
{
|
||||||
upgradeRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(upgradeRecord.Supplies, DateTime.Parse(upgradeRecord.Date), upgradeRecord.Description);
|
upgradeRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(upgradeRecord.Supplies, DateTime.Parse(upgradeRecord.Date), upgradeRecord.Description);
|
||||||
|
if (upgradeRecord.CopySuppliesAttachment)
|
||||||
|
{
|
||||||
|
upgradeRecord.Files.AddRange(GetSuppliesAttachments(upgradeRecord.Supplies));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//push back any reminders
|
//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());
|
var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord.ToUpgradeRecord());
|
||||||
if (result)
|
if (result)
|
||||||
@@ -1795,6 +1866,7 @@ namespace CarCareTracker.Controllers
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult SaveNoteToVehicleId(Note note)
|
public IActionResult SaveNoteToVehicleId(Note note)
|
||||||
{
|
{
|
||||||
|
note.Files = note.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||||
var result = _noteDataAccess.SaveNoteToVehicle(note);
|
var result = _noteDataAccess.SaveNoteToVehicle(note);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
@@ -1863,6 +1935,16 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
return result;
|
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)
|
private List<SupplyUsageHistory> RequisitionSupplyRecordsByUsage(List<SupplyUsage> supplyUsage, DateTime dateRequisitioned, string usageDescription)
|
||||||
{
|
{
|
||||||
List<SupplyUsageHistory> results = new List<SupplyUsageHistory>();
|
List<SupplyUsageHistory> results = new List<SupplyUsageHistory>();
|
||||||
@@ -1915,6 +1997,33 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
return PartialView("_SupplyRecords", result);
|
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))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult GetSupplyRecordsForRecordsByVehicleId(int vehicleId)
|
public IActionResult GetSupplyRecordsForRecordsByVehicleId(int vehicleId)
|
||||||
@@ -1934,7 +2043,11 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
result = result.OrderBy(x => x.Date).ToList();
|
result = result.OrderBy(x => x.Date).ToList();
|
||||||
}
|
}
|
||||||
return PartialView("_SupplyUsage", result);
|
var viewModel = new SupplyUsageViewModel
|
||||||
|
{
|
||||||
|
Supplies = result
|
||||||
|
};
|
||||||
|
return PartialView("_SupplyUsage", viewModel);
|
||||||
}
|
}
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult SaveSupplyRecordToVehicleId(SupplyRecordInput supplyRecord)
|
public IActionResult SaveSupplyRecordToVehicleId(SupplyRecordInput supplyRecord)
|
||||||
@@ -2009,6 +2122,10 @@ namespace CarCareTracker.Controllers
|
|||||||
if (planRecord.Supplies.Any())
|
if (planRecord.Supplies.Any())
|
||||||
{
|
{
|
||||||
planRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(planRecord.Supplies, DateTime.Parse(planRecord.DateCreated), planRecord.Description);
|
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());
|
var result = _planRecordDataAccess.SavePlanRecordToVehicle(planRecord.ToPlanRecord());
|
||||||
if (result)
|
if (result)
|
||||||
@@ -2022,7 +2139,7 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
//check if template name already taken.
|
//check if template name already taken.
|
||||||
var existingRecord = _planRecordTemplateDataAccess.GetPlanRecordTemplatesByVehicleId(planRecord.VehicleId).Where(x => x.Description == planRecord.Description).Any();
|
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" });
|
return Json(new OperationResponse { Success = false, Message = "A template with that description already exists for this vehicle" });
|
||||||
}
|
}
|
||||||
@@ -2076,6 +2193,10 @@ namespace CarCareTracker.Controllers
|
|||||||
if (existingRecord.Supplies.Any())
|
if (existingRecord.Supplies.Any())
|
||||||
{
|
{
|
||||||
existingRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(existingRecord.Supplies, DateTime.Parse(existingRecord.DateCreated), existingRecord.Description);
|
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());
|
var result = _planRecordDataAccess.SavePlanRecordToVehicle(existingRecord.ToPlanRecord());
|
||||||
return Json(new OperationResponse { Success = result, Message = result ? "Plan Record Added" : StaticHelper.GenericErrorMessage });
|
return Json(new OperationResponse { Success = result, Message = result ? "Plan Record Added" : StaticHelper.GenericErrorMessage });
|
||||||
@@ -2108,7 +2229,7 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
_odometerLogic.AutoInsertOdometerRecord(new OdometerRecord
|
||||||
{
|
{
|
||||||
Date = DateTime.Now,
|
Date = DateTime.Now.Date,
|
||||||
VehicleId = existingRecord.VehicleId,
|
VehicleId = existingRecord.VehicleId,
|
||||||
Mileage = odometer,
|
Mileage = odometer,
|
||||||
Notes = $"Auto Insert From Plan Record: {existingRecord.Description}",
|
Notes = $"Auto Insert From Plan Record: {existingRecord.Description}",
|
||||||
@@ -2121,7 +2242,7 @@ namespace CarCareTracker.Controllers
|
|||||||
var newRecord = new ServiceRecord()
|
var newRecord = new ServiceRecord()
|
||||||
{
|
{
|
||||||
VehicleId = existingRecord.VehicleId,
|
VehicleId = existingRecord.VehicleId,
|
||||||
Date = DateTime.Now,
|
Date = DateTime.Now.Date,
|
||||||
Mileage = odometer,
|
Mileage = odometer,
|
||||||
Description = existingRecord.Description,
|
Description = existingRecord.Description,
|
||||||
Cost = existingRecord.Cost,
|
Cost = existingRecord.Cost,
|
||||||
@@ -2137,7 +2258,7 @@ namespace CarCareTracker.Controllers
|
|||||||
var newRecord = new CollisionRecord()
|
var newRecord = new CollisionRecord()
|
||||||
{
|
{
|
||||||
VehicleId = existingRecord.VehicleId,
|
VehicleId = existingRecord.VehicleId,
|
||||||
Date = DateTime.Now,
|
Date = DateTime.Now.Date,
|
||||||
Mileage = odometer,
|
Mileage = odometer,
|
||||||
Description = existingRecord.Description,
|
Description = existingRecord.Description,
|
||||||
Cost = existingRecord.Cost,
|
Cost = existingRecord.Cost,
|
||||||
@@ -2153,7 +2274,7 @@ namespace CarCareTracker.Controllers
|
|||||||
var newRecord = new UpgradeRecord()
|
var newRecord = new UpgradeRecord()
|
||||||
{
|
{
|
||||||
VehicleId = existingRecord.VehicleId,
|
VehicleId = existingRecord.VehicleId,
|
||||||
Date = DateTime.Now,
|
Date = DateTime.Now.Date,
|
||||||
Mileage = odometer,
|
Mileage = odometer,
|
||||||
Description = existingRecord.Description,
|
Description = existingRecord.Description,
|
||||||
Cost = existingRecord.Cost,
|
Cost = existingRecord.Cost,
|
||||||
@@ -2167,12 +2288,18 @@ namespace CarCareTracker.Controllers
|
|||||||
//push back any reminders
|
//push back any reminders
|
||||||
if (existingRecord.ReminderRecordId != default)
|
if (existingRecord.ReminderRecordId != default)
|
||||||
{
|
{
|
||||||
PushbackRecurringReminderRecordWithChecks(existingRecord.ReminderRecordId);
|
PushbackRecurringReminderRecordWithChecks(existingRecord.ReminderRecordId, DateTime.Now, odometer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
public IActionResult GetPlanRecordTemplateForEditById(int planRecordTemplateId)
|
||||||
|
{
|
||||||
|
var result = _planRecordTemplateDataAccess.GetPlanRecordTemplateById(planRecordTemplateId);
|
||||||
|
return PartialView("_PlanRecordTemplateEditModal", result);
|
||||||
|
}
|
||||||
|
[HttpGet]
|
||||||
public IActionResult GetPlanRecordForEditById(int planRecordId)
|
public IActionResult GetPlanRecordForEditById(int planRecordId)
|
||||||
{
|
{
|
||||||
var result = _planRecordDataAccess.GetPlanRecordById(planRecordId);
|
var result = _planRecordDataAccess.GetPlanRecordById(planRecordId);
|
||||||
@@ -2335,6 +2462,95 @@ namespace CarCareTracker.Controllers
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#region "Shared Methods"
|
#region "Shared Methods"
|
||||||
|
[HttpPost]
|
||||||
|
public IActionResult GetFilesPendingUpload(List<UploadedFiles> uploadedFiles)
|
||||||
|
{
|
||||||
|
var filesPendingUpload = uploadedFiles.Where(x => x.Location.StartsWith("/temp/")).ToList();
|
||||||
|
return PartialView("_FilesToUpload", filesPendingUpload);
|
||||||
|
}
|
||||||
|
[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)
|
public IActionResult MoveRecord(int recordId, ImportMode source, ImportMode destination)
|
||||||
{
|
{
|
||||||
var genericRecord = new GenericRecord();
|
var genericRecord = new GenericRecord();
|
||||||
|
|||||||
9
Enum/DashboardMetric.cs
Normal file
9
Enum/DashboardMetric.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace CarCareTracker.Models
|
||||||
|
{
|
||||||
|
public enum DashboardMetric
|
||||||
|
{
|
||||||
|
Default = 0,
|
||||||
|
TotalCost = 1,
|
||||||
|
CostPerMile = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,51 +7,48 @@ namespace CarCareTracker.External.Implementations
|
|||||||
{
|
{
|
||||||
public class CollisionRecordDataAccess : ICollisionRecordDataAccess
|
public class CollisionRecordDataAccess : ICollisionRecordDataAccess
|
||||||
{
|
{
|
||||||
private static string dbName = StaticHelper.DbName;
|
private ILiteDBHelper _liteDB { get; set; }
|
||||||
private static string tableName = "collisionrecords";
|
private static string tableName = "collisionrecords";
|
||||||
|
public CollisionRecordDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<CollisionRecord> GetCollisionRecordsByVehicleId(int vehicleId)
|
public List<CollisionRecord> GetCollisionRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
var collisionRecords = table.Find(Query.EQ(nameof(CollisionRecord.VehicleId), vehicleId));
|
||||||
var collisionRecords = table.Find(Query.EQ(nameof(CollisionRecord.VehicleId), vehicleId));
|
return collisionRecords.ToList() ?? new List<CollisionRecord>();
|
||||||
return collisionRecords.ToList() ?? new List<CollisionRecord>();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public CollisionRecord GetCollisionRecordById(int collisionRecordId)
|
public CollisionRecord GetCollisionRecordById(int collisionRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
return table.FindById(collisionRecordId);
|
||||||
return table.FindById(collisionRecordId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteCollisionRecordById(int collisionRecordId)
|
public bool DeleteCollisionRecordById(int collisionRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
table.Delete(collisionRecordId);
|
||||||
table.Delete(collisionRecordId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveCollisionRecordToVehicle(CollisionRecord collisionRecord)
|
public bool SaveCollisionRecordToVehicle(CollisionRecord collisionRecord)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
table.Upsert(collisionRecord);
|
||||||
table.Upsert(collisionRecord);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteAllCollisionRecordsByVehicleId(int vehicleId)
|
public bool DeleteAllCollisionRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<CollisionRecord>(tableName);
|
||||||
var table = db.GetCollection<CollisionRecord>(tableName);
|
var collisionRecords = table.DeleteMany(Query.EQ(nameof(CollisionRecord.VehicleId), vehicleId));
|
||||||
var collisionRecords = table.DeleteMany(Query.EQ(nameof(CollisionRecord.VehicleId), vehicleId));
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
using CarCareTracker.External.Interfaces;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.Helper;
|
using CarCareTracker.Helper;
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
using LiteDB;
|
|
||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
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";
|
private static string tableName = "extrafields";
|
||||||
|
public ExtraFieldDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public RecordExtraField GetExtraFieldsById(int importMode)
|
public RecordExtraField GetExtraFieldsById(int importMode)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<RecordExtraField>(tableName);
|
||||||
var table = db.GetCollection<RecordExtraField>(tableName);
|
return table.FindById(importMode) ?? new RecordExtraField();
|
||||||
return table.FindById(importMode) ?? new RecordExtraField();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveExtraFields(RecordExtraField record)
|
public bool SaveExtraFields(RecordExtraField record)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<RecordExtraField>(tableName);
|
||||||
var table = db.GetCollection<RecordExtraField>(tableName);
|
table.Upsert(record);
|
||||||
table.Upsert(record);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,53 +5,50 @@ using LiteDB;
|
|||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
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";
|
private static string tableName = "gasrecords";
|
||||||
|
public GasRecordDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<GasRecord> GetGasRecordsByVehicleId(int vehicleId)
|
public List<GasRecord> GetGasRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<GasRecord>(tableName);
|
||||||
var table = db.GetCollection<GasRecord>(tableName);
|
var gasRecords = table.Find(Query.EQ(nameof(GasRecord.VehicleId), vehicleId));
|
||||||
var gasRecords = table.Find(Query.EQ(nameof(GasRecord.VehicleId), vehicleId));
|
return gasRecords.ToList() ?? new List<GasRecord>();
|
||||||
return gasRecords.ToList() ?? new List<GasRecord>();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public GasRecord GetGasRecordById(int gasRecordId)
|
public GasRecord GetGasRecordById(int gasRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<GasRecord>(tableName);
|
||||||
var table = db.GetCollection<GasRecord>(tableName);
|
return table.FindById(gasRecordId);
|
||||||
return table.FindById(gasRecordId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteGasRecordById(int gasRecordId)
|
public bool DeleteGasRecordById(int gasRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<GasRecord>(tableName);
|
||||||
var table = db.GetCollection<GasRecord>(tableName);
|
table.Delete(gasRecordId);
|
||||||
table.Delete(gasRecordId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveGasRecordToVehicle(GasRecord gasRecord)
|
public bool SaveGasRecordToVehicle(GasRecord gasRecord)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<GasRecord>(tableName);
|
||||||
var table = db.GetCollection<GasRecord>(tableName);
|
table.Upsert(gasRecord);
|
||||||
table.Upsert(gasRecord);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteAllGasRecordsByVehicleId(int vehicleId)
|
public bool DeleteAllGasRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<GasRecord>(tableName);
|
||||||
var table = db.GetCollection<GasRecord>(tableName);
|
var gasRecords = table.DeleteMany(Query.EQ(nameof(GasRecord.VehicleId), vehicleId));
|
||||||
var gasRecords = table.DeleteMany(Query.EQ(nameof(GasRecord.VehicleId), vehicleId));
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,54 @@
|
|||||||
using CarCareTracker.External.Interfaces;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.Helper;
|
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
|
using CarCareTracker.Helper;
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
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";
|
private static string tableName = "notes";
|
||||||
|
public NoteDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<Note> GetNotesByVehicleId(int vehicleId)
|
public List<Note> GetNotesByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Note>(tableName);
|
||||||
var table = db.GetCollection<Note>(tableName);
|
var noteToReturn = table.Find(Query.EQ(nameof(Note.VehicleId), vehicleId));
|
||||||
var noteToReturn = table.Find(Query.EQ(nameof(Note.VehicleId), vehicleId));
|
return noteToReturn.ToList() ?? new List<Note>();
|
||||||
return noteToReturn.ToList() ?? new List<Note>();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public Note GetNoteById(int noteId)
|
public Note GetNoteById(int noteId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Note>(tableName);
|
||||||
var table = db.GetCollection<Note>(tableName);
|
return table.FindById(noteId);
|
||||||
return table.FindById(noteId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveNoteToVehicle(Note note)
|
public bool SaveNoteToVehicle(Note note)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Note>(tableName);
|
||||||
var table = db.GetCollection<Note>(tableName);
|
table.Upsert(note);
|
||||||
table.Upsert(note);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteNoteById(int noteId)
|
public bool DeleteNoteById(int noteId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Note>(tableName);
|
||||||
var table = db.GetCollection<Note>(tableName);
|
table.Delete(noteId);
|
||||||
table.Delete(noteId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteAllNotesByVehicleId(int vehicleId)
|
public bool DeleteAllNotesByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Note>(tableName);
|
||||||
var table = db.GetCollection<Note>(tableName);
|
var notes = table.DeleteMany(Query.EQ(nameof(Note.VehicleId), vehicleId));
|
||||||
var notes = table.DeleteMany(Query.EQ(nameof(Note.VehicleId), vehicleId));
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,54 @@
|
|||||||
using CarCareTracker.External.Interfaces;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.Helper;
|
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
|
using CarCareTracker.Helper;
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
namespace CarCareTracker.External.Implementations
|
||||||
{
|
{
|
||||||
public class OdometerRecordDataAccess : IOdometerRecordDataAccess
|
public class OdometerRecordDataAccess : IOdometerRecordDataAccess
|
||||||
{
|
{
|
||||||
private static string dbName = StaticHelper.DbName;
|
private ILiteDBHelper _liteDB { get; set; }
|
||||||
private static string tableName = "odometerrecords";
|
private static string tableName = "odometerrecords";
|
||||||
|
public OdometerRecordDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<OdometerRecord> GetOdometerRecordsByVehicleId(int vehicleId)
|
public List<OdometerRecord> GetOdometerRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
var odometerRecords = table.Find(Query.EQ(nameof(OdometerRecord.VehicleId), vehicleId));
|
||||||
var odometerRecords = table.Find(Query.EQ(nameof(OdometerRecord.VehicleId), vehicleId));
|
return odometerRecords.ToList() ?? new List<OdometerRecord>();
|
||||||
return odometerRecords.ToList() ?? new List<OdometerRecord>();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public OdometerRecord GetOdometerRecordById(int odometerRecordId)
|
public OdometerRecord GetOdometerRecordById(int odometerRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
return table.FindById(odometerRecordId);
|
||||||
return table.FindById(odometerRecordId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteOdometerRecordById(int odometerRecordId)
|
public bool DeleteOdometerRecordById(int odometerRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
table.Delete(odometerRecordId);
|
||||||
table.Delete(odometerRecordId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveOdometerRecordToVehicle(OdometerRecord odometerRecord)
|
public bool SaveOdometerRecordToVehicle(OdometerRecord odometerRecord)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
table.Upsert(odometerRecord);
|
||||||
table.Upsert(odometerRecord);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteAllOdometerRecordsByVehicleId(int vehicleId)
|
public bool DeleteAllOdometerRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
var odometerRecords = table.DeleteMany(Query.EQ(nameof(OdometerRecord.VehicleId), vehicleId));
|
||||||
var odometerRecords = table.DeleteMany(Query.EQ(nameof(OdometerRecord.VehicleId), vehicleId));
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,54 @@
|
|||||||
using CarCareTracker.External.Interfaces;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.Helper;
|
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
|
using CarCareTracker.Helper;
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
namespace CarCareTracker.External.Implementations
|
||||||
{
|
{
|
||||||
public class PlanRecordDataAccess : IPlanRecordDataAccess
|
public class PlanRecordDataAccess : IPlanRecordDataAccess
|
||||||
{
|
{
|
||||||
private static string dbName = StaticHelper.DbName;
|
private ILiteDBHelper _liteDB { get; set; }
|
||||||
private static string tableName = "planrecords";
|
private static string tableName = "planrecords";
|
||||||
|
public PlanRecordDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<PlanRecord> GetPlanRecordsByVehicleId(int vehicleId)
|
public List<PlanRecord> GetPlanRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<PlanRecord>(tableName);
|
||||||
var table = db.GetCollection<PlanRecord>(tableName);
|
var planRecords = table.Find(Query.EQ(nameof(PlanRecord.VehicleId), vehicleId));
|
||||||
var planRecords = table.Find(Query.EQ(nameof(PlanRecord.VehicleId), vehicleId));
|
return planRecords.ToList() ?? new List<PlanRecord>();
|
||||||
return planRecords.ToList() ?? new List<PlanRecord>();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public PlanRecord GetPlanRecordById(int planRecordId)
|
public PlanRecord GetPlanRecordById(int planRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<PlanRecord>(tableName);
|
||||||
var table = db.GetCollection<PlanRecord>(tableName);
|
return table.FindById(planRecordId);
|
||||||
return table.FindById(planRecordId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeletePlanRecordById(int planRecordId)
|
public bool DeletePlanRecordById(int planRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<PlanRecord>(tableName);
|
||||||
var table = db.GetCollection<PlanRecord>(tableName);
|
table.Delete(planRecordId);
|
||||||
table.Delete(planRecordId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SavePlanRecordToVehicle(PlanRecord planRecord)
|
public bool SavePlanRecordToVehicle(PlanRecord planRecord)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<PlanRecord>(tableName);
|
||||||
var table = db.GetCollection<PlanRecord>(tableName);
|
table.Upsert(planRecord);
|
||||||
table.Upsert(planRecord);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteAllPlanRecordsByVehicleId(int vehicleId)
|
public bool DeleteAllPlanRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<PlanRecord>(tableName);
|
||||||
var table = db.GetCollection<PlanRecord>(tableName);
|
var planRecords = table.DeleteMany(Query.EQ(nameof(PlanRecord.VehicleId), vehicleId));
|
||||||
var planRecords = table.DeleteMany(Query.EQ(nameof(PlanRecord.VehicleId), vehicleId));
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,54 @@
|
|||||||
using CarCareTracker.External.Interfaces;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.Helper;
|
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
|
using CarCareTracker.Helper;
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
namespace CarCareTracker.External.Implementations
|
||||||
{
|
{
|
||||||
public class PlanRecordTemplateDataAccess : IPlanRecordTemplateDataAccess
|
public class PlanRecordTemplateDataAccess : IPlanRecordTemplateDataAccess
|
||||||
{
|
{
|
||||||
private static string dbName = StaticHelper.DbName;
|
private ILiteDBHelper _liteDB { get; set; }
|
||||||
private static string tableName = "planrecordtemplates";
|
private static string tableName = "planrecordtemplates";
|
||||||
|
public PlanRecordTemplateDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<PlanRecordInput> GetPlanRecordTemplatesByVehicleId(int vehicleId)
|
public List<PlanRecordInput> GetPlanRecordTemplatesByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
var planRecords = table.Find(Query.EQ(nameof(PlanRecordInput.VehicleId), vehicleId));
|
||||||
var planRecords = table.Find(Query.EQ(nameof(PlanRecordInput.VehicleId), vehicleId));
|
return planRecords.ToList() ?? new List<PlanRecordInput>();
|
||||||
return planRecords.ToList() ?? new List<PlanRecordInput>();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public PlanRecordInput GetPlanRecordTemplateById(int planRecordId)
|
public PlanRecordInput GetPlanRecordTemplateById(int planRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
return table.FindById(planRecordId);
|
||||||
return table.FindById(planRecordId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeletePlanRecordTemplateById(int planRecordId)
|
public bool DeletePlanRecordTemplateById(int planRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
table.Delete(planRecordId);
|
||||||
table.Delete(planRecordId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SavePlanRecordTemplateToVehicle(PlanRecordInput planRecord)
|
public bool SavePlanRecordTemplateToVehicle(PlanRecordInput planRecord)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<PlanRecordInput>(tableName);
|
||||||
var table = db.GetCollection<PlanRecordInput>(tableName);
|
table.Upsert(planRecord);
|
||||||
table.Upsert(planRecord);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteAllPlanRecordTemplatesByVehicleId(int vehicleId)
|
public bool DeleteAllPlanRecordTemplatesByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<PlanRecord>(tableName);
|
||||||
var table = db.GetCollection<PlanRecord>(tableName);
|
var planRecords = table.DeleteMany(Query.EQ(nameof(PlanRecordInput.VehicleId), vehicleId));
|
||||||
var planRecords = table.DeleteMany(Query.EQ(nameof(PlanRecordInput.VehicleId), vehicleId));
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,54 @@
|
|||||||
using CarCareTracker.External.Interfaces;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.Helper;
|
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
|
using CarCareTracker.Helper;
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
namespace CarCareTracker.External.Implementations
|
||||||
{
|
{
|
||||||
public class ReminderRecordDataAccess : IReminderRecordDataAccess
|
public class ReminderRecordDataAccess : IReminderRecordDataAccess
|
||||||
{
|
{
|
||||||
private static string dbName = StaticHelper.DbName;
|
private ILiteDBHelper _liteDB { get; set; }
|
||||||
private static string tableName = "reminderrecords";
|
private static string tableName = "reminderrecords";
|
||||||
|
public ReminderRecordDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<ReminderRecord> GetReminderRecordsByVehicleId(int vehicleId)
|
public List<ReminderRecord> GetReminderRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
var reminderRecords = table.Find(Query.EQ(nameof(ReminderRecord.VehicleId), vehicleId));
|
||||||
var reminderRecords = table.Find(Query.EQ(nameof(ReminderRecord.VehicleId), vehicleId));
|
return reminderRecords.ToList() ?? new List<ReminderRecord>();
|
||||||
return reminderRecords.ToList() ?? new List<ReminderRecord>();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public ReminderRecord GetReminderRecordById(int reminderRecordId)
|
public ReminderRecord GetReminderRecordById(int reminderRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
return table.FindById(reminderRecordId);
|
||||||
return table.FindById(reminderRecordId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteReminderRecordById(int reminderRecordId)
|
public bool DeleteReminderRecordById(int reminderRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
table.Delete(reminderRecordId);
|
||||||
table.Delete(reminderRecordId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveReminderRecordToVehicle(ReminderRecord reminderRecord)
|
public bool SaveReminderRecordToVehicle(ReminderRecord reminderRecord)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
table.Upsert(reminderRecord);
|
||||||
table.Upsert(reminderRecord);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteAllReminderRecordsByVehicleId(int vehicleId)
|
public bool DeleteAllReminderRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<ReminderRecord>(tableName);
|
||||||
var table = db.GetCollection<ReminderRecord>(tableName);
|
var reminderRecords = table.DeleteMany(Query.EQ(nameof(ReminderRecord.VehicleId), vehicleId));
|
||||||
var reminderRecords = table.DeleteMany(Query.EQ(nameof(ReminderRecord.VehicleId), vehicleId));
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,54 @@
|
|||||||
using CarCareTracker.External.Interfaces;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.Helper;
|
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
|
using CarCareTracker.Helper;
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
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";
|
private static string tableName = "servicerecords";
|
||||||
|
public ServiceRecordDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<ServiceRecord> GetServiceRecordsByVehicleId(int vehicleId)
|
public List<ServiceRecord> GetServiceRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
var serviceRecords = table.Find(Query.EQ(nameof(ServiceRecord.VehicleId), vehicleId));
|
||||||
var serviceRecords = table.Find(Query.EQ(nameof(ServiceRecord.VehicleId), vehicleId));
|
return serviceRecords.ToList() ?? new List<ServiceRecord>();
|
||||||
return serviceRecords.ToList() ?? new List<ServiceRecord>();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public ServiceRecord GetServiceRecordById(int serviceRecordId)
|
public ServiceRecord GetServiceRecordById(int serviceRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
return table.FindById(serviceRecordId);
|
||||||
return table.FindById(serviceRecordId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteServiceRecordById(int serviceRecordId)
|
public bool DeleteServiceRecordById(int serviceRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
table.Delete(serviceRecordId);
|
||||||
table.Delete(serviceRecordId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveServiceRecordToVehicle(ServiceRecord serviceRecord)
|
public bool SaveServiceRecordToVehicle(ServiceRecord serviceRecord)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
table.Upsert(serviceRecord);
|
||||||
table.Upsert(serviceRecord);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteAllServiceRecordsByVehicleId(int vehicleId)
|
public bool DeleteAllServiceRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<ServiceRecord>(tableName);
|
||||||
var table = db.GetCollection<ServiceRecord>(tableName);
|
var serviceRecords = table.DeleteMany(Query.EQ(nameof(ServiceRecord.VehicleId), vehicleId));
|
||||||
var serviceRecords = table.DeleteMany(Query.EQ(nameof(ServiceRecord.VehicleId), vehicleId));
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,51 +7,48 @@ namespace CarCareTracker.External.Implementations
|
|||||||
{
|
{
|
||||||
public class SupplyRecordDataAccess : ISupplyRecordDataAccess
|
public class SupplyRecordDataAccess : ISupplyRecordDataAccess
|
||||||
{
|
{
|
||||||
private static string dbName = StaticHelper.DbName;
|
private ILiteDBHelper _liteDB { get; set; }
|
||||||
private static string tableName = "supplyrecords";
|
private static string tableName = "supplyrecords";
|
||||||
|
public SupplyRecordDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<SupplyRecord> GetSupplyRecordsByVehicleId(int vehicleId)
|
public List<SupplyRecord> GetSupplyRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
var supplyRecords = table.Find(Query.EQ(nameof(SupplyRecord.VehicleId), vehicleId));
|
||||||
var supplyRecords = table.Find(Query.EQ(nameof(SupplyRecord.VehicleId), vehicleId));
|
return supplyRecords.ToList() ?? new List<SupplyRecord>();
|
||||||
return supplyRecords.ToList() ?? new List<SupplyRecord>();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public SupplyRecord GetSupplyRecordById(int supplyRecordId)
|
public SupplyRecord GetSupplyRecordById(int supplyRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
return table.FindById(supplyRecordId);
|
||||||
return table.FindById(supplyRecordId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteSupplyRecordById(int supplyRecordId)
|
public bool DeleteSupplyRecordById(int supplyRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
table.Delete(supplyRecordId);
|
||||||
table.Delete(supplyRecordId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveSupplyRecordToVehicle(SupplyRecord supplyRecord)
|
public bool SaveSupplyRecordToVehicle(SupplyRecord supplyRecord)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
table.Upsert(supplyRecord);
|
||||||
table.Upsert(supplyRecord);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteAllSupplyRecordsByVehicleId(int vehicleId)
|
public bool DeleteAllSupplyRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
var supplyRecords = table.DeleteMany(Query.EQ(nameof(SupplyRecord.VehicleId), vehicleId));
|
||||||
var supplyRecords = table.DeleteMany(Query.EQ(nameof(SupplyRecord.VehicleId), vehicleId));
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,54 @@
|
|||||||
using CarCareTracker.External.Interfaces;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.Helper;
|
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
|
using CarCareTracker.Helper;
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
namespace CarCareTracker.External.Implementations
|
||||||
{
|
{
|
||||||
public class TaxRecordDataAccess : ITaxRecordDataAccess
|
public class TaxRecordDataAccess : ITaxRecordDataAccess
|
||||||
{
|
{
|
||||||
private static string dbName = StaticHelper.DbName;
|
private ILiteDBHelper _liteDB { get; set; }
|
||||||
private static string tableName = "taxrecords";
|
private static string tableName = "taxrecords";
|
||||||
|
public TaxRecordDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<TaxRecord> GetTaxRecordsByVehicleId(int vehicleId)
|
public List<TaxRecord> GetTaxRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<TaxRecord>(tableName);
|
||||||
var table = db.GetCollection<TaxRecord>(tableName);
|
var taxRecords = table.Find(Query.EQ(nameof(TaxRecord.VehicleId), vehicleId));
|
||||||
var taxRecords = table.Find(Query.EQ(nameof(TaxRecord.VehicleId), vehicleId));
|
return taxRecords.ToList() ?? new List<TaxRecord>();
|
||||||
return taxRecords.ToList() ?? new List<TaxRecord>();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public TaxRecord GetTaxRecordById(int taxRecordId)
|
public TaxRecord GetTaxRecordById(int taxRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<TaxRecord>(tableName);
|
||||||
var table = db.GetCollection<TaxRecord>(tableName);
|
return table.FindById(taxRecordId);
|
||||||
return table.FindById(taxRecordId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteTaxRecordById(int taxRecordId)
|
public bool DeleteTaxRecordById(int taxRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<TaxRecord>(tableName);
|
||||||
var table = db.GetCollection<TaxRecord>(tableName);
|
table.Delete(taxRecordId);
|
||||||
table.Delete(taxRecordId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveTaxRecordToVehicle(TaxRecord taxRecord)
|
public bool SaveTaxRecordToVehicle(TaxRecord taxRecord)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<TaxRecord>(tableName);
|
||||||
var table = db.GetCollection<TaxRecord>(tableName);
|
table.Upsert(taxRecord);
|
||||||
table.Upsert(taxRecord);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteAllTaxRecordsByVehicleId(int vehicleId)
|
public bool DeleteAllTaxRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<TaxRecord>(tableName);
|
||||||
var table = db.GetCollection<TaxRecord>(tableName);
|
var taxRecords = table.DeleteMany(Query.EQ(nameof(TaxRecord.VehicleId), vehicleId));
|
||||||
var taxRecords = table.DeleteMany(Query.EQ(nameof(TaxRecord.VehicleId), vehicleId));
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,51 +7,47 @@ namespace CarCareTracker.External.Implementations
|
|||||||
{
|
{
|
||||||
public class TokenRecordDataAccess : ITokenRecordDataAccess
|
public class TokenRecordDataAccess : ITokenRecordDataAccess
|
||||||
{
|
{
|
||||||
private static string dbName = StaticHelper.DbName;
|
private ILiteDBHelper _liteDB { get; set; }
|
||||||
private static string tableName = "tokenrecords";
|
private static string tableName = "tokenrecords";
|
||||||
|
public TokenRecordDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<Token> GetTokens()
|
public List<Token> GetTokens()
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Token>(tableName);
|
||||||
var table = db.GetCollection<Token>(tableName);
|
return table.FindAll().ToList();
|
||||||
return table.FindAll().ToList();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public Token GetTokenRecordByBody(string tokenBody)
|
public Token GetTokenRecordByBody(string tokenBody)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Token>(tableName);
|
||||||
var table = db.GetCollection<Token>(tableName);
|
var tokenRecord = table.FindOne(Query.EQ(nameof(Token.Body), tokenBody));
|
||||||
var tokenRecord = table.FindOne(Query.EQ(nameof(Token.Body), tokenBody));
|
return tokenRecord ?? new Token();
|
||||||
return tokenRecord ?? new Token();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public Token GetTokenRecordByEmailAddress(string emailAddress)
|
public Token GetTokenRecordByEmailAddress(string emailAddress)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Token>(tableName);
|
||||||
var table = db.GetCollection<Token>(tableName);
|
var tokenRecord = table.FindOne(Query.EQ(nameof(Token.EmailAddress), emailAddress));
|
||||||
var tokenRecord = table.FindOne(Query.EQ(nameof(Token.EmailAddress), emailAddress));
|
return tokenRecord ?? new Token();
|
||||||
return tokenRecord ?? new Token();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool CreateNewToken(Token token)
|
public bool CreateNewToken(Token token)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Token>(tableName);
|
||||||
var table = db.GetCollection<Token>(tableName);
|
table.Insert(token);
|
||||||
table.Insert(token);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteToken(int tokenId)
|
public bool DeleteToken(int tokenId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Token>(tableName);
|
||||||
var table = db.GetCollection<Token>(tableName);
|
table.Delete(tokenId);
|
||||||
table.Delete(tokenId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,51 +7,48 @@ namespace CarCareTracker.External.Implementations
|
|||||||
{
|
{
|
||||||
public class UpgradeRecordDataAccess : IUpgradeRecordDataAccess
|
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";
|
private static string tableName = "upgraderecords";
|
||||||
public List<UpgradeRecord> GetUpgradeRecordsByVehicleId(int vehicleId)
|
public List<UpgradeRecord> GetUpgradeRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
var upgradeRecords = table.Find(Query.EQ(nameof(UpgradeRecord.VehicleId), vehicleId));
|
||||||
var upgradeRecords = table.Find(Query.EQ(nameof(UpgradeRecord.VehicleId), vehicleId));
|
return upgradeRecords.ToList() ?? new List<UpgradeRecord>();
|
||||||
return upgradeRecords.ToList() ?? new List<UpgradeRecord>();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public UpgradeRecord GetUpgradeRecordById(int upgradeRecordId)
|
public UpgradeRecord GetUpgradeRecordById(int upgradeRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
return table.FindById(upgradeRecordId);
|
||||||
return table.FindById(upgradeRecordId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteUpgradeRecordById(int upgradeRecordId)
|
public bool DeleteUpgradeRecordById(int upgradeRecordId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
table.Delete(upgradeRecordId);
|
||||||
table.Delete(upgradeRecordId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveUpgradeRecordToVehicle(UpgradeRecord upgradeRecord)
|
public bool SaveUpgradeRecordToVehicle(UpgradeRecord upgradeRecord)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
table.Upsert(upgradeRecord);
|
||||||
table.Upsert(upgradeRecord);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteAllUpgradeRecordsByVehicleId(int vehicleId)
|
public bool DeleteAllUpgradeRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UpgradeRecord>(tableName);
|
||||||
var table = db.GetCollection<UpgradeRecord>(tableName);
|
var upgradeRecords = table.DeleteMany(Query.EQ(nameof(UpgradeRecord.VehicleId), vehicleId));
|
||||||
var upgradeRecords = table.DeleteMany(Query.EQ(nameof(UpgradeRecord.VehicleId), vehicleId));
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ namespace CarCareTracker.External.Implementations
|
|||||||
{
|
{
|
||||||
public class UserAccessDataAccess : IUserAccessDataAccess
|
public class UserAccessDataAccess : IUserAccessDataAccess
|
||||||
{
|
{
|
||||||
private static string dbName = StaticHelper.DbName;
|
private ILiteDBHelper _liteDB { get; set; }
|
||||||
private static string tableName = "useraccessrecords";
|
private static string tableName = "useraccessrecords";
|
||||||
|
public UserAccessDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of vehicles user have access to.
|
/// Gets a list of vehicles user have access to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -16,45 +20,37 @@ namespace CarCareTracker.External.Implementations
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<UserAccess> GetUserAccessByUserId(int userId)
|
public List<UserAccess> GetUserAccessByUserId(int userId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserAccess>(tableName);
|
||||||
var table = db.GetCollection<UserAccess>(tableName);
|
return table.Find(x => x.Id.UserId == userId).ToList();
|
||||||
return table.Find(x=>x.Id.UserId == userId).ToList();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public UserAccess GetUserAccessByVehicleAndUserId(int userId, int vehicleId)
|
public UserAccess GetUserAccessByVehicleAndUserId(int userId, int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserAccess>(tableName);
|
||||||
var table = db.GetCollection<UserAccess>(tableName);
|
return table.Find(x => x.Id.UserId == userId && x.Id.VehicleId == vehicleId).FirstOrDefault();
|
||||||
return table.Find(x => x.Id.UserId == userId && x.Id.VehicleId == vehicleId).FirstOrDefault();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public List<UserAccess> GetUserAccessByVehicleId(int vehicleId)
|
public List<UserAccess> GetUserAccessByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserAccess>(tableName);
|
||||||
var table = db.GetCollection<UserAccess>(tableName);
|
return table.Find(x => x.Id.VehicleId == vehicleId).ToList();
|
||||||
return table.Find(x => x.Id.VehicleId == vehicleId).ToList();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveUserAccess(UserAccess userAccess)
|
public bool SaveUserAccess(UserAccess userAccess)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserAccess>(tableName);
|
||||||
var table = db.GetCollection<UserAccess>(tableName);
|
table.Upsert(userAccess);
|
||||||
table.Upsert(userAccess);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteUserAccess(int userId, int vehicleId)
|
public bool DeleteUserAccess(int userId, int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserAccess>(tableName);
|
||||||
var table = db.GetCollection<UserAccess>(tableName);
|
table.DeleteMany(x => x.Id.UserId == userId && x.Id.VehicleId == vehicleId);
|
||||||
table.DeleteMany(x => x.Id.UserId == userId && x.Id.VehicleId == vehicleId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete all access records when a vehicle is deleted.
|
/// Delete all access records when a vehicle is deleted.
|
||||||
@@ -63,12 +59,11 @@ namespace CarCareTracker.External.Implementations
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool DeleteAllAccessRecordsByVehicleId(int vehicleId)
|
public bool DeleteAllAccessRecordsByVehicleId(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserAccess>(tableName);
|
||||||
var table = db.GetCollection<UserAccess>(tableName);
|
table.DeleteMany(x => x.Id.VehicleId == vehicleId);
|
||||||
table.DeleteMany(x=>x.Id.VehicleId == vehicleId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delee all access records when a user is deleted.
|
/// Delee all access records when a user is deleted.
|
||||||
@@ -77,12 +72,11 @@ namespace CarCareTracker.External.Implementations
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool DeleteAllAccessRecordsByUserId(int userId)
|
public bool DeleteAllAccessRecordsByUserId(int userId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserAccess>(tableName);
|
||||||
var table = db.GetCollection<UserAccess>(tableName);
|
table.DeleteMany(x => x.Id.UserId == userId);
|
||||||
table.DeleteMany(x => x.Id.UserId == userId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,39 +1,38 @@
|
|||||||
using CarCareTracker.External.Interfaces;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.Helper;
|
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
using LiteDB;
|
using CarCareTracker.Helper;
|
||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
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";
|
private static string tableName = "userconfigrecords";
|
||||||
|
public UserConfigDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public UserConfigData GetUserConfig(int userId)
|
public UserConfigData GetUserConfig(int userId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserConfigData>(tableName);
|
||||||
var table = db.GetCollection<UserConfigData>(tableName);
|
return table.FindById(userId);
|
||||||
return table.FindById(userId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveUserConfig(UserConfigData userConfigData)
|
public bool SaveUserConfig(UserConfigData userConfigData)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserConfigData>(tableName);
|
||||||
var table = db.GetCollection<UserConfigData>(tableName);
|
table.Upsert(userConfigData);
|
||||||
table.Upsert(userConfigData);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteUserConfig(int userId)
|
public bool DeleteUserConfig(int userId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserConfigData>(tableName);
|
||||||
var table = db.GetCollection<UserConfigData>(tableName);
|
table.Delete(userId);
|
||||||
table.Delete(userId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,66 +1,60 @@
|
|||||||
using CarCareTracker.External.Interfaces;
|
using CarCareTracker.External.Interfaces;
|
||||||
using CarCareTracker.Helper;
|
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
|
using CarCareTracker.Helper;
|
||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
namespace CarCareTracker.External.Implementations
|
||||||
{
|
{
|
||||||
public class UserRecordDataAccess : IUserRecordDataAccess
|
public class UserRecordDataAccess : IUserRecordDataAccess
|
||||||
{
|
{
|
||||||
private static string dbName = StaticHelper.DbName;
|
private ILiteDBHelper _liteDB { get; set; }
|
||||||
private static string tableName = "userrecords";
|
private static string tableName = "userrecords";
|
||||||
|
public UserRecordDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public List<UserData> GetUsers()
|
public List<UserData> GetUsers()
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserData>(tableName);
|
||||||
var table = db.GetCollection<UserData>(tableName);
|
return table.FindAll().ToList();
|
||||||
return table.FindAll().ToList();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public UserData GetUserRecordByUserName(string userName)
|
public UserData GetUserRecordByUserName(string userName)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserData>(tableName);
|
||||||
var table = db.GetCollection<UserData>(tableName);
|
var userRecord = table.FindOne(Query.EQ(nameof(UserData.UserName), userName));
|
||||||
var userRecord = table.FindOne(Query.EQ(nameof(UserData.UserName), userName));
|
return userRecord ?? new UserData();
|
||||||
return userRecord ?? new UserData();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public UserData GetUserRecordByEmailAddress(string emailAddress)
|
public UserData GetUserRecordByEmailAddress(string emailAddress)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserData>(tableName);
|
||||||
var table = db.GetCollection<UserData>(tableName);
|
var userRecord = table.FindOne(Query.EQ(nameof(UserData.EmailAddress), emailAddress));
|
||||||
var userRecord = table.FindOne(Query.EQ(nameof(UserData.EmailAddress), emailAddress));
|
return userRecord ?? new UserData();
|
||||||
return userRecord ?? new UserData();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public UserData GetUserRecordById(int userId)
|
public UserData GetUserRecordById(int userId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserData>(tableName);
|
||||||
var table = db.GetCollection<UserData>(tableName);
|
var userRecord = table.FindById(userId);
|
||||||
var userRecord = table.FindById(userId);
|
return userRecord ?? new UserData();
|
||||||
return userRecord ?? new UserData();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool SaveUserRecord(UserData userRecord)
|
public bool SaveUserRecord(UserData userRecord)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserData>(tableName);
|
||||||
var table = db.GetCollection<UserData>(tableName);
|
table.Upsert(userRecord);
|
||||||
table.Upsert(userRecord);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteUserRecord(int userId)
|
public bool DeleteUserRecord(int userId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<UserData>(tableName);
|
||||||
var table = db.GetCollection<UserData>(tableName);
|
table.Delete(userId);
|
||||||
table.Delete(userId);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,42 +5,41 @@ using LiteDB;
|
|||||||
|
|
||||||
namespace CarCareTracker.External.Implementations
|
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";
|
private static string tableName = "vehicles";
|
||||||
|
public VehicleDataAccess(ILiteDBHelper liteDB)
|
||||||
|
{
|
||||||
|
_liteDB = liteDB;
|
||||||
|
}
|
||||||
public bool SaveVehicle(Vehicle vehicle)
|
public bool SaveVehicle(Vehicle vehicle)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Vehicle>(tableName);
|
||||||
var table = db.GetCollection<Vehicle>(tableName);
|
var result = table.Upsert(vehicle);
|
||||||
var result = table.Upsert(vehicle);
|
db.Checkpoint();
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public bool DeleteVehicle(int vehicleId)
|
public bool DeleteVehicle(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Vehicle>(tableName);
|
||||||
var table = db.GetCollection<Vehicle>(tableName);
|
var result = table.Delete(vehicleId);
|
||||||
return table.Delete(vehicleId);
|
db.Checkpoint();
|
||||||
};
|
return result;
|
||||||
}
|
}
|
||||||
public List<Vehicle> GetVehicles()
|
public List<Vehicle> GetVehicles()
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Vehicle>(tableName);
|
||||||
var table = db.GetCollection<Vehicle>(tableName);
|
return table.FindAll().ToList();
|
||||||
return table.FindAll().ToList();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
public Vehicle GetVehicleById(int vehicleId)
|
public Vehicle GetVehicleById(int vehicleId)
|
||||||
{
|
{
|
||||||
using (var db = new LiteDatabase(dbName))
|
var db = _liteDB.GetLiteDB();
|
||||||
{
|
var table = db.GetCollection<Vehicle>(tableName);
|
||||||
var table = db.GetCollection<Vehicle>(tableName);
|
return table.FindById(vehicleId);
|
||||||
return table.FindById(vehicleId);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -141,7 +141,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
} catch (Exception ex)
|
} catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", vehicleId);
|
ctext.Parameters.AddWithValue("id", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -176,7 +176,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
|
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -198,7 +199,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("userId", userId);
|
ctext.Parameters.AddWithValue("userId", userId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -94,7 +94,8 @@ namespace CarCareTracker.External.Implementations
|
|||||||
using (var ctext = pgDataSource.CreateCommand(cmd))
|
using (var ctext = pgDataSource.CreateCommand(cmd))
|
||||||
{
|
{
|
||||||
ctext.Parameters.AddWithValue("id", userId);
|
ctext.Parameters.AddWithValue("id", userId);
|
||||||
return ctext.ExecuteNonQuery() > 0;
|
ctext.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -12,10 +12,12 @@ namespace CarCareTracker.Helper
|
|||||||
UserConfig GetUserConfig(ClaimsPrincipal user);
|
UserConfig GetUserConfig(ClaimsPrincipal user);
|
||||||
bool SaveUserConfig(ClaimsPrincipal user, UserConfig configData);
|
bool SaveUserConfig(ClaimsPrincipal user, UserConfig configData);
|
||||||
bool AuthenticateRootUser(string username, string password);
|
bool AuthenticateRootUser(string username, string password);
|
||||||
|
bool AuthenticateRootUserOIDC(string email);
|
||||||
string GetWebHookUrl();
|
string GetWebHookUrl();
|
||||||
string GetMOTD();
|
string GetMOTD();
|
||||||
string GetLogoUrl();
|
string GetLogoUrl();
|
||||||
string GetServerLanguage();
|
string GetServerLanguage();
|
||||||
|
bool GetServerDisabledRegistration();
|
||||||
bool GetServerEnableShopSupplies();
|
bool GetServerEnableShopSupplies();
|
||||||
string GetServerPostgresConnection();
|
string GetServerPostgresConnection();
|
||||||
string GetAllowedFileUploadExtensions();
|
string GetAllowedFileUploadExtensions();
|
||||||
@@ -89,11 +91,26 @@ namespace CarCareTracker.Helper
|
|||||||
}
|
}
|
||||||
return username == rootUsername && password == rootPassword;
|
return username == rootUsername && password == rootPassword;
|
||||||
}
|
}
|
||||||
|
public bool AuthenticateRootUserOIDC(string email)
|
||||||
|
{
|
||||||
|
var rootEmail = _config[nameof(UserConfig.DefaultReminderEmail)] ?? string.Empty;
|
||||||
|
var rootUserOIDC = bool.Parse(_config[nameof(UserConfig.EnableRootUserOIDC)]);
|
||||||
|
if (!rootUserOIDC || string.IsNullOrWhiteSpace(rootEmail))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return email == rootEmail;
|
||||||
|
}
|
||||||
public string GetServerLanguage()
|
public string GetServerLanguage()
|
||||||
{
|
{
|
||||||
var serverLanguage = _config[nameof(UserConfig.UserLanguage)] ?? "en_US";
|
var serverLanguage = _config[nameof(UserConfig.UserLanguage)] ?? "en_US";
|
||||||
return serverLanguage;
|
return serverLanguage;
|
||||||
}
|
}
|
||||||
|
public bool GetServerDisabledRegistration()
|
||||||
|
{
|
||||||
|
var registrationDisabled = bool.Parse(_config[nameof(UserConfig.DisableRegistration)]);
|
||||||
|
return registrationDisabled;
|
||||||
|
}
|
||||||
public string GetServerPostgresConnection()
|
public string GetServerPostgresConnection()
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(_config["POSTGRES_CONNECTION"]))
|
if (!string.IsNullOrWhiteSpace(_config["POSTGRES_CONNECTION"]))
|
||||||
@@ -162,9 +179,11 @@ namespace CarCareTracker.Helper
|
|||||||
{
|
{
|
||||||
EnableCsvImports = bool.Parse(_config[nameof(UserConfig.EnableCsvImports)]),
|
EnableCsvImports = bool.Parse(_config[nameof(UserConfig.EnableCsvImports)]),
|
||||||
UseDarkMode = bool.Parse(_config[nameof(UserConfig.UseDarkMode)]),
|
UseDarkMode = bool.Parse(_config[nameof(UserConfig.UseDarkMode)]),
|
||||||
|
UseSystemColorMode = bool.Parse(_config[nameof(UserConfig.UseSystemColorMode)]),
|
||||||
UseMPG = bool.Parse(_config[nameof(UserConfig.UseMPG)]),
|
UseMPG = bool.Parse(_config[nameof(UserConfig.UseMPG)]),
|
||||||
UseDescending = bool.Parse(_config[nameof(UserConfig.UseDescending)]),
|
UseDescending = bool.Parse(_config[nameof(UserConfig.UseDescending)]),
|
||||||
EnableAuth = bool.Parse(_config[nameof(UserConfig.EnableAuth)]),
|
EnableAuth = bool.Parse(_config[nameof(UserConfig.EnableAuth)]),
|
||||||
|
EnableRootUserOIDC = bool.Parse(_config[nameof(UserConfig.EnableRootUserOIDC)]),
|
||||||
HideZero = bool.Parse(_config[nameof(UserConfig.HideZero)]),
|
HideZero = bool.Parse(_config[nameof(UserConfig.HideZero)]),
|
||||||
UseUKMPG = bool.Parse(_config[nameof(UserConfig.UseUKMPG)]),
|
UseUKMPG = bool.Parse(_config[nameof(UserConfig.UseUKMPG)]),
|
||||||
UseMarkDownOnSavedNotes = bool.Parse(_config[nameof(UserConfig.UseMarkDownOnSavedNotes)]),
|
UseMarkDownOnSavedNotes = bool.Parse(_config[nameof(UserConfig.UseMarkDownOnSavedNotes)]),
|
||||||
@@ -180,7 +199,9 @@ namespace CarCareTracker.Helper
|
|||||||
VisibleTabs = _config.GetSection(nameof(UserConfig.VisibleTabs)).Get<List<ImportMode>>(),
|
VisibleTabs = _config.GetSection(nameof(UserConfig.VisibleTabs)).Get<List<ImportMode>>(),
|
||||||
UserColumnPreferences = _config.GetSection(nameof(UserConfig.UserColumnPreferences)).Get<List<UserColumnPreference>>() ?? new List<UserColumnPreference>(),
|
UserColumnPreferences = _config.GetSection(nameof(UserConfig.UserColumnPreferences)).Get<List<UserColumnPreference>>() ?? new List<UserColumnPreference>(),
|
||||||
ReminderUrgencyConfig = _config.GetSection(nameof(UserConfig.ReminderUrgencyConfig)).Get<ReminderUrgencyConfig>() ?? new ReminderUrgencyConfig(),
|
ReminderUrgencyConfig = _config.GetSection(nameof(UserConfig.ReminderUrgencyConfig)).Get<ReminderUrgencyConfig>() ?? new ReminderUrgencyConfig(),
|
||||||
DefaultTab = (ImportMode)int.Parse(_config[nameof(UserConfig.DefaultTab)])
|
DefaultTab = (ImportMode)int.Parse(_config[nameof(UserConfig.DefaultTab)]),
|
||||||
|
DefaultReminderEmail = _config[nameof(UserConfig.DefaultReminderEmail)],
|
||||||
|
DisableRegistration = bool.Parse(_config[nameof(UserConfig.DisableRegistration)])
|
||||||
};
|
};
|
||||||
int userId = 0;
|
int userId = 0;
|
||||||
if (user != null)
|
if (user != null)
|
||||||
|
|||||||
@@ -13,15 +13,20 @@ namespace CarCareTracker.Helper
|
|||||||
bool RestoreBackup(string fileName, bool clearExisting = false);
|
bool RestoreBackup(string fileName, bool clearExisting = false);
|
||||||
string MakeAttachmentsExport(List<GenericReportModel> exportData);
|
string MakeAttachmentsExport(List<GenericReportModel> exportData);
|
||||||
List<string> GetLanguages();
|
List<string> GetLanguages();
|
||||||
|
int ClearTempFolder();
|
||||||
|
int ClearUnlinkedThumbnails(List<string> linkedImages);
|
||||||
|
int ClearUnlinkedDocuments(List<string> linkedDocuments);
|
||||||
}
|
}
|
||||||
public class FileHelper : IFileHelper
|
public class FileHelper : IFileHelper
|
||||||
{
|
{
|
||||||
private readonly IWebHostEnvironment _webEnv;
|
private readonly IWebHostEnvironment _webEnv;
|
||||||
private readonly ILogger<IFileHelper> _logger;
|
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;
|
_webEnv = webEnv;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_liteDB = liteDB;
|
||||||
}
|
}
|
||||||
public List<string> GetLanguages()
|
public List<string> GetLanguages()
|
||||||
{
|
{
|
||||||
@@ -164,6 +169,8 @@ namespace CarCareTracker.Helper
|
|||||||
}
|
}
|
||||||
if (File.Exists(dataPath))
|
if (File.Exists(dataPath))
|
||||||
{
|
{
|
||||||
|
//Relinquish current DB file lock
|
||||||
|
_liteDB.DisposeLiteDB();
|
||||||
//data path will always exist as it is created on startup if not.
|
//data path will always exist as it is created on startup if not.
|
||||||
File.Move(dataPath, StaticHelper.DbName, true);
|
File.Move(dataPath, StaticHelper.DbName, true);
|
||||||
}
|
}
|
||||||
@@ -310,5 +317,56 @@ namespace CarCareTracker.Helper
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public int ClearTempFolder()
|
||||||
|
{
|
||||||
|
int filesDeleted = 0;
|
||||||
|
var tempPath = GetFullFilePath("temp", false);
|
||||||
|
if (Directory.Exists(tempPath))
|
||||||
|
{
|
||||||
|
var files = Directory.GetFiles(tempPath);
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
filesDeleted++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filesDeleted;
|
||||||
|
}
|
||||||
|
public int ClearUnlinkedThumbnails(List<string> linkedImages)
|
||||||
|
{
|
||||||
|
int filesDeleted = 0;
|
||||||
|
var imagePath = GetFullFilePath("images", false);
|
||||||
|
if (Directory.Exists(imagePath))
|
||||||
|
{
|
||||||
|
var files = Directory.GetFiles(imagePath);
|
||||||
|
foreach(var file in files)
|
||||||
|
{
|
||||||
|
if (!linkedImages.Contains(Path.GetFileName(file)))
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
filesDeleted++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filesDeleted;
|
||||||
|
}
|
||||||
|
public int ClearUnlinkedDocuments(List<string> linkedDocuments)
|
||||||
|
{
|
||||||
|
int filesDeleted = 0;
|
||||||
|
var documentPath = GetFullFilePath("documents", false);
|
||||||
|
if (Directory.Exists(documentPath))
|
||||||
|
{
|
||||||
|
var files = Directory.GetFiles(documentPath);
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
if (!linkedDocuments.Contains(Path.GetFileName(file)))
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
filesDeleted++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filesDeleted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ namespace CarCareTracker.Helper
|
|||||||
if (i > 0)
|
if (i > 0)
|
||||||
{
|
{
|
||||||
var deltaMileage = currentObject.Mileage - previousMileage;
|
var deltaMileage = currentObject.Mileage - previousMileage;
|
||||||
|
if (deltaMileage < 0)
|
||||||
|
{
|
||||||
|
deltaMileage = 0;
|
||||||
|
}
|
||||||
var gasRecordViewModel = new GasRecordViewModel()
|
var gasRecordViewModel = new GasRecordViewModel()
|
||||||
{
|
{
|
||||||
Id = currentObject.Id,
|
Id = currentObject.Id,
|
||||||
|
|||||||
36
Helper/LiteDBHelper.cs
Normal file
36
Helper/LiteDBHelper.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using LiteDB;
|
||||||
|
|
||||||
|
namespace CarCareTracker.Helper;
|
||||||
|
|
||||||
|
public interface ILiteDBHelper
|
||||||
|
{
|
||||||
|
LiteDatabase GetLiteDB();
|
||||||
|
void DisposeLiteDB();
|
||||||
|
}
|
||||||
|
public class LiteDBHelper: ILiteDBHelper
|
||||||
|
{
|
||||||
|
public LiteDatabase db { get; set; }
|
||||||
|
public LiteDBHelper()
|
||||||
|
{
|
||||||
|
if (db == null)
|
||||||
|
{
|
||||||
|
db = new LiteDatabase(StaticHelper.DbName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public LiteDatabase GetLiteDB()
|
||||||
|
{
|
||||||
|
if (db == null)
|
||||||
|
{
|
||||||
|
db = new LiteDatabase(StaticHelper.DbName);
|
||||||
|
}
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
public void DisposeLiteDB()
|
||||||
|
{
|
||||||
|
if (db != null)
|
||||||
|
{
|
||||||
|
db.Dispose();
|
||||||
|
db = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
using System.Net.Mail;
|
using MimeKit;
|
||||||
using System.Net;
|
using MailKit.Net.Smtp;
|
||||||
|
|
||||||
namespace CarCareTracker.Helper
|
namespace CarCareTracker.Helper
|
||||||
{
|
{
|
||||||
@@ -15,13 +15,16 @@ namespace CarCareTracker.Helper
|
|||||||
{
|
{
|
||||||
private readonly MailConfig mailConfig;
|
private readonly MailConfig mailConfig;
|
||||||
private readonly IFileHelper _fileHelper;
|
private readonly IFileHelper _fileHelper;
|
||||||
|
private readonly ILogger<MailHelper> _logger;
|
||||||
public MailHelper(
|
public MailHelper(
|
||||||
IConfiguration config,
|
IConfiguration config,
|
||||||
IFileHelper fileHelper
|
IFileHelper fileHelper,
|
||||||
|
ILogger<MailHelper> logger
|
||||||
) {
|
) {
|
||||||
//load mailConfig from Configuration
|
//load mailConfig from Configuration
|
||||||
mailConfig = config.GetSection("MailConfig").Get<MailConfig>();
|
mailConfig = config.GetSection("MailConfig").Get<MailConfig>() ?? new MailConfig();
|
||||||
_fileHelper = fileHelper;
|
_fileHelper = fileHelper;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
public OperationResponse NotifyUserForRegistration(string emailAddress, string token)
|
public OperationResponse NotifyUserForRegistration(string emailAddress, string token)
|
||||||
{
|
{
|
||||||
@@ -34,7 +37,7 @@ namespace CarCareTracker.Helper
|
|||||||
}
|
}
|
||||||
string emailSubject = "Your Registration Token for LubeLogger";
|
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}";
|
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)
|
if (result)
|
||||||
{
|
{
|
||||||
return new OperationResponse { Success = true, Message = "Email Sent!" };
|
return new OperationResponse { Success = true, Message = "Email Sent!" };
|
||||||
@@ -55,7 +58,7 @@ namespace CarCareTracker.Helper
|
|||||||
}
|
}
|
||||||
string emailSubject = "Your Password Reset Token for LubeLogger";
|
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}";
|
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)
|
if (result)
|
||||||
{
|
{
|
||||||
return new OperationResponse { Success = true, Message = "Email Sent!" };
|
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 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}";
|
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)
|
if (result)
|
||||||
{
|
{
|
||||||
return new OperationResponse { Success = true, Message = "Email Sent!" };
|
return new OperationResponse { Success = true, Message = "Email Sent!" };
|
||||||
@@ -110,49 +113,60 @@ namespace CarCareTracker.Helper
|
|||||||
string tableBody = "";
|
string tableBody = "";
|
||||||
foreach(ReminderRecordViewModel reminder in reminders)
|
foreach(ReminderRecordViewModel reminder in reminders)
|
||||||
{
|
{
|
||||||
var dueOn = reminder.Metric == ReminderMetric.Both ? $"{reminder.Date} or {reminder.Mileage}" : reminder.Metric == ReminderMetric.Date ? $"{reminder.Date.ToShortDateString()}" : $"{reminder.Mileage}";
|
var dueOn = reminder.Metric == ReminderMetric.Both ? $"{reminder.Date.ToShortDateString()} or {reminder.Mileage}" : reminder.Metric == ReminderMetric.Date ? $"{reminder.Date.ToShortDateString()}" : $"{reminder.Mileage}";
|
||||||
tableBody += $"<tr class='{reminder.Urgency}'><td>{StaticHelper.GetTitleCaseReminderUrgency(reminder.Urgency)}</td><td>{reminder.Description}</td><td>{dueOn}</td></tr>";
|
tableBody += $"<tr class='{reminder.Urgency}'><td>{StaticHelper.GetTitleCaseReminderUrgency(reminder.Urgency)}</td><td>{reminder.Description}</td><td>{dueOn}</td></tr>";
|
||||||
}
|
}
|
||||||
emailBody = emailBody.Replace("{TableBody}", tableBody);
|
emailBody = emailBody.Replace("{TableBody}", tableBody);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (string emailAddress in emailAddresses)
|
var result = SendEmail(emailAddresses, emailSubject, emailBody);
|
||||||
|
if (result)
|
||||||
{
|
{
|
||||||
SendEmail(emailAddress, emailSubject, emailBody, true, true);
|
return new OperationResponse { Success = true, Message = "Email Sent!" };
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return new OperationResponse { Success = false, Message = StaticHelper.GenericErrorMessage };
|
||||||
}
|
}
|
||||||
return new OperationResponse { Success = true, Message = "Email Sent!" };
|
|
||||||
} catch (Exception ex)
|
} catch (Exception ex)
|
||||||
{
|
{
|
||||||
return new OperationResponse { Success = false, Message = ex.Message };
|
return new OperationResponse { Success = false, Message = ex.Message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private bool SendEmail(string emailTo, string emailSubject, string emailBody, bool isBodyHtml = false, bool useAsync = false) {
|
private bool SendEmail(List<string> emailTo, string emailSubject, string emailBody) {
|
||||||
string to = emailTo;
|
|
||||||
string from = mailConfig.EmailFrom;
|
string from = mailConfig.EmailFrom;
|
||||||
var server = mailConfig.EmailServer;
|
var server = mailConfig.EmailServer;
|
||||||
MailMessage message = new MailMessage(from, to);
|
var message = new MimeMessage();
|
||||||
message.Subject = emailSubject;
|
message.From.Add(new MailboxAddress(from, from));
|
||||||
message.Body = emailBody;
|
foreach(string emailRecipient in emailTo)
|
||||||
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
|
|
||||||
{
|
{
|
||||||
if (useAsync)
|
message.To.Add(new MailboxAddress(emailRecipient, emailRecipient));
|
||||||
{
|
}
|
||||||
client.SendMailAsync(message, new CancellationToken());
|
message.Subject = emailSubject;
|
||||||
|
|
||||||
|
var builder = new BodyBuilder();
|
||||||
|
|
||||||
|
builder.HtmlBody = emailBody;
|
||||||
|
|
||||||
|
message.Body = builder.ToMessageBody();
|
||||||
|
|
||||||
|
using (var client = new SmtpClient())
|
||||||
|
{
|
||||||
|
client.Connect(server, mailConfig.Port, MailKit.Security.SecureSocketOptions.Auto);
|
||||||
|
//perform authentication if either username or password is provided.
|
||||||
|
//do not perform authentication if neither are provided.
|
||||||
|
if (!string.IsNullOrWhiteSpace(mailConfig.Username) || !string.IsNullOrWhiteSpace(mailConfig.Password)) {
|
||||||
|
client.Authenticate(mailConfig.Username, mailConfig.Password);
|
||||||
}
|
}
|
||||||
else
|
try
|
||||||
{
|
{
|
||||||
client.Send(message);
|
client.Send(message);
|
||||||
|
client.Disconnect(true);
|
||||||
|
return true;
|
||||||
|
} catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex.Message);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace CarCareTracker.Helper
|
|||||||
{
|
{
|
||||||
public interface IReminderHelper
|
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);
|
List<ReminderRecordViewModel> GetReminderRecordViewModels(List<ReminderRecord> reminders, int currentMileage, DateTime dateCompare);
|
||||||
}
|
}
|
||||||
public class ReminderHelper: IReminderHelper
|
public class ReminderHelper: IReminderHelper
|
||||||
@@ -14,46 +14,48 @@ namespace CarCareTracker.Helper
|
|||||||
{
|
{
|
||||||
_config = config;
|
_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.Metric == ReminderMetric.Both)
|
||||||
{
|
{
|
||||||
if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other)
|
if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other)
|
||||||
{
|
{
|
||||||
existingReminder.Date = existingReminder.Date.AddMonths((int)existingReminder.ReminderMonthInterval);
|
existingReminder.Date = newDate.AddMonths((int)existingReminder.ReminderMonthInterval);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
existingReminder.Date = existingReminder.Date.AddMonths(existingReminder.CustomMonthInterval);
|
existingReminder.Date = newDate.Date.AddMonths(existingReminder.CustomMonthInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other)
|
if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other)
|
||||||
{
|
{
|
||||||
existingReminder.Mileage += (int)existingReminder.ReminderMileageInterval;
|
existingReminder.Mileage = newMileage + (int)existingReminder.ReminderMileageInterval;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
existingReminder.Mileage += existingReminder.CustomMileageInterval;
|
existingReminder.Mileage = newMileage + existingReminder.CustomMileageInterval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (existingReminder.Metric == ReminderMetric.Odometer)
|
else if (existingReminder.Metric == ReminderMetric.Odometer)
|
||||||
{
|
{
|
||||||
if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other)
|
if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other)
|
||||||
{
|
{
|
||||||
existingReminder.Mileage += (int)existingReminder.ReminderMileageInterval;
|
existingReminder.Mileage = newMileage + (int)existingReminder.ReminderMileageInterval;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
existingReminder.Mileage += existingReminder.CustomMileageInterval;
|
existingReminder.Mileage = newMileage + existingReminder.CustomMileageInterval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (existingReminder.Metric == ReminderMetric.Date)
|
else if (existingReminder.Metric == ReminderMetric.Date)
|
||||||
{
|
{
|
||||||
if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other)
|
if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other)
|
||||||
{
|
{
|
||||||
existingReminder.Date = existingReminder.Date.AddMonths((int)existingReminder.ReminderMonthInterval);
|
existingReminder.Date = newDate.AddMonths((int)existingReminder.ReminderMonthInterval);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
existingReminder.Date = existingReminder.Date.AddMonths(existingReminder.CustomMonthInterval);
|
existingReminder.Date = newDate.AddMonths(existingReminder.CustomMonthInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return existingReminder;
|
return existingReminder;
|
||||||
@@ -64,6 +66,10 @@ namespace CarCareTracker.Helper
|
|||||||
var reminderUrgencyConfig = _config.GetReminderUrgencyConfig();
|
var reminderUrgencyConfig = _config.GetReminderUrgencyConfig();
|
||||||
foreach (var reminder in reminders)
|
foreach (var reminder in reminders)
|
||||||
{
|
{
|
||||||
|
if (reminder.UseCustomThresholds)
|
||||||
|
{
|
||||||
|
reminderUrgencyConfig = reminder.CustomThresholds;
|
||||||
|
}
|
||||||
var reminderViewModel = new ReminderRecordViewModel()
|
var reminderViewModel = new ReminderRecordViewModel()
|
||||||
{
|
{
|
||||||
Id = reminder.Id,
|
Id = reminder.Id,
|
||||||
@@ -73,7 +79,8 @@ namespace CarCareTracker.Helper
|
|||||||
Description = reminder.Description,
|
Description = reminder.Description,
|
||||||
Notes = reminder.Notes,
|
Notes = reminder.Notes,
|
||||||
Metric = reminder.Metric,
|
Metric = reminder.Metric,
|
||||||
IsRecurring = reminder.IsRecurring
|
IsRecurring = reminder.IsRecurring,
|
||||||
|
Tags = reminder.Tags
|
||||||
};
|
};
|
||||||
if (reminder.Metric == ReminderMetric.Both)
|
if (reminder.Metric == ReminderMetric.Both)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
|
using CsvHelper;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
namespace CarCareTracker.Helper
|
namespace CarCareTracker.Helper
|
||||||
@@ -8,13 +9,13 @@ namespace CarCareTracker.Helper
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class StaticHelper
|
public static class StaticHelper
|
||||||
{
|
{
|
||||||
public static string VersionNumber = "1.2.7";
|
public static string VersionNumber = "1.3.8";
|
||||||
public static string DbName = "data/cartracker.db";
|
public static string DbName = "data/cartracker.db";
|
||||||
public static string UserConfigPath = "config/userConfig.json";
|
public static string UserConfigPath = "config/userConfig.json";
|
||||||
public static string GenericErrorMessage = "An error occurred, please try again later";
|
public static string GenericErrorMessage = "An error occurred, please try again later";
|
||||||
public static string ReminderEmailTemplate = "defaults/reminderemailtemplate.txt";
|
public static string ReminderEmailTemplate = "defaults/reminderemailtemplate.txt";
|
||||||
public static string DefaultAllowedFileExtensions = ".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx";
|
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)
|
public static string GetTitleCaseReminderUrgency(ReminderUrgency input)
|
||||||
{
|
{
|
||||||
switch (input)
|
switch (input)
|
||||||
@@ -259,5 +260,230 @@ namespace CarCareTracker.Helper
|
|||||||
};
|
};
|
||||||
httpClient.PostAsJsonAsync(webhookURL, httpParams);
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//CSV Write Methods
|
||||||
|
public static void WriteGenericRecordExportModel(CsvWriter _csv, IEnumerable<GenericRecordExportModel> genericRecords)
|
||||||
|
{
|
||||||
|
var extraHeaders = genericRecords.SelectMany(x => x.ExtraFields).Select(y => y.Name).Distinct();
|
||||||
|
//write headers
|
||||||
|
_csv.WriteField(nameof(GenericRecordExportModel.Date));
|
||||||
|
_csv.WriteField(nameof(GenericRecordExportModel.Description));
|
||||||
|
_csv.WriteField(nameof(GenericRecordExportModel.Cost));
|
||||||
|
_csv.WriteField(nameof(GenericRecordExportModel.Notes));
|
||||||
|
_csv.WriteField(nameof(GenericRecordExportModel.Odometer));
|
||||||
|
_csv.WriteField(nameof(GenericRecordExportModel.Tags));
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
_csv.WriteField($"extrafield_{extraHeader}");
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
foreach (GenericRecordExportModel genericRecord in genericRecords)
|
||||||
|
{
|
||||||
|
_csv.WriteField(genericRecord.Date);
|
||||||
|
_csv.WriteField(genericRecord.Description);
|
||||||
|
_csv.WriteField(genericRecord.Cost);
|
||||||
|
_csv.WriteField(genericRecord.Notes);
|
||||||
|
_csv.WriteField(genericRecord.Odometer);
|
||||||
|
_csv.WriteField(genericRecord.Tags);
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
var extraField = genericRecord.ExtraFields.Where(x => x.Name == extraHeader).FirstOrDefault();
|
||||||
|
_csv.WriteField(extraField != null ? extraField.Value : string.Empty);
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void WriteOdometerRecordExportModel(CsvWriter _csv, IEnumerable<OdometerRecordExportModel> genericRecords)
|
||||||
|
{
|
||||||
|
var extraHeaders = genericRecords.SelectMany(x => x.ExtraFields).Select(y => y.Name).Distinct();
|
||||||
|
//write headers
|
||||||
|
_csv.WriteField(nameof(OdometerRecordExportModel.Date));
|
||||||
|
_csv.WriteField(nameof(OdometerRecordExportModel.InitialOdometer));
|
||||||
|
_csv.WriteField(nameof(OdometerRecordExportModel.Odometer));
|
||||||
|
_csv.WriteField(nameof(OdometerRecordExportModel.Notes));
|
||||||
|
_csv.WriteField(nameof(OdometerRecordExportModel.Tags));
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
_csv.WriteField($"extrafield_{extraHeader}");
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
foreach (OdometerRecordExportModel genericRecord in genericRecords)
|
||||||
|
{
|
||||||
|
_csv.WriteField(genericRecord.Date);
|
||||||
|
_csv.WriteField(genericRecord.InitialOdometer);
|
||||||
|
_csv.WriteField(genericRecord.Odometer);
|
||||||
|
_csv.WriteField(genericRecord.Notes);
|
||||||
|
_csv.WriteField(genericRecord.Tags);
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
var extraField = genericRecord.ExtraFields.Where(x => x.Name == extraHeader).FirstOrDefault();
|
||||||
|
_csv.WriteField(extraField != null ? extraField.Value : string.Empty);
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void WriteTaxRecordExportModel(CsvWriter _csv, IEnumerable<TaxRecordExportModel> genericRecords)
|
||||||
|
{
|
||||||
|
var extraHeaders = genericRecords.SelectMany(x => x.ExtraFields).Select(y => y.Name).Distinct();
|
||||||
|
//write headers
|
||||||
|
_csv.WriteField(nameof(TaxRecordExportModel.Date));
|
||||||
|
_csv.WriteField(nameof(TaxRecordExportModel.Description));
|
||||||
|
_csv.WriteField(nameof(TaxRecordExportModel.Cost));
|
||||||
|
_csv.WriteField(nameof(TaxRecordExportModel.Notes));
|
||||||
|
_csv.WriteField(nameof(TaxRecordExportModel.Tags));
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
_csv.WriteField($"extrafield_{extraHeader}");
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
foreach (TaxRecordExportModel genericRecord in genericRecords)
|
||||||
|
{
|
||||||
|
_csv.WriteField(genericRecord.Date);
|
||||||
|
_csv.WriteField(genericRecord.Description);
|
||||||
|
_csv.WriteField(genericRecord.Cost);
|
||||||
|
_csv.WriteField(genericRecord.Notes);
|
||||||
|
_csv.WriteField(genericRecord.Tags);
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
var extraField = genericRecord.ExtraFields.Where(x => x.Name == extraHeader).FirstOrDefault();
|
||||||
|
_csv.WriteField(extraField != null ? extraField.Value : string.Empty);
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void WriteSupplyRecordExportModel(CsvWriter _csv, IEnumerable<SupplyRecordExportModel> genericRecords)
|
||||||
|
{
|
||||||
|
var extraHeaders = genericRecords.SelectMany(x => x.ExtraFields).Select(y => y.Name).Distinct();
|
||||||
|
//write headers
|
||||||
|
_csv.WriteField(nameof(SupplyRecordExportModel.Date));
|
||||||
|
_csv.WriteField(nameof(SupplyRecordExportModel.PartNumber));
|
||||||
|
_csv.WriteField(nameof(SupplyRecordExportModel.PartSupplier));
|
||||||
|
_csv.WriteField(nameof(SupplyRecordExportModel.PartQuantity));
|
||||||
|
_csv.WriteField(nameof(SupplyRecordExportModel.Description));
|
||||||
|
_csv.WriteField(nameof(SupplyRecordExportModel.Notes));
|
||||||
|
_csv.WriteField(nameof(SupplyRecordExportModel.Cost));
|
||||||
|
_csv.WriteField(nameof(SupplyRecordExportModel.Tags));
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
_csv.WriteField($"extrafield_{extraHeader}");
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
foreach (SupplyRecordExportModel genericRecord in genericRecords)
|
||||||
|
{
|
||||||
|
_csv.WriteField(genericRecord.Date);
|
||||||
|
_csv.WriteField(genericRecord.PartNumber);
|
||||||
|
_csv.WriteField(genericRecord.PartSupplier);
|
||||||
|
_csv.WriteField(genericRecord.PartQuantity);
|
||||||
|
_csv.WriteField(genericRecord.Description);
|
||||||
|
_csv.WriteField(genericRecord.Notes);
|
||||||
|
_csv.WriteField(genericRecord.Cost);
|
||||||
|
_csv.WriteField(genericRecord.Tags);
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
var extraField = genericRecord.ExtraFields.Where(x => x.Name == extraHeader).FirstOrDefault();
|
||||||
|
_csv.WriteField(extraField != null ? extraField.Value : string.Empty);
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void WritePlanRecordExportModel(CsvWriter _csv, IEnumerable<PlanRecordExportModel> genericRecords)
|
||||||
|
{
|
||||||
|
var extraHeaders = genericRecords.SelectMany(x => x.ExtraFields).Select(y => y.Name).Distinct();
|
||||||
|
//write headers
|
||||||
|
_csv.WriteField(nameof(PlanRecordExportModel.DateCreated));
|
||||||
|
_csv.WriteField(nameof(PlanRecordExportModel.DateModified));
|
||||||
|
_csv.WriteField(nameof(PlanRecordExportModel.Description));
|
||||||
|
_csv.WriteField(nameof(PlanRecordExportModel.Notes));
|
||||||
|
_csv.WriteField(nameof(PlanRecordExportModel.Type));
|
||||||
|
_csv.WriteField(nameof(PlanRecordExportModel.Priority));
|
||||||
|
_csv.WriteField(nameof(PlanRecordExportModel.Progress));
|
||||||
|
_csv.WriteField(nameof(PlanRecordExportModel.Cost));
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
_csv.WriteField($"extrafield_{extraHeader}");
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
foreach (PlanRecordExportModel genericRecord in genericRecords)
|
||||||
|
{
|
||||||
|
_csv.WriteField(genericRecord.DateCreated);
|
||||||
|
_csv.WriteField(genericRecord.DateModified);
|
||||||
|
_csv.WriteField(genericRecord.Description);
|
||||||
|
_csv.WriteField(genericRecord.Notes);
|
||||||
|
_csv.WriteField(genericRecord.Type);
|
||||||
|
_csv.WriteField(genericRecord.Priority);
|
||||||
|
_csv.WriteField(genericRecord.Progress);
|
||||||
|
_csv.WriteField(genericRecord.Cost);
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
var extraField = genericRecord.ExtraFields.Where(x => x.Name == extraHeader).FirstOrDefault();
|
||||||
|
_csv.WriteField(extraField != null ? extraField.Value : string.Empty);
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void WriteGasRecordExportModel(CsvWriter _csv, IEnumerable<GasRecordExportModel> genericRecords)
|
||||||
|
{
|
||||||
|
var extraHeaders = genericRecords.SelectMany(x => x.ExtraFields).Select(y => y.Name).Distinct();
|
||||||
|
//write headers
|
||||||
|
_csv.WriteField(nameof(GasRecordExportModel.Date));
|
||||||
|
_csv.WriteField(nameof(GasRecordExportModel.Odometer));
|
||||||
|
_csv.WriteField(nameof(GasRecordExportModel.FuelConsumed));
|
||||||
|
_csv.WriteField(nameof(GasRecordExportModel.Cost));
|
||||||
|
_csv.WriteField(nameof(GasRecordExportModel.FuelEconomy));
|
||||||
|
_csv.WriteField(nameof(GasRecordExportModel.IsFillToFull));
|
||||||
|
_csv.WriteField(nameof(GasRecordExportModel.MissedFuelUp));
|
||||||
|
_csv.WriteField(nameof(GasRecordExportModel.Notes));
|
||||||
|
_csv.WriteField(nameof(GasRecordExportModel.Tags));
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
_csv.WriteField($"extrafield_{extraHeader}");
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
foreach (GasRecordExportModel genericRecord in genericRecords)
|
||||||
|
{
|
||||||
|
_csv.WriteField(genericRecord.Date);
|
||||||
|
_csv.WriteField(genericRecord.Odometer);
|
||||||
|
_csv.WriteField(genericRecord.FuelConsumed);
|
||||||
|
_csv.WriteField(genericRecord.Cost);
|
||||||
|
_csv.WriteField(genericRecord.FuelEconomy);
|
||||||
|
_csv.WriteField(genericRecord.IsFillToFull);
|
||||||
|
_csv.WriteField(genericRecord.MissedFuelUp);
|
||||||
|
_csv.WriteField(genericRecord.Notes);
|
||||||
|
_csv.WriteField(genericRecord.Tags);
|
||||||
|
foreach (string extraHeader in extraHeaders)
|
||||||
|
{
|
||||||
|
var extraField = genericRecord.ExtraFields.Where(x => x.Name == extraHeader).FirstOrDefault();
|
||||||
|
_csv.WriteField(extraField != null ? extraField.Value : string.Empty);
|
||||||
|
}
|
||||||
|
_csv.NextRecord();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
LICENSE
7
LICENSE
@@ -1,11 +1,6 @@
|
|||||||
LubeLogger by Hargata Softworks is licensed under the MIT License for individual
|
|
||||||
and personal use. Commercial users and/or corporate entities are required
|
|
||||||
to maintain an active subscription in order to continue using LubeLogger.
|
|
||||||
For pricing information please contact us at hargatasoftworks@gmail.com
|
|
||||||
|
|
||||||
MIT License
|
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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using CarCareTracker.Helper;
|
using CarCareTracker.Helper;
|
||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@@ -28,7 +29,7 @@ namespace CarCareTracker.Logic
|
|||||||
bool GenerateTokenForEmailAddress(string emailAddress, bool isPasswordReset);
|
bool GenerateTokenForEmailAddress(string emailAddress, bool isPasswordReset);
|
||||||
List<UserData> GetAllUsers();
|
List<UserData> GetAllUsers();
|
||||||
List<Token> GetAllTokens();
|
List<Token> GetAllTokens();
|
||||||
|
KeyValuePair<string, string> GetPKCEChallengeCode();
|
||||||
}
|
}
|
||||||
public class LoginLogic : ILoginLogic
|
public class LoginLogic : ILoginLogic
|
||||||
{
|
{
|
||||||
@@ -244,14 +245,7 @@ namespace CarCareTracker.Logic
|
|||||||
{
|
{
|
||||||
if (UserIsRoot(credentials))
|
if (UserIsRoot(credentials))
|
||||||
{
|
{
|
||||||
return new UserData()
|
return GetRootUserData(credentials.UserName);
|
||||||
{
|
|
||||||
Id = -1,
|
|
||||||
UserName = credentials.UserName,
|
|
||||||
IsAdmin = true,
|
|
||||||
IsRootUser = true,
|
|
||||||
EmailAddress = string.Empty
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -270,6 +264,13 @@ namespace CarCareTracker.Logic
|
|||||||
}
|
}
|
||||||
public UserData ValidateOpenIDUser(LoginModel credentials)
|
public UserData ValidateOpenIDUser(LoginModel credentials)
|
||||||
{
|
{
|
||||||
|
//validate for root user
|
||||||
|
var isRootUser = _configHelper.AuthenticateRootUserOIDC(credentials.EmailAddress);
|
||||||
|
if (isRootUser)
|
||||||
|
{
|
||||||
|
return GetRootUserData(credentials.EmailAddress);
|
||||||
|
}
|
||||||
|
|
||||||
var result = _userData.GetUserRecordByEmailAddress(credentials.EmailAddress);
|
var result = _userData.GetUserRecordByEmailAddress(credentials.EmailAddress);
|
||||||
if (result.Id != default)
|
if (result.Id != default)
|
||||||
{
|
{
|
||||||
@@ -419,6 +420,17 @@ namespace CarCareTracker.Logic
|
|||||||
var hashedPassword = GetHash(credentials.Password);
|
var hashedPassword = GetHash(credentials.Password);
|
||||||
return _configHelper.AuthenticateRootUser(hashedUserName, hashedPassword);
|
return _configHelper.AuthenticateRootUser(hashedUserName, hashedPassword);
|
||||||
}
|
}
|
||||||
|
private UserData GetRootUserData(string username)
|
||||||
|
{
|
||||||
|
return new UserData()
|
||||||
|
{
|
||||||
|
Id = -1,
|
||||||
|
UserName = username,
|
||||||
|
IsAdmin = true,
|
||||||
|
IsRootUser = true,
|
||||||
|
EmailAddress = string.Empty
|
||||||
|
};
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
private static string GetHash(string value)
|
private static string GetHash(string value)
|
||||||
{
|
{
|
||||||
@@ -439,6 +451,14 @@ namespace CarCareTracker.Logic
|
|||||||
{
|
{
|
||||||
return Guid.NewGuid().ToString().Substring(0, 8);
|
return Guid.NewGuid().ToString().Substring(0, 8);
|
||||||
}
|
}
|
||||||
|
public KeyValuePair<string, string> GetPKCEChallengeCode()
|
||||||
|
{
|
||||||
|
var verifierCode = Base64UrlEncoder.Encode(Guid.NewGuid().ToString().Replace("-", ""));
|
||||||
|
var verifierBytes = Encoding.UTF8.GetBytes(verifierCode);
|
||||||
|
var hashedCode = SHA256.Create().ComputeHash(verifierBytes);
|
||||||
|
var encodedChallengeCode = Base64UrlEncoder.Encode(hashedCode);
|
||||||
|
return new KeyValuePair<string, string>(verifierCode, encodedChallengeCode);
|
||||||
|
}
|
||||||
public bool GenerateTokenForEmailAddress(string emailAddress, bool isPasswordReset)
|
public bool GenerateTokenForEmailAddress(string emailAddress, bool isPasswordReset)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ namespace CarCareTracker.Logic
|
|||||||
}
|
}
|
||||||
public bool AutoInsertOdometerRecord(OdometerRecord odometer)
|
public bool AutoInsertOdometerRecord(OdometerRecord odometer)
|
||||||
{
|
{
|
||||||
|
if (odometer.Mileage == default)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
var lastReportedMileage = GetLastOdometerRecordMileage(odometer.VehicleId, new List<OdometerRecord>());
|
var lastReportedMileage = GetLastOdometerRecordMileage(odometer.VehicleId, new List<OdometerRecord>());
|
||||||
odometer.InitialMileage = lastReportedMileage != default ? lastReportedMileage : odometer.Mileage;
|
odometer.InitialMileage = lastReportedMileage != default ? lastReportedMileage : odometer.Mileage;
|
||||||
|
|
||||||
|
|||||||
222
Logic/VehicleLogic.cs
Normal file
222
Logic/VehicleLogic.cs
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
using CarCareTracker.External.Interfaces;
|
||||||
|
using CarCareTracker.Helper;
|
||||||
|
using CarCareTracker.Models;
|
||||||
|
|
||||||
|
namespace CarCareTracker.Logic
|
||||||
|
{
|
||||||
|
public interface IVehicleLogic
|
||||||
|
{
|
||||||
|
VehicleRecords GetVehicleRecords(int vehicleId);
|
||||||
|
decimal GetVehicleTotalCost(VehicleRecords vehicleRecords);
|
||||||
|
int GetMaxMileage(int vehicleId);
|
||||||
|
int GetMaxMileage(VehicleRecords vehicleRecords);
|
||||||
|
int GetMinMileage(int vehicleId);
|
||||||
|
int GetMinMileage(VehicleRecords vehicleRecords);
|
||||||
|
int GetOwnershipDays(string purchaseDate, string soldDate, List<ServiceRecord> serviceRecords, List<CollisionRecord> repairRecords, List<GasRecord> gasRecords, List<UpgradeRecord> upgradeRecords, List<OdometerRecord> odometerRecords, List<TaxRecord> taxRecords);
|
||||||
|
bool GetVehicleHasUrgentOrPastDueReminders(int vehicleId, int currentMileage);
|
||||||
|
}
|
||||||
|
public class VehicleLogic: IVehicleLogic
|
||||||
|
{
|
||||||
|
private readonly IServiceRecordDataAccess _serviceRecordDataAccess;
|
||||||
|
private readonly IGasRecordDataAccess _gasRecordDataAccess;
|
||||||
|
private readonly ICollisionRecordDataAccess _collisionRecordDataAccess;
|
||||||
|
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
|
||||||
|
private readonly ITaxRecordDataAccess _taxRecordDataAccess;
|
||||||
|
private readonly IOdometerRecordDataAccess _odometerRecordDataAccess;
|
||||||
|
private readonly IReminderRecordDataAccess _reminderRecordDataAccess;
|
||||||
|
private readonly IReminderHelper _reminderHelper;
|
||||||
|
public VehicleLogic(
|
||||||
|
IServiceRecordDataAccess serviceRecordDataAccess,
|
||||||
|
IGasRecordDataAccess gasRecordDataAccess,
|
||||||
|
ICollisionRecordDataAccess collisionRecordDataAccess,
|
||||||
|
IUpgradeRecordDataAccess upgradeRecordDataAccess,
|
||||||
|
ITaxRecordDataAccess taxRecordDataAccess,
|
||||||
|
IOdometerRecordDataAccess odometerRecordDataAccess,
|
||||||
|
IReminderRecordDataAccess reminderRecordDataAccess,
|
||||||
|
IReminderHelper reminderHelper
|
||||||
|
) {
|
||||||
|
_serviceRecordDataAccess = serviceRecordDataAccess;
|
||||||
|
_gasRecordDataAccess = gasRecordDataAccess;
|
||||||
|
_collisionRecordDataAccess = collisionRecordDataAccess;
|
||||||
|
_upgradeRecordDataAccess = upgradeRecordDataAccess;
|
||||||
|
_taxRecordDataAccess = taxRecordDataAccess;
|
||||||
|
_odometerRecordDataAccess = odometerRecordDataAccess;
|
||||||
|
_reminderRecordDataAccess = reminderRecordDataAccess;
|
||||||
|
_reminderHelper = reminderHelper;
|
||||||
|
}
|
||||||
|
public VehicleRecords GetVehicleRecords(int vehicleId)
|
||||||
|
{
|
||||||
|
return new VehicleRecords
|
||||||
|
{
|
||||||
|
ServiceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId),
|
||||||
|
GasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId),
|
||||||
|
CollisionRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId),
|
||||||
|
TaxRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId),
|
||||||
|
UpgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId),
|
||||||
|
OdometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public decimal GetVehicleTotalCost(VehicleRecords vehicleRecords)
|
||||||
|
{
|
||||||
|
var serviceRecordSum = vehicleRecords.ServiceRecords.Sum(x => x.Cost);
|
||||||
|
var repairRecordSum = vehicleRecords.CollisionRecords.Sum(x => x.Cost);
|
||||||
|
var upgradeRecordSum = vehicleRecords.UpgradeRecords.Sum(x => x.Cost);
|
||||||
|
var taxRecordSum = vehicleRecords.TaxRecords.Sum(x => x.Cost);
|
||||||
|
var gasRecordSum = vehicleRecords.GasRecords.Sum(x => x.Cost);
|
||||||
|
return serviceRecordSum + repairRecordSum + upgradeRecordSum + taxRecordSum + gasRecordSum;
|
||||||
|
}
|
||||||
|
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 GetMaxMileage(VehicleRecords vehicleRecords)
|
||||||
|
{
|
||||||
|
var numbersArray = new List<int>();
|
||||||
|
if (vehicleRecords.ServiceRecords.Any())
|
||||||
|
{
|
||||||
|
numbersArray.Add(vehicleRecords.ServiceRecords.Max(x => x.Mileage));
|
||||||
|
}
|
||||||
|
if (vehicleRecords.CollisionRecords.Any())
|
||||||
|
{
|
||||||
|
numbersArray.Add(vehicleRecords.CollisionRecords.Max(x => x.Mileage));
|
||||||
|
}
|
||||||
|
if (vehicleRecords.GasRecords.Any())
|
||||||
|
{
|
||||||
|
numbersArray.Add(vehicleRecords.GasRecords.Max(x => x.Mileage));
|
||||||
|
}
|
||||||
|
if (vehicleRecords.UpgradeRecords.Any())
|
||||||
|
{
|
||||||
|
numbersArray.Add(vehicleRecords.UpgradeRecords.Max(x => x.Mileage));
|
||||||
|
}
|
||||||
|
if (vehicleRecords.OdometerRecords.Any())
|
||||||
|
{
|
||||||
|
numbersArray.Add(vehicleRecords.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 int GetMinMileage(VehicleRecords vehicleRecords)
|
||||||
|
{
|
||||||
|
var numbersArray = new List<int>();
|
||||||
|
var _serviceRecords = vehicleRecords.ServiceRecords.Where(x => x.Mileage != default).ToList();
|
||||||
|
if (_serviceRecords.Any())
|
||||||
|
{
|
||||||
|
numbersArray.Add(_serviceRecords.Min(x => x.Mileage));
|
||||||
|
}
|
||||||
|
var _repairRecords = vehicleRecords.CollisionRecords.Where(x => x.Mileage != default).ToList();
|
||||||
|
if (_repairRecords.Any())
|
||||||
|
{
|
||||||
|
numbersArray.Add(_repairRecords.Min(x => x.Mileage));
|
||||||
|
}
|
||||||
|
var _gasRecords = vehicleRecords.GasRecords.Where(x => x.Mileage != default).ToList();
|
||||||
|
if (_gasRecords.Any())
|
||||||
|
{
|
||||||
|
numbersArray.Add(_gasRecords.Min(x => x.Mileage));
|
||||||
|
}
|
||||||
|
var _upgradeRecords = vehicleRecords.UpgradeRecords.Where(x => x.Mileage != default).ToList();
|
||||||
|
if (_upgradeRecords.Any())
|
||||||
|
{
|
||||||
|
numbersArray.Add(_upgradeRecords.Min(x => x.Mileage));
|
||||||
|
}
|
||||||
|
var _odometerRecords = vehicleRecords.OdometerRecords.Where(x => x.Mileage != default).ToList();
|
||||||
|
if (_odometerRecords.Any())
|
||||||
|
{
|
||||||
|
numbersArray.Add(_odometerRecords.Min(x => x.Mileage));
|
||||||
|
}
|
||||||
|
return numbersArray.Any() ? numbersArray.Min() : 0;
|
||||||
|
}
|
||||||
|
public int GetOwnershipDays(string purchaseDate, string soldDate, List<ServiceRecord> serviceRecords, List<CollisionRecord> repairRecords, List<GasRecord> gasRecords, List<UpgradeRecord> upgradeRecords, List<OdometerRecord> odometerRecords, List<TaxRecord> taxRecords)
|
||||||
|
{
|
||||||
|
var startDate = DateTime.Now;
|
||||||
|
var endDate = DateTime.Now;
|
||||||
|
if (!string.IsNullOrWhiteSpace(soldDate))
|
||||||
|
{
|
||||||
|
endDate = DateTime.Parse(soldDate);
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrWhiteSpace(purchaseDate))
|
||||||
|
{
|
||||||
|
//if purchase date is provided, then we just have to subtract the begin date to end date and return number of months
|
||||||
|
startDate = DateTime.Parse(purchaseDate);
|
||||||
|
var timeElapsed = (int)Math.Floor((endDate - startDate).TotalDays);
|
||||||
|
return timeElapsed;
|
||||||
|
}
|
||||||
|
var dateArray = new List<DateTime>();
|
||||||
|
dateArray.AddRange(serviceRecords.Select(x => x.Date));
|
||||||
|
dateArray.AddRange(repairRecords.Select(x => x.Date));
|
||||||
|
dateArray.AddRange(gasRecords.Select(x => x.Date));
|
||||||
|
dateArray.AddRange(upgradeRecords.Select(x => x.Date));
|
||||||
|
dateArray.AddRange(odometerRecords.Select(x => x.Date));
|
||||||
|
dateArray.AddRange(taxRecords.Select(x => x.Date));
|
||||||
|
if (dateArray.Any())
|
||||||
|
{
|
||||||
|
startDate = dateArray.Min();
|
||||||
|
var timeElapsed = (int)Math.Floor((endDate - startDate).TotalDays);
|
||||||
|
return timeElapsed;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public bool GetVehicleHasUrgentOrPastDueReminders(int vehicleId, int currentMileage)
|
||||||
|
{
|
||||||
|
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
||||||
|
var results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, DateTime.Now);
|
||||||
|
return results.Any(x => x.Urgency == ReminderUrgency.VeryUrgent || x.Urgency == ReminderUrgency.PastDue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,18 @@ namespace CarCareTracker.MapProfile
|
|||||||
Map(m => m.Type).Name(["type"]);
|
Map(m => m.Type).Name(["type"]);
|
||||||
Map(m => m.Priority).Name(["priority"]);
|
Map(m => m.Priority).Name(["priority"]);
|
||||||
Map(m => m.Tags).Name(["tags"]);
|
Map(m => m.Tags).Name(["tags"]);
|
||||||
|
Map(m => m.ExtraFields).Convert(row =>
|
||||||
|
{
|
||||||
|
var attributes = new Dictionary<string, string>();
|
||||||
|
foreach (var header in row.Row.HeaderRecord)
|
||||||
|
{
|
||||||
|
if (header.ToLower().StartsWith("extrafield_"))
|
||||||
|
{
|
||||||
|
attributes.Add(header.Substring(11), row.Row.GetField(header));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attributes;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
Models/API/VehicleInfo.cs
Normal file
27
Models/API/VehicleInfo.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
namespace CarCareTracker.Models
|
||||||
|
{
|
||||||
|
public class VehicleInfo
|
||||||
|
{
|
||||||
|
public Vehicle VehicleData { get; set; } = new Vehicle();
|
||||||
|
public int VeryUrgentReminderCount { get; set; }
|
||||||
|
public int UrgentReminderCount { get; set;}
|
||||||
|
public int NotUrgentReminderCount { get; set; }
|
||||||
|
public int PastDueReminderCount { get; set; }
|
||||||
|
public ReminderExportModel NextReminder { get; set; }
|
||||||
|
public int ServiceRecordCount { get; set; }
|
||||||
|
public decimal ServiceRecordCost { get; set; }
|
||||||
|
public int RepairRecordCount { get; set; }
|
||||||
|
public decimal RepairRecordCost { get; set; }
|
||||||
|
public int UpgradeRecordCount { get; set; }
|
||||||
|
public decimal UpgradeRecordCost { get; set; }
|
||||||
|
public int TaxRecordCount { get; set; }
|
||||||
|
public decimal TaxRecordCost { get; set; }
|
||||||
|
public int GasRecordCount { get; set; }
|
||||||
|
public decimal GasRecordCost { get; set; }
|
||||||
|
public int LastReportedOdometer { get; set; }
|
||||||
|
public int PlanRecordBackLogCount { get; set; }
|
||||||
|
public int PlanRecordInProgressCount { get; set; }
|
||||||
|
public int PlanRecordTestingCount { get; set; }
|
||||||
|
public int PlanRecordDoneCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public int VehicleId { 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 Date { get; set; } = DateTime.Now.ToShortDateString();
|
||||||
public int Mileage { get; set; }
|
public int Mileage { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
public List<string> Tags { get; set; } = new List<string>();
|
public List<string> Tags { get; set; } = new List<string>();
|
||||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||||
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
||||||
|
public bool CopySuppliesAttachment { get; set; } = false;
|
||||||
public CollisionRecord ToCollisionRecord() { return new CollisionRecord {
|
public CollisionRecord ToCollisionRecord() { return new CollisionRecord {
|
||||||
Id = Id,
|
Id = Id,
|
||||||
VehicleId = VehicleId,
|
VehicleId = VehicleId,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
{
|
{
|
||||||
public string EmailServer { get; set; }
|
public string EmailServer { get; set; }
|
||||||
public string EmailFrom { get; set; }
|
public string EmailFrom { get; set; }
|
||||||
public bool UseSSL { get; set; }
|
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|||||||
@@ -10,7 +10,18 @@
|
|||||||
public string RedirectURL { get; set; }
|
public string RedirectURL { get; set; }
|
||||||
public string Scope { get; set; }
|
public string Scope { get; set; }
|
||||||
public string State { get; set; }
|
public string State { get; set; }
|
||||||
|
public string CodeChallenge { get; set; }
|
||||||
public bool ValidateState { get; set; } = false;
|
public bool ValidateState { get; set; } = false;
|
||||||
public string RemoteAuthURL { get { return $"{AuthURL}?client_id={ClientId}&response_type=code&redirect_uri={RedirectURL}&scope={Scope}&state={State}"; } }
|
public bool DisableRegularLogin { get; set; } = false;
|
||||||
|
public bool UsePKCE { get; set; } = false;
|
||||||
|
public string LogOutURL { get; set; } = "";
|
||||||
|
public string RemoteAuthURL { get {
|
||||||
|
var redirectUrl = $"{AuthURL}?client_id={ClientId}&response_type=code&redirect_uri={RedirectURL}&scope={Scope}&state={State}";
|
||||||
|
if (UsePKCE)
|
||||||
|
{
|
||||||
|
redirectUrl += $"&code_challenge={CodeChallenge}&code_challenge_method=S256";
|
||||||
|
}
|
||||||
|
return redirectUrl;
|
||||||
|
} }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
public decimal Cost { get; set; }
|
public decimal Cost { get; set; }
|
||||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||||
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
||||||
|
public bool CopySuppliesAttachment { get; set; } = false;
|
||||||
public PlanRecord ToPlanRecord() { return new PlanRecord {
|
public PlanRecord ToPlanRecord() { return new PlanRecord {
|
||||||
Id = Id,
|
Id = Id,
|
||||||
VehicleId = VehicleId,
|
VehicleId = VehicleId,
|
||||||
|
|||||||
@@ -9,10 +9,13 @@
|
|||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public string Notes { get; set; }
|
public string Notes { get; set; }
|
||||||
public bool IsRecurring { get; set; } = false;
|
public bool IsRecurring { get; set; } = false;
|
||||||
|
public bool UseCustomThresholds { get; set; } = false;
|
||||||
|
public ReminderUrgencyConfig CustomThresholds { get; set; } = new ReminderUrgencyConfig();
|
||||||
public int CustomMileageInterval { get; set; } = 0;
|
public int CustomMileageInterval { get; set; } = 0;
|
||||||
public int CustomMonthInterval { get; set; } = 0;
|
public int CustomMonthInterval { get; set; } = 0;
|
||||||
public ReminderMileageInterval ReminderMileageInterval { get; set; } = ReminderMileageInterval.FiveThousandMiles;
|
public ReminderMileageInterval ReminderMileageInterval { get; set; } = ReminderMileageInterval.FiveThousandMiles;
|
||||||
public ReminderMonthInterval ReminderMonthInterval { get; set; } = ReminderMonthInterval.OneYear;
|
public ReminderMonthInterval ReminderMonthInterval { get; set; } = ReminderMonthInterval.OneYear;
|
||||||
public ReminderMetric Metric { get; set; } = ReminderMetric.Date;
|
public ReminderMetric Metric { get; set; } = ReminderMetric.Date;
|
||||||
|
public List<string> Tags { get; set; } = new List<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,14 @@
|
|||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public string Notes { get; set; }
|
public string Notes { get; set; }
|
||||||
public bool IsRecurring { get; set; } = false;
|
public bool IsRecurring { get; set; } = false;
|
||||||
|
public bool UseCustomThresholds { get; set; } = false;
|
||||||
|
public ReminderUrgencyConfig CustomThresholds { get; set; } = new ReminderUrgencyConfig();
|
||||||
public int CustomMileageInterval { get; set; } = 0;
|
public int CustomMileageInterval { get; set; } = 0;
|
||||||
public int CustomMonthInterval { get; set; } = 0;
|
public int CustomMonthInterval { get; set; } = 0;
|
||||||
public ReminderMileageInterval ReminderMileageInterval { get; set; } = ReminderMileageInterval.FiveThousandMiles;
|
public ReminderMileageInterval ReminderMileageInterval { get; set; } = ReminderMileageInterval.FiveThousandMiles;
|
||||||
public ReminderMonthInterval ReminderMonthInterval { get; set; } = ReminderMonthInterval.OneYear;
|
public ReminderMonthInterval ReminderMonthInterval { get; set; } = ReminderMonthInterval.OneYear;
|
||||||
public ReminderMetric Metric { get; set; } = ReminderMetric.Date;
|
public ReminderMetric Metric { get; set; } = ReminderMetric.Date;
|
||||||
|
public List<string> Tags { get; set; } = new List<string>();
|
||||||
public ReminderRecord ToReminderRecord()
|
public ReminderRecord ToReminderRecord()
|
||||||
{
|
{
|
||||||
return new ReminderRecord
|
return new ReminderRecord
|
||||||
@@ -25,11 +28,14 @@
|
|||||||
Description = Description,
|
Description = Description,
|
||||||
Metric = Metric,
|
Metric = Metric,
|
||||||
IsRecurring = IsRecurring,
|
IsRecurring = IsRecurring,
|
||||||
|
UseCustomThresholds = UseCustomThresholds,
|
||||||
|
CustomThresholds = CustomThresholds,
|
||||||
ReminderMileageInterval = ReminderMileageInterval,
|
ReminderMileageInterval = ReminderMileageInterval,
|
||||||
ReminderMonthInterval = ReminderMonthInterval,
|
ReminderMonthInterval = ReminderMonthInterval,
|
||||||
CustomMileageInterval = CustomMileageInterval,
|
CustomMileageInterval = CustomMileageInterval,
|
||||||
CustomMonthInterval = CustomMonthInterval,
|
CustomMonthInterval = CustomMonthInterval,
|
||||||
Notes = Notes
|
Notes = Notes,
|
||||||
|
Tags = Tags
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,5 +17,6 @@
|
|||||||
/// Recurring Reminders
|
/// Recurring Reminders
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsRecurring { get; set; } = false;
|
public bool IsRecurring { get; set; } = false;
|
||||||
|
public List<string> Tags { get; set; } = new List<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
Models/Report/CostTableForVehicle.cs
Normal file
27
Models/Report/CostTableForVehicle.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
namespace CarCareTracker.Models
|
||||||
|
{
|
||||||
|
public class CostTableForVehicle
|
||||||
|
{
|
||||||
|
public string DistanceUnit { get; set; } = "Cost Per Mile";
|
||||||
|
public int TotalDistance { get; set; }
|
||||||
|
public int NumberOfDays { get; set; }
|
||||||
|
public decimal ServiceRecordSum { get; set; }
|
||||||
|
public decimal GasRecordSum { get; set; }
|
||||||
|
public decimal TaxRecordSum { get; set; }
|
||||||
|
public decimal CollisionRecordSum { get; set; }
|
||||||
|
public decimal UpgradeRecordSum { get; set; }
|
||||||
|
public decimal ServiceRecordPerMile { get { return TotalDistance != default ? ServiceRecordSum / TotalDistance : 0; } }
|
||||||
|
public decimal GasRecordPerMile { get { return TotalDistance != default ? GasRecordSum / TotalDistance : 0; } }
|
||||||
|
public decimal CollisionRecordPerMile { get { return TotalDistance != default ? CollisionRecordSum / TotalDistance : 0; } }
|
||||||
|
public decimal UpgradeRecordPerMile { get { return TotalDistance != default ? UpgradeRecordSum / TotalDistance : 0; } }
|
||||||
|
public decimal TaxRecordPerMile { get { return TotalDistance != default ? TaxRecordSum / TotalDistance : 0; } }
|
||||||
|
public decimal ServiceRecordPerDay { get { return NumberOfDays != default ? ServiceRecordSum / NumberOfDays : 0; } }
|
||||||
|
public decimal GasRecordPerDay { get { return NumberOfDays != default ? GasRecordSum / NumberOfDays : 0; } }
|
||||||
|
public decimal CollisionRecordPerDay { get { return NumberOfDays != default ? CollisionRecordSum / NumberOfDays : 0; } }
|
||||||
|
public decimal UpgradeRecordPerDay { get { return NumberOfDays != default ? UpgradeRecordSum / NumberOfDays : 0; } }
|
||||||
|
public decimal TaxRecordPerDay { get { return NumberOfDays != default ? TaxRecordSum / NumberOfDays : 0; } }
|
||||||
|
public decimal TotalPerDay { get { return ServiceRecordPerDay + CollisionRecordPerDay + UpgradeRecordPerDay + GasRecordPerDay + TaxRecordPerDay; } }
|
||||||
|
public decimal TotalPerMile { get { return ServiceRecordPerMile + CollisionRecordPerMile + UpgradeRecordPerMile + GasRecordPerMile + TaxRecordPerMile; } }
|
||||||
|
public decimal TotalCost { get { return ServiceRecordSum + CollisionRecordSum + UpgradeRecordSum + GasRecordSum + TaxRecordSum; } }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,5 +13,8 @@
|
|||||||
public decimal TotalCostPerMile { get; set; }
|
public decimal TotalCostPerMile { get; set; }
|
||||||
public decimal TotalGasCostPerMile { get; set; }
|
public decimal TotalGasCostPerMile { get; set; }
|
||||||
public string DistanceUnit { get; set; }
|
public string DistanceUnit { get; set; }
|
||||||
|
public decimal TotalDepreciation { get; set; }
|
||||||
|
public decimal DepreciationPerDay { get; set; }
|
||||||
|
public decimal DepreciationPerMile { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
Models/SearchResult.cs
Normal file
9
Models/SearchResult.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace CarCareTracker.Models
|
||||||
|
{
|
||||||
|
public class SearchResult
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public ImportMode RecordType { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public int VehicleId { 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 Date { get; set; } = DateTime.Now.ToShortDateString();
|
||||||
public int Mileage { get; set; }
|
public int Mileage { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
public List<string> Tags { get; set; } = new List<string>();
|
public List<string> Tags { get; set; } = new List<string>();
|
||||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||||
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
||||||
|
public bool CopySuppliesAttachment { get; set; } = false;
|
||||||
public ServiceRecord ToServiceRecord() { return new ServiceRecord {
|
public ServiceRecord ToServiceRecord() { return new ServiceRecord {
|
||||||
Id = Id,
|
Id = Id,
|
||||||
VehicleId = VehicleId,
|
VehicleId = VehicleId,
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ namespace CarCareTracker.Models
|
|||||||
{
|
{
|
||||||
public UserConfig UserConfig { get; set; }
|
public UserConfig UserConfig { get; set; }
|
||||||
public List<string> UILanguages { get; set; }
|
public List<string> UILanguages { get; set; }
|
||||||
|
public Sponsors Sponsors { get; set; } = new Sponsors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
public string PartSupplier { get; set; }
|
public string PartSupplier { get; set; }
|
||||||
public string PartQuantity { get; set; }
|
public string PartQuantity { get; set; }
|
||||||
public string Tags { get; set; }
|
public string Tags { get; set; }
|
||||||
|
public Dictionary<string,string> ExtraFields {get;set;}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SupplyRecordExportModel
|
public class SupplyRecordExportModel
|
||||||
@@ -37,9 +38,9 @@
|
|||||||
public string Cost { get; set; }
|
public string Cost { get; set; }
|
||||||
public string Notes { get; set; }
|
public string Notes { get; set; }
|
||||||
public string Tags { get; set; }
|
public string Tags { get; set; }
|
||||||
|
public List<ExtraField> ExtraFields { get; set; }
|
||||||
}
|
}
|
||||||
|
public class GenericRecordExportModel
|
||||||
public class ServiceRecordExportModel
|
|
||||||
{
|
{
|
||||||
public string Date { get; set; }
|
public string Date { get; set; }
|
||||||
public string Odometer { get; set; }
|
public string Odometer { get; set; }
|
||||||
@@ -47,6 +48,7 @@
|
|||||||
public string Notes { get; set; }
|
public string Notes { get; set; }
|
||||||
public string Cost { get; set; }
|
public string Cost { get; set; }
|
||||||
public string Tags { get; set; }
|
public string Tags { get; set; }
|
||||||
|
public List<ExtraField> ExtraFields { get; set; }
|
||||||
}
|
}
|
||||||
public class OdometerRecordExportModel
|
public class OdometerRecordExportModel
|
||||||
{
|
{
|
||||||
@@ -55,6 +57,7 @@
|
|||||||
public string Odometer { get; set; }
|
public string Odometer { get; set; }
|
||||||
public string Notes { get; set; }
|
public string Notes { get; set; }
|
||||||
public string Tags { get; set; }
|
public string Tags { get; set; }
|
||||||
|
public List<ExtraField> ExtraFields { get; set; }
|
||||||
}
|
}
|
||||||
public class TaxRecordExportModel
|
public class TaxRecordExportModel
|
||||||
{
|
{
|
||||||
@@ -63,6 +66,7 @@
|
|||||||
public string Notes { get; set; }
|
public string Notes { get; set; }
|
||||||
public string Cost { get; set; }
|
public string Cost { get; set; }
|
||||||
public string Tags { get; set; }
|
public string Tags { get; set; }
|
||||||
|
public List<ExtraField> ExtraFields { get; set; }
|
||||||
}
|
}
|
||||||
public class GasRecordExportModel
|
public class GasRecordExportModel
|
||||||
{
|
{
|
||||||
@@ -75,6 +79,7 @@
|
|||||||
public string MissedFuelUp { get; set; }
|
public string MissedFuelUp { get; set; }
|
||||||
public string Notes { get; set; }
|
public string Notes { get; set; }
|
||||||
public string Tags { get; set; }
|
public string Tags { get; set; }
|
||||||
|
public List<ExtraField> ExtraFields { get; set; }
|
||||||
}
|
}
|
||||||
public class ReminderExportModel
|
public class ReminderExportModel
|
||||||
{
|
{
|
||||||
@@ -82,6 +87,8 @@
|
|||||||
public string Urgency { get; set; }
|
public string Urgency { get; set; }
|
||||||
public string Metric { get; set; }
|
public string Metric { get; set; }
|
||||||
public string Notes { get; set; }
|
public string Notes { get; set; }
|
||||||
|
public string DueDate { get; set; }
|
||||||
|
public string DueOdometer { get; set; }
|
||||||
}
|
}
|
||||||
public class PlanRecordExportModel
|
public class PlanRecordExportModel
|
||||||
{
|
{
|
||||||
@@ -93,6 +100,6 @@
|
|||||||
public string Priority { get; set; }
|
public string Priority { get; set; }
|
||||||
public string Progress { get; set; }
|
public string Progress { get; set; }
|
||||||
public string Cost { get; set; }
|
public string Cost { get; set; }
|
||||||
|
public List<ExtraField> ExtraFields { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
12
Models/Shared/VehicleRecords.cs
Normal file
12
Models/Shared/VehicleRecords.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
namespace CarCareTracker.Models
|
||||||
|
{
|
||||||
|
public class VehicleRecords
|
||||||
|
{
|
||||||
|
public List<ServiceRecord> ServiceRecords { get; set; } = new List<ServiceRecord>();
|
||||||
|
public List<CollisionRecord> CollisionRecords { get; set; } = new List<CollisionRecord>();
|
||||||
|
public List<UpgradeRecord> UpgradeRecords { get; set; } = new List<UpgradeRecord>();
|
||||||
|
public List<GasRecord> GasRecords { get; set; } = new List<GasRecord>();
|
||||||
|
public List<TaxRecord> TaxRecords { get; set; } = new List<TaxRecord>();
|
||||||
|
public List<OdometerRecord> OdometerRecords { get; set; } = new List<OdometerRecord>();
|
||||||
|
}
|
||||||
|
}
|
||||||
10
Models/Sponsors.cs
Normal file
10
Models/Sponsors.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace CarCareTracker.Models
|
||||||
|
{
|
||||||
|
public class Sponsors
|
||||||
|
{
|
||||||
|
public List<string> LifeTime { get; set; } = new List<string>();
|
||||||
|
public List<string> Bronze { get; set; } = new List<string>();
|
||||||
|
public List<string> Silver { get; set; } = new List<string>();
|
||||||
|
public List<string> Gold { get; set; } = new List<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
8
Models/Supply/SupplyUsageViewModel.cs
Normal file
8
Models/Supply/SupplyUsageViewModel.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace CarCareTracker.Models
|
||||||
|
{
|
||||||
|
public class SupplyUsageViewModel
|
||||||
|
{
|
||||||
|
public List<SupplyRecord> Supplies { get; set; } = new List<SupplyRecord>();
|
||||||
|
public List<SupplyUsage> Usage { get; set; } = new List<SupplyUsage>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public int VehicleId { 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 Date { get; set; } = DateTime.Now.ToShortDateString();
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public decimal Cost { get; set; }
|
public decimal Cost { get; set; }
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public int VehicleId { 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 Date { get; set; } = DateTime.Now.ToShortDateString();
|
||||||
public int Mileage { get; set; }
|
public int Mileage { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
public List<string> Tags { get; set; } = new List<string>();
|
public List<string> Tags { get; set; } = new List<string>();
|
||||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||||
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
|
||||||
|
public bool CopySuppliesAttachment { get; set; } = false;
|
||||||
public UpgradeRecord ToUpgradeRecord() { return new UpgradeRecord {
|
public UpgradeRecord ToUpgradeRecord() { return new UpgradeRecord {
|
||||||
Id = Id,
|
Id = Id,
|
||||||
VehicleId = VehicleId,
|
VehicleId = VehicleId,
|
||||||
|
|||||||
@@ -3,10 +3,13 @@
|
|||||||
public class UserConfig
|
public class UserConfig
|
||||||
{
|
{
|
||||||
public bool UseDarkMode { get; set; }
|
public bool UseDarkMode { get; set; }
|
||||||
|
public bool UseSystemColorMode { get; set; }
|
||||||
public bool EnableCsvImports { get; set; }
|
public bool EnableCsvImports { get; set; }
|
||||||
public bool UseMPG { get; set; }
|
public bool UseMPG { get; set; }
|
||||||
public bool UseDescending { get; set; }
|
public bool UseDescending { get; set; }
|
||||||
public bool EnableAuth { get; set; }
|
public bool EnableAuth { get; set; }
|
||||||
|
public bool DisableRegistration { get; set; }
|
||||||
|
public bool EnableRootUserOIDC { get; set; }
|
||||||
public bool HideZero { get; set; }
|
public bool HideZero { get; set; }
|
||||||
public bool UseUKMPG {get;set;}
|
public bool UseUKMPG {get;set;}
|
||||||
public bool UseThreeDecimalGasCost { get; set; }
|
public bool UseThreeDecimalGasCost { get; set; }
|
||||||
@@ -22,6 +25,7 @@
|
|||||||
public ReminderUrgencyConfig ReminderUrgencyConfig { get; set; } = new ReminderUrgencyConfig();
|
public ReminderUrgencyConfig ReminderUrgencyConfig { get; set; } = new ReminderUrgencyConfig();
|
||||||
public string UserNameHash { get; set; }
|
public string UserNameHash { get; set; }
|
||||||
public string UserPasswordHash { get; set;}
|
public string UserPasswordHash { get; set;}
|
||||||
|
public string DefaultReminderEmail { get; set; } = string.Empty;
|
||||||
public string UserLanguage { get; set; } = "en_US";
|
public string UserLanguage { get; set; } = "en_US";
|
||||||
public List<ImportMode> VisibleTabs { get; set; } = new List<ImportMode>() {
|
public List<ImportMode> VisibleTabs { get; set; } = new List<ImportMode>() {
|
||||||
ImportMode.Dashboard,
|
ImportMode.Dashboard,
|
||||||
|
|||||||
@@ -10,8 +10,12 @@
|
|||||||
public string LicensePlate { get; set; }
|
public string LicensePlate { get; set; }
|
||||||
public string PurchaseDate { get; set; }
|
public string PurchaseDate { get; set; }
|
||||||
public string SoldDate { 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 IsElectric { get; set; } = false;
|
||||||
|
public bool IsDiesel { get; set; } = false;
|
||||||
public bool UseHours { get; set; } = false;
|
public bool UseHours { get; set; } = false;
|
||||||
|
public bool OdometerOptional { get; set; } = false;
|
||||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||||
public List<string> Tags { get; set; } = new List<string>();
|
public List<string> Tags { get; set; } = new List<string>();
|
||||||
public bool HasOdometerAdjustment { get; set; } = false;
|
public bool HasOdometerAdjustment { get; set; } = false;
|
||||||
@@ -23,5 +27,6 @@
|
|||||||
/// Primarily used for vehicles where the odometer does not reflect actual mileage.
|
/// Primarily used for vehicles where the odometer does not reflect actual mileage.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OdometerDifference { get; set; } = "0";
|
public string OdometerDifference { get; set; } = "0";
|
||||||
|
public List<DashboardMetric> DashboardMetrics { get; set; } = new List<DashboardMetric>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
Models/VehicleViewModel.cs
Normal file
26
Models/VehicleViewModel.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
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 IsDiesel { get; set; } = false;
|
||||||
|
public bool UseHours { get; set; } = false;
|
||||||
|
public bool OdometerOptional { get; set; } = false;
|
||||||
|
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||||
|
public List<string> Tags { get; set; } = new List<string>();
|
||||||
|
//Dashboard Metric Attributes
|
||||||
|
public List<DashboardMetric> DashboardMetrics { get; set; } = new List<DashboardMetric>();
|
||||||
|
public int LastReportedMileage { get; set; }
|
||||||
|
public bool HasReminders { get; set; } = false;
|
||||||
|
public decimal CostPerMile { get; set; }
|
||||||
|
public decimal TotalCost { get; set; }
|
||||||
|
public string DistanceUnit { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
20
Program.cs
20
Program.cs
@@ -16,6 +16,9 @@ StaticHelper.InitMessage(builder.Configuration);
|
|||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
builder.Services.AddControllersWithViews();
|
builder.Services.AddControllersWithViews();
|
||||||
|
|
||||||
|
//LiteDB is always injected even if user uses Postgres.
|
||||||
|
builder.Services.AddSingleton<ILiteDBHelper, LiteDBHelper>();
|
||||||
|
|
||||||
//data access method
|
//data access method
|
||||||
if (!string.IsNullOrWhiteSpace(builder.Configuration["POSTGRES_CONNECTION"])){
|
if (!string.IsNullOrWhiteSpace(builder.Configuration["POSTGRES_CONNECTION"])){
|
||||||
builder.Services.AddSingleton<IVehicleDataAccess, PGVehicleDataAccess>();
|
builder.Services.AddSingleton<IVehicleDataAccess, PGVehicleDataAccess>();
|
||||||
@@ -70,6 +73,7 @@ builder.Services.AddSingleton<ITranslationHelper, TranslationHelper>();
|
|||||||
builder.Services.AddSingleton<ILoginLogic, LoginLogic>();
|
builder.Services.AddSingleton<ILoginLogic, LoginLogic>();
|
||||||
builder.Services.AddSingleton<IUserLogic, UserLogic>();
|
builder.Services.AddSingleton<IUserLogic, UserLogic>();
|
||||||
builder.Services.AddSingleton<IOdometerLogic, OdometerLogic>();
|
builder.Services.AddSingleton<IOdometerLogic, OdometerLogic>();
|
||||||
|
builder.Services.AddSingleton<IVehicleLogic, VehicleLogic>();
|
||||||
|
|
||||||
if (!Directory.Exists("data"))
|
if (!Directory.Exists("data"))
|
||||||
{
|
{
|
||||||
@@ -107,7 +111,21 @@ var app = builder.Build();
|
|||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
app.UseExceptionHandler("/Home/Error");
|
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();
|
app.UseRouting();
|
||||||
|
|
||||||
|
|||||||
37
README.md
37
README.md
@@ -20,38 +20,31 @@ Try it out before you download it! The live demo resets every 20 minutes.
|
|||||||
## Download
|
## Download
|
||||||
LubeLogger is available as both a Docker Image and a Windows Standalone Executable.
|
LubeLogger is available as both a Docker Image and a Windows Standalone Executable.
|
||||||
|
|
||||||
Read this [Getting Started Guide](https://docs.lubelogger.com/Getting%20Started) on how to download either of them
|
Read this [Getting Started Guide](https://docs.lubelogger.com/Installation/Getting%20Started) on how to download either of them
|
||||||
|
|
||||||
### Docker Setup (Manual Build for Advanced Users)
|
### Kubernetes Deployment
|
||||||
1. Install Docker
|
[Helm Chart](https://artifacthub.io/packages/helm/anza-labs/lubelogger) provided by [Anza-Labs](https://github.com/anza-labs)
|
||||||
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?
|
### Need Help?
|
||||||
[Documentation](https://docs.lubelogger.com/)
|
[Documentation](https://docs.lubelogger.com/)
|
||||||
|
|
||||||
[Troubleshooting Guide](https://docs.lubelogger.com/Troubleshooting)
|
[Troubleshooting Guide](https://docs.lubelogger.com/Installation/Troubleshooting)
|
||||||
|
|
||||||
[Search Existing Issues](https://github.com/hargata/lubelog/issues)
|
[Search Existing Issues](https://github.com/hargata/lubelog/issues)
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
- Bootstrap
|
- [Bootstrap](https://github.com/twbs/bootstrap)
|
||||||
- LiteDB
|
- [LiteDB](https://github.com/mbdavid/litedb)
|
||||||
- Npgsql
|
- [Npgsql](https://github.com/npgsql/npgsql)
|
||||||
- Bootstrap-DatePicker
|
- [Bootstrap-DatePicker](https://github.com/uxsolutions/bootstrap-datepicker)
|
||||||
- SweetAlert2
|
- [SweetAlert2](https://github.com/sweetalert2/sweetalert2)
|
||||||
- CsvHelper
|
- [CsvHelper](https://github.com/JoshClose/CsvHelper)
|
||||||
- Chart.js
|
- [Chart.js](https://github.com/chartjs/Chart.js)
|
||||||
- Drawdown
|
- [Drawdown](https://github.com/adamvleggett/drawdown)
|
||||||
|
- [MailKit](https://github.com/jstedfast/MailKit)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
LubeLogger utilizes a dual-licensing model, see [License](/LICENSE) for more information
|
MIT
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
Support this project by [Subscribing on Patreon](https://patreon.com/LubeLogger) or [Making a Donation](https://buy.stripe.com/aEU9Egc8DdMc9bO144)
|
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.
|
|
||||||
@@ -40,6 +40,86 @@
|
|||||||
No Params
|
No Params
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-1">
|
||||||
|
GET
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/info</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Returns details for list of vehicles or specific vehicle
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
VehicleId - Id of Vehicle(optional)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-1">
|
||||||
|
GET
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/adjustedodometer</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Returns odometer reading with adjustments applied
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
vehicleId - Id of Vehicle
|
||||||
|
<br />
|
||||||
|
odometer - Unadjusted odometer
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-1">
|
||||||
|
GET
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/odometerrecords</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Returns a list of odometer records for the vehicle
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
vehicleId - Id of Vehicle
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-1">
|
||||||
|
GET
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/odometerrecords/latest</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Returns last reported odometer for the vehicle
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
vehicleId - Id of Vehicle
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-1">
|
||||||
|
POST
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/odometerrecords/add</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Adds Odometer Record to the vehicle
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
vehicleId - Id of Vehicle
|
||||||
|
<br />
|
||||||
|
Body(form-data): {<br />
|
||||||
|
date - Date to be entered<br />
|
||||||
|
initialOdometer - Initial Odometer reading(optional)<br />
|
||||||
|
odometer - Odometer reading<br />
|
||||||
|
notes - notes(optional)<br />
|
||||||
|
extrafields - <a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover reminder-calendar-item" onclick="showExtraFieldsInfo()">extrafields(optional)</a><br />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-1">
|
<div class="col-1">
|
||||||
GET
|
GET
|
||||||
@@ -73,6 +153,7 @@
|
|||||||
description - Description<br/>
|
description - Description<br/>
|
||||||
cost - Cost<br />
|
cost - Cost<br />
|
||||||
notes - notes(optional)<br />
|
notes - notes(optional)<br />
|
||||||
|
extrafields - <a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover reminder-calendar-item" onclick="showExtraFieldsInfo()">extrafields(optional)</a><br />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -109,6 +190,7 @@
|
|||||||
description - Description<br />
|
description - Description<br />
|
||||||
cost - Cost<br />
|
cost - Cost<br />
|
||||||
notes - notes(optional)<br />
|
notes - notes(optional)<br />
|
||||||
|
extrafields - <a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover reminder-calendar-item" onclick="showExtraFieldsInfo()">extrafields(optional)</a><br />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -145,6 +227,7 @@
|
|||||||
description - Description<br />
|
description - Description<br />
|
||||||
cost - Cost<br />
|
cost - Cost<br />
|
||||||
notes - notes(optional)<br />
|
notes - notes(optional)<br />
|
||||||
|
extrafields - <a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover reminder-calendar-item" onclick="showExtraFieldsInfo()">extrafields(optional)</a><br />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -180,6 +263,7 @@
|
|||||||
description - Description<br />
|
description - Description<br />
|
||||||
cost - Cost<br />
|
cost - Cost<br />
|
||||||
notes - notes(optional)<br />
|
notes - notes(optional)<br />
|
||||||
|
extrafields - <a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover reminder-calendar-item" onclick="showExtraFieldsInfo()">extrafields(optional)</a><br />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -222,6 +306,7 @@
|
|||||||
isFillToFull(bool) - Filled To Full<br />
|
isFillToFull(bool) - Filled To Full<br />
|
||||||
missedFuelUp(bool) - Missed Fuel Up<br />
|
missedFuelUp(bool) - Missed Fuel Up<br />
|
||||||
notes - notes(optional)<br />
|
notes - notes(optional)<br />
|
||||||
|
extrafields - <a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover reminder-calendar-item" onclick="showExtraFieldsInfo()">extrafields(optional)</a><br />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -270,58 +355,31 @@
|
|||||||
No Params(must be root user)
|
No Params(must be root user)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-1">
|
||||||
|
GET
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/cleanup</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Clears out temp files. Deep clean will also delete unlinked thumbnails and documents. Returns number of deleted files.
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
(must be root user)<br />
|
||||||
|
deepClean(bool) - Perform deep clean
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
<div class="row">
|
|
||||||
<div class="col-1">
|
|
||||||
GET
|
|
||||||
</div>
|
|
||||||
<div class="col-5 copyable">
|
|
||||||
<code>/api/vehicle/odometerrecords</code>
|
|
||||||
</div>
|
|
||||||
<div class="col-3">
|
|
||||||
Returns a list of odometer records for the vehicle
|
|
||||||
</div>
|
|
||||||
<div class="col-3">
|
|
||||||
vehicleId - Id of Vehicle
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-1">
|
|
||||||
GET
|
|
||||||
</div>
|
|
||||||
<div class="col-5 copyable">
|
|
||||||
<code>/api/vehicle/odometerrecords/latest</code>
|
|
||||||
</div>
|
|
||||||
<div class="col-3">
|
|
||||||
Returns last reported odometer for the vehicle
|
|
||||||
</div>
|
|
||||||
<div class="col-3">
|
|
||||||
vehicleId - Id of Vehicle
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-1">
|
|
||||||
POST
|
|
||||||
</div>
|
|
||||||
<div class="col-5 copyable">
|
|
||||||
<code>/api/vehicle/odometerrecords/add</code>
|
|
||||||
</div>
|
|
||||||
<div class="col-3">
|
|
||||||
Adds Odometer Record to the vehicle
|
|
||||||
</div>
|
|
||||||
<div class="col-3">
|
|
||||||
vehicleId - Id of Vehicle
|
|
||||||
<br />
|
|
||||||
Body(form-data): {<br />
|
|
||||||
date - Date to be entered<br />
|
|
||||||
initialOdometer - Initial Odometer reading(optional)<br />
|
|
||||||
odometer - Odometer reading<br />
|
|
||||||
notes - notes(optional)<br />
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
<script>
|
||||||
$('.copyable').on('click', function (e) {
|
$('.copyable').on('click', function (e) {
|
||||||
copyToClipboard(e.currentTarget);
|
copyToClipboard(e.currentTarget);
|
||||||
})
|
})
|
||||||
|
function showExtraFieldsInfo(){
|
||||||
|
Swal.fire({
|
||||||
|
title: "Format for Extra Fields",
|
||||||
|
html: "extrafields[i][name] - Name of Extra Field<br/>extrafields[i][value] - Value of Extra Field<br/>i is an integer that starts at 0 and increments with each extrafield",
|
||||||
|
icon: "info"
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
}
|
}
|
||||||
@section Scripts {
|
@section Scripts {
|
||||||
<script src="~/js/garage.js?v=@StaticHelper.VersionNumber"></script>
|
<script src="~/js/garage.js?v=@StaticHelper.VersionNumber"></script>
|
||||||
|
<script src="~/js/settings.js?v=@StaticHelper.VersionNumber"></script>
|
||||||
<script src="~/js/supplyrecord.js?v=@StaticHelper.VersionNumber"></script>
|
<script src="~/js/supplyrecord.js?v=@StaticHelper.VersionNumber"></script>
|
||||||
<script src="~/lib/drawdown/drawdown.js"></script>
|
<script src="~/lib/drawdown/drawdown.js"></script>
|
||||||
}
|
}
|
||||||
@@ -41,7 +42,12 @@
|
|||||||
<a class="dropdown-item" href="/Admin"><span class="display-3 ms-2"><i class="bi bi-people me-2"></i>@translator.Translate(userLanguage,"Admin Panel")</span></a>
|
<a class="dropdown-item" href="/Admin"><span class="display-3 ms-2"><i class="bi bi-people me-2"></i>@translator.Translate(userLanguage,"Admin Panel")</span></a>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
@if (!User.IsInRole(nameof(UserData.IsRootUser)))
|
@if (User.IsInRole(nameof(UserData.IsRootUser)))
|
||||||
|
{
|
||||||
|
<li>
|
||||||
|
<button class="nav-link" onclick="showRootAccountInformationModal()"><span class="display-3 ms-2"><i class="bi bi-person-gear me-2"></i>@translator.Translate(userLanguage, "Profile")</span></button>
|
||||||
|
</li>
|
||||||
|
} else
|
||||||
{
|
{
|
||||||
<li>
|
<li>
|
||||||
<button class="nav-link" onclick="showAccountInformationModal()"><span class="display-3 ms-2"><i class="bi bi-person-gear me-2"></i>@translator.Translate(userLanguage, "Profile")</span></button>
|
<button class="nav-link" onclick="showAccountInformationModal()"><span class="display-3 ms-2"><i class="bi bi-person-gear me-2"></i>@translator.Translate(userLanguage, "Profile")</span></button>
|
||||||
@@ -58,7 +64,7 @@
|
|||||||
<div class="d-flex lubelogger-navbar">
|
<div class="d-flex lubelogger-navbar">
|
||||||
<img src="@logoUrl" />
|
<img src="@logoUrl" />
|
||||||
<div class="lubelogger-navbar-button">
|
<div class="lubelogger-navbar-button">
|
||||||
<button type="button" class="btn btn-dark" onclick="showMobileNav()"><i class="bi bi-list lubelogger-menu-icon"></i></button>
|
<button type="button" class="btn btn-adaptive" onclick="showMobileNav()"><i class="bi bi-list lubelogger-menu-icon"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -90,7 +96,12 @@
|
|||||||
<a class="dropdown-item" href="/Admin"><i class="bi bi-people me-2"></i>@translator.Translate(userLanguage,"Admin Panel")</a>
|
<a class="dropdown-item" href="/Admin"><i class="bi bi-people me-2"></i>@translator.Translate(userLanguage,"Admin Panel")</a>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
@if (!User.IsInRole(nameof(UserData.IsRootUser)))
|
@if (User.IsInRole(nameof(UserData.IsRootUser)))
|
||||||
|
{
|
||||||
|
<li>
|
||||||
|
<button class="dropdown-item" onclick="showRootAccountInformationModal()"><i class="bi bi-person-gear me-2"></i>@translator.Translate(userLanguage, "Profile")</button>
|
||||||
|
</li>
|
||||||
|
} else
|
||||||
{
|
{
|
||||||
<li>
|
<li>
|
||||||
<button class="dropdown-item" onclick="showAccountInformationModal()"><i class="bi bi-person-gear me-2"></i>@translator.Translate(userLanguage, "Profile")</button>
|
<button class="dropdown-item" onclick="showAccountInformationModal()"><i class="bi bi-person-gear me-2"></i>@translator.Translate(userLanguage, "Profile")</button>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
var userLanguage = userConfig.UserLanguage;
|
var userLanguage = userConfig.UserLanguage;
|
||||||
}
|
}
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="addVehicleModalLabel">@translator.Translate(userLanguage, "Update Profile")</h5>
|
<h5 class="modal-title" id="updateAccountModalLabel">@translator.Translate(userLanguage, "Update Profile")</h5>
|
||||||
<button type="button" class="btn-close" onclick="hideAccountInformationModal()" aria-label="Close"></button>
|
<button type="button" class="btn-close" onclick="hideAccountInformationModal()" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
@using CarCareTracker.Helper
|
@using CarCareTracker.Helper
|
||||||
@inject IConfigHelper config
|
@inject IConfigHelper config
|
||||||
@inject ITranslationHelper translator
|
@inject ITranslationHelper translator
|
||||||
@model List<Vehicle>
|
@model List<VehicleViewModel>
|
||||||
@{
|
@{
|
||||||
var userConfig = config.GetUserConfig(User);
|
var userConfig = config.GetUserConfig(User);
|
||||||
var userLanguage = userConfig.UserLanguage;
|
var userLanguage = userConfig.UserLanguage;
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
}
|
}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="row gy-3 align-items-stretch vehiclesContainer">
|
<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)))
|
@if (!(userConfig.HideSoldVehicles && !string.IsNullOrWhiteSpace(vehicle.SoldDate)))
|
||||||
{
|
{
|
||||||
@@ -36,6 +36,41 @@
|
|||||||
@if (!string.IsNullOrWhiteSpace(vehicle.SoldDate))
|
@if (!string.IsNullOrWhiteSpace(vehicle.SoldDate))
|
||||||
{
|
{
|
||||||
<div class="vehicle-sold-banner"><p class='display-6 mb-0'>@translator.Translate(userLanguage, "SOLD")</p></div>
|
<div class="vehicle-sold-banner"><p class='display-6 mb-0'>@translator.Translate(userLanguage, "SOLD")</p></div>
|
||||||
|
} else if (vehicle.DashboardMetrics.Any())
|
||||||
|
{
|
||||||
|
<div class="vehicle-sold-banner">
|
||||||
|
@if (vehicle.DashboardMetrics.Contains(DashboardMetric.Default) && vehicle.LastReportedMileage != default)
|
||||||
|
{
|
||||||
|
|
||||||
|
<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>
|
||||||
|
}
|
||||||
|
@if (vehicle.DashboardMetrics.Contains(DashboardMetric.CostPerMile) && vehicle.CostPerMile != default)
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div>
|
||||||
|
<span class="ms-2"><i class="bi bi-cash-coin me-2"></i>@($"{vehicle.CostPerMile.ToString("C2")}/{vehicle.DistanceUnit}")</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (vehicle.DashboardMetrics.Contains(DashboardMetric.TotalCost) && vehicle.TotalCost != default)
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div>
|
||||||
|
<span class="ms-2"><i class="bi bi-cash-coin me-2"></i>@($"{vehicle.TotalCost.ToString("C2")}")</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title text-truncate garage-item-year" data-unit="@vehicle.Year">@($"{vehicle.Year}")</h5>
|
<h5 class="card-title text-truncate garage-item-year" data-unit="@vehicle.Year">@($"{vehicle.Year}")</h5>
|
||||||
|
|||||||
26
Views/Home/_RootAccountModal.cshtml
Normal file
26
Views/Home/_RootAccountModal.cshtml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
@using CarCareTracker.Helper
|
||||||
|
@inject IConfigHelper config
|
||||||
|
@inject ITranslationHelper translator
|
||||||
|
@model UserData
|
||||||
|
@{
|
||||||
|
var userConfig = config.GetUserConfig(User);
|
||||||
|
var userLanguage = userConfig.UserLanguage;
|
||||||
|
}
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="updateRootAccountModalLabel">@translator.Translate(userLanguage, "Update Profile")</h5>
|
||||||
|
<button type="button" class="btn-close" onclick="hideAccountInformationModal()" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form class="form-inline">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="inputUsername">@translator.Translate(userLanguage, "Username")</label>
|
||||||
|
<input type="text" id="inputUsername" class="form-control" placeholder="@translator.Translate(userLanguage, "Account Username")" value="@Model.UserName">
|
||||||
|
<label for="inputPassword">@translator.Translate(userLanguage, "Password")</label>
|
||||||
|
<input type="password" id="inputPassword" class="form-control" placeholder="@translator.Translate(userLanguage, "Password")" value="">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" onclick="hideAccountInformationModal()">@translator.Translate(userLanguage, "Cancel")</button>
|
||||||
|
<button type="button" onclick="validateAndSaveRootUserAccount()" class="btn btn-primary">@translator.Translate(userLanguage, "Update")</button>
|
||||||
|
</div>
|
||||||
@@ -13,10 +13,14 @@
|
|||||||
<div class="col-12 col-md-6">
|
<div class="col-12 col-md-6">
|
||||||
<input id="preferredGasUnit" style="display:none;" value="@Model.UserConfig.PreferredGasUnit" />
|
<input id="preferredGasUnit" style="display:none;" value="@Model.UserConfig.PreferredGasUnit" />
|
||||||
<input id="preferredFuelMileageUnit" style="display:none;" value="@Model.UserConfig.PreferredGasMileageUnit" />
|
<input id="preferredFuelMileageUnit" style="display:none;" value="@Model.UserConfig.PreferredGasMileageUnit" />
|
||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch form-check-inline">
|
||||||
<input class="form-check-input" onChange="updateSettings()" type="checkbox" role="switch" id="enableDarkMode" checked="@Model.UserConfig.UseDarkMode">
|
<input class="form-check-input" onChange="updateColorModeSettings(this)" type="checkbox" role="switch" id="enableDarkMode" checked="@Model.UserConfig.UseDarkMode">
|
||||||
<label class="form-check-label" for="enableDarkMode">@translator.Translate(userLanguage, "Dark Mode")</label>
|
<label class="form-check-label" for="enableDarkMode">@translator.Translate(userLanguage, "Dark Mode")</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-check form-switch form-check-inline">
|
||||||
|
<input class="form-check-input" onChange="updateColorModeSettings(this)" type="checkbox" role="switch" id="useSystemColorMode" checked="@Model.UserConfig.UseSystemColorMode">
|
||||||
|
<label class="form-check-label" for="useSystemColorMode">@translator.Translate(userLanguage, "Adaptive Color Mode")</label>
|
||||||
|
</div>
|
||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch">
|
||||||
<input class="form-check-input" onChange="updateSettings()" type="checkbox" role="switch" id="enableCsvImports" checked="@Model.UserConfig.EnableCsvImports">
|
<input class="form-check-input" onChange="updateSettings()" type="checkbox" role="switch" id="enableCsvImports" checked="@Model.UserConfig.EnableCsvImports">
|
||||||
<label class="form-check-label" for="enableCsvImports">@translator.Translate(userLanguage, "Enable CSV Imports")</label>
|
<label class="form-check-label" for="enableCsvImports">@translator.Translate(userLanguage, "Enable CSV Imports")</label>
|
||||||
@@ -71,6 +75,17 @@
|
|||||||
<input class="form-check-input" onChange="enableAuthCheckChanged()" type="checkbox" role="switch" id="enableAuth" checked="@Model.UserConfig.EnableAuth">
|
<input class="form-check-input" onChange="enableAuthCheckChanged()" type="checkbox" role="switch" id="enableAuth" checked="@Model.UserConfig.EnableAuth">
|
||||||
<label class="form-check-label" for="enableAuth">@translator.Translate(userLanguage, "Enable Authentication")</label>
|
<label class="form-check-label" for="enableAuth">@translator.Translate(userLanguage, "Enable Authentication")</label>
|
||||||
</div>
|
</div>
|
||||||
|
@if (Model.UserConfig.EnableAuth)
|
||||||
|
{
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" onChange="updateSettings()" type="checkbox" role="switch" id="disableRegistration" checked="@Model.UserConfig.DisableRegistration">
|
||||||
|
<label class="form-check-label" for="disableRegistration">@translator.Translate(userLanguage, "Disable Registration")</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" onChange="updateSettings()" type="checkbox" role="switch" id="enableRootUserOIDC" checked="@Model.UserConfig.EnableRootUserOIDC">
|
||||||
|
<label class="form-check-label" for="enableRootUserOIDC">@translator.Translate(userLanguage, "Enable OIDC for Root User")<br /><small class="text-body-secondary">@translator.Translate(userLanguage, "Uses the Default Reminder Email for OIDC Auth")</small></label>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-md-6">
|
<div class="col-12 col-md-6">
|
||||||
@@ -198,6 +213,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<span class="lead">@translator.Translate(userLanguage, "Default Reminder Email")</span>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 d-grid">
|
||||||
|
<div class="input-group">
|
||||||
|
<input id="inputDefaultEmail" class="form-control" placeholder="@translator.Translate(userLanguage,"Default Email for Reminder")" value="@Model.UserConfig.DefaultReminderEmail">
|
||||||
|
<div class="input-group-text">
|
||||||
|
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="updateSettings()"><i class="bi bi-floppy"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -219,7 +247,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<p class="lead">
|
<p class="lead">
|
||||||
If you enjoyed using this app, please consider spreading the good word.<br />
|
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>
|
</p>
|
||||||
<div class="d-flex justify-content-center">
|
<div class="d-flex justify-content-center">
|
||||||
<h6 class="display-7 mt-2">Hometown Shoutout</h6>
|
<h6 class="display-7 mt-2">Hometown Shoutout</h6>
|
||||||
@@ -247,9 +275,11 @@
|
|||||||
<li class="list-group-item">CsvHelper</li>
|
<li class="list-group-item">CsvHelper</li>
|
||||||
<li class="list-group-item">Chart.js</li>
|
<li class="list-group-item">Chart.js</li>
|
||||||
<li class="list-group-item">Drawdown</li>
|
<li class="list-group-item">Drawdown</li>
|
||||||
|
<li class="list-group-item">MailKit</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</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 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-dialog modal-lg" role="document">
|
||||||
<div class="modal-content" id="extraFieldModalContent">
|
<div class="modal-content" id="extraFieldModalContent">
|
||||||
@@ -304,137 +334,6 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function showExtraFieldModal() {
|
|
||||||
$.get(`/Home/GetExtraFieldsModal?importMode=0`, function (data) {
|
|
||||||
$("#extraFieldModalContent").html(data);
|
|
||||||
$("#extraFieldModal").modal('show');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function hideExtraFieldModal() {
|
|
||||||
$("#extraFieldModal").modal('hide');
|
|
||||||
}
|
|
||||||
function getCheckedTabs() {
|
|
||||||
var visibleTabs = $("#visibleTabs :checked").map(function () {
|
|
||||||
return this.value;
|
|
||||||
});
|
|
||||||
return visibleTabs.toArray();
|
|
||||||
}
|
|
||||||
function deleteLanguage() {
|
|
||||||
var languageFileLocation = `/translations/${$("#defaultLanguage").val()}.json`;
|
|
||||||
$.post('/Files/DeleteFiles', { fileLocation: languageFileLocation }, function (data) {
|
|
||||||
//reset user language back to en_US
|
|
||||||
$("#defaultLanguage").val('en_US');
|
|
||||||
updateSettings();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function updateSettings() {
|
|
||||||
var visibleTabs = getCheckedTabs();
|
|
||||||
var defaultTab = $("#defaultTab").val();
|
|
||||||
if (!visibleTabs.includes(defaultTab)) {
|
|
||||||
defaultTab = "Dashboard"; //default to dashboard.
|
|
||||||
}
|
|
||||||
var userConfigObject = {
|
|
||||||
useDarkMode: $("#enableDarkMode").is(':checked'),
|
|
||||||
enableCsvImports: $("#enableCsvImports").is(':checked'),
|
|
||||||
useMPG: $("#useMPG").is(':checked'),
|
|
||||||
useDescending: $("#useDescending").is(':checked'),
|
|
||||||
hideZero: $("#hideZero").is(":checked"),
|
|
||||||
useUKMpg: $("#useUKMPG").is(":checked"),
|
|
||||||
useThreeDecimalGasCost: $("#useThreeDecimal").is(":checked"),
|
|
||||||
useMarkDownOnSavedNotes: $("#useMarkDownOnSavedNotes").is(":checked"),
|
|
||||||
enableAutoReminderRefresh: $("#enableAutoReminderRefresh").is(":checked"),
|
|
||||||
enableAutoOdometerInsert: $("#enableAutoOdometerInsert").is(":checked"),
|
|
||||||
enableShopSupplies: $("#enableShopSupplies").is(":checked"),
|
|
||||||
enableExtraFieldColumns: $("#enableExtraFieldColumns").is(":checked"),
|
|
||||||
hideSoldVehicles: $("#hideSoldVehicles").is(":checked"),
|
|
||||||
preferredGasUnit: $("#preferredGasUnit").val(),
|
|
||||||
preferredGasMileageUnit: $("#preferredFuelMileageUnit").val(),
|
|
||||||
userLanguage: $("#defaultLanguage").val(),
|
|
||||||
visibleTabs: visibleTabs,
|
|
||||||
defaultTab: defaultTab
|
|
||||||
}
|
|
||||||
sloader.show();
|
|
||||||
$.post('/Home/WriteToSettings', { userConfig: userConfigObject }, function (data) {
|
|
||||||
sloader.hide();
|
|
||||||
if (data) {
|
|
||||||
setTimeout(function () { window.location.href = '/Home/Index?tab=settings' }, 500);
|
|
||||||
} else {
|
|
||||||
errorToast(genericErrorMessage());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
function makeBackup() {
|
|
||||||
$.get('/Files/MakeBackup', function (data) {
|
|
||||||
window.location.href = data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function openUploadLanguage() {
|
|
||||||
$("#inputLanguage").click();
|
|
||||||
}
|
|
||||||
function openRestoreBackup() {
|
|
||||||
$("#inputBackup").click();
|
|
||||||
}
|
|
||||||
function uploadLanguage(event) {
|
|
||||||
let formData = new FormData();
|
|
||||||
formData.append("file", event.files[0]);
|
|
||||||
sloader.show();
|
|
||||||
$.ajax({
|
|
||||||
url: "/Files/HandleTranslationFileUpload",
|
|
||||||
data: formData,
|
|
||||||
cache: false,
|
|
||||||
processData: false,
|
|
||||||
contentType: false,
|
|
||||||
type: 'POST',
|
|
||||||
success: function (response) {
|
|
||||||
sloader.hide();
|
|
||||||
if (response.success) {
|
|
||||||
setTimeout(function () { window.location.href = '/Home/Index?tab=settings' }, 500);
|
|
||||||
} else {
|
|
||||||
errorToast(response.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
sloader.hide();
|
|
||||||
errorToast("An error has occurred, please check the file size and try again later.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function restoreBackup(event) {
|
|
||||||
let formData = new FormData();
|
|
||||||
formData.append("file", event.files[0]);
|
|
||||||
console.log('LubeLogger - DB Restoration Started');
|
|
||||||
sloader.show();
|
|
||||||
$.ajax({
|
|
||||||
url: "/Files/HandleFileUpload",
|
|
||||||
data: formData,
|
|
||||||
cache: false,
|
|
||||||
processData: false,
|
|
||||||
contentType: false,
|
|
||||||
type: 'POST',
|
|
||||||
success: function (response) {
|
|
||||||
if (response.trim() != '') {
|
|
||||||
$.post('/Files/RestoreBackup', { fileName: response }, function (data) {
|
|
||||||
sloader.hide();
|
|
||||||
if (data) {
|
|
||||||
console.log('LubeLogger - DB Restoration Completed');
|
|
||||||
successToast("Backup Restored");
|
|
||||||
setTimeout(function () { window.location.href = '/Home/Index' }, 500);
|
|
||||||
} else {
|
|
||||||
errorToast(genericErrorMessage());
|
|
||||||
console.log('LubeLogger - DB Restoration Failed - Failed to process backup file.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.log('LubeLogger - DB Restoration Failed - Failed to upload backup file.');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
sloader.hide();
|
|
||||||
console.log('LubeLogger - DB Restoration Failed - Request failed to reach backend, please check file size.');
|
|
||||||
errorToast("An error has occurred, please check the file size and try again later.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function enableAuthCheckChanged() {
|
function enableAuthCheckChanged() {
|
||||||
var enableAuth = $("#enableAuth").is(":checked");
|
var enableAuth = $("#enableAuth").is(":checked");
|
||||||
if (enableAuth) {
|
if (enableAuth) {
|
||||||
|
|||||||
73
Views/Home/_Sponsors.cshtml
Normal file
73
Views/Home/_Sponsors.cshtml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
@using CarCareTracker.Helper
|
||||||
|
@model Sponsors
|
||||||
|
@inject ITranslationHelper translator
|
||||||
|
@inject IConfigHelper config
|
||||||
|
@{
|
||||||
|
var userConfig = config.GetUserConfig(User);
|
||||||
|
var enableAuth = userConfig.EnableAuth;
|
||||||
|
var userLanguage = userConfig.UserLanguage;
|
||||||
|
}
|
||||||
|
<div class="row">
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
<h6 class="display-6 mt-2">@translator.Translate(userLanguage, "Sponsors")</h6>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
<p><a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover" href="https://docs.lubelogger.com/Misc/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>
|
||||||
|
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
@{
|
@{
|
||||||
var logoUrl = config.GetLogoUrl();
|
var logoUrl = config.GetLogoUrl();
|
||||||
var userLanguage = config.GetServerLanguage();
|
var userLanguage = config.GetServerLanguage();
|
||||||
|
var registrationDisabled = config.GetServerDisabledRegistration();
|
||||||
var openIdConfigName = config.GetOpenIDConfig().Name;
|
var openIdConfigName = config.GetOpenIDConfig().Name;
|
||||||
}
|
}
|
||||||
@{
|
@{
|
||||||
@@ -46,9 +47,12 @@
|
|||||||
<div class="d-grid">
|
<div class="d-grid">
|
||||||
<a href="/Login/ForgotPassword" class="btn btn-link mt-2">@translator.Translate(userLanguage, "Forgot Password")</a>
|
<a href="/Login/ForgotPassword" class="btn btn-link mt-2">@translator.Translate(userLanguage, "Forgot Password")</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-grid">
|
@if (!registrationDisabled)
|
||||||
<a href="/Login/Registration" class="btn btn-link mt-2">@translator.Translate(userLanguage, "Register")</a>
|
{
|
||||||
</div>
|
<div class="d-grid">
|
||||||
|
<a href="/Login/Registration" class="btn btn-link mt-2">@translator.Translate(userLanguage, "Register")</a>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
@{
|
@{
|
||||||
var userConfig = config.GetUserConfig(User);
|
var userConfig = config.GetUserConfig(User);
|
||||||
var useDarkMode = userConfig.UseDarkMode;
|
var useDarkMode = userConfig.UseDarkMode;
|
||||||
|
var useSystemColorMode = userConfig.UseSystemColorMode;
|
||||||
var enableCsvImports = userConfig.EnableCsvImports;
|
var enableCsvImports = userConfig.EnableCsvImports;
|
||||||
var useMPG = userConfig.UseMPG;
|
var useMPG = userConfig.UseMPG;
|
||||||
var useMarkDown = userConfig.UseMarkDownOnSavedNotes;
|
var useMarkDown = userConfig.UseMarkDownOnSavedNotes;
|
||||||
@@ -54,7 +55,7 @@
|
|||||||
<script>
|
<script>
|
||||||
function getGlobalConfig() {
|
function getGlobalConfig() {
|
||||||
return {
|
return {
|
||||||
useDarkMode : "@useDarkMode" == "True",
|
useDarkMode: "@useDarkMode" == "True" || ("@useSystemColorMode" == "True" && window.matchMedia('(prefers-color-scheme: dark)').matches),
|
||||||
enableCsvImport : "@enableCsvImports" == "True",
|
enableCsvImport : "@enableCsvImports" == "True",
|
||||||
useMarkDown: "@useMarkDown" == "True",
|
useMarkDown: "@useMarkDown" == "True",
|
||||||
currencySymbol: decodeHTMLEntities("@numberFormat.CurrencySymbol"),
|
currencySymbol: decodeHTMLEntities("@numberFormat.CurrencySymbol"),
|
||||||
@@ -70,8 +71,8 @@
|
|||||||
}
|
}
|
||||||
function globalParseFloat(input){
|
function globalParseFloat(input){
|
||||||
//remove thousands separator.
|
//remove thousands separator.
|
||||||
var thousandSeparator = "@numberFormat.NumberGroupSeparator";
|
var thousandSeparator = decodeHTMLEntities("@numberFormat.NumberGroupSeparator");
|
||||||
var decimalSeparator = "@numberFormat.NumberDecimalSeparator";
|
var decimalSeparator = decodeHTMLEntities("@numberFormat.NumberDecimalSeparator");
|
||||||
var currencySymbol = decodeHTMLEntities("@numberFormat.CurrencySymbol");
|
var currencySymbol = decodeHTMLEntities("@numberFormat.CurrencySymbol");
|
||||||
if (input == "---") {
|
if (input == "---") {
|
||||||
input = "0";
|
input = "0";
|
||||||
@@ -85,13 +86,38 @@
|
|||||||
return parseFloat(input);
|
return parseFloat(input);
|
||||||
}
|
}
|
||||||
function globalFloatToString(input) {
|
function globalFloatToString(input) {
|
||||||
var decimalSeparator = "@numberFormat.NumberDecimalSeparator";
|
var decimalSeparator = decodeHTMLEntities("@numberFormat.NumberDecimalSeparator");
|
||||||
input = input.replace(".", decimalSeparator);
|
input = input.replace(".", decimalSeparator);
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
function genericErrorMessage(){
|
function genericErrorMessage(){
|
||||||
return decodeHTMLEntities('@translator.Translate(userLanguage, "An error has occurred, please try again later")');
|
return decodeHTMLEntities('@translator.Translate(userLanguage, "An error has occurred, please try again later")');
|
||||||
}
|
}
|
||||||
|
function globalAppendCurrency(input){
|
||||||
|
//check currency symbol position
|
||||||
|
var currencySymbolPosition = "@numberFormat.CurrencyPositivePattern";
|
||||||
|
var currencySymbol = decodeHTMLEntities("@numberFormat.CurrencySymbol");
|
||||||
|
switch (currencySymbolPosition) {
|
||||||
|
case "0":
|
||||||
|
return `${currencySymbol}${input}`;
|
||||||
|
break;
|
||||||
|
case "1":
|
||||||
|
return `${input}${currencySymbol}`;
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
return `${currencySymbol} ${input}`;
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
return `${input} ${currencySymbol}`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function setThemeBasedOnDevice() {
|
||||||
|
var systemPrefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
|
if (systemPrefersDarkMode) {
|
||||||
|
$(document.documentElement).attr("data-bs-theme", "dark");
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
@await RenderSectionAsync("Scripts", required: false)
|
@await RenderSectionAsync("Scripts", required: false)
|
||||||
</head>
|
</head>
|
||||||
@@ -103,3 +129,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@if (useSystemColorMode)
|
||||||
|
{
|
||||||
|
<script>
|
||||||
|
setThemeBasedOnDevice();
|
||||||
|
</script>
|
||||||
|
}
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
<h1 class="text-truncate display-4">@($"{Model.Year} {Model.Make} {Model.Model}")<small class="text-body-secondary">@($"(#{Model.LicensePlate})")</small></h1>
|
<h1 class="text-truncate display-4">@($"{Model.Year} {Model.Make} {Model.Model}")<small class="text-body-secondary">@($"(#{Model.LicensePlate})")</small></h1>
|
||||||
<button onclick="editVehicle(@Model.Id)" class="lubelogger-tab btn btn-warning btn-md mt-1 mb-1"><i class="bi bi-pencil-square"></i></button>
|
<button onclick="editVehicle(@Model.Id)" class="lubelogger-tab btn btn-warning btn-md mt-1 mb-1"><i class="bi bi-pencil-square"></i></button>
|
||||||
<div class="lubelogger-navbar-button">
|
<div class="lubelogger-navbar-button">
|
||||||
<button type="button" class="btn btn-dark" onclick="showMobileNav()"><i class="bi bi-list lubelogger-menu-icon"></i></button>
|
<button type="button" class="btn btn-adaptive" onclick="showMobileNav()"><i class="bi bi-list lubelogger-menu-icon"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -171,6 +171,7 @@
|
|||||||
function GetVehicleId() {
|
function GetVehicleId() {
|
||||||
return {
|
return {
|
||||||
vehicleId: @Model.Id,
|
vehicleId: @Model.Id,
|
||||||
|
odometerOptional: @Model.OdometerOptional.ToString().ToLower(),
|
||||||
hasOdometerAdjustment: @Model.HasOdometerAdjustment.ToString().ToLower(),
|
hasOdometerAdjustment: @Model.HasOdometerAdjustment.ToString().ToLower(),
|
||||||
odometerDifference: decodeHTMLEntities('@Model.OdometerDifference'),
|
odometerDifference: decodeHTMLEntities('@Model.OdometerDifference'),
|
||||||
odometerMultiplier: decodeHTMLEntities('@Model.OdometerMultiplier')
|
odometerMultiplier: decodeHTMLEntities('@Model.OdometerMultiplier')
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
var userLanguage = userConfig.UserLanguage;
|
var userLanguage = userConfig.UserLanguage;
|
||||||
}
|
}
|
||||||
<div class="modal-header">
|
<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>
|
<button type="button" class="btn-close" onclick="hideAddCollisionRecordModal()" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@@ -17,14 +17,22 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6 col-12">
|
<div class="col-md-6 col-12">
|
||||||
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
|
<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">
|
<div class="input-group">
|
||||||
<input type="text" id="collisionRecordDate" class="form-control" placeholder="@translator.Translate(userLanguage,"Date repair was performed")" value="@Model.Date">
|
<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>
|
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<label for="collisionRecordMileage">@translator.Translate(userLanguage,"Odometer")</label>
|
<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)">
|
<div class="input-group">
|
||||||
<label for="collisionRecordDescription">@translator.Translate(userLanguage,"Description")</label>
|
<input type="number" inputmode="numeric" id="collisionRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when repaired")" value="@(isNew || Model.Mileage == default ? "" : Model.Mileage)">
|
||||||
|
@if (isNew)
|
||||||
|
{
|
||||||
|
<div class="input-group-text">
|
||||||
|
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('collisionRecordMileage')"><i class="bi bi-plus"></i></button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<label for="collisionRecordDescription">@translator.Translate(userLanguage, "Description")</label>
|
||||||
<input type="text" id="collisionRecordDescription" class="form-control" placeholder="@translator.Translate(userLanguage,"Description of item(s) repaired(i.e. Alternator)")" value="@Model.Description">
|
<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)
|
@if (isNew)
|
||||||
{
|
{
|
||||||
@@ -34,13 +42,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</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)">
|
<input type="text" inputmode="decimal" id="collisionRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"Cost of the repair")" value="@(isNew ? "" : Model.Cost)">
|
||||||
@if (isNew)
|
@if (isNew)
|
||||||
{
|
{
|
||||||
@await Html.PartialAsync("_SupplyStore", "RepairRecord")
|
@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">
|
<select multiple class="form-select" id="collisionRecordTag">
|
||||||
@foreach (string tag in Model.Tags)
|
@foreach (string tag in Model.Tags)
|
||||||
{
|
{
|
||||||
@@ -57,15 +65,15 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 col-12">
|
<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>
|
<textarea id="collisionRecordNotes" class="form-control" rows="5">@Model.Notes</textarea>
|
||||||
@if (Model.Files.Any())
|
@if (Model.Files.Any())
|
||||||
{
|
{
|
||||||
<div>
|
<div>
|
||||||
@await Html.PartialAsync("_UploadedFiles", Model.Files)
|
@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">
|
<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>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -75,14 +83,15 @@
|
|||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" value="" id="addReminderCheck">
|
<input class="form-check-input" type="checkbox" value="" id="addReminderCheck">
|
||||||
<label class="form-check-label" for="addReminderCheck">
|
<label class="form-check-label" for="addReminderCheck">
|
||||||
@translator.Translate(userLanguage,"Add Reminder")
|
@translator.Translate(userLanguage, "Add Reminder")
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</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">
|
<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 id="filesPendingUpload"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -96,39 +105,40 @@
|
|||||||
<button type="button" class="btn btn-warning" onclick="toggleSupplyUsageHistory()"><i class="bi bi-shop"></i></button>
|
<button type="button" class="btn btn-warning" onclick="toggleSupplyUsageHistory()"><i class="bi bi-shop"></i></button>
|
||||||
}
|
}
|
||||||
<div class="btn-group" style="margin-right:auto;">
|
<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">
|
<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>
|
<span class="visually-hidden">Toggle Dropdown</span>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><h6 class="dropdown-header">@translator.Translate(userLanguage,"Move To")</h6></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', '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><a class="dropdown-item" href="#" onclick="moveRecord(@Model.Id, 'RepairRecord', 'UpgradeRecord')">@translator.Translate(userLanguage, "Upgrades")</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</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)
|
@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)
|
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>
|
</div>
|
||||||
@await Html.PartialAsync("_SupplyRequisitionHistory", Model.RequisitionHistory)
|
@await Html.PartialAsync("_SupplyRequisitionHistory", Model.RequisitionHistory)
|
||||||
<script>
|
<script>
|
||||||
var uploadedFiles = [];
|
var uploadedFiles = [];
|
||||||
var selectedSupplies = [];
|
var selectedSupplies = [];
|
||||||
var recurringReminderRecordId = 0;
|
var copySuppliesAttachments = false;
|
||||||
|
var recurringReminderRecordId = [];
|
||||||
getUploadedFilesFromModel();
|
getUploadedFilesFromModel();
|
||||||
function getUploadedFilesFromModel() {
|
function getUploadedFilesFromModel() {
|
||||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||||
{
|
{
|
||||||
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
|
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function getCollisionRecordModelData() {
|
function getCollisionRecordModelData() {
|
||||||
return { id: @Model.Id}
|
return { id: @Model.Id}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,13 +123,25 @@
|
|||||||
{
|
{
|
||||||
<tr class="d-flex user-select-none" style="cursor:pointer;" onmouseup="stopEvent()" ontouchstart="detectRowLongTouch(this)" ontouchend="detectRowTouchEndPremature(this)" data-rowId="@collisionRecord.Id" oncontextmenu="showTableContextMenu(this)" onmousemove="rangeMouseMove(this)" onclick="handleTableRowClick(this, showEditCollisionRecordModal,@collisionRecord.Id)" data-tags='@string.Join(" ", collisionRecord.Tags)'>
|
<tr class="d-flex user-select-none" style="cursor:pointer;" onmouseup="stopEvent()" ontouchstart="detectRowLongTouch(this)" ontouchend="detectRowTouchEndPremature(this)" data-rowId="@collisionRecord.Id" oncontextmenu="showTableContextMenu(this)" onmousemove="rangeMouseMove(this)" onclick="handleTableRowClick(this, showEditCollisionRecordModal,@collisionRecord.Id)" data-tags='@string.Join(" ", collisionRecord.Tags)'>
|
||||||
<td class="col-2 col-xl-1 flex-grow-1" data-column="date" data-date="@StaticHelper.GetEpochFromDateTime(collisionRecord.Date)">@collisionRecord.Date.ToShortDateString()</td>
|
<td class="col-2 col-xl-1 flex-grow-1" data-column="date" data-date="@StaticHelper.GetEpochFromDateTime(collisionRecord.Date)">@collisionRecord.Date.ToShortDateString()</td>
|
||||||
<td class="col-2 flex-grow-1 flex-shrink-1" data-column="odometer">@collisionRecord.Mileage</td>
|
<td class="col-2 flex-grow-1 flex-shrink-1" data-column="odometer">@(collisionRecord.Mileage == default ? "---" : collisionRecord.Mileage.ToString())</td>
|
||||||
<td class="col-3 col-xl-4 flex-grow-1 flex-shrink-1" data-column="description">@collisionRecord.Description</td>
|
<td class="col-3 col-xl-4 flex-grow-1 flex-shrink-1" data-column="description">@collisionRecord.Description</td>
|
||||||
<td class="col-2 flex-grow-1 flex-shrink-1" data-column="cost" data-record-type="cost">@((hideZero && collisionRecord.Cost == default) ? "---" : collisionRecord.Cost.ToString("C"))</td>
|
<td class="col-2 flex-grow-1 flex-shrink-1" data-column="cost" data-record-type="cost">@((hideZero && collisionRecord.Cost == default) ? "---" : collisionRecord.Cost.ToString("C"))</td>
|
||||||
<td class="col-3 flex-grow-1 flex-shrink-1 text-truncate" data-column="notes">@CarCareTracker.Helper.StaticHelper.TruncateStrings(collisionRecord.Notes)</td>
|
<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)
|
@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>
|
</tr>
|
||||||
}
|
}
|
||||||
@@ -139,7 +151,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" data-bs-focus="false" id="collisionRecordModal" tabindex="-1" role="dialog" aria-hidden="true">
|
<div class="modal fade" data-bs-focus="false" id="collisionRecordModal" tabindex="-1" role="dialog" aria-hidden="true" onpaste="handleModalPaste(event, 'collisionRecordFiles')">
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
<div class="modal-content" id="collisionRecordModalContent">
|
<div class="modal-content" id="collisionRecordModalContent">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -36,6 +36,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
|
onClick: (e) => {
|
||||||
|
showDataTable();
|
||||||
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: {
|
legend: {
|
||||||
position: "bottom",
|
position: "bottom",
|
||||||
|
|||||||
78
Views/Vehicle/_CostTableReport.cshtml
Normal file
78
Views/Vehicle/_CostTableReport.cshtml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
@using CarCareTracker.Helper
|
||||||
|
@inject IConfigHelper config
|
||||||
|
@inject ITranslationHelper translator
|
||||||
|
@{
|
||||||
|
var userConfig = config.GetUserConfig(User);
|
||||||
|
var userLanguage = userConfig.UserLanguage;
|
||||||
|
var hideZero = userConfig.HideZero;
|
||||||
|
}
|
||||||
|
@model CostTableForVehicle
|
||||||
|
@if (Model.CollisionRecordSum + Model.ServiceRecordSum + Model.GasRecordSum + Model.TaxRecordSum + Model.UpgradeRecordSum > 0)
|
||||||
|
{
|
||||||
|
<div>
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">@(translator.Translate(userLanguage, "Vehicle Cost Breakdown"))</h5>
|
||||||
|
<button type="button" class="btn-close" onclick="hideDataTable()" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead class="sticky-top">
|
||||||
|
<tr class="d-flex">
|
||||||
|
<th scope="col" class="col-3 flex-grow-1">@translator.Translate(userLanguage, "Type")</th>
|
||||||
|
<th scope="col" class="col-3 flex-grow-1">@translator.Translate(userLanguage, "Cost Per Day")</th>
|
||||||
|
<th scope="col" class="col-3 flex-grow-1">@translator.Translate(userLanguage, Model.DistanceUnit)</th>
|
||||||
|
<th scope="col" class="col-3 flex-grow-1">@translator.Translate(userLanguage, "Total")</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr class="d-flex">
|
||||||
|
<td class="col-3 flex-grow-1">@translator.Translate(userLanguage, "Service Records")</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.ServiceRecordPerDay == default ? "---" : Model.ServiceRecordPerDay.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.ServiceRecordPerMile == default ? "---" :Model.ServiceRecordPerMile.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.ServiceRecordSum == default ? "---" :Model.ServiceRecordSum.ToString("C2"))</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="d-flex">
|
||||||
|
<td class="col-3 flex-grow-1">@translator.Translate(userLanguage, "Repairs")</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.CollisionRecordPerDay == default ? "---" :Model.CollisionRecordPerDay.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.CollisionRecordPerMile == default ? "---" :Model.CollisionRecordPerMile.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.CollisionRecordSum == default ? "---" :Model.CollisionRecordSum.ToString("C2"))</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="d-flex">
|
||||||
|
<td class="col-3 flex-grow-1">@translator.Translate(userLanguage, "Upgrades")</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.UpgradeRecordPerDay == default ? "---" :Model.UpgradeRecordPerDay.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.UpgradeRecordPerMile == default ? "---" :Model.UpgradeRecordPerMile.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.UpgradeRecordSum == default ? "---" :Model.UpgradeRecordSum.ToString("C2"))</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="d-flex">
|
||||||
|
<td class="col-3 flex-grow-1">@translator.Translate(userLanguage, "Fuel")</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.GasRecordPerDay == default ? "---" :Model.GasRecordPerDay.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.GasRecordPerMile == default ? "---" :Model.GasRecordPerMile.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.GasRecordSum == default ? "---" :Model.GasRecordSum.ToString("C2"))</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="d-flex">
|
||||||
|
<td class="col-3 flex-grow-1">@translator.Translate(userLanguage, "Taxes")</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.TaxRecordPerDay == default ? "---" :Model.TaxRecordPerDay.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.TaxRecordPerMile == default ? "---" : Model.TaxRecordPerMile.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.TaxRecordSum == default ? "---" :Model.TaxRecordSum.ToString("C2"))</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="d-flex">
|
||||||
|
<td class="col-3 flex-grow-1">@translator.Translate(userLanguage, "Total")</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.TotalPerDay == default ? "---" : Model.TotalPerDay.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.TotalPerMile == default ? "---" : Model.TotalPerMile.ToString("C2"))</td>
|
||||||
|
<td class="col-3 flex-grow-1">@(hideZero && Model.TotalCost == default ? "---" : Model.TotalCost.ToString("C2"))</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="text-center">
|
||||||
|
<h4>@translator.Translate(userLanguage, "No data found or all records have zero sums, insert records with non-zero sums to see visualizations here.")</h4>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
23
Views/Vehicle/_FilesToUpload.cshtml
Normal file
23
Views/Vehicle/_FilesToUpload.cshtml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
@using CarCareTracker.Helper
|
||||||
|
@inject IConfigHelper config
|
||||||
|
@inject ITranslationHelper translator
|
||||||
|
@{
|
||||||
|
var userConfig = config.GetUserConfig(User);
|
||||||
|
var userLanguage = userConfig.UserLanguage;
|
||||||
|
}
|
||||||
|
@model List<UploadedFiles>
|
||||||
|
<label id="documentsPendingUploadLabel">@translator.Translate(userLanguage, "Documents Pending Upload")</label>
|
||||||
|
<ul class="list-group" id="documentsPendingUploadList">
|
||||||
|
@foreach (UploadedFiles filesUploaded in Model)
|
||||||
|
{
|
||||||
|
<li class="list-group-item">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<a type="button" class="btn btn-link text-truncate uploadedFileName" href="@filesUploaded.Location" target="_blank">@filesUploaded.Name</a>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary me-2" onclick="editFileName('@filesUploaded.Location', this)"><i class="bi bi-pencil"></i></button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-danger" onclick="deleteFileFromUploadedFiles('@filesUploaded.Location', this)"><i class="bi bi-trash"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
@@ -190,7 +190,7 @@
|
|||||||
{
|
{
|
||||||
<tr class="d-flex user-select-none" style="cursor:pointer;" onmouseup="stopEvent()" ontouchstart="detectRowLongTouch(this)" ontouchend="detectRowTouchEndPremature(this)" data-rowId="@gasRecord.Id" oncontextmenu="showTableContextMenu(this)" onmousemove="rangeMouseMove(this)" onclick="handleTableRowClick(this, showEditGasRecordModal,@gasRecord.Id)" data-tags='@string.Join(" ", gasRecord.Tags)'>
|
<tr class="d-flex user-select-none" style="cursor:pointer;" onmouseup="stopEvent()" ontouchstart="detectRowLongTouch(this)" ontouchend="detectRowTouchEndPremature(this)" data-rowId="@gasRecord.Id" oncontextmenu="showTableContextMenu(this)" onmousemove="rangeMouseMove(this)" onclick="handleTableRowClick(this, showEditGasRecordModal,@gasRecord.Id)" data-tags='@string.Join(" ", gasRecord.Tags)'>
|
||||||
<td class="col-2 flex-grow-1" data-column="daterefueled">@gasRecord.Date</td>
|
<td class="col-2 flex-grow-1" data-column="daterefueled">@gasRecord.Date</td>
|
||||||
<td class="col-2 flex-grow-1 flex-shrink-1" data-column="odometer" data-gas-type="mileage" data-gas-aggregate="@gasRecord.DeltaMileage" data-gas-original="@gasRecord.Mileage">@gasRecord.Mileage</td>
|
<td class="col-2 flex-grow-1 flex-shrink-1" data-column="odometer" data-gas-type="mileage" data-gas-aggregate="@gasRecord.DeltaMileage" data-gas-original="@gasRecord.Mileage">@(gasRecord.Mileage == default ? "---" : gasRecord.Mileage.ToString())</td>
|
||||||
<td class="col-1 flex-grow-1 flex-shrink-1" data-column="delta">@(gasRecord.DeltaMileage == default ? "---" : gasRecord.DeltaMileage)</td>
|
<td class="col-1 flex-grow-1 flex-shrink-1" data-column="delta">@(gasRecord.DeltaMileage == default ? "---" : gasRecord.DeltaMileage)</td>
|
||||||
<td class="col-2 flex-grow-1 flex-shrink-1" data-column="consumption" data-gas-type="consumption" data-gas-aggregate="@gasRecord.Gallons">@gasRecord.Gallons.ToString("F")</td>
|
<td class="col-2 flex-grow-1 flex-shrink-1" data-column="consumption" data-gas-type="consumption" data-gas-aggregate="@gasRecord.Gallons">@gasRecord.Gallons.ToString("F")</td>
|
||||||
<td class="col-3 flex-grow-1 flex-shrink-1" data-column="fueleconomy" data-gas-type="fueleconomy" data-aggregated='@(gasRecord.IncludeInAverage.ToString().ToLower())'>@(gasRecord.MilesPerGallon == 0 ? "---" : gasRecord.MilesPerGallon.ToString("F"))</td>
|
<td class="col-3 flex-grow-1 flex-shrink-1" data-column="fueleconomy" data-gas-type="fueleconomy" data-aggregated='@(gasRecord.IncludeInAverage.ToString().ToLower())'>@(gasRecord.MilesPerGallon == 0 ? "---" : gasRecord.MilesPerGallon.ToString("F"))</td>
|
||||||
@@ -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>
|
<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)
|
@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>
|
</tr>
|
||||||
}
|
}
|
||||||
@@ -209,7 +221,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" data-bs-focus="false" id="gasRecordModal" tabindex="-1" role="dialog" aria-hidden="true">
|
<div class="modal fade" data-bs-focus="false" id="gasRecordModal" tabindex="-1" role="dialog" aria-hidden="true" onpaste="handleModalPaste(event, 'gasRecordFiles')">
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
<div class="modal-content" id="gasRecordModalContent">
|
<div class="modal-content" id="gasRecordModalContent">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,27 +17,27 @@
|
|||||||
consumptionUnit = "kWh";
|
consumptionUnit = "kWh";
|
||||||
} else if (useUKMPG)
|
} else if (useUKMPG)
|
||||||
{
|
{
|
||||||
consumptionUnit = "liters";
|
consumptionUnit = @translator.Translate(userLanguage, "liters");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
consumptionUnit = useMPG ? "gallons" : "liters";
|
consumptionUnit = useMPG ? @translator.Translate(userLanguage, "gallons") : @translator.Translate(userLanguage, "liters");
|
||||||
}
|
}
|
||||||
if (useHours)
|
if (useHours)
|
||||||
{
|
{
|
||||||
distanceUnit = "hours";
|
distanceUnit = @translator.Translate(userLanguage, "hours");
|
||||||
}
|
}
|
||||||
else if (useUKMPG)
|
else if (useUKMPG)
|
||||||
{
|
{
|
||||||
distanceUnit = "miles";
|
distanceUnit = @translator.Translate(userLanguage, "miles");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
distanceUnit = useMPG ? "miles" : "kilometers";
|
distanceUnit = useMPG ? @translator.Translate(userLanguage, "miles") : @translator.Translate(userLanguage, "kilometers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
<div class="modal-header">
|
<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>
|
<button type="button" class="btn-close" onclick="hideAddGasRecordModal()" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@@ -52,7 +52,15 @@
|
|||||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<label for="gasRecordMileage">@($"{translator.Translate(userLanguage,"Odometer Reading")}({distanceUnit})")</label>
|
<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 == default ? "" : Model.GasRecord.Mileage)">
|
||||||
|
@if (isNew)
|
||||||
|
{
|
||||||
|
<div class="input-group-text">
|
||||||
|
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('gasRecordMileage')"><i class="bi bi-plus"></i></button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
<label for="gasRecordGallons">@($"{translator.Translate(userLanguage, "Fuel Consumption")}({consumptionUnit})")</label>
|
<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)">
|
<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">
|
<div class="form-check form-switch">
|
||||||
@@ -113,6 +121,7 @@
|
|||||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="gasRecordFiles">
|
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="gasRecordFiles">
|
||||||
<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 id="filesPendingUpload"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
34
Views/Vehicle/_GlobalSearchResult.cshtml
Normal file
34
Views/Vehicle/_GlobalSearchResult.cshtml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
@using CarCareTracker.Helper
|
||||||
|
@inject IConfigHelper config
|
||||||
|
@inject ITranslationHelper translator
|
||||||
|
@model List<SearchResult>
|
||||||
|
@{
|
||||||
|
var userConfig = config.GetUserConfig(User);
|
||||||
|
var userLanguage = userConfig.UserLanguage;
|
||||||
|
}
|
||||||
|
<div style="max-height:50vh; overflow-y:auto;">
|
||||||
|
@if (Model.Any())
|
||||||
|
{
|
||||||
|
@foreach (SearchResult result in Model)
|
||||||
|
{
|
||||||
|
<div class="row border p-2 m-1" onclick="loadGlobalSearchResult(@result.Id, '@result.RecordType')" style="cursor:pointer;">
|
||||||
|
<div class="col-1">
|
||||||
|
<i class="bi @StaticHelper.GetImportModeIcon(result.RecordType)"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col-11">
|
||||||
|
@result.Description
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
<div class="row border p-2 m-1">
|
||||||
|
<div class="col-1">
|
||||||
|
<i class="bi bi-ban"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col-11">
|
||||||
|
@translator.Translate(userLanguage, "No Data Found")
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
var userLanguage = userConfig.UserLanguage;
|
var userLanguage = userConfig.UserLanguage;
|
||||||
}
|
}
|
||||||
<div class="modal-header">
|
<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>
|
<button type="button" class="btn-close" onclick="hideAddNoteModal()" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@@ -45,6 +45,7 @@
|
|||||||
<br />
|
<br />
|
||||||
<small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
|
<small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
|
||||||
}
|
}
|
||||||
|
<div id="filesPendingUpload"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<label for="noteRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
|
<label for="noteRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" data-bs-focus="false" id="noteModal" tabindex="-1" role="dialog" aria-hidden="true">
|
<div class="modal fade" data-bs-focus="false" id="noteModal" tabindex="-1" role="dialog" aria-hidden="true" onpaste="handleModalPaste(event, 'noteFiles')">
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<div class="modal-content" id="noteModalContent">
|
<div class="modal-content" id="noteModalContent">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
var userLanguage = userConfig.UserLanguage;
|
var userLanguage = userConfig.UserLanguage;
|
||||||
}
|
}
|
||||||
<div class="modal-header">
|
<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>
|
<button type="button" class="btn-close" onclick="hideAddOdometerRecordModal()" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@@ -23,9 +23,25 @@
|
|||||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<label for="initialOdometerRecordMileage">@translator.Translate(userLanguage, "Initial Odometer")</label>
|
<label for="initialOdometerRecordMileage">@translator.Translate(userLanguage, "Initial Odometer")</label>
|
||||||
<input type="number" inputmode="numeric" id="initialOdometerRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Initial Odometer reading")" value="@(Model.InitialMileage)">
|
<div class="input-group">
|
||||||
|
<input type="number" inputmode="numeric" id="initialOdometerRecordMileage" @(Model.InitialMileage != default ? "disabled" : "") class="form-control" placeholder="@translator.Translate(userLanguage,"Initial Odometer reading")" value="@(Model.InitialMileage)">
|
||||||
|
@if (Model.InitialMileage != default)
|
||||||
|
{
|
||||||
|
<div class="input-group-text">
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary zero-y-padding" onclick="toggleInitialOdometerEnabled()"><i class="bi bi-pencil"></i></button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
<label for="odometerRecordMileage">@translator.Translate(userLanguage,"Odometer")</label>
|
<label for="odometerRecordMileage">@translator.Translate(userLanguage,"Odometer")</label>
|
||||||
<input type="number" inputmode="numeric" id="odometerRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading")" value="@(isNew ? "" : Model.Mileage)">
|
<div class="input-group">
|
||||||
|
<input type="number" inputmode="numeric" id="odometerRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading")" value="@(isNew ? "" : Model.Mileage)">
|
||||||
|
@if (isNew)
|
||||||
|
{
|
||||||
|
<div class="input-group-text">
|
||||||
|
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('odometerRecordMileage')"><i class="bi bi-plus"></i></button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
<label for="odometerRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
|
<label for="odometerRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
|
||||||
<select multiple class="form-select" id="odometerRecordTag">
|
<select multiple class="form-select" id="odometerRecordTag">
|
||||||
@foreach (string tag in Model.Tags)
|
@foreach (string tag in Model.Tags)
|
||||||
@@ -60,6 +76,7 @@
|
|||||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="odometerRecordFiles">
|
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="odometerRecordFiles">
|
||||||
<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 id="filesPendingUpload"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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>
|
<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)
|
@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>
|
</tr>
|
||||||
}
|
}
|
||||||
@@ -139,7 +151,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" data-bs-focus="false" id="odometerRecordModal" tabindex="-1" role="dialog" aria-hidden="true">
|
<div class="modal fade" data-bs-focus="false" id="odometerRecordModal" tabindex="-1" role="dialog" aria-hidden="true" onpaste="handleModalPaste(event, 'odometerRecordFiles')">
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
<div class="modal-content" id="odometerRecordModalContent">
|
<div class="modal-content" id="odometerRecordModalContent">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@model PlanRecord
|
@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="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-lg-8 text-truncate">
|
<div class="col-12 col-lg-8 text-truncate">
|
||||||
@@ -18,36 +18,36 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
@if (Model.ReminderRecordId != default)
|
@if (Model.ReminderRecordId != default)
|
||||||
{
|
{
|
||||||
<div class="col-4 col-md-1">
|
<div class="col-3 col-md-1">
|
||||||
<i class="bi bi-bell"></i>
|
<span class="badge text-bg-light planner-indicator"><i class="bi bi-bell-fill text-warning"></i></span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div class="@(Model.ReminderRecordId != default ? "col-4" : "col-6") col-md-1">
|
<div class="@(Model.ReminderRecordId != default ? "col-3" : "col-6") col-md-1">
|
||||||
@if (Model.ImportMode == ImportMode.ServiceRecord)
|
@if (Model.ImportMode == ImportMode.ServiceRecord)
|
||||||
{
|
{
|
||||||
<i class="bi bi-card-checklist"></i>
|
<span class="badge text-bg-primary planner-indicator"><i class="bi bi-card-checklist text-white"></i></span>
|
||||||
}
|
}
|
||||||
else if (Model.ImportMode == ImportMode.UpgradeRecord)
|
else if (Model.ImportMode == ImportMode.UpgradeRecord)
|
||||||
{
|
{
|
||||||
<i class="bi bi-wrench-adjustable"></i>
|
<span class="badge text-bg-success planner-indicator"><i class="bi bi-wrench-adjustable text-white"></i></span>
|
||||||
}
|
}
|
||||||
else if (Model.ImportMode == ImportMode.RepairRecord)
|
else if (Model.ImportMode == ImportMode.RepairRecord)
|
||||||
{
|
{
|
||||||
<i class="bi bi-exclamation-octagon"></i>
|
<span class="badge text-bg-warning planner-indicator"><i class="bi bi-exclamation-octagon text-white"></i></span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="@(Model.ReminderRecordId != default ? "col-4" : "col-6") col-md-1">
|
<div class="@(Model.ReminderRecordId != default ? "col-3" : "col-6") col-md-1">
|
||||||
@if (Model.Priority == PlanPriority.Critical)
|
@if (Model.Priority == PlanPriority.Critical)
|
||||||
{
|
{
|
||||||
<i class="bi bi-fire"></i>
|
<span class="badge text-bg-danger planner-indicator"><i class="bi bi-fire text-white"></i></span>
|
||||||
}
|
}
|
||||||
else if (Model.Priority == PlanPriority.Normal)
|
else if (Model.Priority == PlanPriority.Normal)
|
||||||
{
|
{
|
||||||
<i class="bi bi-water"></i>
|
<span class="badge text-bg-primary planner-indicator"><i class="bi bi-water text-white"></i></span>
|
||||||
}
|
}
|
||||||
else if (Model.Priority == PlanPriority.Low)
|
else if (Model.Priority == PlanPriority.Low)
|
||||||
{
|
{
|
||||||
<i class="bi bi-snow"></i>
|
<span class="badge text-bg-info planner-indicator"><i class="bi bi-snow text-white"></i></span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
var userLanguage = userConfig.UserLanguage;
|
var userLanguage = userConfig.UserLanguage;
|
||||||
}
|
}
|
||||||
<div class="modal-header">
|
<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>
|
<button type="button" class="btn-close" onclick="hideAddPlanRecordModal()" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@@ -73,10 +73,9 @@
|
|||||||
{
|
{
|
||||||
<label for="planRecordFiles">@translator.Translate(userLanguage, "Upload documents(optional)")</label>
|
<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">
|
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="planRecordFiles">
|
||||||
<br />
|
<br /><small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
|
||||||
|
|
||||||
<small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
|
|
||||||
}
|
}
|
||||||
|
<div id="filesPendingUpload"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -101,10 +100,6 @@
|
|||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a class="dropdown-item" href="#" onclick="savePlanRecordTemplate()">@translator.Translate(userLanguage, "Save as Template")</a></li>
|
<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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -117,6 +112,7 @@
|
|||||||
<script>
|
<script>
|
||||||
var uploadedFiles = [];
|
var uploadedFiles = [];
|
||||||
var selectedSupplies = [];
|
var selectedSupplies = [];
|
||||||
|
var copySuppliesAttachments = false;
|
||||||
getUploadedFilesFromModel();
|
getUploadedFilesFromModel();
|
||||||
function getUploadedFilesFromModel() {
|
function getUploadedFilesFromModel() {
|
||||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||||
@@ -129,7 +125,8 @@
|
|||||||
id: @Model.Id,
|
id: @Model.Id,
|
||||||
dateCreated: decodeHTMLEntities('@(Model.DateCreated)'),
|
dateCreated: decodeHTMLEntities('@(Model.DateCreated)'),
|
||||||
reminderRecordId: decodeHTMLEntities('@Model.ReminderRecordId'),
|
reminderRecordId: decodeHTMLEntities('@Model.ReminderRecordId'),
|
||||||
createdFromReminder: @Model.CreatedFromReminder.ToString().ToLower()
|
createdFromReminder: @Model.CreatedFromReminder.ToString().ToLower(),
|
||||||
|
isTemplate: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user