Compare commits

...

7 Commits

Author SHA1 Message Date
Hargata Softworks
3c2715840e Merge pull request #233 from hargata/Hargata/increase.upload.size
1.1.3
2024-02-05 18:29:36 -07:00
DESKTOP-GENO133\IvanPlex
dfbd90aaf4 Merge branch 'main' into Hargata/increase.upload.size
# Conflicts:
#	Views/Login/Index.cshtml
2024-02-05 18:26:14 -07:00
DESKTOP-GENO133\IvanPlex
2b3a4ce8ce more things to translate 2024-02-05 18:23:06 -07:00
DESKTOP-GENO133\IvanPlex
135292f2b4 added attachment features to Notes. 2024-02-05 18:08:54 -07:00
Hargata Softworks
499c697b0b Merge pull request #229 from hargata/Hargata/redirectURL
added redirectURL
2024-02-05 08:46:05 -07:00
DESKTOP-T0O5CDB\DESK-555BD
fb74f01609 added redirectURL 2024-02-05 08:44:49 -07:00
DESKTOP-GENO133\IvanPlex
6ab2216742 greatly increase the max upload size. 2024-02-04 15:32:34 -07:00
16 changed files with 119 additions and 32 deletions

View File

@@ -26,9 +26,9 @@ namespace CarCareTracker.Controllers
_logger = logger; _logger = logger;
_loginLogic = loginLogic; _loginLogic = loginLogic;
} }
public IActionResult Index() public IActionResult Index(string redirectURL = "")
{ {
return View(); return View(model: redirectURL);
} }
public IActionResult Registration() public IActionResult Registration()
{ {

View File

@@ -10,6 +10,7 @@ namespace CarCareTracker.Helper
UserConfig GetUserConfig(ClaimsPrincipal user); UserConfig GetUserConfig(ClaimsPrincipal user);
bool SaveUserConfig(ClaimsPrincipal user, UserConfig configData); bool SaveUserConfig(ClaimsPrincipal user, UserConfig configData);
string GetLogoUrl(); string GetLogoUrl();
string GetServerLanguage();
public bool DeleteUserConfig(int userId); public bool DeleteUserConfig(int userId);
} }
public class ConfigHelper : IConfigHelper public class ConfigHelper : IConfigHelper
@@ -34,6 +35,11 @@ namespace CarCareTracker.Helper
} }
return logoUrl; return logoUrl;
} }
public string GetServerLanguage()
{
var serverLanguage = _config[nameof(UserConfig.UserLanguage)] ?? "en_US";
return serverLanguage;
}
public bool SaveUserConfig(ClaimsPrincipal user, UserConfig configData) public bool SaveUserConfig(ClaimsPrincipal user, UserConfig configData)
{ {
var storedUserId = user.FindFirstValue(ClaimTypes.NameIdentifier); var storedUserId = user.FindFirstValue(ClaimTypes.NameIdentifier);

View File

@@ -157,7 +157,13 @@ namespace CarCareTracker.Middleware
return Task.CompletedTask; return Task.CompletedTask;
} }
} }
Response.Redirect("/Login/Index"); if (Request.Path.Value == "/Vehicle/Index" && Request.QueryString.HasValue)
{
Response.Redirect($"/Login/Index?redirectURL={Request.Path.Value}{Request.QueryString.Value}");
} else
{
Response.Redirect("/Login/Index");
}
return Task.CompletedTask; return Task.CompletedTask;
} }
protected override Task HandleForbiddenAsync(AuthenticationProperties properties) protected override Task HandleForbiddenAsync(AuthenticationProperties properties)

View File

@@ -8,5 +8,6 @@
public string NoteText { get; set; } public string NoteText { get; set; }
public bool Pinned { get; set; } public bool Pinned { get; set; }
public List<string> Tags { get; set; } = new List<string>(); public List<string> Tags { get; set; } = new List<string>();
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
} }
} }

View File

