Compare commits

...

29 Commits

Author SHA1 Message Date
Hargata Softworks
64ea0e2eee Merge pull request #533 from hargata/Hargata/532
add support for smtp clients that requires no authentication.
2024-05-31 09:11:52 -06:00
DESKTOP-T0O5CDB\DESK-555BD
7ab476a88f add support for smtp clients that requires no authentication. 2024-05-31 09:11:09 -06:00
Hargata Softworks
de41ca911d Merge pull request #530 from hargata/Hargata/527
Minor Bug Fixes
2024-05-29 09:36:56 -06:00
DESKTOP-T0O5CDB\DESK-555BD
dde9688f96 Updated supplies usage validation to allow for free supplies. 2024-05-28 14:54:12 -06:00
DESKTOP-T0O5CDB\DESK-555BD
c1ca63edc0 removed unnecessary tostring 2024-05-28 14:26:05 -06:00
DESKTOP-T0O5CDB\DESK-555BD
cbc430499f added new currency formatting function 2024-05-28 14:14:25 -06:00
DESKTOP-T0O5CDB\DESK-555BD
4da9fa4802 See 514 2024-05-28 13:55:14 -06:00
DESKTOP-T0O5CDB\DESK-555BD
42586d9556 Updated version number 2024-05-28 12:56:29 -06:00
DESKTOP-T0O5CDB\DESK-555BD
ea4387d4ab Add missing translation keys 2024-05-28 12:53:20 -06:00
Hargata Softworks
0707b515ab Merge pull request #525 from hargata/Hargata/sponsor.tiers
Updated Sponsors File Path
2024-05-21 15:42:58 -06:00
DESKTOP-T0O5CDB\DESK-555BD
78ae71fc46 Updated Sponsors File Path 2024-05-21 15:41:05 -06:00
Hargata Softworks
3f62cd40e7 Merge pull request #524 from hargata/Hargata/sponsor.tiers
Add Sponsor Section
2024-05-21 15:32:20 -06:00
DESKTOP-T0O5CDB\DESK-555BD
47657c0093 Added sponsor section. 2024-05-21 15:29:46 -06:00
Hargata Softworks
a5b0fde4b6 Merge pull request #522 from hargata/Hargata/swal.uncensored
Hargata/swal.uncensored
2024-05-20 12:26:10 -06:00
DESKTOP-T0O5CDB\DESK-555BD
78cc0b34b1 Updated version number 2024-05-20 12:25:07 -06:00
Hargata Softworks
e3017e986b Merge pull request #520 from hargata/Hargata/license.change
Removed commercial license restrictions from license.
2024-05-20 12:22:21 -06:00
DESKTOP-T0O5CDB\DESK-555BD
e12cd876db removed unused files 2024-05-20 12:21:54 -06:00
DESKTOP-T0O5CDB\DESK-555BD
5292e4b814 utilize uncensored version of sweet alert 2024-05-20 12:16:10 -06:00
DESKTOP-T0O5CDB\DESK-555BD
dbdd16ab89 Removed commercial license restrictions from license. 2024-05-14 08:46:47 -06:00
Hargata Softworks
ddc3c2e1b5 Merge pull request #503 from hargata/Hargata/null.mail.config
null check for mail config
2024-04-25 12:45:36 -06:00
DESKTOP-T0O5CDB\DESK-555BD
49184b287b null check for mail config 2024-04-25 12:45:21 -06:00
Hargata Softworks
f6139bda0d Merge pull request #502 from hargata/Hargata/mailkit.upgrade
fix inefficiencies
2024-04-25 11:33:14 -06:00
DESKTOP-T0O5CDB\DESK-555BD
a6471b823b fix inefficiencies 2024-04-25 11:11:54 -06:00
Hargata Softworks
7c34003647 Merge pull request #501 from hargata/Hargata/mailkit.upgrade
MailKit Upgrade
2024-04-25 10:46:53 -06:00
DESKTOP-T0O5CDB\DESK-555BD
1aa21f9980 Uprgade from .NET SMTPClient to MailKit as the default smtpclient does not support modern protocols. 2024-04-25 10:45:55 -06:00
Hargata Softworks
ce4ca50939 Merge pull request #499 from hargata/Hargata/persist.metric.bug
fix getyear method
2024-04-23 23:50:31 -06:00
DESKTOP-T0O5CDB\DESK-555BD
fb28260c4a fix getyear method 2024-04-23 23:50:06 -06:00
Hargata Softworks
626a904747 Merge pull request #498 from hargata/Hargata/persist.metric.bug
Minor bug fix
2024-04-23 23:43:18 -06:00
DESKTOP-T0O5CDB\DESK-555BD
893cdafdc5 Fixes a very minor bug where the persisted year metric blanks out when viewing a different car that doesn't have that specific year. 2024-04-23 23:42:09 -06:00
25 changed files with 207 additions and 10487 deletions

