Merge pull request #363 from hargata/Hargata/record.delta.stats

Hargata/record.delta.stats
This commit is contained in:
Hargata Softworks 2024-03-03 21:10:14 -07:00 committed by GitHub
commit a18b81d52e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 75 additions and 23 deletions

View File

@ -15,6 +15,7 @@ namespace CarCareTracker.Helper
string GetServerLanguage();
bool GetServerEnableShopSupplies();
string GetServerPostgresConnection();
string GetAllowedFileUploadExtensions();
public bool DeleteUserConfig(int userId);
}
public class ConfigHelper : IConfigHelper
@ -44,6 +45,14 @@ namespace CarCareTracker.Helper
}
return logoUrl;
}
public string GetAllowedFileUploadExtensions()
{
var allowedFileExtensions = _config["LUBELOGGER_ALLOWED_FILE_EXTENSIONS"];
if (string.IsNullOrWhiteSpace(allowedFileExtensions)){
return ".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx";
}
return allowedFileExtensions;
}
public bool AuthenticateRootUser(string username, string password)
{
var rootUsername = _config[nameof(UserConfig.UserNameHash)] ?? string.Empty;

View File

@ -205,7 +205,7 @@
<img src="/defaults/lubelogger_logo.png" />
</div>
<div class="d-flex justify-content-center">
<small class="text-body-secondary">Version 1.2.4</small>
<small class="text-body-secondary">Version 1.2.5</small>
</div>
<p class="lead">
Proudly developed in the rural town of Price, Utah by Hargata Softworks.

View File

@ -64,7 +64,7 @@
<div>
@await Html.PartialAsync("_UploadedFiles", Model.Files)
<label for="collisionRecordFiles">@translator.Translate(userLanguage,"Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="collisionRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="collisionRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
</div>
}
@ -80,7 +80,7 @@
</div>
}
<label for="collisionRecordFiles">@translator.Translate(userLanguage,"Upload documents(optional)")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="collisionRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="collisionRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
}
</div>

View File

@ -122,7 +122,7 @@
@foreach (CollisionRecord collisionRecord in Model)
{
<tr class="d-flex user-select-none" style="cursor:pointer;" onmouseup="stopEvent()" ontouchstart="detectRowLongTouch(this)" ontouchend="detectRowTouchEndPremature(this)" data-rowId="@collisionRecord.Id" oncontextmenu="showTableContextMenu(this)" onmousemove="rangeMouseMove(this)" onclick="handleTableRowClick(this, showEditCollisionRecordModal,@collisionRecord.Id)" data-tags='@string.Join(" ", collisionRecord.Tags)'>
<td class="col-2 col-xl-1 flex-grow-1" data-column="date">@collisionRecord.Date.ToShortDateString()</td>
<td class="col-2 col-xl-1 flex-grow-1" data-column="date" data-date="@StaticHelper.GetEpochFromDateTime(collisionRecord.Date)">@collisionRecord.Date.ToShortDateString()</td>
<td class="col-2 flex-grow-1" data-column="odometer">@collisionRecord.Mileage</td>
<td class="col-3 col-xl-4 flex-grow-1" data-column="description">@collisionRecord.Description</td>
<td class="col-2 flex-grow-1" data-column="cost" data-record-type="cost">@((hideZero && collisionRecord.Cost == default) ? "---" : collisionRecord.Cost.ToString("C"))</td>
@ -157,6 +157,8 @@
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" onclick="duplicateRecords(selectedRow, 'RepairRecord')">@translator.Translate(userLanguage, "Duplicate")</a></li>
<li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'RepairRecord')">@translator.Translate(userLanguage, "Delete")</a></li>
<li><hr class="context-menu-active-multiple dropdown-divider"></li>
<li><a class="context-menu-active-multiple dropdown-item" href="#" onclick="getRecordsDeltaStats(selectedRow)">@translator.Translate(userLanguage, "Statistics")</a></li>
</ul>
@if (userColumnPreferences.Any())
{

View File

@ -103,14 +103,14 @@
<div>
@await Html.PartialAsync("_UploadedFiles", Model.GasRecord.Files)
<label for="gasRecordFiles">@translator.Translate(userLanguage,"Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="gasRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="gasRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
</div>
}
else
{
<label for="gasRecordFiles">@translator.Translate(userLanguage,"Upload documents(optional)")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="gasRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="gasRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
}
</div>

View File

@ -34,14 +34,14 @@
<div>
@await Html.PartialAsync("_UploadedFiles", Model.Files)
<label for="serviceRecordFiles">@translator.Translate(userLanguage, "Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="noteFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="noteFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
</div>
}
else
{
<label for="serviceRecordFiles">@translator.Translate(userLanguage, "Upload documents(optional)")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="noteFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="noteFiles">
<br />
<small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
}

View File

@ -48,14 +48,14 @@
<div>
@await Html.PartialAsync("_UploadedFiles", Model.Files)
<label for="odometerRecordFiles">@translator.Translate(userLanguage,"Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="odometerRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="odometerRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
</div>
}
else
{
<label for="odometerRecordFiles">@translator.Translate(userLanguage,"Upload documents(optional)")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="odometerRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="odometerRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
}
</div>

View File

@ -65,14 +65,14 @@
<div>
@await Html.PartialAsync("_UploadedFiles", Model.Files)
<label for="planRecordFiles">@translator.Translate(userLanguage, "Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="planRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="planRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>
</div>
}
else
{
<label for="planRecordFiles">@translator.Translate(userLanguage, "Upload documents(optional)")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="planRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="planRecordFiles">
<br />
<small class="text-body-secondary">@translator.Translate(userLanguage, "Max File Size: 28.6MB")</small>

View File

@ -64,7 +64,7 @@
<div>
@await Html.PartialAsync("_UploadedFiles", Model.Files)
<label for="serviceRecordFiles">@translator.Translate(userLanguage,"Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="serviceRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="serviceRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
</div>
}
@ -80,7 +80,7 @@
</div>
}
<label for="serviceRecordFiles">@translator.Translate(userLanguage,"Upload documents(optional)")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="serviceRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="serviceRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
}
</div>

