Merge pull request #1086 from hargata/Hargata/garage.select.mobile

add context menu to mobile devices.
This commit is contained in:
Hargata Softworks 2025-10-07 14:19:56 -06:00 committed by GitHub
commit 0bfef450ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 55 additions and 23 deletions

View File

@ -173,15 +173,6 @@
</div>
<div class="stickerPrintContainer hideOnPrint">
</div>
<ul class="garage-context-menu dropdown-menu" style="display:none;">
<li><a class="context-menu-multiple context-menu-select-all dropdown-item" href="#" onclick="selectAllVehicles()"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Select All")</span><i class="bi bi-check-square"></i></div></a></li>
<li><a class="context-menu-multiple context-menu-deselect-all dropdown-item" href="#" onclick="clearSelectedVehicles()"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Deselect All")</span><i class="bi bi-x-square"></i></div></a></li>
<li><hr class="context-menu-multiple dropdown-divider"></li>
<li><a class="dropdown-item" href="#" onclick="manageCollaborators(selectedVehicles)"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Manage Collaborators")</span><i class="bi bi-people"></i></div></a></li>
<li><a class="dropdown-item" href="#" onclick="sortGarage()"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Sort")</span><i class="garage-sort-icon bi bi-arrow-down-up"></i></div></a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-danger" href="#" onclick="deleteVehicles(selectedVehicles)"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Delete")</span><i class="bi bi-trash"></i></div></a></li>
</ul>
<script>
bindWindowResize();
checkNavBarOverflow();

View File