View File

@@ -13,6 +13,7 @@
<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="MailKit" Version="4.5.0" />
<PackageReference Include="Npgsql" Version="8.0.2" /> <PackageReference Include="Npgsql" Version="8.0.2" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" />
</ItemGroup> </ItemGroup>

View File

@@ -105,7 +105,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();
@@ -114,6 +114,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]

View File

@@ -1153,6 +1153,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++)

View File

@@ -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!" };
@@ -116,43 +119,48 @@ namespace CarCareTracker.Helper
emailBody = emailBody.Replace("{TableBody}", tableBody); emailBody = emailBody.Replace("{TableBody}", tableBody);
try try
{ {
foreach (string emailAddress in emailAddresses) SendEmail(emailAddresses, emailSubject, emailBody);
{
SendEmail(emailAddress, emailSubject, emailBody, true, true);
}
return new OperationResponse { Success = true, Message = "Email Sent!" }; 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;
} }
} }
} }

View File

@@ -8,13 +8,13 @@ namespace CarCareTracker.Helper
/// </summary> /// </summary>
public static class StaticHelper public static class StaticHelper
{ {
public static string VersionNumber = "1.3.1"; public static string VersionNumber = "1.3.4";
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)

View File

@@ -1,11 +1,6 @@
LubeLogger by Hargata Softworks is licensed under the MIT License for individual
and personal use. Commercial users and/or corporate entities are required
to maintain an active subscription in order to continue using LubeLogger.
For pricing information please contact us at hargatasoftworks@gmail.com
MIT License 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

View File

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

10
Models/Sponsors.cs Normal file
View File

@@ -0,0 +1,10 @@
namespace CarCareTracker.Models
{
public class Sponsors
{
public List<string> LifeTime { get; set; } = new List<string>();
public List<string> Bronze { get; set; } = new List<string>();
public List<string> Silver { get; set; } = new List<string>();
public List<string> Gold { get; set; } = new List<string>();
}
}

View File

@@ -30,19 +30,18 @@ Read this [Getting Started Guide](https://docs.lubelogger.com/Getting%20Started)
[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.

View File

@@ -219,7 +219,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-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> 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 +247,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">

View File

@@ -0,0 +1,73 @@
@using CarCareTracker.Helper
@model Sponsors
@inject ITranslationHelper translator
@inject IConfigHelper config
@{
var userConfig = config.GetUserConfig(User);
var enableAuth = userConfig.EnableAuth;
var userLanguage = userConfig.UserLanguage;
}
<div class="row">
<div class="d-flex justify-content-center">
<h6 class="display-6 mt-2">@translator.Translate(userLanguage, "Sponsors")</h6>
</div>
<hr />
<div class="col-12">
<div class="d-flex justify-content-center">
<p><a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover" href="https://docs.lubelogger.com/Funding" target="_blank">Become a Sponsor</a></p>
</div>
</div>
@if (Model.LifeTime.Any())
{
<div class="col-12">
<div class="d-flex justify-content-center">
<h6 class="display-7 mt-2">Lifetime</h6>
</div>
<div class="d-flex justify-content-center">
<p class="lead">
@string.Join(", ", Model.LifeTime)
</p>
</div>
</div>
}
@if (Model.Gold.Any())
{
<div class="col-12">
<div class="d-flex justify-content-center">
<h6 class="display-7 mt-2">Gold</h6>
</div>
<div class="d-flex justify-content-center">
<p class="lead">
@string.Join(", ", Model.Gold)
</p>
</div>
</div>
}
@if (Model.Silver.Any())
{
<div class="col-12">
<div class="d-flex justify-content-center">
<h6 class="display-7 mt-2">Silver</h6>
</div>
<div class="d-flex justify-content-center">
<p class="lead">
@string.Join(", ", Model.Silver)
</p>
</div>
</div>
}
@if (Model.Bronze.Any())
{
<div class="col-12">
<div class="d-flex justify-content-center">
<h6 class="display-7 mt-2">Bronze</h6>
</div>
<div class="d-flex justify-content-center">
<p class="lead">
@string.Join(", ", Model.Bronze)
</p>
</div>
</div>
}
</div>

View File

@@ -70,8 +70,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 +85,32 @@
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;
}
}
</script> </script>
@await RenderSectionAsync("Scripts", required: false) @await RenderSectionAsync("Scripts", required: false)
</head> </head>

View File

@@ -17,23 +17,23 @@
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">

View File

@@ -12,7 +12,7 @@
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<select class="form-select" id="yearOption" onchange="yearUpdated()"> <select class="form-select" id="yearOption" onchange="yearUpdated()">
<option value="0">All Time</option> <option value="0">@translator.Translate(userLanguage, "All Time")</option>
@foreach (int year in Model.Years) @foreach (int year in Model.Years)
{ {
<option value="@year">@year</option> <option value="@year">@year</option>
@@ -32,7 +32,7 @@
<div class="col-12 col-md-10"> <div class="col-12 col-md-10">
<div class="dropdown d-grid dropdown-center"> <div class="dropdown d-grid dropdown-center">
<button class="btn btn-outline-warning dropdown-toggle" type="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false"> <button class="btn btn-outline-warning dropdown-toggle" type="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
Metrics @translator.Translate(userLanguage, "Metrics")
</button> </button>
<ul class="dropdown-menu" style="width:100%;"> <ul class="dropdown-menu" style="width:100%;">
<li class="dropdown-item"> <li class="dropdown-item">

View File

@@ -110,7 +110,7 @@
var inStockQuantity = globalParseFloat(inStock.text()); var inStockQuantity = globalParseFloat(inStock.text());
var unitPrice = globalParseFloat(priceField.text()); var unitPrice = globalParseFloat(priceField.text());
//validation //validation
if (isNaN(requestedQuantity) || requestedQuantity > inStockQuantity) { if (isNaN(requestedQuantity) || requestedQuantity > inStockQuantity || requestedQuantity <= 0) {
textField.addClass("is-invalid"); textField.addClass("is-invalid");
hasError = true; hasError = true;
} else { } else {
@@ -131,7 +131,7 @@
var parsedFloat = globalFloatToString(totalSum); var parsedFloat = globalFloatToString(totalSum);
$("#supplySumLabel").text(`Total: ${parsedFloat}`); $("#supplySumLabel").text(`Total: ${parsedFloat}`);
} }
$("#selectSuppliesButton").attr('disabled', (hasError || totalSum == 0)); $("#selectSuppliesButton").attr('disabled', (hasError || selectedSupplies.toArray().length == 0));
if (!hasError) { if (!hasError) {
return { return {
totalSum: globalFloatToString(totalSum), totalSum: globalFloatToString(totalSum),

File diff suppressed because one or more lines are too long

View File

@@ -182,7 +182,7 @@ function convertGasConsumptionUnits(currentUnit, destinationUnit, save) {
$("[data-gas-type='unitcost']").map((index, elem) => { $("[data-gas-type='unitcost']").map((index, elem) => {
var convertedAmount = globalParseFloat(elem.innerText) / 3.785; var convertedAmount = globalParseFloat(elem.innerText) / 3.785;
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2; var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
elem.innerText = `${getGlobalConfig().currencySymbol}${globalFloatToString(convertedAmount.toFixed(decimalPoints))}`; elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
}); });
if (save) { setDebounce(saveUserGasTabPreferences); } if (save) { setDebounce(saveUserGasTabPreferences); }
break; break;
@@ -196,7 +196,7 @@ function convertGasConsumptionUnits(currentUnit, destinationUnit, save) {
$("[data-gas-type='unitcost']").map((index, elem) => { $("[data-gas-type='unitcost']").map((index, elem) => {
var convertedAmount = globalParseFloat(elem.innerText) * 1.201; var convertedAmount = globalParseFloat(elem.innerText) * 1.201;
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2; var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
elem.innerText = `${getGlobalConfig().currencySymbol}${globalFloatToString(convertedAmount.toFixed(decimalPoints))}`; elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
}); });
if (save) { setDebounce(saveUserGasTabPreferences); } if (save) { setDebounce(saveUserGasTabPreferences); }
break; break;
@@ -213,7 +213,7 @@ function convertGasConsumptionUnits(currentUnit, destinationUnit, save) {
$("[data-gas-type='unitcost']").map((index, elem) => { $("[data-gas-type='unitcost']").map((index, elem) => {
var convertedAmount = globalParseFloat(elem.innerText) * 3.785; var convertedAmount = globalParseFloat(elem.innerText) * 3.785;
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2; var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
elem.innerText = `${getGlobalConfig().currencySymbol}${globalFloatToString(convertedAmount.toFixed(decimalPoints))}`; elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
}); });
if (save) { setDebounce(saveUserGasTabPreferences); } if (save) { setDebounce(saveUserGasTabPreferences); }
break; break;
@@ -227,7 +227,7 @@ function convertGasConsumptionUnits(currentUnit, destinationUnit, save) {
$("[data-gas-type='unitcost']").map((index, elem) => { $("[data-gas-type='unitcost']").map((index, elem) => {
var convertedAmount = globalParseFloat(elem.innerText) * 4.546; var convertedAmount = globalParseFloat(elem.innerText) * 4.546;
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2; var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
elem.innerText = `${getGlobalConfig().currencySymbol}${globalFloatToString(convertedAmount.toFixed(decimalPoints))}`; elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
}); });
if (save) { setDebounce(saveUserGasTabPreferences); } if (save) { setDebounce(saveUserGasTabPreferences); }
break; break;
@@ -244,7 +244,7 @@ function convertGasConsumptionUnits(currentUnit, destinationUnit, save) {
$("[data-gas-type='unitcost']").map((index, elem) => { $("[data-gas-type='unitcost']").map((index, elem) => {
var convertedAmount = globalParseFloat(elem.innerText) / 1.201; var convertedAmount = globalParseFloat(elem.innerText) / 1.201;
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2; var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
elem.innerText = `${getGlobalConfig().currencySymbol}${globalFloatToString(convertedAmount.toFixed(decimalPoints))}`; elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
}); });
if (save) { setDebounce(saveUserGasTabPreferences); } if (save) { setDebounce(saveUserGasTabPreferences); }
break; break;
@@ -258,7 +258,7 @@ function convertGasConsumptionUnits(currentUnit, destinationUnit, save) {
$("[data-gas-type='unitcost']").map((index, elem) => { $("[data-gas-type='unitcost']").map((index, elem) => {
var convertedAmount = globalParseFloat(elem.innerText) / 4.546; var convertedAmount = globalParseFloat(elem.innerText) / 4.546;
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2; var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
elem.innerText = `${getGlobalConfig().currencySymbol}${globalFloatToString(convertedAmount.toFixed(decimalPoints))}`; elem.innerText = `${globalAppendCurrency(globalFloatToString(convertedAmount.toFixed(decimalPoints)))}`;
}); });
if (save) { setDebounce(saveUserGasTabPreferences); } if (save) { setDebounce(saveUserGasTabPreferences); }
break; break;

View File

@@ -1,5 +1,5 @@
function getYear() { function getYear() {
return $("#yearOption").val(); return $("#yearOption").val() ?? '0';
} }
function generateVehicleHistoryReport() { function generateVehicleHistoryReport() {
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
@@ -54,7 +54,10 @@ function getSelectedMetrics() {
if (selectedMetricCheckBoxes.length == 6) { if (selectedMetricCheckBoxes.length == 6) {
$("#selectAllExpenseCheck").prop("checked", true); $("#selectAllExpenseCheck").prop("checked", true);
} }
$('#yearOption').val(yearMetric); //check if option is available
if ($("#yearOption").has(`option[value=${yearMetric}]`).length > 0) {
$('#yearOption').val(yearMetric);
}
$("#reminderOption").val(reminderMetric); $("#reminderOption").val(reminderMetric);
//retrieve data. //retrieve data.
yearUpdated(); yearUpdated();

View File

@@ -339,7 +339,7 @@ function updateAggregateLabels() {
if (labelsToSum.length > 0) { if (labelsToSum.length > 0) {
newSum = labelsToSum.map(x => globalParseFloat(x.textContent)).reduce((a, b,) => a + b).toFixed(2); newSum = labelsToSum.map(x => globalParseFloat(x.textContent)).reduce((a, b,) => a + b).toFixed(2);
} }
sumLabel.text(`${sumLabel.text().split(':')[0]}: ${getGlobalConfig().currencySymbol}${newSum}`) sumLabel.text(`${sumLabel.text().split(':')[0]}: ${globalAppendCurrency(globalFloatToString(newSum))}`)
} }
//Sum Distance //Sum Distance
var sumDistanceLabel = $("[data-aggregate-type='sum-distance']"); var sumDistanceLabel = $("[data-aggregate-type='sum-distance']");

View File

@@ -480,9 +480,9 @@ function getRecordsDeltaStats(recordIds) {
var diffOdo = maxOdo - minOdo; var diffOdo = maxOdo - minOdo;
var diffDate = maxDate - minDate; var diffDate = maxDate - minDate;
var divisibleCount = recordIds.length - 1; var divisibleCount = recordIds.length - 1;
var averageOdo = diffOdo > 0 ? (diffOdo / divisibleCount).toFixed(2) : 0; var averageOdo = diffOdo > 0 ? (diffOdo / divisibleCount).toFixed(2) : '0';
var averageDays = diffDate > 0 ? Math.floor((diffDate / divisibleCount) / 8.64e7) : 0; var averageDays = diffDate > 0 ? Math.floor((diffDate / divisibleCount) / 8.64e7) : '0';
var averageSum = costSum > 0 ? (costSum / recordIds.length).toFixed(2) : 0; var averageSum = costSum > 0 ? (costSum / recordIds.length).toFixed(2) : '0';
costSum = costSum.toFixed(2); costSum = costSum.toFixed(2);
Swal.fire({ Swal.fire({
title: "Record Statistics", title: "Record Statistics",
@@ -490,9 +490,9 @@ function getRecordsDeltaStats(recordIds) {
<br /> <br />
<p>Average Days between Records: ${averageDays}</p> <p>Average Days between Records: ${averageDays}</p>
<br /> <br />
<p>Total Cost: ${getGlobalConfig().currencySymbol} ${globalFloatToString(costSum)}</p> <p>Total Cost: ${globalAppendCurrency(globalFloatToString(costSum))}</p>
<br /> <br />
<p>Average Cost: ${getGlobalConfig().currencySymbol} ${globalFloatToString(averageSum)}</p>` <p>Average Cost: ${globalAppendCurrency(globalFloatToString(averageSum))}</p>`
, ,
icon: "info" icon: "info"
}); });

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long