[IMP] web: adapt dialog for mobile
This commit modifies the dialog to make it more user friendly on small screen. On small screen, the dialog opens in fullscreen and saves the scroll position when opening to restore it on close. Part-of: odoo/odoo#92475
This commit is contained in:
committed by
Aaron Bohy
parent
466cfbfb42
commit
b1f072cba4
@@ -15,6 +15,16 @@ export class Dialog extends Component {
|
||||
});
|
||||
this.id = `dialog_${this.data.id}`;
|
||||
useChildSubEnv({ inDialog: true, dialogId: this.id });
|
||||
|
||||
owl.onWillDestroy(() => {
|
||||
if (this.env.isSmall) {
|
||||
this.data.scrollToOrigin();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get isFullscreen() {
|
||||
return this.props.fullscreen || this.env.isSmall;
|
||||
}
|
||||
}
|
||||
Dialog.template = "web.Dialog";
|
||||
|
||||
@@ -5,16 +5,21 @@
|
||||
<div class="o_dialog" t-att-id="id" t-att-class="{ o_inactive_modal: !data.isActive }">
|
||||
<div role="dialog" class="modal d-block"
|
||||
tabindex="-1"
|
||||
t-att-class="{ o_technical_modal: props.technical, o_modal_full: props.fullscreen }"
|
||||
t-att-class="{ o_technical_modal: props.technical, o_modal_full: isFullscreen }"
|
||||
t-ref="modalRef"
|
||||
>
|
||||
<div class="modal-dialog" t-attf-class="modal-{{props.size}}">
|
||||
<div class="modal-content" t-att-class="props.contentClass">
|
||||
<header t-if="props.header" class="modal-header">
|
||||
<t t-if="isFullscreen">
|
||||
<button class="btn fa fa-arrow-left" data-dismiss="modal" aria-label="Close" t-on-click="data.close" />
|
||||
</t>
|
||||
<h4 class="modal-title text-break">
|
||||
<t t-esc="props.title"/>
|
||||
</h4>
|
||||
<button type="button" class="close" aria-label="Close" tabindex="-1" t-on-click="data.close">×</button>
|
||||
<t t-if="!isFullscreen">
|
||||
<button type="button" class="close" aria-label="Close" tabindex="-1" t-on-click="data.close">×</button>
|
||||
</t>
|
||||
</header>
|
||||
<!-- FIXME: WOWL there is a bug on t-portal on owl, in which t-portal don't work on multinode.
|
||||
To avoid this we place the footer before the body -->
|
||||
|
||||
@@ -22,7 +22,7 @@ const { markRaw, reactive } = owl;
|
||||
|
||||
export const dialogService = {
|
||||
/** @returns {DialogServiceInterface} */
|
||||
start() {
|
||||
start(env) {
|
||||
const dialogs = reactive({});
|
||||
let dialogId = 0;
|
||||
|
||||
@@ -52,8 +52,20 @@ export const dialogService = {
|
||||
id,
|
||||
class: dialogClass,
|
||||
props: markRaw({ ...props, close }),
|
||||
dialogData: { isActive: true, close, id },
|
||||
dialogData: {
|
||||
isActive: true,
|
||||
close,
|
||||
id,
|
||||
},
|
||||
};
|
||||
if (env.isSmall) {
|
||||
const scrollOrigin = { top: window.scrollY, left: window.scrollX };
|
||||
dialog.dialogData.scrollToOrigin = () => {
|
||||
if (!Object.keys(dialogs).length) {
|
||||
window.scrollTo(scrollOrigin);
|
||||
}
|
||||
};
|
||||
}
|
||||
dialogs[id] = dialog;
|
||||
|
||||
return close;
|
||||
|
||||
@@ -11,6 +11,7 @@ import { errorService } from "@web/core/errors/error_service";
|
||||
import { ConnectionLostError, RPCError } from "@web/core/network/rpc_service";
|
||||
import { notificationService } from "@web/core/notifications/notification_service";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { uiService } from "@web/core/ui/ui_service";
|
||||
import { registerCleanup } from "../../helpers/cleanup";
|
||||
import { makeTestEnv } from "../../helpers/mock_env";
|
||||
import {
|
||||
@@ -36,6 +37,7 @@ QUnit.module("Error Service", {
|
||||
serviceRegistry.add("notification", notificationService);
|
||||
serviceRegistry.add("rpc", makeFakeRPCService());
|
||||
serviceRegistry.add("localization", makeFakeLocalizationService());
|
||||
serviceRegistry.add("ui", uiService);
|
||||
const windowAddEventListener = browser.addEventListener;
|
||||
browser.addEventListener = (type, cb) => {
|
||||
if (type === "unhandledrejection") {
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
getFixture,
|
||||
makeDeferred,
|
||||
nextTick,
|
||||
patchWithCleanup,
|
||||
} from "../helpers/utils";
|
||||
import { makeView, setupViewRegistries } from "../views/helpers";
|
||||
|
||||
@@ -391,4 +392,79 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
`preserve current scroll position on form view while closing dialog`,
|
||||
async function (assert) {
|
||||
serverData.views = {
|
||||
"partner,false,kanban": `
|
||||
<kanban>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_kanban_global_click">
|
||||
<field name="display_name" />
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
`,
|
||||
"partner,false,search": `
|
||||
<search />
|
||||
`,
|
||||
};
|
||||
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
resId: 2,
|
||||
serverData,
|
||||
arch: `
|
||||
<form>
|
||||
<sheet>
|
||||
<p style="height:500px" />
|
||||
<field name="trululu" />
|
||||
<p style="height:500px" />
|
||||
</sheet>
|
||||
</form>
|
||||
`,
|
||||
});
|
||||
|
||||
let position = { top: 0, left: 0 };
|
||||
patchWithCleanup(window, {
|
||||
scrollTo(newPosition) {
|
||||
position = newPosition;
|
||||
},
|
||||
get scrollX() {
|
||||
return position.left;
|
||||
},
|
||||
get scrollY() {
|
||||
return position.top;
|
||||
},
|
||||
});
|
||||
|
||||
await clickEdit(fixture);
|
||||
|
||||
window.scrollTo({ top: 265, left: 0 });
|
||||
assert.strictEqual(window.scrollY, 265, "Should have scrolled 265 px vertically");
|
||||
assert.strictEqual(window.screenLeft, 0, "Should be 0 px from left as it is");
|
||||
|
||||
// click on m2o field
|
||||
await click(fixture, ".o_field_many2one input");
|
||||
// assert.strictEqual(window.scrollY, 0, "Should have scrolled to top (0) px");
|
||||
assert.containsOnce(
|
||||
fixture,
|
||||
".modal.o_modal_full",
|
||||
"there should be a many2one modal opened in full screen"
|
||||
);
|
||||
|
||||
// click on back button
|
||||
await click(fixture, ".modal .modal-header .fa-arrow-left");
|
||||
assert.strictEqual(
|
||||
window.scrollY,
|
||||
265,
|
||||
"Should have scrolled back to 265 px vertically"
|
||||
);
|
||||
assert.strictEqual(window.screenLeft, 0, "Should be 0 px from left as it is");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user