[IMP] website: improve frontend mini UI navbar
- Make the animation smoother and less prompt to bad UX:
1. The animation duration of the closing part is now slower. Somehow
it looked like the closing animation was faster than the opening.
2. The animation delay of the closing part is now bigger. It will
prevent some weird UX issues when the cursor is moving out of
the window by mistake (eg moving a bit too far in the bookmarks
bar or the Ubuntu left panel for instance). In those case, despite
the user wanting to open and click inside the navbar, it would
directly close it.
- Make the edit button only visible for editors
- Make the go to backend button only visible for internal users (not
portal anymore)
- Restore a behavior that was lost during the frontend > backend task
[1]: clicking on the app switcher in community should show the list of
apps so you can directly access where you want to go in the backend.
It improves the usability in community where you otherwise have to
click twice every time as the first click always brings you to the
discuss module from where you have to click again on the app switcher
to select the app you wanted to land on.
[1]: https://github.com/odoo/odoo/commit/31cc10b91dc7762e23b4bde9b945be0c4ce3fe3b
closes odoo/odoo#97745
Related: odoo/enterprise#30218
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { session } from '@web/session';
|
||||
// import { _t } from "@web/core/l10n/translation"; // FIXME don't know why it does not work
|
||||
const _t = str => str;
|
||||
|
||||
/**
|
||||
* This script, served with frontend pages, displays buttons in the top left
|
||||
@@ -16,62 +14,22 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
if (!window.frameElement) {
|
||||
const websiteId = document.documentElement.dataset.websiteId;
|
||||
const {pathname, search} = window.location;
|
||||
const params = new URLSearchParams(search);
|
||||
const enableEditor = params.get('enable_editor');
|
||||
const editTranslations = params.get('edit_translations');
|
||||
params.delete('enable_editor');
|
||||
let newSearch = params.toString();
|
||||
if (newSearch) {
|
||||
newSearch = '?' + newSearch;
|
||||
const frontendToBackendNavEl = document.querySelector('.o_frontend_to_backend_nav');
|
||||
if (frontendToBackendNavEl) {
|
||||
frontendToBackendNavEl.classList.add('d-flex');
|
||||
frontendToBackendNavEl.classList.remove('d-none');
|
||||
}
|
||||
const backendPath = `/web#action=website.website_preview&path=${encodeURIComponent(`${pathname}${newSearch}`)}&website_id=${websiteId}`;
|
||||
|
||||
const autoredirectToBackendAction = enableEditor || editTranslations;
|
||||
if (autoredirectToBackendAction) {
|
||||
// Auto redirect to frontend if edit/translation mode is requested
|
||||
const currentUrl = new URL(window.location.href);
|
||||
currentUrl.pathname = `/@${currentUrl.pathname}`;
|
||||
if (currentUrl.searchParams.get('enable_editor') || currentUrl.searchParams.get('edit_translations')) {
|
||||
document.body.innerHTML = '';
|
||||
if (enableEditor) {
|
||||
window.location.replace(`${backendPath}&enable_editor=1`);
|
||||
} else if (editTranslations) {
|
||||
window.location.replace(`${backendPath}&edit_translations=1`);
|
||||
} else {
|
||||
window.location.replace(backendPath);
|
||||
}
|
||||
} else {
|
||||
// FIXME this UI does not respect access rights yet but we will
|
||||
// probably end up doing it in XML instead of JS anyway.
|
||||
const frontendToBackendBtnClasses = ['position-relative', 'd-flex', 'align-items-center', 'justify-content-center', 'text-decoration-none'];
|
||||
const frontendToBackendNavEl = document.createElement('div');
|
||||
frontendToBackendNavEl.classList.add('o_frontend_to_backend_nav', 'position-fixed', 'd-flex');
|
||||
|
||||
const loadingIconEl = document.createElementNS("http://www.w3.org/2000/svg", 'svg');
|
||||
loadingIconEl.classList.add('o_frontend_to_backend_icon', 'position-absolute');
|
||||
loadingIconEl.setAttribute('width', "24px");
|
||||
loadingIconEl.setAttribute('height', "24px");
|
||||
loadingIconEl.setAttribute('viewBox', "-7 -7 24 24");
|
||||
loadingIconEl.setAttribute('xmlns', "http://www.w3.org/2000/svg");
|
||||
loadingIconEl.setAttribute('preserveAspectRatio', "xMinYMin");
|
||||
loadingIconEl.innerHTML = "<path fill='#FFF' d='M8 8V1a1 1 0 1 1 2 0v8a1 1 0 0 1-1 1H1a1 1 0 1 1 0-2h7z'/>";
|
||||
frontendToBackendNavEl.appendChild(loadingIconEl);
|
||||
|
||||
const backendAppsButtonEl = document.createElement('a');
|
||||
backendAppsButtonEl.href = '/web';
|
||||
backendAppsButtonEl.title = _t("Go to your Odoo Apps");
|
||||
backendAppsButtonEl.classList.add('o_frontend_to_backend_apps_btn', 'fa', 'fa-th', ...frontendToBackendBtnClasses);
|
||||
frontendToBackendNavEl.appendChild(backendAppsButtonEl);
|
||||
|
||||
const backendEditButtonEl = document.createElement('a');
|
||||
backendEditButtonEl.href = backendPath;
|
||||
backendEditButtonEl.textContent = _t("Edit");
|
||||
backendEditButtonEl.title = _t("Edit this content");
|
||||
backendEditButtonEl.classList.add('o_frontend_to_backend_edit_btn', 'px-3', ...frontendToBackendBtnClasses);
|
||||
const backendEditButtonIconEl = document.createElement('i');
|
||||
backendEditButtonIconEl.classList.add('fa', 'fa-pencil', 'me-1');
|
||||
backendEditButtonEl.prepend(backendEditButtonIconEl);
|
||||
frontendToBackendNavEl.appendChild(backendEditButtonEl);
|
||||
|
||||
document.body.appendChild(frontendToBackendNavEl);
|
||||
window.location.replace(currentUrl.href);
|
||||
return;
|
||||
}
|
||||
const backendEditBtnEl = document.querySelector('.o_frontend_to_backend_edit_btn');
|
||||
if (backendEditBtnEl) {
|
||||
backendEditBtnEl.href = currentUrl.href;
|
||||
}
|
||||
} else {
|
||||
const backendUserDropdownLinkEl = document.getElementById('o_backend_user_dropdown_link');
|
||||
@@ -79,7 +37,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
backendUserDropdownLinkEl.classList.add('d-none');
|
||||
backendUserDropdownLinkEl.classList.remove('d-flex');
|
||||
}
|
||||
|
||||
// Multiple reasons to do this:
|
||||
// - It seems like DOMContentLoaded doesn't always trigger when
|
||||
// listened from the parent window
|
||||
|
||||
@@ -20,16 +20,29 @@ $-mini-nav-size: 40px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&::before, .o_frontend_to_backend_icon, .o_frontend_to_backend_apps_btn, .o_frontend_to_backend_edit_btn {
|
||||
&::before, .o_frontend_to_backend_icon, .o_frontend_to_backend_buttons {
|
||||
transform-origin: top left;
|
||||
transition: transform 400ms ease 0s;
|
||||
transition: transform 400ms ease 1s;
|
||||
}
|
||||
|
||||
.o_frontend_to_backend_apps_btn, .o_frontend_to_backend_edit_btn {
|
||||
min-width: $-mini-nav-size;
|
||||
height: $-mini-nav-size;
|
||||
color: #FFFFFF;
|
||||
.o_frontend_to_backend_buttons {
|
||||
transition-duration: 800ms;
|
||||
}
|
||||
|
||||
.o_frontend_to_backend_buttons {
|
||||
transform: translateX(-250%) scaleX(0.5);
|
||||
|
||||
> a {
|
||||
min-width: $-mini-nav-size;
|
||||
height: $-mini-nav-size;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
.o_frontend_to_backend_apps_menu {
|
||||
font-size: $o-font-size-base * ($o-root-font-size / 14px);
|
||||
max-height: 70vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@each $-name, $-color in ('edit': $o-enterprise-primary-color, 'apps': $o-enterprise-color) {
|
||||
@@ -45,10 +58,14 @@ $-mini-nav-size: 40px;
|
||||
&:hover {
|
||||
&:before, .o_frontend_to_backend_icon {
|
||||
transform: scale(.3);
|
||||
transition-delay: 0ms;
|
||||
transition-duration: 400ms;
|
||||
}
|
||||
|
||||
.o_frontend_to_backend_apps_btn, .o_frontend_to_backend_edit_btn {
|
||||
.o_frontend_to_backend_buttons {
|
||||
transform: translateX(0);
|
||||
transition-delay: 0ms;
|
||||
transition-duration: 400ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +176,23 @@
|
||||
<input t-if="optionName in main_object" type="hidden" class="o_page_option_data" autocomplete="off" t-att-name="optionName" t-att-value="main_object[optionName]"/>
|
||||
</t>
|
||||
</t>
|
||||
<div groups="base.group_user" class="o_frontend_to_backend_nav position-fixed d-none">
|
||||
<svg class="o_frontend_to_backend_icon position-absolute" width="24px" height="24px"
|
||||
viewBox="-7 -7 24 24" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin">
|
||||
<path fill="#FFF" d="M8 8V1a1 1 0 1 1 2 0v8a1 1 0 0 1-1 1H1a1 1 0 1 1 0-2h7z"/>
|
||||
</svg>
|
||||
<div class="o_frontend_to_backend_buttons d-flex">
|
||||
<a href="#" title="Go to your Odoo Apps" class="o_frontend_to_backend_apps_btn fa fa-th d-flex align-items-center justify-content-center text-decoration-none" data-bs-toggle="dropdown"/>
|
||||
<div class="dropdown-menu o_frontend_to_backend_apps_menu" role="menu">
|
||||
<a role="menuitem" class="dropdown-item" t-esc="menu['name']"
|
||||
t-as="menu" t-foreach="env['ir.ui.menu'].load_menus_root()['children']"
|
||||
t-attf-href="/web#menu_id=#{menu['id']}&action=#{menu['action'] and menu['action'].split(',')[1] or ''}"/>
|
||||
</div>
|
||||
<a groups="website.group_website_publisher" href="#" title="Edit this content" class="o_frontend_to_backend_edit_btn px-3 d-flex align-items-center justify-content-center text-decoration-none">
|
||||
<i class="fa fa-pencil me-1"/>Edit
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
<xpath expr="//div[@id='wrapwrap']" position="attributes">
|
||||
<attribute name="t-attf-class" add="#{'o_header_overlay' if 'header_overlay' in main_object and main_object.header_overlay else ''}" separator=" "/>
|
||||
|
||||
Reference in New Issue
Block a user