Compare commits
26 Commits
v1.4.4
...
Hargata/be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21846c8957 | ||
|
|
efa2bbf6cc | ||
|
|
66ed9ba699 | ||
|
|
e841e64f78 | ||
|
|
b0f46803c5 | ||
|
|
ac0bef5de0 | ||
|
|
08ea40a08e | ||
|
|
1d8e8059cd | ||
|
|
20b4396a4c | ||
|
|
4c39cb4d06 | ||
|
|
f58e6abd9f | ||
|
|
4f1e83a7d7 | ||
|
|
e39b38c2d5 | ||
|
|
b9ffa6ce91 | ||
|
|
76c6753785 | ||
|
|
54f5062377 | ||
|
|
7e60fd9e40 | ||
|
|
926947bae4 | ||
|
|
2652e47018 | ||
|
|
c1500b6ed0 | ||
|
|
125bc44d2e | ||
|
|
c317c0a058 | ||
|
|
beb9498399 | ||
|
|
4e74940684 | ||
|
|
c0f73080d2 | ||
|
|
cd0a35537b |
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
@@ -8,6 +8,8 @@ Ideally, the Issues tab should only consist of bug reports and feature requests
|
|||||||
## Feature Requests
|
## Feature Requests
|
||||||
Feature Requests are cool, but we do want to avoid bloat and scope/feature creep.
|
Feature Requests are cool, but we do want to avoid bloat and scope/feature creep.
|
||||||
|
|
||||||
|
Read [this](https://github.com/hargata/lubelog/wiki/Scope-and-Purpose) to better understand the scope and purpose of this project.
|
||||||
|
|
||||||
LubeLogger is a Vehicle Maintenance and Fuel Mileage Tracker.
|
LubeLogger is a Vehicle Maintenance and Fuel Mileage Tracker.
|
||||||
It is not and should not be used for the following:
|
It is not and should not be used for the following:
|
||||||
- Project Management Software(e.g.: Jira)
|
- Project Management Software(e.g.: Jira)
|
||||||
|
|||||||
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Report a bug
|
about: Report a bug
|
||||||
title: ''
|
title: "[BUG]"
|
||||||
labels: ''
|
labels: ''
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ Please make sure you have performed the following steps before opening a new bug
|
|||||||
|
|
||||||
**Platform**
|
**Platform**
|
||||||
- [ ] Docker Image
|
- [ ] Docker Image
|
||||||
- [ ] Windows Standalone Executable
|
- [ ] Windows/Linux Standalone Executable
|
||||||
|
|
||||||
**Browser Console Errors(F12)**
|
**Browser Console Errors(F12)**
|
||||||
<!-- Attach a screenshot or codeblock containing the browser console error -->
|
<!-- Attach a screenshot or codeblock containing the browser console error -->
|
||||||
|
|||||||
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: "[FEATURE REQUEST]"
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Checklist**
|
||||||
|
Please make sure you have performed the following steps before submitting a new feature request, change `[ ]` to `[x]` to mark it as done
|
||||||
|
|
||||||
|
- [ ] I have read the [Contributing Guidelines](https://github.com/hargata/lubelog/blob/main/.github/CONTRIBUTING.md) and [Scope and Purpose](https://github.com/hargata/lubelog/wiki/Scope-and-Purpose)
|
||||||
|
- [ ] I have searched through existing issues.
|
||||||
|
|
||||||
|
**Description**
|
||||||
|
<!-- Describe the feature request below this line -->
|
||||||
@@ -92,6 +92,26 @@ namespace CarCareTracker.Controllers
|
|||||||
return int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier));
|
return int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier));
|
||||||
}
|
}
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
[Route("/api/whoami")]
|
||||||
|
public IActionResult WhoAmI()
|
||||||
|
{
|
||||||
|
var result = new UserExportModel
|
||||||
|
{
|
||||||
|
Username = User.FindFirstValue(ClaimTypes.Name),
|
||||||
|
EmailAddress = User.IsInRole(nameof(UserData.IsRootUser)) ? _config.GetUserConfig(User).DefaultReminderEmail : User.FindFirstValue(ClaimTypes.Email),
|
||||||
|
IsAdmin = User.IsInRole(nameof(UserData.IsAdmin)).ToString(),
|
||||||
|
IsRoot = User.IsInRole(nameof(UserData.IsRootUser)).ToString()
|
||||||
|
};
|
||||||
|
if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant"))
|
||||||
|
{
|
||||||
|
return Json(result, StaticHelper.GetInvariantOption());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Json(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[HttpGet]
|
||||||
[Route("/api/vehicles")]
|
[Route("/api/vehicles")]
|
||||||
public IActionResult Vehicles()
|
public IActionResult Vehicles()
|
||||||
{
|
{
|
||||||
@@ -153,6 +173,210 @@ namespace CarCareTracker.Controllers
|
|||||||
return Json(convertedOdometer);
|
return Json(convertedOdometer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#region PlanRecord
|
||||||
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
|
[HttpGet]
|
||||||
|
[Route("/api/vehicle/planrecords")]
|
||||||
|
public IActionResult PlanRecords(int vehicleId)
|
||||||
|
{
|
||||||
|
if (vehicleId == default)
|
||||||
|
{
|
||||||
|
var response = OperationResponse.Failed("Must provide a valid vehicle id");
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(response);
|
||||||
|
}
|
||||||
|
var vehicleRecords = _planRecordDataAccess.GetPlanRecordsByVehicleId(vehicleId);
|
||||||
|
var result = vehicleRecords.Select(x => new PlanRecordExportModel {
|
||||||
|
Id = x.Id.ToString(),
|
||||||
|
DateCreated = x.DateCreated.ToShortDateString(),
|
||||||
|
DateModified = x.DateModified.ToShortDateString(),
|
||||||
|
Description = x.Description,
|
||||||
|
Cost = x.Cost.ToString(),
|
||||||
|
Notes = x.Notes,
|
||||||
|
Type = x.ImportMode.ToString(),
|
||||||
|
Priority = x.Priority.ToString(),
|
||||||
|
Progress = x.Progress.ToString(),
|
||||||
|
ExtraFields = x.ExtraFields,
|
||||||
|
Files = x.Files });
|
||||||
|
if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant"))
|
||||||
|
{
|
||||||
|
return Json(result, StaticHelper.GetInvariantOption());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Json(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
|
[HttpPost]
|
||||||
|
[Route("/api/vehicle/planrecords/add")]
|
||||||
|
[Consumes("application/json")]
|
||||||
|
public IActionResult AddPlanRecordJson(int vehicleId, [FromBody] PlanRecordExportModel input) => AddPlanRecord(vehicleId, input);
|
||||||
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
|
[HttpPost]
|
||||||
|
[Route("/api/vehicle/planrecords/add")]
|
||||||
|
public IActionResult AddPlanRecord(int vehicleId, PlanRecordExportModel input)
|
||||||
|
{
|
||||||
|
if (vehicleId == default)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Must provide a valid vehicle id"));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(input.Description) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Cost) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Type) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Priority) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Progress))
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, Description, Cost, Type, Priority, and Progress cannot be empty."));
|
||||||
|
}
|
||||||
|
bool validType = Enum.TryParse(input.Type, out ImportMode parsedType);
|
||||||
|
bool validPriority = Enum.TryParse(input.Priority, out PlanPriority parsedPriority);
|
||||||
|
bool validProgress = Enum.TryParse(input.Progress, out PlanProgress parsedProgress);
|
||||||
|
if (!validType || !validPriority || !validProgress)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, values for Type(ServiceRecord, RepairRecord, UpgradeRecord), Priority(Critical, Normal, Low), or Progress(Backlog, InProgress, Testing) is invalid."));
|
||||||
|
}
|
||||||
|
if (parsedType != ImportMode.ServiceRecord && parsedType != ImportMode.RepairRecord && parsedType != ImportMode.UpgradeRecord)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, Type can only ServiceRecord, RepairRecord, or UpgradeRecord"));
|
||||||
|
}
|
||||||
|
if (parsedProgress == PlanProgress.Done)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, Progress cannot be set to Done."));
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var planRecord = new PlanRecord()
|
||||||
|
{
|
||||||
|
VehicleId = vehicleId,
|
||||||
|
DateCreated = DateTime.Now,
|
||||||
|
DateModified = DateTime.Now,
|
||||||
|
Description = input.Description,
|
||||||
|
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
|
||||||
|
Cost = decimal.Parse(input.Cost),
|
||||||
|
ImportMode = parsedType,
|
||||||
|
Priority = parsedPriority,
|
||||||
|
Progress = parsedProgress,
|
||||||
|
ExtraFields = input.ExtraFields,
|
||||||
|
Files = input.Files
|
||||||
|
};
|
||||||
|
_planRecordDataAccess.SavePlanRecordToVehicle(planRecord);
|
||||||
|
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromPlanRecord(planRecord, "planrecord.add.api", User.Identity.Name));
|
||||||
|
return Json(OperationResponse.Succeed("Plan Record Added"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 500;
|
||||||
|
return Json(OperationResponse.Failed(ex.Message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[HttpDelete]
|
||||||
|
[Route("/api/vehicle/planrecords/delete")]
|
||||||
|
public IActionResult DeletePlanRecord(int id)
|
||||||
|
{
|
||||||
|
var existingRecord = _planRecordDataAccess.GetPlanRecordById(id);
|
||||||
|
if (existingRecord == null || existingRecord.Id == default)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Invalid Record Id"));
|
||||||
|
}
|
||||||
|
//security check.
|
||||||
|
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId))
|
||||||
|
{
|
||||||
|
Response.StatusCode = 401;
|
||||||
|
return Json(OperationResponse.Failed("Access Denied, you don't have access to this vehicle."));
|
||||||
|
}
|
||||||
|
//restore any requisitioned supplies.
|
||||||
|
if (existingRecord.RequisitionHistory.Any())
|
||||||
|
{
|
||||||
|
_vehicleLogic.RestoreSupplyRecordsByUsage(existingRecord.RequisitionHistory, existingRecord.Description);
|
||||||
|
}
|
||||||
|
var result = _planRecordDataAccess.DeletePlanRecordById(existingRecord.Id);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromPlanRecord(existingRecord, "planrecord.delete.api", User.Identity.Name));
|
||||||
|
}
|
||||||
|
return Json(OperationResponse.Conditional(result, "Plan Record Deleted"));
|
||||||
|
}
|
||||||
|
[HttpPut]
|
||||||
|
[Route("/api/vehicle/planrecords/update")]
|
||||||
|
[Consumes("application/json")]
|
||||||
|
public IActionResult UpdatePlanRecordJson([FromBody] PlanRecordExportModel input) => UpdatePlanRecord(input);
|
||||||
|
[HttpPut]
|
||||||
|
[Route("/api/vehicle/planrecords/update")]
|
||||||
|
public IActionResult UpdatePlanRecord(PlanRecordExportModel input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(input.Id) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Description) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Cost) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Type) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Priority) ||
|
||||||
|
string.IsNullOrWhiteSpace(input.Progress))
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, Id, Description, Cost, Type, Priority, and Progress cannot be empty."));
|
||||||
|
}
|
||||||
|
bool validType = Enum.TryParse(input.Type, out ImportMode parsedType);
|
||||||
|
bool validPriority = Enum.TryParse(input.Priority, out PlanPriority parsedPriority);
|
||||||
|
bool validProgress = Enum.TryParse(input.Progress, out PlanProgress parsedProgress);
|
||||||
|
if (!validType || !validPriority || !validProgress)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, values for Type(ServiceRecord, RepairRecord, UpgradeRecord), Priority(Critical, Normal, Low), or Progress(Backlog, InProgress, Testing) is invalid."));
|
||||||
|
}
|
||||||
|
if (parsedType != ImportMode.ServiceRecord && parsedType != ImportMode.RepairRecord && parsedType != ImportMode.UpgradeRecord)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, Type can only ServiceRecord, RepairRecord, or UpgradeRecord"));
|
||||||
|
}
|
||||||
|
if (parsedProgress == PlanProgress.Done)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Input object invalid, Progress cannot be set to Done."));
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//retrieve existing record
|
||||||
|
var existingRecord = _planRecordDataAccess.GetPlanRecordById(int.Parse(input.Id));
|
||||||
|
if (existingRecord != null && existingRecord.Id == int.Parse(input.Id))
|
||||||
|
{
|
||||||
|
//check if user has access to the vehicleId
|
||||||
|
if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId))
|
||||||
|
{
|
||||||
|
Response.StatusCode = 401;
|
||||||
|
return Json(OperationResponse.Failed("Access Denied, you don't have access to this vehicle."));
|
||||||
|
}
|
||||||
|
existingRecord.DateModified = DateTime.Now;
|
||||||
|
existingRecord.Description = input.Description;
|
||||||
|
existingRecord.Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes;
|
||||||
|
existingRecord.Cost = decimal.Parse(input.Cost);
|
||||||
|
existingRecord.ImportMode = parsedType;
|
||||||
|
existingRecord.Priority = parsedPriority;
|
||||||
|
existingRecord.Progress = parsedProgress;
|
||||||
|
existingRecord.Files = input.Files;
|
||||||
|
existingRecord.ExtraFields = input.ExtraFields;
|
||||||
|
_planRecordDataAccess.SavePlanRecordToVehicle(existingRecord);
|
||||||
|
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromPlanRecord(existingRecord, "planrecord.update.api", User.Identity.Name));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Response.StatusCode = 400;
|
||||||
|
return Json(OperationResponse.Failed("Invalid Record Id"));
|
||||||
|
}
|
||||||
|
return Json(OperationResponse.Succeed("Plan Record Updated"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 500;
|
||||||
|
return Json(OperationResponse.Failed(ex.Message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
#region ServiceRecord
|
#region ServiceRecord
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
public IActionResult Unauthorized()
|
public IActionResult Unauthorized()
|
||||||
{
|
{
|
||||||
if (!User.IsInRole("CookieAuth"))
|
if (User.IsInRole("APIAuth"))
|
||||||
{
|
{
|
||||||
Response.StatusCode = 403;
|
Response.StatusCode = 403;
|
||||||
return new EmptyResult();
|
return new EmptyResult();
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using CarCareTracker.Models;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.DataProtection;
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace CarCareTracker.Controllers
|
namespace CarCareTracker.Controllers
|
||||||
@@ -134,12 +133,10 @@ namespace CarCareTracker.Controllers
|
|||||||
if (!string.IsNullOrWhiteSpace(userJwt))
|
if (!string.IsNullOrWhiteSpace(userJwt))
|
||||||
{
|
{
|
||||||
//validate JWT token
|
//validate JWT token
|
||||||
var tokenParser = new JwtSecurityTokenHandler();
|
var jwtResult = _loginLogic.ValidateOAuthToken(userJwt);
|
||||||
var parsedToken = tokenParser.ReadJwtToken(userJwt);
|
if (jwtResult.Success && !string.IsNullOrWhiteSpace(jwtResult.EmailAddress))
|
||||||
var userEmailAddress = parsedToken.Claims.First(x => x.Type == "email").Value;
|
|
||||||
if (!string.IsNullOrWhiteSpace(userEmailAddress))
|
|
||||||
{
|
{
|
||||||
var userData = _loginLogic.ValidateOpenIDUser(new LoginModel() { EmailAddress = userEmailAddress });
|
var userData = _loginLogic.ValidateOpenIDUser(new LoginModel { EmailAddress = jwtResult.EmailAddress });
|
||||||
if (userData.Id != default)
|
if (userData.Id != default)
|
||||||
{
|
{
|
||||||
AuthCookie authCookie = new AuthCookie
|
AuthCookie authCookie = new AuthCookie
|
||||||
@@ -153,12 +150,15 @@ namespace CarCareTracker.Controllers
|
|||||||
return new RedirectResult("/Home");
|
return new RedirectResult("/Home");
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"User {userEmailAddress} tried to login via OpenID but is not a registered user in LubeLogger.");
|
_logger.LogInformation($"User {jwtResult.EmailAddress} tried to login via OpenID but is not a registered user in LubeLogger.");
|
||||||
return View("OpenIDRegistration", model: userEmailAddress);
|
return View("OpenIDRegistration", model: jwtResult.EmailAddress);
|
||||||
}
|
}
|
||||||
} else
|
} else if (jwtResult.Success)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("OpenID Provider did not provide a valid email address for the user");
|
_logger.LogInformation("OpenID Provider did not provide a valid email address for the user");
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
_logger.LogError("OpenID Token Failed Validation");
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,176 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
return PartialView("_BulkDataImporter", mode);
|
return PartialView("_BulkDataImporter", mode);
|
||||||
}
|
}
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult GenerateCsvSample(ImportMode mode)
|
||||||
|
{
|
||||||
|
string uploadDirectory = "temp/";
|
||||||
|
string uploadPath = Path.Combine(_webEnv.ContentRootPath, "data", uploadDirectory);
|
||||||
|
if (!Directory.Exists(uploadPath))
|
||||||
|
Directory.CreateDirectory(uploadPath);
|
||||||
|
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
||||||
|
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case ImportMode.ServiceRecord:
|
||||||
|
case ImportMode.RepairRecord:
|
||||||
|
case ImportMode.UpgradeRecord:
|
||||||
|
{
|
||||||
|
var exportData = new List<GenericRecordExportModel> { new GenericRecordExportModel
|
||||||
|
{
|
||||||
|
Date = DateTime.Now.ToShortDateString(),
|
||||||
|
Description = "Test",
|
||||||
|
Cost = 123.45M.ToString("C"),
|
||||||
|
Notes = "Test Note",
|
||||||
|
Odometer = 12345.ToString(),
|
||||||
|
Tags = "test1 test2"
|
||||||
|
} };
|
||||||
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
|
{
|
||||||
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
|
{
|
||||||
|
//custom writer
|
||||||
|
StaticHelper.WriteGenericRecordExportModel(csv, exportData);
|
||||||
|
}
|
||||||
|
writer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ImportMode.GasRecord:
|
||||||
|
{
|
||||||
|
var exportData = new List<GasRecordExportModel> { new GasRecordExportModel
|
||||||
|
{
|
||||||
|
Date = DateTime.Now.ToShortDateString(),
|
||||||
|
Odometer = 12345.ToString(),
|
||||||
|
FuelConsumed = 12.34M.ToString(),
|
||||||
|
Cost = 45.67M.ToString("C"),
|
||||||
|
IsFillToFull = true.ToString(),
|
||||||
|
MissedFuelUp = false.ToString(),
|
||||||
|
Notes = "Test Note",
|
||||||
|
Tags = "test1 test2"
|
||||||
|
} };
|
||||||
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
|
{
|
||||||
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
|
{
|
||||||
|
//custom writer
|
||||||
|
StaticHelper.WriteGasRecordExportModel(csv, exportData);
|
||||||
|
}
|
||||||
|
writer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ImportMode.OdometerRecord:
|
||||||
|
{
|
||||||
|
var exportData = new List<OdometerRecordExportModel> { new OdometerRecordExportModel
|
||||||
|
{
|
||||||
|
Date = DateTime.Now.ToShortDateString(),
|
||||||
|
InitialOdometer = 12345.ToString(),
|
||||||
|
Odometer = 12345.ToString(),
|
||||||
|
Notes = "Test Note",
|
||||||
|
Tags = "test1 test2"
|
||||||
|
} };
|
||||||
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
|
{
|
||||||
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
|
{
|
||||||
|
//custom writer
|
||||||
|
StaticHelper.WriteOdometerRecordExportModel(csv, exportData);
|
||||||
|
}
|
||||||
|
writer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ImportMode.TaxRecord:
|
||||||
|
{
|
||||||
|
var exportData = new List<TaxRecordExportModel> { new TaxRecordExportModel
|
||||||
|
{
|
||||||
|
Date = DateTime.Now.ToShortDateString(),
|
||||||
|
Description = "Test",
|
||||||
|
Cost = 123.45M.ToString("C"),
|
||||||
|
Notes = "Test Note",
|
||||||
|
Tags = "test1 test2"
|
||||||
|
} };
|
||||||
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
|
{
|
||||||
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
|
{
|
||||||
|
//custom writer
|
||||||
|
StaticHelper.WriteTaxRecordExportModel(csv, exportData);
|
||||||
|
}
|
||||||
|
writer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ImportMode.SupplyRecord:
|
||||||
|
{
|
||||||
|
var exportData = new List<SupplyRecordExportModel> { new SupplyRecordExportModel
|
||||||
|
{
|
||||||
|
Date = DateTime.Now.ToShortDateString(),
|
||||||
|
PartNumber = "TEST-123456",
|
||||||
|
PartSupplier = "Test Supplier",
|
||||||
|
PartQuantity = 1.5M.ToString(),
|
||||||
|
Description = "Test",
|
||||||
|
Cost = 123.45M.ToString("C"),
|
||||||
|
Notes = "Test Note",
|
||||||
|
Tags = "test1 test2"
|
||||||
|
} };
|
||||||
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
|
{
|
||||||
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
|
{
|
||||||
|
//custom writer
|
||||||
|
StaticHelper.WriteSupplyRecordExportModel(csv, exportData);
|
||||||
|
}
|
||||||
|
writer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ImportMode.PlanRecord:
|
||||||
|
{
|
||||||
|
var exportData = new List<PlanRecordExportModel> { new PlanRecordExportModel
|
||||||
|
{
|
||||||
|
DateCreated = DateTime.Now.ToString(),
|
||||||
|
DateModified = DateTime.Now.ToString(),
|
||||||
|
Description = "Test",
|
||||||
|
Type = ImportMode.RepairRecord.ToString(),
|
||||||
|
Priority = PlanPriority.Normal.ToString(),
|
||||||
|
Progress = PlanProgress.Testing.ToString(),
|
||||||
|
Cost = 123.45M.ToString("C"),
|
||||||
|
Notes = "Test Note"
|
||||||
|
} };
|
||||||
|
using (var writer = new StreamWriter(fullExportFilePath))
|
||||||
|
{
|
||||||
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||||
|
{
|
||||||
|
//custom writer
|
||||||
|
StaticHelper.WritePlanRecordExportModel(csv, exportData);
|
||||||
|
}
|
||||||
|
writer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return Json(OperationResponse.Failed("No parameters"));
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fileBytes = _fileHelper.GetFileBytes(fullExportFilePath, true);
|
||||||
|
if (fileBytes.Length > 0)
|
||||||
|
{
|
||||||
|
return File(fileBytes, "text/csv", $"{mode.ToString().ToLower()}sample.csv");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Json(OperationResponse.Failed("An error has occurred while generating CSV sample: file has zero bytes"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex.Message);
|
||||||
|
return Json(OperationResponse.Failed($"An error has occurred while generating CSV sample: {ex.Message}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
[TypeFilter(typeof(CollaboratorFilter))]
|
[TypeFilter(typeof(CollaboratorFilter))]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult ExportFromVehicleToCsv(int vehicleId, ImportMode mode)
|
public IActionResult ExportFromVehicleToCsv(int vehicleId, ImportMode mode)
|
||||||
|
|||||||
@@ -473,7 +473,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Notes = x.Notes,
|
Notes = x.Notes,
|
||||||
Cost = x.Cost,
|
Cost = x.Cost,
|
||||||
DataType = ImportMode.ServiceRecord,
|
DataType = ImportMode.ServiceRecord,
|
||||||
ExtraFields = x.ExtraFields
|
ExtraFields = x.ExtraFields,
|
||||||
|
RequisitionHistory = x.RequisitionHistory
|
||||||
}));
|
}));
|
||||||
//repair records
|
//repair records
|
||||||
reportData.AddRange(vehicleRecords.CollisionRecords.Select(x => new GenericReportModel
|
reportData.AddRange(vehicleRecords.CollisionRecords.Select(x => new GenericReportModel
|
||||||
@@ -484,7 +485,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Notes = x.Notes,
|
Notes = x.Notes,
|
||||||
Cost = x.Cost,
|
Cost = x.Cost,
|
||||||
DataType = ImportMode.RepairRecord,
|
DataType = ImportMode.RepairRecord,
|
||||||
ExtraFields = x.ExtraFields
|
ExtraFields = x.ExtraFields,
|
||||||
|
RequisitionHistory = x.RequisitionHistory
|
||||||
}));
|
}));
|
||||||
reportData.AddRange(vehicleRecords.UpgradeRecords.Select(x => new GenericReportModel
|
reportData.AddRange(vehicleRecords.UpgradeRecords.Select(x => new GenericReportModel
|
||||||
{
|
{
|
||||||
@@ -494,7 +496,8 @@ namespace CarCareTracker.Controllers
|
|||||||
Notes = x.Notes,
|
Notes = x.Notes,
|
||||||
Cost = x.Cost,
|
Cost = x.Cost,
|
||||||
DataType = ImportMode.UpgradeRecord,
|
DataType = ImportMode.UpgradeRecord,
|
||||||
ExtraFields = x.ExtraFields
|
ExtraFields = x.ExtraFields,
|
||||||
|
RequisitionHistory = x.RequisitionHistory
|
||||||
}));
|
}));
|
||||||
reportData.AddRange(vehicleRecords.TaxRecords.Select(x => new GenericReportModel
|
reportData.AddRange(vehicleRecords.TaxRecords.Select(x => new GenericReportModel
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1129,6 +1129,7 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
var existingPreference = existingUserColumnPreference.Single();
|
var existingPreference = existingUserColumnPreference.Single();
|
||||||
existingPreference.VisibleColumns = columnPreference.VisibleColumns;
|
existingPreference.VisibleColumns = columnPreference.VisibleColumns;
|
||||||
|
existingPreference.ColumnOrder = columnPreference.ColumnOrder;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace CarCareTracker.Helper
|
|||||||
public interface IFileHelper
|
public interface IFileHelper
|
||||||
{
|
{
|
||||||
string GetFullFilePath(string currentFilePath, bool mustExist = true);
|
string GetFullFilePath(string currentFilePath, bool mustExist = true);
|
||||||
|
byte[] GetFileBytes(string fullFilePath, bool deleteFile = false);
|
||||||
string MoveFileFromTemp(string currentFilePath, string newFolder);
|
string MoveFileFromTemp(string currentFilePath, string newFolder);
|
||||||
bool RenameFile(string currentFilePath, string newName);
|
bool RenameFile(string currentFilePath, string newName);
|
||||||
bool DeleteFile(string currentFilePath);
|
bool DeleteFile(string currentFilePath);
|
||||||
@@ -85,6 +86,19 @@ namespace CarCareTracker.Helper
|
|||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public byte[] GetFileBytes(string fullFilePath, bool deleteFile = false)
|
||||||
|
{
|
||||||
|
if (File.Exists(fullFilePath))
|
||||||
|
{
|
||||||
|
var fileBytes = File.ReadAllBytes(fullFilePath);
|
||||||
|
if (deleteFile)
|
||||||
|
{
|
||||||
|
File.Delete(fullFilePath);
|
||||||
|
}
|
||||||
|
return fileBytes;
|
||||||
|
}
|
||||||
|
return Array.Empty<byte>();
|
||||||
|
}
|
||||||
public bool RestoreBackup(string fileName, bool clearExisting = false)
|
public bool RestoreBackup(string fileName, bool clearExisting = false)
|
||||||
{
|
{
|
||||||
var fullFilePath = GetFullFilePath(fileName);
|
var fullFilePath = GetFullFilePath(fileName);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace CarCareTracker.Helper
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class StaticHelper
|
public static class StaticHelper
|
||||||
{
|
{
|
||||||
public const string VersionNumber = "1.4.4";
|
public const string VersionNumber = "1.4.5";
|
||||||
public const string DbName = "data/cartracker.db";
|
public const string DbName = "data/cartracker.db";
|
||||||
public const string UserConfigPath = "data/config/userConfig.json";
|
public const string UserConfigPath = "data/config/userConfig.json";
|
||||||
public const string LegacyUserConfigPath = "config/userConfig.json";
|
public const string LegacyUserConfigPath = "config/userConfig.json";
|
||||||
@@ -303,6 +303,10 @@ namespace CarCareTracker.Helper
|
|||||||
{
|
{
|
||||||
return new DateTimeOffset(date).ToUnixTimeMilliseconds();
|
return new DateTimeOffset(date).ToUnixTimeMilliseconds();
|
||||||
}
|
}
|
||||||
|
public static long GetEpochFromDateTimeSeconds(DateTime date)
|
||||||
|
{
|
||||||
|
return new DateTimeOffset(date).ToUnixTimeSeconds();
|
||||||
|
}
|
||||||
public static void InitMessage(IConfiguration config)
|
public static void InitMessage(IConfiguration config)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"LubeLogger {VersionNumber}");
|
Console.WriteLine($"LubeLogger {VersionNumber}");
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using CarCareTracker.Helper;
|
|||||||
using CarCareTracker.Models;
|
using CarCareTracker.Models;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@@ -23,6 +24,7 @@ namespace CarCareTracker.Logic
|
|||||||
OperationResponse ResetUserPassword(LoginModel credentials);
|
OperationResponse ResetUserPassword(LoginModel credentials);
|
||||||
OperationResponse SendRegistrationToken(LoginModel credentials);
|
OperationResponse SendRegistrationToken(LoginModel credentials);
|
||||||
UserData ValidateUserCredentials(LoginModel credentials);
|
UserData ValidateUserCredentials(LoginModel credentials);
|
||||||
|
JWTValidateResult ValidateOAuthToken(string jwtToken);
|
||||||
UserData ValidateOpenIDUser(LoginModel credentials);
|
UserData ValidateOpenIDUser(LoginModel credentials);
|
||||||
bool CheckIfUserIsValid(int userId);
|
bool CheckIfUserIsValid(int userId);
|
||||||
bool CreateRootUserCredentials(LoginModel credentials);
|
bool CreateRootUserCredentials(LoginModel credentials);
|
||||||
@@ -38,18 +40,20 @@ namespace CarCareTracker.Logic
|
|||||||
private readonly ITokenRecordDataAccess _tokenData;
|
private readonly ITokenRecordDataAccess _tokenData;
|
||||||
private readonly IMailHelper _mailHelper;
|
private readonly IMailHelper _mailHelper;
|
||||||
private readonly IConfigHelper _configHelper;
|
private readonly IConfigHelper _configHelper;
|
||||||
|
private readonly ILogger<LoginLogic> _logger;
|
||||||
private IMemoryCache _cache;
|
private IMemoryCache _cache;
|
||||||
public LoginLogic(IUserRecordDataAccess userData,
|
public LoginLogic(IUserRecordDataAccess userData,
|
||||||
ITokenRecordDataAccess tokenData,
|
ITokenRecordDataAccess tokenData,
|
||||||
IMailHelper mailHelper,
|
IMailHelper mailHelper,
|
||||||
IConfigHelper configHelper,
|
IConfigHelper configHelper,
|
||||||
IMemoryCache memoryCache)
|
IMemoryCache memoryCache, ILogger<LoginLogic> logger)
|
||||||
{
|
{
|
||||||
_userData = userData;
|
_userData = userData;
|
||||||
_tokenData = tokenData;
|
_tokenData = tokenData;
|
||||||
_mailHelper = mailHelper;
|
_mailHelper = mailHelper;
|
||||||
_configHelper = configHelper;
|
_configHelper = configHelper;
|
||||||
_cache = memoryCache;
|
_cache = memoryCache;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
public bool CheckIfUserIsValid(int userId)
|
public bool CheckIfUserIsValid(int userId)
|
||||||
{
|
{
|
||||||
@@ -273,6 +277,39 @@ namespace CarCareTracker.Logic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public JWTValidateResult ValidateOAuthToken(string jwtToken)
|
||||||
|
{
|
||||||
|
var jwtResult = new JWTValidateResult();
|
||||||
|
var tokenParser = new JwtSecurityTokenHandler();
|
||||||
|
var openIdConfig = _configHelper.GetOpenIDConfig();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var parsedToken = tokenParser.ReadJwtToken(jwtToken);
|
||||||
|
//Validate Token
|
||||||
|
var expiration = long.Parse(parsedToken.Claims.First(x => x.Type == "exp").Value);
|
||||||
|
var audience = parsedToken.Claims.First(x => x.Type == "aud").Value;
|
||||||
|
if (audience != openIdConfig.ClientId)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Error Validating JWT Token: mismatch audience, expecting {openIdConfig.ClientId} but received {audience}");
|
||||||
|
jwtResult.Success = false;
|
||||||
|
return jwtResult;
|
||||||
|
}
|
||||||
|
if (expiration < StaticHelper.GetEpochFromDateTimeSeconds(DateTime.Now))
|
||||||
|
{
|
||||||
|
_logger.LogError($"Error Validating JWT Token: expired token");
|
||||||
|
jwtResult.Success = false;
|
||||||
|
return jwtResult;
|
||||||
|
}
|
||||||
|
var userEmailAddress = parsedToken.Claims.First(x => x.Type == "email").Value;
|
||||||
|
jwtResult.EmailAddress = userEmailAddress;
|
||||||
|
jwtResult.Success = true;
|
||||||
|
} catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Error Validating JWT Token: {ex.Message}");
|
||||||
|
jwtResult.Success = false;
|
||||||
|
}
|
||||||
|
return jwtResult;
|
||||||
|
}
|
||||||
public UserData ValidateOpenIDUser(LoginModel credentials)
|
public UserData ValidateOpenIDUser(LoginModel credentials)
|
||||||
{
|
{
|
||||||
//validate for root user
|
//validate for root user
|
||||||
|
|||||||
@@ -58,37 +58,51 @@ namespace CarCareTracker.Middleware
|
|||||||
}
|
}
|
||||||
else if (!string.IsNullOrWhiteSpace(request_header))
|
else if (!string.IsNullOrWhiteSpace(request_header))
|
||||||
{
|
{
|
||||||
var cleanedHeader = request_header.ToString().Replace("Basic ", "").Trim();
|
bool useBearerAuth = request_header.ToString().Contains("Bearer");
|
||||||
byte[] data = Convert.FromBase64String(cleanedHeader);
|
var cleanedHeader = useBearerAuth ? request_header.ToString().Replace("Bearer ", "").Trim() : request_header.ToString().Replace("Basic ", "").Trim();
|
||||||
string decodedString = Encoding.UTF8.GetString(data);
|
var userData = new UserData();
|
||||||
var splitString = decodedString.Split(":");
|
if (useBearerAuth)
|
||||||
if (splitString.Count() != 2)
|
|
||||||
{
|
{
|
||||||
return AuthenticateResult.Fail("Invalid credentials");
|
//validate OpenID User from Bearer token
|
||||||
|
var jwtResult = _loginLogic.ValidateOAuthToken(cleanedHeader);
|
||||||
|
if (jwtResult.Success)
|
||||||
|
{
|
||||||
|
userData = _loginLogic.ValidateOpenIDUser(new LoginModel { EmailAddress = jwtResult.EmailAddress });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var userData = _loginLogic.ValidateUserCredentials(new LoginModel { UserName = splitString[0], Password = splitString[1] });
|
//perform basic auth.
|
||||||
if (userData.Id != default)
|
byte[] data = Convert.FromBase64String(cleanedHeader);
|
||||||
|
string decodedString = Encoding.UTF8.GetString(data);
|
||||||
|
var splitString = decodedString.Split(":");
|
||||||
|
if (splitString.Count() != 2)
|
||||||
{
|
{
|
||||||
var appIdentity = new ClaimsIdentity("Custom");
|
return AuthenticateResult.Fail("Invalid credentials");
|
||||||
var userIdentity = new List<Claim>
|
|
||||||
{
|
|
||||||
new(ClaimTypes.Name, splitString[0]),
|
|
||||||
new(ClaimTypes.NameIdentifier, userData.Id.ToString())
|
|
||||||
};
|
|
||||||
if (userData.IsAdmin)
|
|
||||||
{
|
|
||||||
userIdentity.Add(new(ClaimTypes.Role, nameof(UserData.IsAdmin)));
|
|
||||||
}
|
|
||||||
if (userData.IsRootUser)
|
|
||||||
{
|
|
||||||
userIdentity.Add(new(ClaimTypes.Role, nameof(UserData.IsRootUser)));
|
|
||||||
}
|
|
||||||
appIdentity.AddClaims(userIdentity);
|
|
||||||
AuthenticationTicket ticket = new AuthenticationTicket(new ClaimsPrincipal(appIdentity), Scheme.Name);
|
|
||||||
return AuthenticateResult.Success(ticket);
|
|
||||||
}
|
}
|
||||||
|
userData = _loginLogic.ValidateUserCredentials(new LoginModel { UserName = splitString[0], Password = splitString[1] });
|
||||||
|
}
|
||||||
|
if (userData.Id != default)
|
||||||
|
{
|
||||||
|
var appIdentity = new ClaimsIdentity("Custom");
|
||||||
|
var userIdentity = new List<Claim>
|
||||||
|
{
|
||||||
|
new(ClaimTypes.Name, userData.UserName),
|
||||||
|
new(ClaimTypes.NameIdentifier, userData.Id.ToString()),
|
||||||
|
new(ClaimTypes.Email, userData.EmailAddress),
|
||||||
|
new(ClaimTypes.Role, "APIAuth")
|
||||||
|
};
|
||||||
|
if (userData.IsAdmin)
|
||||||
|
{
|
||||||
|
userIdentity.Add(new(ClaimTypes.Role, nameof(UserData.IsAdmin)));
|
||||||
|
}
|
||||||
|
if (userData.IsRootUser)
|
||||||
|
{
|
||||||
|
userIdentity.Add(new(ClaimTypes.Role, nameof(UserData.IsRootUser)));
|
||||||
|
}
|
||||||
|
appIdentity.AddClaims(userIdentity);
|
||||||
|
AuthenticationTicket ticket = new AuthenticationTicket(new ClaimsPrincipal(appIdentity), Scheme.Name);
|
||||||
|
return AuthenticateResult.Success(ticket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!string.IsNullOrWhiteSpace(access_token))
|
else if (!string.IsNullOrWhiteSpace(access_token))
|
||||||
|
|||||||
8
Models/OIDC/JWTValidateResult.cs
Normal file
8
Models/OIDC/JWTValidateResult.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace CarCareTracker.Models
|
||||||
|
{
|
||||||
|
public class JWTValidateResult
|
||||||
|
{
|
||||||
|
public bool Success { get; set; }
|
||||||
|
public string EmailAddress { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,5 +13,6 @@
|
|||||||
public decimal Cost { get; set; }
|
public decimal Cost { get; set; }
|
||||||
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
|
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
|
||||||
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>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,6 @@
|
|||||||
public bool FilterByDateRange { get; set; } = false;
|
public bool FilterByDateRange { get; set; } = false;
|
||||||
public string StartDate { get; set; } = "";
|
public string StartDate { get; set; } = "";
|
||||||
public string EndDate { get; set; } = "";
|
public string EndDate { get; set; } = "";
|
||||||
|
public bool PrintIndividualRecords { get; set; } = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,14 +126,29 @@ namespace CarCareTracker.Models
|
|||||||
}
|
}
|
||||||
public class PlanRecordExportModel
|
public class PlanRecordExportModel
|
||||||
{
|
{
|
||||||
|
[JsonConverter(typeof(FromIntOptional))]
|
||||||
|
public string Id { get; set; }
|
||||||
|
[JsonConverter(typeof(FromDateOptional))]
|
||||||
public string DateCreated { get; set; }
|
public string DateCreated { get; set; }
|
||||||
|
[JsonConverter(typeof(FromDateOptional))]
|
||||||
public string DateModified { get; set; }
|
public string DateModified { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public string Notes { get; set; }
|
public string Notes { get; set; }
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
public string Priority { get; set; }
|
public string Priority { get; set; }
|
||||||
public string Progress { get; set; }
|
public string Progress { get; set; }
|
||||||
|
[JsonConverter(typeof(FromDecimalOptional))]
|
||||||
public string Cost { get; set; }
|
public string Cost { get; set; }
|
||||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||||
|
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
|
||||||
|
}
|
||||||
|
public class UserExportModel
|
||||||
|
{
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string EmailAddress { get; set; }
|
||||||
|
[JsonConverter(typeof(FromBoolOptional))]
|
||||||
|
public string IsAdmin { get; set; }
|
||||||
|
[JsonConverter(typeof(FromBoolOptional))]
|
||||||
|
public string IsRoot { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,5 +4,6 @@
|
|||||||
{
|
{
|
||||||
public ImportMode Tab { get; set; }
|
public ImportMode Tab { get; set; }
|
||||||
public List<string> VisibleColumns { get; set; } = new List<string>();
|
public List<string> VisibleColumns { get; set; } = new List<string>();
|
||||||
|
public List<string> ColumnOrder { get; set; } = new List<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,6 +26,20 @@
|
|||||||
<h6>Parameters</h6>
|
<h6>Parameters</h6>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row api-method">
|
||||||
|
<div class="col-1">
|
||||||
|
<span class="badge bg-success">GET</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable testable">
|
||||||
|
<code>/api/whoami</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Returns information for current user
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
No Params
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row api-method">
|
<div class="row api-method">
|
||||||
<div class="col-1">
|
<div class="col-1">
|
||||||
<span class="badge bg-success">GET</span>
|
<span class="badge bg-success">GET</span>
|
||||||
@@ -159,6 +173,83 @@
|
|||||||
Id - Id of Odometer Record
|
Id - Id of Odometer Record
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row api-method">
|
||||||
|
<div class="col-1">
|
||||||
|
<span class="badge bg-success">GET</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/planrecords</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Returns a list of plan records for the vehicle
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
vehicleId - Id of Vehicle
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row api-method">
|
||||||
|
<div class="col-1">
|
||||||
|
<span class="badge bg-primary">POST</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/planrecords/add</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Adds Plan Record to the vehicle
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
vehicleId - Id of Vehicle
|
||||||
|
<br />
|
||||||
|
Body(form-data): {<br />
|
||||||
|
description - Description<br />
|
||||||
|
cost - Cost<br />
|
||||||
|
type - ServiceRecord/RepairRecord/UpgradeRecord<br />
|
||||||
|
priority - Low/Normal/Critical<br />
|
||||||
|
progress - Backlog/InProgress/Testing<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 />
|
||||||
|
files - <a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover reminder-calendar-item" onclick="showAttachmentsInfo()">attachments(optional)</a><br />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row api-method">
|
||||||
|
<div class="col-1">
|
||||||
|
<span class="badge text-bg-warning">PUT</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/planrecords/update</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Updates Plan Record
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Body(form-data): {<br />
|
||||||
|
Id - Id of Plan Record<br />
|
||||||
|
description - Description<br />
|
||||||
|
cost - Cost<br />
|
||||||
|
type - ServiceRecord/RepairRecord/UpgradeRecord<br />
|
||||||
|
priority - Low/Normal/Critical<br />
|
||||||
|
progress - Backlog/InProgress/Testing<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 />
|
||||||
|
files - <a class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover reminder-calendar-item" onclick="showAttachmentsInfo()">attachments(optional)</a><br />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row api-method">
|
||||||
|
<div class="col-1">
|
||||||
|
<span class="badge text-bg-danger">DELETE</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-5 copyable">
|
||||||
|
<code>/api/vehicle/planrecords/delete</code>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Deletes Plan Record
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
Id - Id of Plan Record
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row api-method">
|
<div class="row api-method">
|
||||||
<div class="col-1">
|
<div class="col-1">
|
||||||
<span class="badge bg-success">GET</span>
|
<span class="badge bg-success">GET</span>
|
||||||
@@ -408,7 +499,7 @@
|
|||||||
<div class="col-1">
|
<div class="col-1">
|
||||||
<span class="badge bg-success">GET</span>
|
<span class="badge bg-success">GET</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-5 copyable">
|
<div class="col-5 copyable testable">
|
||||||
<code>/api/vehicle/taxrecords/check</code>
|
<code>/api/vehicle/taxrecords/check</code>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link @(Model == "settings" ? "active" : "")" id="settings-tab" data-bs-toggle="tab" data-bs-target="#settings-tab-pane" type="button" role="tab"><span class="ms-2 display-3"><i class="bi bi-gear me-2"></i>@translator.Translate(userLanguage,"Settings")</span></button>
|
<button class="nav-link @(Model == "settings" ? "active" : "")" id="settings-tab" data-bs-toggle="tab" data-bs-target="#settings-tab-pane" type="button" role="tab"><span class="ms-2 display-3"><i class="bi bi-gear me-2"></i>@translator.Translate(userLanguage,"Settings")</span></button>
|
||||||
</li>
|
</li>
|
||||||
@if (User.IsInRole("CookieAuth"))
|
@if (User.IsInRole("CookieAuth") || User.IsInRole("APIAuth"))
|
||||||
{
|
{
|
||||||
@if (User.IsInRole(nameof(UserData.IsAdmin)))
|
@if (User.IsInRole(nameof(UserData.IsAdmin)))
|
||||||
{
|
{
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
<li class="nav-item ms-auto" role="presentation">
|
<li class="nav-item ms-auto" role="presentation">
|
||||||
<button class="nav-link resizable-nav-link @(Model == "settings" ? "active" : "")" id="settings-tab" data-bs-toggle="tab" data-bs-target="#settings-tab-pane" type="button" role="tab"><i class="bi bi-gear"></i><span class="ms-2 d-sm-none d-md-inline">@translator.Translate(userLanguage, "Settings")</span></button>
|
<button class="nav-link resizable-nav-link @(Model == "settings" ? "active" : "")" id="settings-tab" data-bs-toggle="tab" data-bs-target="#settings-tab-pane" type="button" role="tab"><i class="bi bi-gear"></i><span class="ms-2 d-sm-none d-md-inline">@translator.Translate(userLanguage, "Settings")</span></button>
|
||||||
</li>
|
</li>
|
||||||
@if (User.IsInRole("CookieAuth"))
|
@if (User.IsInRole("CookieAuth") || User.IsInRole("APIAuth"))
|
||||||
{
|
{
|
||||||
<li class="nav-item dropdown" role="presentation">
|
<li class="nav-item dropdown" role="presentation">
|
||||||
<a class="nav-link resizable-nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false"><i class="bi bi-person"></i><span class="ms-2 d-sm-none d-md-inline">@User.Identity.Name</span></a>
|
<a class="nav-link resizable-nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false"><i class="bi bi-person"></i><span class="ms-2 d-sm-none d-md-inline">@User.Identity.Name</span></a>
|
||||||
|
|||||||
@@ -21,30 +21,7 @@
|
|||||||
<div class="alert alert-danger" role="alert">
|
<div class="alert alert-danger" role="alert">
|
||||||
@translator.Translate(userLanguage, "Failure to format the data correctly can cause data corruption. Please make sure you make a copy of the local database before proceeding.")
|
@translator.Translate(userLanguage, "Failure to format the data correctly can cause data corruption. Please make sure you make a copy of the local database before proceeding.")
|
||||||
</div>
|
</div>
|
||||||
@if (Model == ImportMode.GasRecord)
|
<a class="btn btn-link" href="@($"/Vehicle/GenerateCsvSample?mode={Model.ToString()}")" target="_blank">@translator.Translate(userLanguage, "Download Sample")</a>
|
||||||
{
|
|
||||||
<a class="btn btn-link" href="/defaults/gassample.csv" target="_blank">@translator.Translate(userLanguage, "Download Sample")</a>
|
|
||||||
}
|
|
||||||
else if (Model == ImportMode.ServiceRecord || Model == ImportMode.RepairRecord || Model == ImportMode.UpgradeRecord)
|
|
||||||
{
|
|
||||||
<a class="btn btn-link" href="/defaults/servicerecordsample.csv" target="_blank">@translator.Translate(userLanguage, "Download Sample")</a>
|
|
||||||
}
|
|
||||||
else if (Model == ImportMode.TaxRecord)
|
|
||||||
{
|
|
||||||
<a class="btn btn-link" href="/defaults/taxrecordsample.csv" target="_blank">@translator.Translate(userLanguage, "Download Sample")</a>
|
|
||||||
}
|
|
||||||
else if (Model == ImportMode.SupplyRecord)
|
|
||||||
{
|
|
||||||
<a class="btn btn-link" href="/defaults/supplysample.csv" target="_blank">@translator.Translate(userLanguage, "Download Sample")</a>
|
|
||||||
}
|
|
||||||
else if (Model == ImportMode.PlanRecord)
|
|
||||||
{
|
|
||||||
<a class="btn btn-link" href="/defaults/plansample.csv" target="_blank">@translator.Translate(userLanguage, "Download Sample")</a>
|
|
||||||
}
|
|
||||||
else if (Model == ImportMode.OdometerRecord)
|
|
||||||
{
|
|
||||||
<a class="btn btn-link" href="/defaults/odometersample.csv" target="_blank">@translator.Translate(userLanguage, "Download Sample")</a>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-2">
|
<div class="row mt-2">
|
||||||
|
|||||||
@@ -54,37 +54,37 @@
|
|||||||
</li>
|
</li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('RepairRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Date" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Date" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('RepairRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='odometer' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Odometer" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='odometer' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Odometer" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Odometer">@translator.Translate(userLanguage, "Odometer")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Odometer">@translator.Translate(userLanguage, "Odometer")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('RepairRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='description' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Description" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='description' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Description" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Description">@translator.Translate(userLanguage, "Description")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Description">@translator.Translate(userLanguage, "Description")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('RepairRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Cost" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Cost" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('RepairRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Attachment">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Attachment">
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('RepairRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Notes" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="chkCol_Notes" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
@foreach (string extraFieldColumn in extraFields)
|
@foreach (string extraFieldColumn in extraFields)
|
||||||
{
|
{
|
||||||
var elementId = Guid.NewGuid();
|
var elementId = Guid.NewGuid();
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('RepairRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="@elementId">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'RepairRecord')" type="checkbox" id="@elementId">
|
||||||
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
||||||
|
|||||||
@@ -104,55 +104,55 @@
|
|||||||
</li>
|
</li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('GasRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='daterefueled' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_DateRefueled" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='daterefueled' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_DateRefueled" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_DateRefueled">@translator.Translate(userLanguage, "Date Refueled")</label>
|
<label class="form-check-label stretched-link" for="chkCol_DateRefueled">@translator.Translate(userLanguage, "Date Refueled")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('GasRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='odometer' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Odometer" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='odometer' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Odometer" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Odometer">@translator.Translate(userLanguage, "Odometer")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Odometer">@translator.Translate(userLanguage, "Odometer")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('GasRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='delta' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Delta" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='delta' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Delta" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Delta">@translator.Translate(userLanguage, "Delta")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Delta">@translator.Translate(userLanguage, "Delta")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('GasRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='consumption' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Consumption" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='consumption' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Consumption" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Consumption">@translator.Translate(userLanguage, "Consumption")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Consumption">@translator.Translate(userLanguage, "Consumption")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('GasRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='fueleconomy' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_FuelEconomy" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='fueleconomy' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_FuelEconomy" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_FuelEconomy">@translator.Translate(userLanguage, "Fuel Economy")</label>
|
<label class="form-check-label stretched-link" for="chkCol_FuelEconomy">@translator.Translate(userLanguage, "Fuel Economy")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('GasRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Cost" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Cost" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('GasRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='unitcost' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_UnitCost" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='unitcost' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_UnitCost" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_UnitCost">@translator.Translate(userLanguage, "Unit Cost")</label>
|
<label class="form-check-label stretched-link" for="chkCol_UnitCost">@translator.Translate(userLanguage, "Unit Cost")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('GasRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Attachment">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Attachment">
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('GasRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Notes">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="chkCol_Notes">
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
@foreach (string extraFieldColumn in extraFields)
|
@foreach (string extraFieldColumn in extraFields)
|
||||||
{
|
{
|
||||||
var elementId = Guid.NewGuid();
|
var elementId = Guid.NewGuid();
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('GasRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="@elementId">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'GasRecord')" type="checkbox" id="@elementId">
|
||||||
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
||||||
|
|||||||
@@ -54,37 +54,37 @@
|
|||||||
</li>
|
</li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('OdometerRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_Date" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_Date" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('OdometerRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='initialodometer' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_InitialOdometer" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='initialodometer' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_InitialOdometer" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_InitialOdometer">@translator.Translate(userLanguage, "Initial Odometer")</label>
|
<label class="form-check-label stretched-link" for="chkCol_InitialOdometer">@translator.Translate(userLanguage, "Initial Odometer")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('OdometerRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='odometer' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_Odometer" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='odometer' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_Odometer" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Odometer">@translator.Translate(userLanguage, "Odometer")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Odometer">@translator.Translate(userLanguage, "Odometer")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('OdometerRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='distance' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_Distance" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='distance' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_Distance" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Distance">@translator.Translate(userLanguage, "Distance")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Distance">@translator.Translate(userLanguage, "Distance")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('OdometerRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_Attachment">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_Attachment">
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('OdometerRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_Notes" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="chkCol_Notes" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
@foreach (string extraFieldColumn in extraFields)
|
@foreach (string extraFieldColumn in extraFields)
|
||||||
{
|
{
|
||||||
var elementId = Guid.NewGuid();
|
var elementId = Guid.NewGuid();
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('OdometerRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="@elementId">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'OdometerRecord')" type="checkbox" id="@elementId">
|
||||||
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
||||||
|
|||||||
@@ -25,6 +25,14 @@
|
|||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mt-2 mb-2">
|
||||||
|
<ul class="list-group">
|
||||||
|
<li class="list-group-item text-start">
|
||||||
|
<input class="form-check-input" type="checkbox" role="switch" id="printIndividualRecordsCheck">
|
||||||
|
<label class="form-check-label" for="printIndividualRecordsCheck">@translator.Translate(userLanguage, "Print Individual Records")</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
<div class="mt-2 mb-2">
|
<div class="mt-2 mb-2">
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item text-center" style="cursor:pointer;" onclick="showReportAdvancedParameters()">
|
<li class="list-group-item text-center" style="cursor:pointer;" onclick="showReportAdvancedParameters()">
|
||||||
|
|||||||
@@ -54,37 +54,37 @@
|
|||||||
</li>
|
</li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('ServiceRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Date" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Date" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('ServiceRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='odometer' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Odometer" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='odometer' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Odometer" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Odometer">@translator.Translate(userLanguage, "Odometer")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Odometer">@translator.Translate(userLanguage, "Odometer")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('ServiceRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='description' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Description" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='description' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Description" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Description">@translator.Translate(userLanguage, "Description")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Description">@translator.Translate(userLanguage, "Description")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('ServiceRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Cost" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Cost" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('ServiceRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Attachment">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Attachment">
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('ServiceRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Notes" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="chkCol_Notes" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
@foreach (string extraFieldColumn in extraFields)
|
@foreach (string extraFieldColumn in extraFields)
|
||||||
{
|
{
|
||||||
var elementId = Guid.NewGuid();
|
var elementId = Guid.NewGuid();
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('ServiceRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="@elementId">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'ServiceRecord')" type="checkbox" id="@elementId">
|
||||||
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
||||||
|
|||||||
@@ -54,49 +54,49 @@
|
|||||||
</li>
|
</li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('SupplyRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Date" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Date" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('SupplyRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='partnumber' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_PartNumber" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='partnumber' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_PartNumber" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_PartNumber">@translator.Translate(userLanguage, "Part Number")</label>
|
<label class="form-check-label stretched-link" for="chkCol_PartNumber">@translator.Translate(userLanguage, "Part Number")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('SupplyRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='supplier' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Supplier" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='supplier' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Supplier" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Supplier">@translator.Translate(userLanguage, "Supplier")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Supplier">@translator.Translate(userLanguage, "Supplier")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('SupplyRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='description' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Description" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='description' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Description" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Description">@translator.Translate(userLanguage, "Description")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Description">@translator.Translate(userLanguage, "Description")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('SupplyRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='quantity' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Quantity" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='quantity' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Quantity" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Quantity">@translator.Translate(userLanguage, "Quantity")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Quantity">@translator.Translate(userLanguage, "Quantity")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('SupplyRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Cost" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Cost" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('SupplyRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Attachment">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Attachment">
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('SupplyRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Notes" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="chkCol_Notes" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
@foreach (string extraFieldColumn in extraFields)
|
@foreach (string extraFieldColumn in extraFields)
|
||||||
{
|
{
|
||||||
var elementId = Guid.NewGuid();
|
var elementId = Guid.NewGuid();
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('SupplyRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="@elementId">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'SupplyRecord')" type="checkbox" id="@elementId">
|
||||||
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
||||||
|
|||||||
@@ -54,31 +54,31 @@
|
|||||||
</li>
|
</li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('TaxRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="chkCol_Date" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="chkCol_Date" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('TaxRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='description' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="chkCol_Description" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='description' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="chkCol_Description" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Description">@translator.Translate(userLanguage, "Description")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Description">@translator.Translate(userLanguage, "Description")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('TaxRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="chkCol_Cost" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="chkCol_Cost" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('TaxRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="chkCol_Attachment">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="chkCol_Attachment">
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('TaxRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="chkCol_Notes" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="chkCol_Notes" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
@foreach (string extraFieldColumn in extraFields)
|
@foreach (string extraFieldColumn in extraFields)
|
||||||
{
|
{
|
||||||
var elementId = Guid.NewGuid();
|
var elementId = Guid.NewGuid();
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('TaxRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="@elementId">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'TaxRecord')" type="checkbox" id="@elementId">
|
||||||
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
||||||
|
|||||||
@@ -54,37 +54,37 @@
|
|||||||
</li>
|
</li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
<li><h6 class="dropdown-header">@translator.Translate(userLanguage, "Visible Columns")</h6></li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('UpgradeRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Date" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='date' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Date" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Date">@translator.Translate(userLanguage, "Date")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('UpgradeRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='odometer' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Odometer" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='odometer' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Odometer" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Odometer">@translator.Translate(userLanguage, "Odometer")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Odometer">@translator.Translate(userLanguage, "Odometer")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('UpgradeRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='description' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Description" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='description' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Description" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Description">@translator.Translate(userLanguage, "Description")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Description">@translator.Translate(userLanguage, "Description")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('UpgradeRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Cost" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='cost' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Cost" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Cost">@translator.Translate(userLanguage, "Cost")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('UpgradeRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Attachment">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='attachments' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Attachment">
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Attachment">@translator.Translate(userLanguage, "Attachments")</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('UpgradeRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Notes" checked>
|
<input class="form-check-input col-visible-toggle" data-column-toggle='notes' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="chkCol_Notes" checked>
|
||||||
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
<label class="form-check-label stretched-link" for="chkCol_Notes">@translator.Translate(userLanguage, "Notes")</label>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
@foreach (string extraFieldColumn in extraFields)
|
@foreach (string extraFieldColumn in extraFields)
|
||||||
{
|
{
|
||||||
var elementId = Guid.NewGuid();
|
var elementId = Guid.NewGuid();
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item" draggable="true" ondragstart="handleTableColumnDragStart(event)" ondragover="handleTableColumnDragOver(event)" ondragend="handleTableColumnDragEnd('UpgradeRecord')">
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="@elementId">
|
<input class="form-check-input col-visible-toggle" data-column-toggle='@extraFieldColumn' onChange="showTableColumns(this, 'UpgradeRecord')" type="checkbox" id="@elementId">
|
||||||
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
<label class="form-check-label stretched-link" for="@elementId">@extraFieldColumn</label>
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
@model IEnumerable<UserColumnPreference>
|
@model IEnumerable<UserColumnPreference>
|
||||||
<script>
|
<script>
|
||||||
var visibleColumns = [];
|
var visibleColumns = [];
|
||||||
|
var columnsOrder = [];
|
||||||
@foreach(string visibleColumn in Model.SelectMany(x=> x.VisibleColumns))
|
@foreach(string visibleColumn in Model.SelectMany(x=> x.VisibleColumns))
|
||||||
{
|
{
|
||||||
@:visibleColumns.push(decodeHTMLEntities('@visibleColumn'));
|
@:visibleColumns.push(decodeHTMLEntities('@visibleColumn'));
|
||||||
}
|
}
|
||||||
loadUserColumnPreferences(visibleColumns);
|
@foreach(string columnOrder in Model.SelectMany(x=>x.ColumnOrder)){
|
||||||
|
@:columnsOrder.push(decodeHTMLEntities('@columnOrder'));
|
||||||
|
}
|
||||||
|
loadUserColumnPreferences(visibleColumns, columnsOrder);
|
||||||
</script>
|
</script>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
var userLanguage = userConfig.UserLanguage;
|
var userLanguage = userConfig.UserLanguage;
|
||||||
var extraFields = Model.ReportParameters.ExtraFields;
|
var extraFields = Model.ReportParameters.ExtraFields;
|
||||||
}
|
}
|
||||||
<div>
|
<div style="page-break-after: always;">
|
||||||
<div class="row mt-2">
|
<div class="row mt-2">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<img src="@config.GetLogoUrl()" class="lubelogger-logo" />
|
<img src="@config.GetLogoUrl()" class="lubelogger-logo" />
|
||||||
@@ -18,13 +18,12 @@
|
|||||||
</span>
|
</span>
|
||||||
@if (!string.IsNullOrWhiteSpace(Model.StartDate) && !string.IsNullOrWhiteSpace(Model.EndDate))
|
@if (!string.IsNullOrWhiteSpace(Model.StartDate) && !string.IsNullOrWhiteSpace(Model.EndDate))
|
||||||
{
|
{
|
||||||
<br />
|
<br />
|
||||||
<span class="lead ms-2">
|
<span class="lead ms-2">
|
||||||
@($"{@translator.Translate(userLanguage, "From")} {Model.StartDate} {@translator.Translate(userLanguage, "To")} {Model.EndDate}")
|
@($"{@translator.Translate(userLanguage, "From")} {Model.StartDate} {@translator.Translate(userLanguage, "To")} {Model.EndDate}")
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
@@ -93,26 +92,26 @@
|
|||||||
<hr />
|
<hr />
|
||||||
@if (Model.TotalDepreciation != default)
|
@if (Model.TotalDepreciation != default)
|
||||||
{
|
{
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
@(Model.TotalDepreciation > 0 ? translator.Translate(userLanguage, "Depreciation") : translator.Translate(userLanguage, "Appreciation"))
|
@(Model.TotalDepreciation > 0 ? translator.Translate(userLanguage, "Depreciation") : translator.Translate(userLanguage, "Appreciation"))
|
||||||
</div>
|
|
||||||
<div class="col-3">
|
|
||||||
<span><i class="bi @(Model.TotalDepreciation > 0 ? "bi-graph-down-arrow" : "bi-graph-up-arrow") me-2"></i>@Math.Abs(Model.TotalDepreciation).ToString("C")</span>
|
|
||||||
</div>
|
|
||||||
@if (Model.DepreciationPerDay != default)
|
|
||||||
{
|
|
||||||
<div class="col-3">
|
|
||||||
<span><i class="bi bi-calendar-event me-2"></i>@($"{Model.DepreciationPerDay.ToString("C")}/{translator.Translate(userLanguage, "day")}")</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (Model.DepreciationPerMile != default)
|
|
||||||
{
|
|
||||||
<div class="col-3">
|
|
||||||
<span><i class="bi bi-speedometer me-2"></i>@($"{Model.DepreciationPerMile.ToString("C")}/{Model.DistanceUnit}")</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<span><i class="bi @(Model.TotalDepreciation > 0 ? "bi-graph-down-arrow" : "bi-graph-up-arrow") me-2"></i>@Math.Abs(Model.TotalDepreciation).ToString("C")</span>
|
||||||
|
</div>
|
||||||
|
@if (Model.DepreciationPerDay != default)
|
||||||
|
{
|
||||||
|
<div class="col-3">
|
||||||
|
<span><i class="bi bi-calendar-event me-2"></i>@($"{Model.DepreciationPerDay.ToString("C")}/{translator.Translate(userLanguage, "day")}")</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (Model.DepreciationPerMile != default)
|
||||||
|
{
|
||||||
|
<div class="col-3">
|
||||||
|
<span><i class="bi bi-speedometer me-2"></i>@($"{Model.DepreciationPerMile.ToString("C")}/{Model.DistanceUnit}")</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
}
|
}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -177,3 +176,113 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@if (Model.ReportParameters.PrintIndividualRecords){
|
||||||
|
@foreach (GenericReportModel genericRecord in Model.VehicleHistory)
|
||||||
|
{
|
||||||
|
<div class="d-flex flex-column recordSticker">
|
||||||
|
<div class="d-flex">
|
||||||
|
<img src="@config.GetLogoUrl()" class="lubelogger-logo" />
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<ul class="list-group">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<span class="display-6">@($"{Model.VehicleData.Year} {Model.VehicleData.Make} {Model.VehicleData.Model}")</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item">
|
||||||
|
<span class="lead">@($"{StaticHelper.GetVehicleIdentifier(Model.VehicleData)}")</span>
|
||||||
|
</li>
|
||||||
|
@foreach (ExtraField extraField in Model.VehicleData.ExtraFields)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(extraField.Value))
|
||||||
|
{
|
||||||
|
<li class="list-group-item">
|
||||||
|
<span class="lead">@($"{extraField.Name}: {extraField.Value}")</span>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<ul class="list-group">
|
||||||
|
@if (!string.IsNullOrWhiteSpace(genericRecord.Description))
|
||||||
|
{
|
||||||
|
<li class="list-group-item">
|
||||||
|
@($"{translator.Translate(userLanguage, "Description")}: {genericRecord.Description}")
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
@switch (genericRecord.DataType)
|
||||||
|
{
|
||||||
|
case ImportMode.ServiceRecord:
|
||||||
|
case ImportMode.RepairRecord:
|
||||||
|
case ImportMode.UpgradeRecord:
|
||||||
|
<li class="list-group-item">
|
||||||
|
@($"{translator.Translate(userLanguage, "Date")}: {genericRecord.Date.ToShortDateString()}")
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item">
|
||||||
|
@($"{translator.Translate(userLanguage, "Odometer")}: {genericRecord.Odometer}")
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item">
|
||||||
|
@($"{translator.Translate(userLanguage, "Cost")}: {genericRecord.Cost.ToString("C")}")
|
||||||
|
</li>
|
||||||
|
break;
|
||||||
|
case ImportMode.TaxRecord:
|
||||||
|
<li class="list-group-item">
|
||||||
|
@($"{translator.Translate(userLanguage, "Date")}: {genericRecord.Date.ToShortDateString()}")
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item">
|
||||||
|
@($"{translator.Translate(userLanguage, "Cost")}: {genericRecord.Cost.ToString("C")}")
|
||||||
|
</li>
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@foreach (ExtraField extraField in genericRecord.ExtraFields)
|
||||||
|
{
|
||||||
|
<li class="list-group-item">
|
||||||
|
@($"{extraField.Name}: {extraField.Value}")
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
@if (genericRecord.RequisitionHistory.Any())
|
||||||
|
{
|
||||||
|
<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-2">@translator.Translate(userLanguage, "Part Number")</th>
|
||||||
|
<th scope="col" class="col-6">@translator.Translate(userLanguage, "Description")</th>
|
||||||
|
<th scope="col" class="col-2">@translator.Translate(userLanguage, "Quantity")</th>
|
||||||
|
<th scope="col" class="col-2">@translator.Translate(userLanguage, "Cost")</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (SupplyUsageHistory usageHistory in genericRecord.RequisitionHistory)
|
||||||
|
{
|
||||||
|
<tr class="d-flex">
|
||||||
|
<td class="col-2 text-truncate">@usageHistory.PartNumber</td>
|
||||||
|
<td class="col-6 text-truncate">@usageHistory.Description</td>
|
||||||
|
<td class="col-2">@usageHistory.Quantity.ToString("F")</td>
|
||||||
|
<td class="col-2">@usageHistory.Cost.ToString("C2")</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
}
|
||||||
|
<div class="row flex-grow-1 flex-shrink-1">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="stickerNote ms-1 me-1 p-1">
|
||||||
|
@(genericRecord.Notes)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<script>setMarkDownStickerNotes()</script>
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,3 +0,0 @@
|
|||||||
Date,Odometer,FuelConsumed,Cost,IsFillToFull,MissedFuelUp,Notes
|
|
||||||
5/8/2020,204836,8.331,16.24,True,False,
|
|
||||||
5/30/2020,205056,11.913,25.72,True,False,
|
|
||||||
|
@@ -1,2 +0,0 @@
|
|||||||
Date,Odometer,Notes
|
|
||||||
1/1/2024,260001,test test
|
|
||||||
|
@@ -1,2 +0,0 @@
|
|||||||
DateCreated,DateModified,Description,Notes,Type,Priority,Progress,Cost
|
|
||||||
1/19/2024 6:01:02 PM,1/19/2024 7:32:58 PM,Repair Exhaust,,RepairRecord,Normal,Testing,$50.00
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
Date,Odometer,Description,Notes,Cost
|
|
||||||
01/01/2020,45000,Test Description 1,Test Note 1,20.60
|
|
||||||
01/02/2020,47000,Test Description 2,Test Note 2,40.45
|
|
||||||
|
@@ -1,2 +0,0 @@
|
|||||||
Date,PartNumber,PartSupplier,PartQuantity,Description,Cost,Notes
|
|
||||||
1/16/2024,EVA17872045551,Evan Fischer,1,Front Bumper,$95.14,Altima Activities
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
Date,Description,Notes,Cost
|
|
||||||
01/01/2020,Test Description 1,Test Note 1,20.60
|
|
||||||
01/02/2020,Test Description 2,Test Note 2,40.45
|
|
||||||
|
@@ -319,15 +319,16 @@ function updateMPGLabels() {
|
|||||||
var rowsToAggregate = $("[data-aggregated='true']").parent(":not('.override-hide')");
|
var rowsToAggregate = $("[data-aggregated='true']").parent(":not('.override-hide')");
|
||||||
var rowsUnaggregated = $("[data-aggregated='false']").parent(":not('.override-hide')");
|
var rowsUnaggregated = $("[data-aggregated='false']").parent(":not('.override-hide')");
|
||||||
var rowMPG = rowsToAggregate.children('[data-gas-type="fueleconomy"]').toArray().map(x => globalParseFloat(x.textContent));
|
var rowMPG = rowsToAggregate.children('[data-gas-type="fueleconomy"]').toArray().map(x => globalParseFloat(x.textContent));
|
||||||
|
var rowNonZeroMPG = rowMPG.filter(x => x > 0);
|
||||||
var maxMPG = rowMPG.length > 0 ? rowMPG.reduce((a, b) => a > b ? a : b) : 0;
|
var maxMPG = rowMPG.length > 0 ? rowMPG.reduce((a, b) => a > b ? a : b) : 0;
|
||||||
var minMPG = rowMPG.length > 0 ? rowMPG.filter(x=>x>0).reduce((a, b) => a < b ? a : b) : 0;
|
var minMPG = rowMPG.length > 0 && rowNonZeroMPG.length > 0 ? rowNonZeroMPG.reduce((a, b) => a < b ? a : b) : 0;
|
||||||
var totalMilesTraveled = rowMPG.length > 0 ? rowsToAggregate.children('[data-gas-type="mileage"]').toArray().map(x => globalParseFloat($(x).attr("data-gas-aggregate"))).reduce((a, b) => a + b) : 0;
|
var totalMilesTraveled = rowMPG.length > 0 ? rowsToAggregate.children('[data-gas-type="mileage"]').toArray().map(x => globalParseFloat($(x).attr("data-gas-aggregate"))).reduce((a, b) => a + b) : 0;
|
||||||
var totalGasConsumed = rowMPG.length > 0 ? rowsToAggregate.children('[data-gas-type="consumption"]').toArray().map(x => globalParseFloat(x.textContent)).reduce((a, b) => a + b) : 0;
|
var totalGasConsumed = rowMPG.length > 0 ? rowsToAggregate.children('[data-gas-type="consumption"]').toArray().map(x => globalParseFloat(x.textContent)).reduce((a, b) => a + b) : 0;
|
||||||
var totalUnaggregatedGasConsumed = rowsUnaggregated.length > 0 ? rowsUnaggregated.children('[data-gas-type="consumption"]').toArray().map(x => globalParseFloat(x.textContent)).reduce((a, b) => a + b) : 0;
|
var totalUnaggregatedGasConsumed = rowsUnaggregated.length > 0 ? rowsUnaggregated.children('[data-gas-type="consumption"]').toArray().map(x => globalParseFloat(x.textContent)).reduce((a, b) => a + b) : 0;
|
||||||
var totalMilesTraveledUnaggregated = rowsUnaggregated.length > 0 ? rowsUnaggregated.children('[data-gas-type="mileage"]').toArray().map(x => globalParseFloat($(x).attr("data-gas-aggregate"))).reduce((a, b) => a + b) : 0;
|
var totalMilesTraveledUnaggregated = rowsUnaggregated.length > 0 ? rowsUnaggregated.children('[data-gas-type="mileage"]').toArray().map(x => globalParseFloat($(x).attr("data-gas-aggregate"))).reduce((a, b) => a + b) : 0;
|
||||||
var fullGasConsumed = totalGasConsumed + totalUnaggregatedGasConsumed;
|
var fullGasConsumed = totalGasConsumed + totalUnaggregatedGasConsumed;
|
||||||
var fullDistanceTraveled = totalMilesTraveled + totalMilesTraveledUnaggregated;
|
var fullDistanceTraveled = totalMilesTraveled + totalMilesTraveledUnaggregated;
|
||||||
if (totalGasConsumed > 0) {
|
if (totalGasConsumed > 0 && rowNonZeroMPG.length > 0) {
|
||||||
var averageMPG = totalMilesTraveled / totalGasConsumed;
|
var averageMPG = totalMilesTraveled / totalGasConsumed;
|
||||||
if (!getGlobalConfig().useMPG && $("[data-gas='fueleconomy']").attr("data-unit") != 'km/l' && averageMPG > 0) {
|
if (!getGlobalConfig().useMPG && $("[data-gas='fueleconomy']").attr("data-unit") != 'km/l' && averageMPG > 0) {
|
||||||
averageMPG = 100 / averageMPG;
|
averageMPG = 100 / averageMPG;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ function getAndValidateSelectedColumns() {
|
|||||||
var tagFilterMode = $("#tagSelector").val();
|
var tagFilterMode = $("#tagSelector").val();
|
||||||
var tagsToFilter = $("#tagSelectorInput").val();
|
var tagsToFilter = $("#tagSelectorInput").val();
|
||||||
var filterByDateRange = $("#dateRangeSelector").is(":checked");
|
var filterByDateRange = $("#dateRangeSelector").is(":checked");
|
||||||
|
var printIndividualRecords = $("#printIndividualRecordsCheck").is(":checked");
|
||||||
var startDate = $("#dateRangeStartDate").val();
|
var startDate = $("#dateRangeStartDate").val();
|
||||||
var endDate = $("#dateRangeEndDate").val();
|
var endDate = $("#dateRangeEndDate").val();
|
||||||
$("#columnSelector :checked").map(function () {
|
$("#columnSelector :checked").map(function () {
|
||||||
@@ -42,7 +43,8 @@ function getAndValidateSelectedColumns() {
|
|||||||
tags: [],
|
tags: [],
|
||||||
filterByDateRange: filterByDateRange,
|
filterByDateRange: filterByDateRange,
|
||||||
startDate: '',
|
startDate: '',
|
||||||
endDate: ''
|
endDate: '',
|
||||||
|
printIndividualRecords: printIndividualRecords
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
@@ -54,7 +56,8 @@ function getAndValidateSelectedColumns() {
|
|||||||
tags: tagsToFilter,
|
tags: tagsToFilter,
|
||||||
filterByDateRange: filterByDateRange,
|
filterByDateRange: filterByDateRange,
|
||||||
startDate: startDate,
|
startDate: startDate,
|
||||||
endDate: endDate
|
endDate: endDate,
|
||||||
|
printIndividualRecords: printIndividualRecords
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,6 +83,7 @@ function getSavedReportParameters() {
|
|||||||
$("#dateRangeSelector").prop('checked', selectedReportColumns.filterByDateRange);
|
$("#dateRangeSelector").prop('checked', selectedReportColumns.filterByDateRange);
|
||||||
$("#dateRangeStartDate").val(selectedReportColumns.startDate);
|
$("#dateRangeStartDate").val(selectedReportColumns.startDate);
|
||||||
$("#dateRangeEndDate").val(selectedReportColumns.endDate);
|
$("#dateRangeEndDate").val(selectedReportColumns.endDate);
|
||||||
|
$("#printIndividualRecordsCheck").prop('checked', selectedReportColumns.printIndividualRecords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function generateVehicleHistoryReport() {
|
function generateVehicleHistoryReport() {
|
||||||
|
|||||||
@@ -1370,7 +1370,7 @@ function searchTableRows(tabName) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function loadUserColumnPreferences(columns) {
|
function loadUserColumnPreferences(columns, order) {
|
||||||
if (columns.length == 0) {
|
if (columns.length == 0) {
|
||||||
//user has no preference saved, reset to default
|
//user has no preference saved, reset to default
|
||||||
return;
|
return;
|
||||||
@@ -1387,12 +1387,35 @@ function loadUserColumnPreferences(columns) {
|
|||||||
$(`[data-column='${x}']`).show();
|
$(`[data-column='${x}']`).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
order.map((x, y) => {
|
||||||
|
//re-order items in menu
|
||||||
|
var itemToMove = $(`[data-column-toggle='${x}'].col-visible-toggle`).closest('.dropdown-item');
|
||||||
|
var itemCurrentlyInPosition = $('.dropdown-item[draggable="true"]')[y];
|
||||||
|
if (itemToMove != undefined && itemToMove.length > 0 && itemCurrentlyInPosition != undefined) {
|
||||||
|
itemToMove.insertBefore(itemCurrentlyInPosition);
|
||||||
|
}
|
||||||
|
//re-order table columns
|
||||||
|
$(`[data-column='${x}']`).css('order', y);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
function saveUserColumnPreferences(importMode) {
|
function saveUserColumnPreferences(importMode) {
|
||||||
var visibleColumns = $('.col-visible-toggle:checked').map((index, elem) => $(elem).attr('data-column-toggle')).toArray();
|
var visibleColumns = $('.col-visible-toggle:checked').map((index, elem) => $(elem).attr('data-column-toggle')).toArray();
|
||||||
|
var columnOrder = [];
|
||||||
|
var sortedOrderedColumns = $("ul.dropdown-menu > li[draggable='true']").toArray().sort((a, b) => {
|
||||||
|
var currentVal = $(a).css("order");
|
||||||
|
var nextVal = $(b).css("order");
|
||||||
|
return currentVal - nextVal;
|
||||||
|
});
|
||||||
|
sortedOrderedColumns.map(elem => {
|
||||||
|
var columnOrderName = $(elem).find('.col-visible-toggle').attr("data-column-toggle");
|
||||||
|
if (columnOrderName != null && columnOrderName != undefined) {
|
||||||
|
columnOrder.push(columnOrderName);
|
||||||
|
}
|
||||||
|
});
|
||||||
var columnPreference = {
|
var columnPreference = {
|
||||||
tab: importMode,
|
tab: importMode,
|
||||||
visibleColumns: visibleColumns
|
visibleColumns: visibleColumns,
|
||||||
|
columnOrder: columnOrder
|
||||||
};
|
};
|
||||||
$.post('/Vehicle/SaveUserColumnPreferences', { columnPreference: columnPreference }, function (data) {
|
$.post('/Vehicle/SaveUserColumnPreferences', { columnPreference: columnPreference }, function (data) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@@ -1473,3 +1496,43 @@ function togglePasswordVisibility(elem) {
|
|||||||
passwordButton.addClass('bi-eye');
|
passwordButton.addClass('bi-eye');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var tableColumnDragToReorder = undefined;
|
||||||
|
function handleTableColumnDragStart(e) {
|
||||||
|
tableColumnDragToReorder = $(e.target).closest('.dropdown-item');
|
||||||
|
//clear out order attribute.
|
||||||
|
$("ul.dropdown-menu > li[draggable='true']").map((index, elem) => {
|
||||||
|
$(elem).css('order', 0);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function handleTableColumnDragOver(e) {
|
||||||
|
if (tableColumnDragToReorder == undefined || tableColumnDragToReorder == "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var potentialDropTarget = $(e.target).closest('.list-group-item').find('.col-visible-toggle').attr("data-column-toggle");
|
||||||
|
var draggedTarget = tableColumnDragToReorder.find('.col-visible-toggle').attr("data-column-toggle");
|
||||||
|
if (draggedTarget != potentialDropTarget) {
|
||||||
|
var targetObj = $(e.target).closest('.dropdown-item');
|
||||||
|
var draggedOrder = tableColumnDragToReorder.index();
|
||||||
|
var targetOrder = targetObj.index();
|
||||||
|
if (draggedOrder < targetOrder) {
|
||||||
|
tableColumnDragToReorder.insertAfter(targetObj);
|
||||||
|
} else {
|
||||||
|
tableColumnDragToReorder.insertBefore(targetObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleTableColumnDragEnd(tabName) {
|
||||||
|
$("ul.dropdown-menu > li[draggable='true']").map((index, elem) => {
|
||||||
|
$(elem).css('order', $(elem).index());
|
||||||
|
var columnName = $(elem).find('.col-visible-toggle').attr('data-column-toggle');
|
||||||
|
$(`[data-column='${columnName}']`).css('order', $(elem).index());
|
||||||
|
});
|
||||||
|
saveUserColumnPreferences(tabName);
|
||||||
|
tableColumnDragToReorder = undefined;
|
||||||
|
if (isDragging) {
|
||||||
|
isDragging = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user