View File

@ -122,7 +122,7 @@
@foreach (ServiceRecord serviceRecord in Model)
{
<tr class="d-flex user-select-none" style="cursor:pointer;" onmouseup="stopEvent()" ontouchstart="detectRowLongTouch(this)" ontouchend="detectRowTouchEndPremature(this)" data-rowId="@serviceRecord.Id" oncontextmenu="showTableContextMenu(this)" onmousemove="rangeMouseMove(this)" onclick="handleTableRowClick(this, showEditServiceRecordModal,@serviceRecord.Id)" data-tags='@string.Join(" ", serviceRecord.Tags)'>
<td class="col-2 col-xl-1 flex-grow-1" data-column="date">@serviceRecord.Date.ToShortDateString()</td>
<td class="col-2 col-xl-1 flex-grow-1" data-column="date" data-date="@StaticHelper.GetEpochFromDateTime(serviceRecord.Date)">@serviceRecord.Date.ToShortDateString()</td>
<td class="col-2 flex-grow-1" data-column="odometer">@serviceRecord.Mileage</td>
<td class="col-3 col-xl-4 flex-grow-1" data-column="description">@serviceRecord.Description</td>
<td class="col-2 flex-grow-1" data-column="cost" data-record-type="cost">@((hideZero && serviceRecord.Cost == default) ? "---" : serviceRecord.Cost.ToString("C"))</td>
@ -157,6 +157,8 @@
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" onclick="duplicateRecords(selectedRow, 'ServiceRecord')">@translator.Translate(userLanguage, "Duplicate")</a></li>
<li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'ServiceRecord')">@translator.Translate(userLanguage, "Delete")</a></li>
<li><hr class="context-menu-active-multiple dropdown-divider"></li>
<li><a class="context-menu-active-multiple dropdown-item" href="#" onclick="getRecordsDeltaStats(selectedRow)">@translator.Translate(userLanguage, "Statistics")</a></li>
</ul>
@if (userColumnPreferences.Any())
{

View File

@ -67,14 +67,14 @@
<div>
@await Html.PartialAsync("_UploadedFiles", Model.Files)
<label for="supplyRecordFiles">@translator.Translate(userLanguage,"Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="supplyRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="supplyRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
</div>
}
else
{
<label for="supplyRecordFiles">@translator.Translate(userLanguage,"Upload documents(optional)")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="supplyRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="supplyRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
}
</div>

View File

@ -73,7 +73,7 @@
<div>
@await Html.PartialAsync("_UploadedFiles", Model.Files)
<label for="taxRecordFiles">@translator.Translate(userLanguage,"Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="taxRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="taxRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
</div>
}
@ -89,7 +89,7 @@
</div>
}
<label for="taxRecordFiles">@translator.Translate(userLanguage,"Upload documents(optional)")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="taxRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="taxRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
}
</div>

View File