@ -45,7 +45,7 @@
{
@if (!(userConfig.HideSoldVehicles && !string.IsNullOrWhiteSpace(vehicle.SoldDate)))
{
<div class="col-xl-2 col-lg-3 col-md-4 col-sm-4 col-6 garage-item" onclick="handleGarageItemClick(this, @vehicle.Id)" oncontextmenu="showGarageContextMenu(this)" data-tags='@string.Join(" ", vehicle.Tags)' data-rowId="@vehicle.Id" id="gridVehicle_@vehicle.Id" data-bs-toggle="tooltip" data-bs-html="true" data-bs-title="@await Html.PartialAsync("_VehicleExtraFields", vehicle.ExtraFields)" data-bs-placement="bottom" data-bs-trigger="manual" onmouseenter="loadPinnedNotes(@vehicle.Id)" ontouchstart="loadPinnedNotes(@vehicle.Id)" ontouchcancel="hidePinnedNotes(@vehicle.Id)" ontouchend="hidePinnedNotes(@vehicle.Id)" onmouseleave="hidePinnedNotes(@vehicle.Id)" onmousemove="garageRangeMouseMove(this)">
<div class="col-xl-2 col-lg-3 col-md-4 col-sm-4 col-6 garage-item" onclick="handleGarageItemClick(this, @vehicle.Id)" oncontextmenu="showGarageContextMenu(this)" data-tags='@string.Join(" ", vehicle.Tags)' data-rowId="@vehicle.Id" id="gridVehicle_@vehicle.Id" data-extra-fields="@await Html.PartialAsync("_VehicleExtraFields", vehicle.ExtraFields)" onmousemove="garageRangeMouseMove(this)" ontouchstart="detectGarageLongTouch(this)" ontouchend="detectGarageTouchEndPremature(this)">
<div class="card">
<img src="@vehicle.ImageLocation" style="height:145px; object-fit:scale-down; pointer-events:none; @(string.IsNullOrWhiteSpace(vehicle.SoldDate) ? "" : "filter: grayscale(100%);")" />
@if (!string.IsNullOrWhiteSpace(vehicle.SoldDate))
@ -103,4 +103,14 @@
</div>
</div>
</div>
</div>
</div>
<ul class="garage-context-menu dropdown-menu" style="display:none;">
<li><a class="context-menu-multiple context-menu-select-all dropdown-item" href="#" onclick="selectAllVehicles()"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Select All")</span><i class="bi bi-check-square"></i></div></a></li>
<li><a class="context-menu-multiple context-menu-deselect-all dropdown-item" href="#" onclick="clearSelectedVehicles()"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Deselect All")</span><i class="bi bi-x-square"></i></div></a></li>
<li><hr class="context-menu-multiple dropdown-divider"></li>
<li><a class="context-menu-multiple dropdown-item" href="#" onclick="sortGarage()"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Sort")</span><i class="garage-sort-icon bi bi-arrow-down-up"></i></div></a></li>
<li><a class="context-menu-extra-field dropdown-item" href="#" onclick="showVehicleExtraFields(selectedVehicles)"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Extra Fields")</span><i class="bi bi-list-ul"></i></div></a></li>
<li><a class="dropdown-item" href="#" onclick="manageCollaborators(selectedVehicles)"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Manage Collaborators")</span><i class="bi bi-people"></i></div></a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-danger" href="#" onclick="deleteVehicles(selectedVehicles)"><div class="d-flex justify-content-between"><span class="me-5">@translator.Translate(userLanguage, "Delete")</span><i class="bi bi-trash"></i></div></a></li>
</ul>

View File

@ -71,7 +71,6 @@ function bindTabEvent() {
$(`.lubelogger-tab #${e.relatedTarget.id}`).removeClass('active');
$(`.lubelogger-mobile-nav #${e.relatedTarget.id}`).removeClass('active');
}
resetGarageSort(); //reset the garage sort, we're not persisting this across tab changes.
setBrowserHistory('tab', getTabNameForURL(e.target.id));
});
}
@ -189,17 +188,6 @@ function performLogOut() {
}
})
}
function loadPinnedNotes(vehicleId) {
var hoveredGrid = $(`#gridVehicle_${vehicleId}`);
if (hoveredGrid.attr("data-bs-title") != '') {
hoveredGrid.tooltip("show");
}
}
function hidePinnedNotes(vehicleId) {
if ($(`#gridVehicle_${vehicleId}`).attr('data-bs-title') != '') {
$(`#gridVehicle_${vehicleId}`).tooltip("hide");
}
}
function filterGarage(sender) {
let searchQuery = $('#garageSearchInput').val();
@ -285,6 +273,19 @@ function showGarageContextMenu(e) {
}
determineGarageContextMenu();
}
function showGarageContextMenuForMobile(e, xPosition, yPosition) {
if (!$(e).hasClass('garage-active')) {
addToSelectedVehicles($(e).attr('data-rowId'));
$(e).addClass('garage-active');
} else {
$(".garage-context-menu").fadeIn("fast");
$(".garage-context-menu").css({
left: getGarageMenuPosition(xPosition, 'width', 'scrollLeft'),
top: getGarageMenuPosition(yPosition, 'height', 'scrollTop')
});
determineGarageContextMenu();
}
}
function determineGarageContextMenu() {
let garageItems = $('.garage-item:visible');
let garageItemsActive = $('.garage-item.garage-active:visible');
@ -298,6 +299,11 @@ function determineGarageContextMenu() {
$(".context-menu-active-single").hide();
$(".context-menu-active-multiple").hide();
}
if (garageItemsActive.length == 1 && garageItemsActive.attr('data-extra-fields') != '') {
$(".context-menu-extra-field").show();
} else {
$(".context-menu-extra-field").hide();
}
if (garageItems.length > 1) {
$(".context-menu-multiple").show();
if (garageItems.length == garageItemsActive.length) {
@ -370,6 +376,31 @@ function manageCollaborators(vehicleIds) {
}
})
}
function showVehicleExtraFields(vehicleIds) {
if (vehicleIds.length != 1) {
return;
}
let extraFieldsHtml = $(`[data-rowId="${vehicleIds[0]}"]`).attr('data-extra-fields');
Swal.fire({
title: 'Vehicle Extra Fields',
html: extraFieldsHtml,
confirmButtonText: 'Close',
focusConfirm: false
});
}
function detectGarageLongTouch(sender) {
var touchX = event.touches[0].clientX;
var touchY = event.touches[0].clientY;
if (!rowTouchTimer) {
rowTouchTimer = setTimeout(function () { showGarageContextMenuForMobile(sender, touchX, touchY); detectGarageTouchEndPremature(sender); }, rowTouchDuration);
}
}
function detectGarageTouchEndPremature(sender) {
if (rowTouchTimer) {
clearTimeout(rowTouchTimer);
rowTouchTimer = null;
}
}
// end context menu
function hideCollaboratorsModal() {
$("#userCollaboratorsModal").modal('hide');