More modal iframe dialog handling improvements

This commit is contained in:
Bernd Bestel 2025-01-10 20:26:37 +01:00
parent 201bda93a2
commit a373f8ae4b
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
24 changed files with 117 additions and 42 deletions

View File

@ -56,7 +56,10 @@
- Optimized nested modal dialogs: - Optimized nested modal dialogs:
- Nested dialogs are now no longer displayed "in each other" and instead "on top of each other" - Nested dialogs are now no longer displayed "in each other" and instead "on top of each other"
- Dialogs can now be closed with the `ESC` key on the keyboard
- There is no longer a close button at the bottom (outside of the displayed `iframe`) and instead one at the top right corner of the dialog
- Wide dialogs (e.g. all showing a table, like showing stock entries of a product from the stock overview more/context menu per line) now use the full screen width - Wide dialogs (e.g. all showing a table, like showing stock entries of a product from the stock overview more/context menu per line) now use the full screen width
- Improved handling of the initial field focus
### API ### API

View File

@ -120,6 +120,11 @@ input[type='number'] {
appearance: textfield; appearance: textfield;
} }
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
.sticky-form-footer { .sticky-form-footer {
border-top: 1px solid #d6d6d6; border-top: 1px solid #d6d6d6;
background-color: white; background-color: white;
@ -275,11 +280,20 @@ a:not([href]) {
z-index: 99998; z-index: 99998;
} }
/* There is a little too much padding around modals */
.modal-body {
padding: 0.75rem;
}
@media (min-width: 576px) { @media (min-width: 576px) {
.form .modal-dialog { .form .modal-dialog {
max-width: 650px; max-width: 650px;
} }
.wider .modal-dialog {
max-width: 800px;
}
.table .modal-dialog { .table .modal-dialog {
max-width: 90%; max-width: 90%;
} }

View File

@ -703,6 +703,30 @@ if (Grocy.CalendarFirstDayOfWeek)
}); });
} }
if (GetUriParam("embedded"))
{
$("body").append('<div class="fixed-top"> \
<button class="btn btn-light float-right close-last-modal-button" \
type="button" \> \
<i class="fa-solid fa-xmark"></i> \
</button> \
</div>');
}
$(document).on("click", ".close-last-modal-button", function()
{
window.parent.postMessage(WindowMessageBag("CloseLastModal"), Grocy.BaseUrl);
});
$("body").on("keydown", function(e)
{
if (e.key == "Escape")
{
window.parent.postMessage(WindowMessageBag("CloseLastModal"), Grocy.BaseUrl);
}
});
$(window).on("message", function(e) $(window).on("message", function(e)
{ {
var data = e.originalEvent.data; var data = e.originalEvent.data;
@ -769,17 +793,7 @@ function IframeModal(link, dialogClass = "form")
size: 'large', size: 'large',
backdrop: true, backdrop: true,
closeButton: false, closeButton: false,
className: dialogClass, className: dialogClass
buttons: {
cancel: {
label: __t('Close'),
className: 'btn-secondary responsive-button',
callback: function()
{
$(".modal").last().modal("hide");
}
}
}
}); });
} }

View File

@ -107,5 +107,5 @@ Grocy.Components.UserfieldsForm.Load();
setTimeout(function() setTimeout(function()
{ {
$('#name').focus(); $('#name').focus();
}, 250); }, 150);
Grocy.FrontendHelpers.ValidateForm('battery-form'); Grocy.FrontendHelpers.ValidateForm('battery-form');

View File