@ -64,7 +64,7 @@
<div>
@await Html.PartialAsync("_UploadedFiles", Model.Files)
<label for="upgradeRecordFiles">@translator.Translate(userLanguage,"Upload more documents")</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="upgradeRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="upgradeRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
</div>
}
@ -80,7 +80,7 @@
</div>
}
<label for="upgradeRecordFiles">Upload documents(optional)</label>
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="upgradeRecordFiles">
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept="@config.GetAllowedFileUploadExtensions()" class="form-control-file" id="upgradeRecordFiles">
<br /><small class="text-body-secondary">@translator.Translate(userLanguage,"Max File Size: 28.6MB")</small>
}
</div>

View File

@ -122,7 +122,7 @@
@foreach (UpgradeRecord upgradeRecord in Model)
{
<tr class="d-flex user-select-none" style="cursor:pointer;" onmouseup="stopEvent()" ontouchstart="detectRowLongTouch(this)" ontouchend="detectRowTouchEndPremature(this)" data-rowId="@upgradeRecord.Id" oncontextmenu="showTableContextMenu(this)" onmousemove="rangeMouseMove(this)" onclick="handleTableRowClick(this, showEditUpgradeRecordModal,@upgradeRecord.Id)" data-tags='@string.Join(" ", upgradeRecord.Tags)'>
<td class="col-2 flex-grow-1 col-xl-1" data-column="date">@upgradeRecord.Date.ToShortDateString()</td>
<td class="col-2 flex-grow-1 col-xl-1" data-column="date" data-date="@StaticHelper.GetEpochFromDateTime(upgradeRecord.Date)">@upgradeRecord.Date.ToShortDateString()</td>
<td class="col-2 flex-grow-1" data-column="odometer">@upgradeRecord.Mileage</td>
<td class="col-3 flex-grow-1 col-xl-4" data-column="description">@upgradeRecord.Description</td>
<td class="col-2 flex-grow-1" data-column="cost" data-record-type="cost">@((hideZero && upgradeRecord.Cost == default) ? "---" : upgradeRecord.Cost.ToString("C"))</td>
@ -156,6 +156,8 @@
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" onclick="duplicateRecords(selectedRow, 'UpgradeRecord')">@translator.Translate(userLanguage, "Duplicate")</a></li>
<li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'UpgradeRecord')">@translator.Translate(userLanguage, "Delete")</a></li>
<li><hr class="context-menu-active-multiple dropdown-divider"></li>
<li><a class="context-menu-active-multiple dropdown-item" href="#" onclick="getRecordsDeltaStats(selectedRow)">@translator.Translate(userLanguage, "Statistics")</a></li>
</ul>
@if (userColumnPreferences.Any())
{

File diff suppressed because one or more lines are too long

View File

@ -678,6 +678,9 @@ function isRightClick(e) {
return false;
}
function stopEvent() {
if (isDragging) {
isDragging = false;
}
event.stopPropagation();
}
function rangeMouseUp(e) {

View File

@ -441,3 +441,37 @@ function getAndValidateGenericRecordValues() {
}
}
}
function getRecordsDeltaStats(recordIds) {
if (recordIds.length < 2) {
return;
}
var odometerReadings = [];
var dateReadings = [];
//get all of the odometer readings
recordIds.map(x => {
var odometerReading = parseInt($(`tr[data-rowId='${x}'] td[data-column='odometer']`).text());
if (!isNaN(odometerReading)) {
odometerReadings.push(odometerReading);
}
var dateReading = parseInt($(`tr[data-rowId=${x}] td[data-column='date']`).attr('data-date'));
if (!isNaN(dateReading)) {
dateReadings.push(dateReading);
}
});
//get max stats
var maxOdo = odometerReadings.length > 0 ? odometerReadings.reduce((a, b) => a > b ? a : b) : 0;
var maxDate = dateReadings.length > 0 ? dateReadings.reduce((a, b) => a > b ? a : b) : 0;
//get min stats
var minOdo = odometerReadings.length > 0 ? odometerReadings.reduce((a, b) => a < b ? a : b) : 0;
var minDate = dateReadings.length > 0 ? dateReadings.reduce((a, b) => a < b ? a : b) : 0;
var diffOdo = maxOdo - minOdo;
var diffDate = maxDate - minDate;
var divisibleCount = recordIds.length - 1;
var averageOdo = diffOdo > 0 ? (diffOdo / divisibleCount).toFixed(2) : 0;
var averageDays = diffDate > 0 ? Math.floor((diffDate / divisibleCount) / 8.64e7) : 0;
Swal.fire({
title: "Record Statistics",
html: `<p>Average Distance Traveled between Records: ${averageOdo}</p><br /><p>Average Days between Records: ${averageDays}</p>`,
icon: "info"
});
}