@@ -5,6 +5,8 @@ using CarCareTracker.Logic;
using CarCareTracker.Middleware; using CarCareTracker.Middleware;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@@ -55,6 +57,17 @@ builder.Services.AddAuthorization(options =>
{ {
options.DefaultPolicy = new AuthorizationPolicyBuilder().AddAuthenticationSchemes("AuthN").RequireAuthenticatedUser().Build(); options.DefaultPolicy = new AuthorizationPolicyBuilder().AddAuthenticationSchemes("AuthN").RequireAuthenticatedUser().Build();
}); });
//Configure max file upload size
builder.Services.Configure<KestrelServerOptions>(options =>
{
options.Limits.MaxRequestBodySize = int.MaxValue; // if don't set default value is: 30 MB
});
builder.Services.Configure<FormOptions>(options =>
{
options.ValueLengthLimit = int.MaxValue;
options.MultipartBodyLengthLimit = int.MaxValue; // if don't set default value is: 128 MB
options.MultipartHeadersLengthLimit = int.MaxValue;
});
var app = builder.Build(); var app = builder.Build();

View File

@@ -1,7 +1,9 @@
@using CarCareTracker.Helper @using CarCareTracker.Helper
@inject IConfigHelper config @inject IConfigHelper config
@inject ITranslationHelper translator
@{ @{
var logoUrl = config.GetLogoUrl(); var logoUrl = config.GetLogoUrl();
var userLanguage = config.GetServerLanguage();
} }
@{ @{
ViewData["Title"] = "LubeLogger - Login"; ViewData["Title"] = "LubeLogger - Login";
@@ -14,17 +16,17 @@
<div class="col-12"> <div class="col-12">
<img src="@logoUrl" /> <img src="@logoUrl" />
<div class="form-group"> <div class="form-group">
<label for="inputUserName">Username</label> <label for="inputUserName">@translator.Translate(userLanguage, "Username")</label>
<input type="text" id="inputUserName" class="form-control"> <input type="text" id="inputUserName" class="form-control">
</div> </div>
<div class="d-grid"> <div class="d-grid">
<button type="button" class="btn btn-warning mt-2" onclick="requestPasswordReset()"><i class="bi bi-box-arrow-in-right me-2"></i>Request</button> <button type="button" class="btn btn-warning mt-2" onclick="requestPasswordReset()"><i class="bi bi-box-arrow-in-right me-2"></i>@translator.Translate(userLanguage, "Request")</button>
</div> </div>
<div class="d-grid"> <div class="d-grid">
<a href="/Login/ResetPassword" class="btn btn-link mt-2">I Have a Token</a> <a href="/Login/ResetPassword" class="btn btn-link mt-2">@translator.Translate(userLanguage, "I Have a Token")</a>
</div> </div>
<div class="d-grid"> <div class="d-grid">
<a href="/Login/Index" class="btn btn-link mt-2">Back to Login</a> <a href="/Login/Index" class="btn btn-link mt-2">@translator.Translate(userLanguage, "Back to Login")</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,7 +1,10 @@
@using CarCareTracker.Helper @using CarCareTracker.Helper
@inject IConfigHelper config @inject IConfigHelper config
@inject ITranslationHelper translator
@model string
@{ @{
var logoUrl = config.GetLogoUrl(); var logoUrl = config.GetLogoUrl();
var userLanguage = config.GetServerLanguage();
} }
@{ @{
ViewData["Title"] = "LubeLogger - Login"; ViewData["Title"] = "LubeLogger - Login";
@@ -14,26 +17,31 @@
<div class="col-12"> <div class="col-12">
<img src="@logoUrl" /> <img src="@logoUrl" />
<div class="form-group"> <div class="form-group">
<label for="inputUserName">Username</label> <label for="inputUserName">@translator.Translate(userLanguage, "Username")</label>
<input type="text" id="inputUserName" class="form-control"> <input type="text" id="inputUserName" class="form-control">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="inputUserPassword">Password</label> <label for="inputUserPassword">@translator.Translate(userLanguage, "Password")</label>
<input type="password" id="inputUserPassword" onkeyup="handlePasswordKeyPress(event)" class="form-control"> <input type="password" id="inputUserPassword" onkeyup="handlePasswordKeyPress(event)" class="form-control">
</div> </div>
<div class="form-check form-switch"> <div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="inputPersistent"> <input class="form-check-input" type="checkbox" role="switch" id="inputPersistent">
<label class="form-check-label" for="inputPersistent">Remember Me</label> <label class="form-check-label" for="inputPersistent">@translator.Translate(userLanguage, "Remember Me")</label>
</div> </div>
<div class="d-grid"> <div class="d-grid">
<button type="button" class="btn btn-warning mt-2" onclick="performLogin()"><i class="bi bi-box-arrow-in-right me-2"></i>Login</button> <button type="button" class="btn btn-warning mt-2" onclick="performLogin()"><i class="bi bi-box-arrow-in-right me-2"></i>@translator.Translate(userLanguage, "Login")</button>
</div> </div>
<div class="d-grid"> <div class="d-grid">
<a href="/Login/ForgotPassword" class="btn btn-link mt-2">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"> <div class="d-grid">
<a href="/Login/Registration" class="btn btn-link mt-2">Register</a> <a href="/Login/Registration" class="btn btn-link mt-2">@translator.Translate(userLanguage, "Register")</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script>
function getRedirectURL(){
return { url: decodeHTMLEntities('@Model') };
}
</script>

View File

@@ -1,7 +1,9 @@
@using CarCareTracker.Helper @using CarCareTracker.Helper
@inject IConfigHelper config @inject IConfigHelper config
@inject ITranslationHelper translator
@{ @{
var logoUrl = config.GetLogoUrl(); var logoUrl = config.GetLogoUrl();
var userLanguage = config.GetServerLanguage();
} }
@{ @{
ViewData["Title"] = "LubeLogger - Register"; ViewData["Title"] = "LubeLogger - Register";
@@ -14,26 +16,26 @@
<div class="col-12"> <div class="col-12">
<img src="@logoUrl" /> <img src="@logoUrl" />
<div class="form-group"> <div class="form-group">
<label for="inputToken">Token</label> <label for="inputToken">@translator.Translate(userLanguage, "Token")</label>
<input type="text" id="inputToken" class="form-control"> <input type="text" id="inputToken" class="form-control">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="inputUserName">Email Address</label> <label for="inputUserName">@translator.Translate(userLanguage, "Email Address")</label>
<input type="text" id="inputEmail" class="form-control"> <input type="text" id="inputEmail" class="form-control">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="inputUserName">Username</label> <label for="inputUserName">@translator.Translate(userLanguage, "Username")</label>
<input type="text" id="inputUserName" class="form-control"> <input type="text" id="inputUserName" class="form-control">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="inputUserPassword">Password</label> <label for="inputUserPassword">@translator.Translate(userLanguage, "Password")</label>
<input type="password" id="inputUserPassword" class="form-control"> <input type="password" id="inputUserPassword" class="form-control">
</div> </div>
<div class="d-grid"> <div class="d-grid">
<button type="button" class="btn btn-warning mt-2" onclick="performRegistration()"><i class="bi bi-box-arrow-in-right me-2"></i>Register</button> <button type="button" class="btn btn-warning mt-2" onclick="performRegistration()"><i class="bi bi-box-arrow-in-right me-2"></i>@translator.Translate(userLanguage, "Register")</button>
</div> </div>
<div class="d-grid"> <div class="d-grid">
<a href="/Login/Index" class="btn btn-link mt-2">Back to Login</a> <a href="/Login/Index" class="btn btn-link mt-2">@translator.Translate(userLanguage, "Back to Login")</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,7 +1,9 @@
@using CarCareTracker.Helper @using CarCareTracker.Helper
@inject IConfigHelper config @inject IConfigHelper config
@inject ITranslationHelper translator
@{ @{
var logoUrl = config.GetLogoUrl(); var logoUrl = config.GetLogoUrl();
var userLanguage = config.GetServerLanguage();
} }
@{ @{
ViewData["Title"] = "LubeLogger - Register"; ViewData["Title"] = "LubeLogger - Register";
@@ -14,22 +16,22 @@
<div class="col-12"> <div class="col-12">
<img src="@logoUrl" /> <img src="@logoUrl" />
<div class="form-group"> <div class="form-group">
<label for="inputToken">Token</label> <label for="inputToken">@translator.Translate(userLanguage, "Token")</label>
<input type="text" id="inputToken" class="form-control"> <input type="text" id="inputToken" class="form-control">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="inputUserName">Email Address</label> <label for="inputUserName">@translator.Translate(userLanguage, "Email Address")</label>
<input type="text" id="inputEmail" class="form-control"> <input type="text" id="inputEmail" class="form-control">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="inputUserPassword">New Password</label> <label for="inputUserPassword">@translator.Translate(userLanguage, "New Password")</label>
<input type="password" id="inputUserPassword" class="form-control"> <input type="password" id="inputUserPassword" class="form-control">
</div> </div>
<div class="d-grid"> <div class="d-grid">
<button type="button" class="btn btn-warning mt-2" onclick="performPasswordReset()"><i class="bi bi-box-arrow-in-right me-2"></i>Reset Password</button> <button type="button" class="btn btn-warning mt-2" onclick="performPasswordReset()"><i class="bi bi-box-arrow-in-right me-2"></i>@translator.Translate(userLanguage, "Reset Password")</button>
</div> </div>
<div class="d-grid"> <div class="d-grid">
<a href="/Login/Index" class="btn btn-link mt-2">Back to Login</a> <a href="/Login/Index" class="btn btn-link mt-2">@translator.Translate(userLanguage, "Back to Login")</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1 +1,8 @@
<h1>Access Denied</h1> <div class="row">
<div class="col-1">
<a href="/Home" class="btn btn-secondary btn-md mt-1 mb-1"><i class="bi bi-arrow-left-square"></i></a>
</div>
<div class="col-11">
<h1>Access Denied</h1>
</div>
</div>

View File

@@ -1,6 +1,7 @@
@using CarCareTracker.Helper @using CarCareTracker.Helper
<!DOCTYPE html> <!DOCTYPE html>
@inject IConfigHelper config @inject IConfigHelper config
@inject ITranslationHelper translator
@{ @{
var userConfig = config.GetUserConfig(User); var userConfig = config.GetUserConfig(User);
var useDarkMode = userConfig.UseDarkMode; var useDarkMode = userConfig.UseDarkMode;
@@ -10,6 +11,7 @@
var useThreeDecimals = userConfig.UseThreeDecimalGasCost; var useThreeDecimals = userConfig.UseThreeDecimalGasCost;
var shortDatePattern = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern; var shortDatePattern = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
var numberFormat = System.Globalization.CultureInfo.CurrentCulture.NumberFormat; var numberFormat = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
var userLanguage = userConfig.UserLanguage;
shortDatePattern = shortDatePattern.ToLower(); shortDatePattern = shortDatePattern.ToLower();
if (!shortDatePattern.Contains("dd")) if (!shortDatePattern.Contains("dd"))
{ {
@@ -86,7 +88,7 @@
return input; return input;
} }
function genericErrorMessage(){ function genericErrorMessage(){
return "An error has occurred, please try again later"; return decodeHTMLEntities('@translator.Translate(userLanguage, "An error has occurred, please try again later")');
} }
</script> </script>
@await RenderSectionAsync("Scripts", required: false) @await RenderSectionAsync("Scripts", required: false)

View File

@@ -28,6 +28,24 @@
<label for="noteTextArea">@translator.Translate(userLanguage,"Notes")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label> <label for="noteTextArea">@translator.Translate(userLanguage,"Notes")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
<textarea class="form-control vehicleNoteContainer" id="noteTextArea">@Model.NoteText</textarea> <textarea class="form-control vehicleNoteContainer" id="noteTextArea">@Model.NoteText</textarea>
</div> </div>
<div class="col-12">
@if (Model.Files.Any())
{
<div>
@await Html.PartialAsync("_UploadedFiles", Model.Files)
<label for="serviceRecordFiles">@translator.Translate(userLanguage, "Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="noteFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
</div>
}
else
{
<label for="serviceRecordFiles">@translator.Translate(userLanguage, "Upload documents(optional)")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="noteFiles">
<br />
<small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
}
</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>
<select multiple class="form-select" id="noteRecordTag"> <select multiple class="form-select" id="noteRecordTag">
@@ -57,6 +75,14 @@
} }
</div> </div>
<script> <script>
var uploadedFiles = [];
getUploadedFilesFromModel();
function getUploadedFilesFromModel() {
@foreach (UploadedFiles filesUploaded in Model.Files)
{
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
}
}
function getNoteModelData(){ function getNoteModelData(){
return { id: @Model.Id} return { id: @Model.Id}
} }

View File

@@ -16,10 +16,15 @@
new Chart($("#donut-chart"), { new Chart($("#donut-chart"), {
type: 'doughnut', type: 'doughnut',
data: { data: {
labels: ['@translator.Translate(userLanguage,"Not Urgent")', '@translator.Translate(userLanguage,"Urgent")', '@translator.Translate(userLanguage,"Very Urgent")', '@translator.Translate(userLanguage,"Past Due")'], labels: [
decodeHTMLEntities('@translator.Translate(userLanguage, "Not Urgent")'),
decodeHTMLEntities('@translator.Translate(userLanguage, "Urgent")'),
decodeHTMLEntities('@translator.Translate(userLanguage, "Very Urgent")'),
decodeHTMLEntities('@translator.Translate(userLanguage, "Past Due")')
],
datasets: [ datasets: [
{ {
label: '@translator.Translate(userLanguage,"Reminders by Category")', label: decodeHTMLEntities('@translator.Translate(userLanguage, "Reminders by Category")'),
backgroundColor: ["#488f31", "#ffa600", "#de425b", "#cccccc"], backgroundColor: ["#488f31", "#ffa600", "#de425b", "#cccccc"],
data: [ data: [
@Model.NotUrgentCount, @Model.NotUrgentCount,
@@ -40,7 +45,7 @@
}, },
title: { title: {
display: true, display: true,
text: '@translator.Translate(userLanguage,"Reminders by Urgency")', text: decodeHTMLEntities('@translator.Translate(userLanguage, "Reminders by Urgency")'),
color: useDarkMode ? "#fff" : "#000" color: useDarkMode ? "#fff" : "#000"
}, },
} }

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,13 @@
var isPersistent = $("#inputPersistent").is(":checked"); var isPersistent = $("#inputPersistent").is(":checked");
$.post('/Login/Login', {userName: userName, password: userPassword, isPersistent: isPersistent}, function (data) { $.post('/Login/Login', {userName: userName, password: userPassword, isPersistent: isPersistent}, function (data) {
if (data) { if (data) {
window.location.href = '/Home'; //check for redirectURL
var redirectURL = getRedirectURL().url;
if (redirectURL.trim() != "") {
window.location.href = redirectURL;
} else {
window.location.href = '/Home';
}
} else { } else {
errorToast("Invalid Login Credentials, please try again."); errorToast("Invalid Login Credentials, please try again.");
} }

View File

@@ -96,6 +96,7 @@ function getAndValidateNoteValues() {
vehicleId: vehicleId, vehicleId: vehicleId,
description: noteDescription, description: noteDescription,
noteText: noteText, noteText: noteText,
files: uploadedFiles,
pinned: noteIsPinned, pinned: noteIsPinned,
tags: noteTags tags: noteTags
} }