@ -492,7 +492,10 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
Grocy.Components.ProductPicker.HideCustomError(); Grocy.Components.ProductPicker.HideCustomError();
Grocy.FrontendHelpers.ValidateForm('consume-form'); Grocy.FrontendHelpers.ValidateForm('consume-form');
$('#display_amount').focus(); setTimeout(function()
{
$('#display_amount').focus();
}, 150);
if (productDetails.stock_amount == productDetails.stock_amount_opened || productDetails.product.enable_tare_weight_handling == 1) if (productDetails.stock_amount == productDetails.stock_amount_opened || productDetails.product.enable_tare_weight_handling == 1)
{ {

View File

@ -311,7 +311,10 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
$('#display_amount').val(productDetails.stock_amount); $('#display_amount').val(productDetails.stock_amount);
RefreshLocaleNumberInput(); RefreshLocaleNumberInput();
$(".input-group-productamountpicker").trigger("change"); $(".input-group-productamountpicker").trigger("change");
$('#display_amount').focus(); setTimeout(function()
{
$('#display_amount').focus();
}, 150);
$('#display_amount').trigger('keyup'); $('#display_amount').trigger('keyup');
RefreshPriceHint(); RefreshPriceHint();
}, },

View File

@ -93,4 +93,4 @@ Grocy.FrontendHelpers.ValidateForm('location-form');
setTimeout(function() setTimeout(function()
{ {
$('#name').focus(); $('#name').focus();
}, 250); }, 150);

View File

@ -99,7 +99,7 @@ Grocy.FrontendHelpers.ValidateForm('barcode-form');
setTimeout(function() setTimeout(function()
{ {
$('#barcode').focus(); $('#barcode').focus();
}, 250); }, 150);
RefreshLocaleNumberInput(); RefreshLocaleNumberInput();
Grocy.Components.UserfieldsForm.Load() Grocy.Components.UserfieldsForm.Load()

View File

@ -78,5 +78,5 @@ Grocy.Components.UserfieldsForm.Load();
setTimeout(function() setTimeout(function()
{ {
$('#name').focus(); $('#name').focus();
}, 250); }, 150);
Grocy.FrontendHelpers.ValidateForm('product-group-form'); Grocy.FrontendHelpers.ValidateForm('product-group-form');

View File

@ -343,7 +343,10 @@ if (Grocy.Components.ProductPicker !== undefined)
$("#stock_label_type").trigger("change"); $("#stock_label_type").trigger("change");
} }
$("#display_amount").focus(); setTimeout(function()
{
$('#display_amount').focus();
}, 150);
Grocy.FrontendHelpers.ValidateForm('purchase-form'); Grocy.FrontendHelpers.ValidateForm('purchase-form');
if (GetUriParam("flow") === "shoppinglistitemtostock" && BoolVal(Grocy.UserSettings.shopping_list_to_stock_workflow_auto_submit_when_prefilled) && Grocy.FrontendHelpers.ValidateForm("purchase-form")) if (GetUriParam("flow") === "shoppinglistitemtostock" && BoolVal(Grocy.UserSettings.shopping_list_to_stock_workflow_auto_submit_when_prefilled) && Grocy.FrontendHelpers.ValidateForm("purchase-form"))

View File

@ -124,14 +124,14 @@ if (!Grocy.Components.ProductPicker.InAnyFlow())
setTimeout(function() setTimeout(function()
{ {
$("#display_amount").focus(); $("#display_amount").focus();
}, 250); }, 150);
} }
else else
{ {
setTimeout(function() setTimeout(function()
{ {
Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.Components.ProductPicker.GetInputElement().focus();
}, 250); }, 150);
} }
} }
else else
@ -143,7 +143,7 @@ else
setTimeout(function() setTimeout(function()
{ {
Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.Components.ProductPicker.GetInputElement().focus();
}, 250); }, 150);
} }
} }

View File

@ -82,5 +82,5 @@ Grocy.Components.UserfieldsForm.Load();
setTimeout(function() setTimeout(function()
{ {
$('#name').focus(); $('#name').focus();
}, 250); }, 150);
Grocy.FrontendHelpers.ValidateForm('shopping-list-form'); Grocy.FrontendHelpers.ValidateForm('shopping-list-form');

View File

