[FIX] web: give enough space to display datepicker on small screens

Before this commit, the datepicker was not displayed entirely on small
screens if the current view wasn't tall enough.

This commit adds a margin (supposedly) big enough to render the entire
picker even on small screens.

Task 3585878

closes odoo/odoo#149510

X-original-commit: 47c0627d218bd846596c9deb84720fc289047365
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Signed-off-by: Julien Mougenot (jum) <jum@odoo.com>
This commit is contained in:
Julien Mougenot
2024-01-22 13:02:17 +00:00
parent 851eb19843
commit 0fc7b3e999
2 changed files with 104 additions and 0 deletions
@@ -67,6 +67,10 @@ export const datetimePickerService = {
updateValueFromInputs();
apply();
setFocusClass(null);
if (restoreTargetMargin) {
restoreTargetMargin();
restoreTargetMargin = null;
}
},
});
// Hook methods
@@ -238,7 +242,14 @@ export const datetimePickerService = {
if (!popover.isOpen) {
const popoverTarget = getPopoverTarget();
if (env.isSmall) {
const { marginBottom } = popoverTarget.style;
// Adds enough space for the popover to be displayed below the target
// even on small screens.
popoverTarget.style.marginBottom = `100vh`;
popoverTarget.scrollIntoView(true);
restoreTargetMargin = async () => {
popoverTarget.style.marginBottom = marginBottom;
};
}
popover.open(popoverTarget, { pickerProps });
}
@@ -416,6 +427,8 @@ export const datetimePickerService = {
/** @type {DateTimePickerProps | null} */
let lastInitialProps = null;
let lastIsRange = pickerProps.range;
/** @type {(() => void) | null} */
let restoreTargetMargin = null;
let shouldFocus = false;
/**
@@ -0,0 +1,91 @@
/** @odoo-module **/
import { Component, xml } from "@odoo/owl";
import { clearRegistryWithCleanup, makeTestEnv } from "@web/../tests/helpers/mock_env";
import { makeFakeLocalizationService } from "@web/../tests/helpers/mock_services";
import { click, getFixture, mount } from "@web/../tests/helpers/utils";
import { DateTimeInput } from "@web/core/datetime/datetime_input";
import { datetimePickerService } from "@web/core/datetime/datetimepicker_service";
import { hotkeyService } from "@web/core/hotkeys/hotkey_service";
import { popoverService } from "@web/core/popover/popover_service";
import { registry } from "@web/core/registry";
import { uiService } from "@web/core/ui/ui_service";
const { DateTime } = luxon;
/**
* @typedef {import("@web/core/datetime/datetime_input").DateTimeInputProps} DateTimeInputProps
*/
/**
* @param {DateTimeInputProps} props
*/
const mountInput = async (props) => {
const env = await makeTestEnv();
await mount(Root, getFixture(), { env, props });
return getFixture().querySelector(".o_datetime_input");
};
class Root extends Component {
static components = { DateTimeInput };
static template = xml`
<div class="d-flex">
<DateTimeInput t-props="props" />
</div>
<t t-foreach="mainComponentEntries" t-as="comp" t-key="comp[0]">
<t t-component="comp[1].Component" t-props="comp[1].props" />
</t>
`;
setup() {
this.mainComponentEntries = mainComponentRegistry.getEntries();
}
}
const mainComponentRegistry = registry.category("main_components");
const serviceRegistry = registry.category("services");
QUnit.module("Components", ({ beforeEach }) => {
beforeEach(() => {
clearRegistryWithCleanup(mainComponentRegistry);
serviceRegistry
.add("datetime_picker", datetimePickerService)
.add("hotkey", hotkeyService)
.add(
"localization",
makeFakeLocalizationService({
dateFormat: "dd/MM/yyyy",
dateTimeFormat: "dd/MM/yyyy HH:mm:ss",
})
)
.add("popover", popoverService)
.add("ui", uiService);
});
QUnit.module("DateTimeInput (date)");
QUnit.test("popover should have enough space to be displayed", async (assert) => {
const { parentElement: parent } = await mountInput({
value: DateTime.fromFormat("09/01/1997", "dd/MM/yyyy"),
type: "date",
});
const initialParentRect = parent.getBoundingClientRect();
await click(parent, ".o_datetime_input");
const pickerRect = getFixture().querySelector(".o_datetime_picker").getBoundingClientRect();
const finalParentRect = parent.getBoundingClientRect();
assert.ok(
initialParentRect.height < pickerRect.height,
"initial height shouldn't be big enough to display the picker"
);
assert.ok(
finalParentRect.height > pickerRect.height,
"initial height should be big enough to display the picker"
);
});
});