@ -210,7 +210,10 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
$("#display_amount").trigger("change"); $("#display_amount").trigger("change");
} }
$('#display_amount').focus(); setTimeout(function()
{
$('#display_amount').focus();
}, 150);
Grocy.FrontendHelpers.ValidateForm('shoppinglist-form'); Grocy.FrontendHelpers.ValidateForm('shoppinglist-form');
Grocy.ShoppingListItemFormInitialLoadDone = true; Grocy.ShoppingListItemFormInitialLoadDone = true;
}, },
@ -289,14 +292,14 @@ if (!Grocy.Components.ProductPicker.InAnyFlow())
setTimeout(function() setTimeout(function()
{ {
$("#display_amount").focus(); $("#display_amount").focus();
}, 250); }, 150);
} }
else else
{ {
setTimeout(function() setTimeout(function()
{ {
Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.Components.ProductPicker.GetInputElement().focus();
}, 250); }, 150);
} }
} }
else else
@ -308,7 +311,7 @@ else
setTimeout(function() setTimeout(function()
{ {
Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.Components.ProductPicker.GetInputElement().focus();
}, 250); }, 150);
} }
} }

View File

@ -92,5 +92,5 @@ Grocy.Components.UserfieldsForm.Load();
setTimeout(function() setTimeout(function()
{ {
$('#name').focus(); $('#name').focus();
}, 250); }, 150);
Grocy.FrontendHelpers.ValidateForm('shoppinglocation-form'); Grocy.FrontendHelpers.ValidateForm('shoppinglocation-form');

View File

@ -149,5 +149,5 @@ Grocy.Components.UserfieldsForm.Load();
setTimeout(function() setTimeout(function()
{ {
$('#amount').focus(); $('#amount').focus();
}, 250); }, 150);
Grocy.FrontendHelpers.ValidateForm("stockentry-form"); Grocy.FrontendHelpers.ValidateForm("stockentry-form");

View File

@ -92,5 +92,5 @@ Grocy.Components.UserfieldsForm.Load();
setTimeout(function() setTimeout(function()
{ {
$('#name').focus(); $('#name').focus();
}, 250); }, 150);
Grocy.FrontendHelpers.ValidateForm('task-category-form'); Grocy.FrontendHelpers.ValidateForm('task-category-form');

View File

@ -112,6 +112,6 @@ Grocy.Components.UserfieldsForm.Load();
setTimeout(function() setTimeout(function()
{ {
$('#name').focus(); $('#name').focus();
}, 250); }, 150);
Grocy.Components.DateTimePicker.GetInputElement().trigger('input'); Grocy.Components.DateTimePicker.GetInputElement().trigger('input');
Grocy.FrontendHelpers.ValidateForm('task-form'); Grocy.FrontendHelpers.ValidateForm('task-form');

View File

@ -280,7 +280,10 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
Grocy.Components.ProductPicker.HideCustomError(); Grocy.Components.ProductPicker.HideCustomError();
Grocy.FrontendHelpers.ValidateForm('transfer-form'); Grocy.FrontendHelpers.ValidateForm('transfer-form');
$('#display_amount').focus(); setTimeout(function()
{
$('#display_amount').focus();
}, 150);
}, },
function(xhr) function(xhr)
{ {

View File

@ -103,7 +103,7 @@ $("#show_in_sidebar_menu").on("click", function()
setTimeout(function() setTimeout(function()
{ {
$('#name').focus(); $('#name').focus();
}, 250); }, 150);
Grocy.FrontendHelpers.ValidateForm('userentity-form'); Grocy.FrontendHelpers.ValidateForm('userentity-form');
// Click twice to trigger on-click but not change the actual checked state // Click twice to trigger on-click but not change the actual checked state

View File

@ -27,7 +27,8 @@
</a> </a>
<a id="batterycard-battery-journal-button" <a id="batterycard-battery-journal-button"
class="btn btn-sm btn-outline-secondary py-0 mr-1 float-right disabled show-as-dialog-link" class="btn btn-sm btn-outline-secondary py-0 mr-1 float-right disabled show-as-dialog-link"
href="#"> href="#"
data-dialog-type="table">
{{ $__t('Battery journal') }} {{ $__t('Battery journal') }}
</a> </a>
</div> </div>

View File

@ -27,7 +27,8 @@
</a> </a>
<a id="chorecard-chore-journal-button" <a id="chorecard-chore-journal-button"
class="btn btn-sm btn-outline-secondary py-0 mr-1 float-right disabled show-as-dialog-link" class="btn btn-sm btn-outline-secondary py-0 mr-1 float-right disabled show-as-dialog-link"
href="#"> href="#"
data-dialog-type="table">
{{ $__t('Chore journal') }} {{ $__t('Chore journal') }}
</a> </a>
</div> </div>

View File

@ -29,12 +29,14 @@
</a> </a>
<a id="productcard-product-journal-button" <a id="productcard-product-journal-button"
class="btn btn-sm btn-outline-secondary py-0 mr-1 float-right disabled show-as-dialog-link" class="btn btn-sm btn-outline-secondary py-0 mr-1 float-right disabled show-as-dialog-link"
href="#"> href="#"
data-dialog-type="table">
{{ $__t('Stock journal') }} {{ $__t('Stock journal') }}
</a> </a>
<a id="productcard-product-stock-button" <a id="productcard-product-stock-button"
class="btn btn-sm btn-outline-secondary py-0 mr-1 float-right disabled show-as-dialog-link" class="btn btn-sm btn-outline-secondary py-0 mr-1 float-right disabled show-as-dialog-link"
href="#"> href="#"
data-dialog-type="table">
{{ $__t('Stock entries') }} {{ $__t('Stock entries') }}
</a> </a>
</div> </div>

View File

@ -672,6 +672,7 @@
href="{{ $U('/barcodescannertesting') }}"><i class="fa-solid fa-fw fa-barcode"></i>&nbsp;{{ $__t('Barcode scanner testing') }}</a> href="{{ $U('/barcodescannertesting') }}"><i class="fa-solid fa-fw fa-barcode"></i>&nbsp;{{ $__t('Barcode scanner testing') }}</a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item discrete-link show-as-dialog-link" <a class="dropdown-item discrete-link show-as-dialog-link"
data-dialog-type="wider"
href="{{ $U('/about?embedded') }}"><i class="fa-solid fa-fw fa-info"></i>&nbsp;{{ $__t('About Grocy') }}</a> href="{{ $U('/about?embedded') }}"><i class="fa-solid fa-fw fa-info"></i>&nbsp;{{ $__t('About Grocy') }}</a>
</div> </div>
</li> </li>
@ -681,7 +682,7 @@
@endif @endif
<div class="@if(GROCY_AUTHENTICATED) content-wrapper @endif pt-0"> <div class="@if(GROCY_AUTHENTICATED) content-wrapper @endif pt-0">
<div class="container-fluid @if(GROCY_AUTHENTICATED) pr-1 pl-md-3 pl-2 @endif"> <div class="container-fluid @if(GROCY_AUTHENTICATED && !$embedded) pr-1 pl-md-3 pl-2 @endif @if($embedded) px-1 @endif">
<div class="row mb-3"> <div class="row mb-3">
<div id="page-content" <div id="page-content"
class="col content-text"> class="col content-text">

View File

@ -25,11 +25,13 @@
<div class="related-links collapse d-md-flex order-2 width-xs-sm-100" <div class="related-links collapse d-md-flex order-2 width-xs-sm-100"
id="related-links"> id="related-links">
<a class="btn btn-outline-secondary m-1 mt-md-0 mb-md-0 float-right show-as-dialog-link" <a class="btn btn-outline-secondary m-1 mt-md-0 mb-md-0 float-right show-as-dialog-link"
href="{{ $U('/stockentries?embedded&product=') }}{{ $product->id }}"> href="{{ $U('/stockentries?embedded&product=') }}{{ $product->id }}"
data-dialog-type="table">
{{ $__t('Stock entries') }} {{ $__t('Stock entries') }}
</a> </a>
<a class="btn btn-outline-secondary m-1 mt-md-0 mb-md-0 float-right show-as-dialog-link" <a class="btn btn-outline-secondary m-1 mt-md-0 mb-md-0 float-right show-as-dialog-link"
href="{{ $U('/stockjournal?embedded&product=') }}{{ $product->id }}"> href="{{ $U('/stockjournal?embedded&product=') }}{{ $product->id }}"
data-dialog-type="table">
{{ $__t('Stock journal') }} {{ $__t('Stock journal') }}
</a> </a>
</div> </div>
@ -156,7 +158,26 @@
for="move_on_open">{{ $__t('Move on open') }}&nbsp;<i class="fa-solid fa-question-circle text-muted" for="move_on_open">{{ $__t('Move on open') }}&nbsp;<i class="fa-solid fa-question-circle text-muted"
data-toggle="tooltip" data-toggle="tooltip"
data-trigger="hover click" data-trigger="hover click"
title="{{ $__t("When enabled, on marking this product as opened, the corresponding amount will be moved to the default consume location") title="{{ $__t("
When
enabled,
on
marking
this
product
as
opened,
the
corresponding
amount
will
be
moved
to
the
default
consume
location")
}}"></i> }}"></i>
</label> </label>
</div> </div>
@ -773,11 +794,13 @@
<div class="related-links collapse d-md-flex order-2 width-xs-sm-100" <div class="related-links collapse d-md-flex order-2 width-xs-sm-100"
id="related-links"> id="related-links">
<a class="btn btn-primary btn-sm m-1 mt-md-0 mb-md-0 float-right show-as-dialog-link" <a class="btn btn-primary btn-sm m-1 mt-md-0 mb-md-0 float-right show-as-dialog-link"
href="{{ $U('/quantityunitconversion/new?embedded&product=' . $product->id ) }}"> href="{{ $U('/quantityunitconversion/new?embedded&product=' . $product->id ) }}"
data-dialog-type="wider">
{{ $__t('Add') }} {{ $__t('Add') }}
</a> </a>
<a class="btn btn-outline-primary btn-sm m-1 mt-md-0 mb-md-0 float-right show-as-dialog-link" <a class="btn btn-outline-primary btn-sm m-1 mt-md-0 mb-md-0 float-right show-as-dialog-link"
href="{{ $U('/quantityunitconversionsresolved?embedded&product=' . $product->id ) }}" href="{{ $U('/quantityunitconversionsresolved?embedded&product=' . $product->id ) }}"
data-dialog-type="wider"
data-toggle="tooltip" data-toggle="tooltip"
title="{{ $__t('This shows all to this product directly or indirectly related quantity units and their derived conversion factors') }}"> title="{{ $__t('This shows all to this product directly or indirectly related quantity units and their derived conversion factors') }}">
{{ $__t('Show resolved conversions') }} {{ $__t('Show resolved conversions') }}
@ -808,7 +831,8 @@
<tr> <tr>
<td class="fit-content border-right"> <td class="fit-content border-right">
<a class="btn btn-sm btn-info show-as-dialog-link @if($quConversion->product_id == null) disabled @endif" <a class="btn btn-sm btn-info show-as-dialog-link @if($quConversion->product_id == null) disabled @endif"
href="{{ $U('/quantityunitconversion/' . $quConversion->id . '?embedded&product=' . $product->id ) }}"> href="{{ $U('/quantityunitconversion/' . $quConversion->id . '?embedded&product=' . $product->id ) }}"
data-dialog-type="wider">
<i class="fa-solid fa-edit"></i> <i class="fa-solid fa-edit"></i>
</a> </a>
<a class="btn btn-sm btn-danger qu-conversion-delete-button @if($quConversion->product_id == null) disabled @endif" <a class="btn btn-sm btn-danger qu-conversion-delete-button @if($quConversion->product_id == null) disabled @endif"