Fix mobile UI for faculty/admin backend dashboard
The faculty/admin backend (sidebar, top nav, dashboard widgets) had zero mobile responsiveness, unlike the login page and student portal which already had proper breakpoints. On a phone the fixed 260px sidebar plus its unconditional margin-left permanently ate most of the screen, and the dashboard's KPI/chart/widget rows used fixed CSS grid columns with no stacking. - sidebar.xml: sidebar goes off-canvas below 768px with a hamburger toggle and tap-to-close backdrop, instead of always being visible - backend_forms.scss: content margin-left and the forced display:flex/overflow:visible on the top menu are now scoped to desktop only, restoring Odoo's native d-none d-md-flex mobile hide that the override was defeating - education_dashboard_templates.xml: KPI/chart/widget grids stack to 2-col/1-col under 768px/420px instead of staying fixed at 5/3 cols Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
faf9e75849
commit
2ac9656203
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<templates xml:space="preserve">
|
<templates xml:space="preserve">
|
||||||
<t t-name="education_dashboard.DashboardMain">
|
<t t-name="education_dashboard.DashboardMain">
|
||||||
<div style="background:#eef9f9; padding:20px 24px 40px 24px; font-family:-apple-system,BlinkMacSystemFont,'Inter',sans-serif;">
|
<div class="edu-dashboard-root" style="background:#eef9f9; padding:20px 24px 40px 24px; font-family:-apple-system,BlinkMacSystemFont,'Inter',sans-serif;">
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.edu-card { background:#fff; border-radius:14px; border:1px solid #e2e8f0; box-shadow:0 2px 12px rgba(15,23,42,0.06); }
|
.edu-card { background:#fff; border-radius:14px; border:1px solid #e2e8f0; box-shadow:0 2px 12px rgba(15,23,42,0.06); }
|
||||||
@ -17,10 +17,28 @@
|
|||||||
.edu-ann-row { display:flex; gap:10px; padding:9px 0; border-bottom:1px solid #f1f5f9; align-items:flex-start; }
|
.edu-ann-row { display:flex; gap:10px; padding:9px 0; border-bottom:1px solid #f1f5f9; align-items:flex-start; }
|
||||||
.edu-ann-row:last-child { border-bottom:none; }
|
.edu-ann-row:last-child { border-bottom:none; }
|
||||||
.edu-pill { padding:3px 9px; border-radius:20px; font-size:0.68rem; font-weight:700; flex-shrink:0; }
|
.edu-pill { padding:3px 9px; border-radius:20px; font-size:0.68rem; font-weight:700; flex-shrink:0; }
|
||||||
|
|
||||||
|
/* ── Responsive overrides (!important needed to beat inline styles) ── */
|
||||||
|
@media (max-width: 1100px) {
|
||||||
|
.edu-charts-grid { grid-template-columns: 1fr 1fr !important; }
|
||||||
|
.edu-charts-grid > :last-child { grid-column: 1 / -1 !important; }
|
||||||
|
}
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.edu-dashboard-root { padding: 14px 14px 32px 14px !important; }
|
||||||
|
.edu-welcome-banner { flex-direction: column !important; align-items: flex-start !important; gap: 16px !important; padding: 20px !important; }
|
||||||
|
.edu-welcome-banner > :last-child { text-align: left !important; flex-direction: row !important; flex-wrap: wrap !important; }
|
||||||
|
.edu-kpi-grid { grid-template-columns: repeat(2, 1fr) !important; }
|
||||||
|
.edu-charts-grid { grid-template-columns: 1fr !important; }
|
||||||
|
.edu-charts-grid > :last-child { grid-column: auto !important; }
|
||||||
|
.edu-bottom-grid { grid-template-columns: 1fr !important; }
|
||||||
|
}
|
||||||
|
@media (max-width: 420px) {
|
||||||
|
.edu-kpi-grid { grid-template-columns: 1fr !important; }
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- ── WELCOME BANNER ─────────────────────────────────────── -->
|
<!-- ── WELCOME BANNER ─────────────────────────────────────── -->
|
||||||
<div style="background:linear-gradient(135deg,rgba(31,143,143,0.65) 0%,rgba(20,77,77,0.70) 55%,rgba(13,53,53,0.75) 100%), url('/education_dashboard/static/src/img/dashboard-bg.png'); background-size:cover; background-position:center 60%; border-radius:16px; padding:26px 32px; margin-bottom:20px; display:flex; align-items:center; justify-content:space-between; position:relative; overflow:hidden;">
|
<div class="edu-welcome-banner" style="background:linear-gradient(135deg,rgba(31,143,143,0.65) 0%,rgba(20,77,77,0.70) 55%,rgba(13,53,53,0.75) 100%), url('/education_dashboard/static/src/img/dashboard-bg.png'); background-size:cover; background-position:center 60%; border-radius:16px; padding:26px 32px; margin-bottom:20px; display:flex; align-items:center; justify-content:space-between; position:relative; overflow:hidden;">
|
||||||
<div style="position:absolute;top:-30px;right:200px;width:180px;height:180px;border-radius:50%;background:rgba(255,255,255,0.05);pointer-events:none;"></div>
|
<div style="position:absolute;top:-30px;right:200px;width:180px;height:180px;border-radius:50%;background:rgba(255,255,255,0.05);pointer-events:none;"></div>
|
||||||
<div style="position:absolute;bottom:-40px;right:60px;width:240px;height:240px;border-radius:50%;background:rgba(255,255,255,0.04);pointer-events:none;"></div>
|
<div style="position:absolute;bottom:-40px;right:60px;width:240px;height:240px;border-radius:50%;background:rgba(255,255,255,0.04);pointer-events:none;"></div>
|
||||||
<div style="position:relative;z-index:1;">
|
<div style="position:relative;z-index:1;">
|
||||||
@ -39,7 +57,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── KPI CARDS ──────────────────────────────────────────── -->
|
<!-- ── KPI CARDS ──────────────────────────────────────────── -->
|
||||||
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:14px;margin-bottom:20px;">
|
<div class="edu-kpi-grid" style="display:grid;grid-template-columns:repeat(5,1fr);gap:14px;margin-bottom:20px;">
|
||||||
<div class="edu-kpi" t-on-click="() => this.openStudents('')">
|
<div class="edu-kpi" t-on-click="() => this.openStudents('')">
|
||||||
<div class="edu-icon" style="background:#e0f7f7;color:#1f8f8f;"><i class="fa fa-users"/></div>
|
<div class="edu-icon" style="background:#e0f7f7;color:#1f8f8f;"><i class="fa fa-users"/></div>
|
||||||
<div>
|
<div>
|
||||||
@ -78,7 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── CHARTS + QUICK ACTIONS ─────────────────────────────── -->
|
<!-- ── CHARTS + QUICK ACTIONS ─────────────────────────────── -->
|
||||||
<div style="display:grid;grid-template-columns:5fr 4fr 3fr;gap:14px;margin-bottom:20px;">
|
<div class="edu-charts-grid" style="display:grid;grid-template-columns:5fr 4fr 3fr;gap:14px;margin-bottom:20px;">
|
||||||
|
|
||||||
<!-- Enrollment Trend -->
|
<!-- Enrollment Trend -->
|
||||||
<div class="edu-card" style="padding:20px;">
|
<div class="edu-card" style="padding:20px;">
|
||||||
@ -156,7 +174,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── BOTTOM ROW ─────────────────────────────────────────── -->
|
<!-- ── BOTTOM ROW ─────────────────────────────────────────── -->
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px;margin-bottom:20px;">
|
<div class="edu-bottom-grid" style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px;margin-bottom:20px;">
|
||||||
|
|
||||||
<!-- Upcoming Examinations -->
|
<!-- Upcoming Examinations -->
|
||||||
<div class="edu-card" style="padding:20px;">
|
<div class="edu-card" style="padding:20px;">
|
||||||
|
|||||||
@ -28,9 +28,13 @@ body.o_web_client {
|
|||||||
height: 100% !important; // fill the available viewport height
|
height: 100% !important; // fill the available viewport height
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only push content when our custom sidebar is present
|
// Only push content when our custom sidebar is present (desktop only —
|
||||||
body.o_web_client:has(.o_sidebar_custom) .o_action_manager {
|
// below 768px the sidebar goes off-canvas, see sidebar.xml, so content
|
||||||
|
// must stay full-width instead of leaving a permanent 260px gap)
|
||||||
|
@media (min-width: 769px) {
|
||||||
|
body.o_web_client:has(.o_sidebar_custom) .o_action_manager {
|
||||||
margin-left: 260px;
|
margin-left: 260px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inner content containers — let them grow freely
|
// Inner content containers — let them grow freely
|
||||||
@ -60,13 +64,20 @@ body.o_web_client:has(.o_sidebar_custom) .o_action_manager {
|
|||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure horizontal menus are always visible in the header
|
// Ensure horizontal menus are always visible in the header — desktop only.
|
||||||
|
// Odoo's own navbar.xml marks .o_menu_sections/.o_menu_brand "d-none d-md-flex"
|
||||||
|
// (hidden under 768px) and relies on that for mobile; forcing display:flex
|
||||||
|
// unconditionally here defeated that native hide and the overflow "more"
|
||||||
|
// dropdown. Below 768px the custom sidebar (see sidebar.xml) is the nav
|
||||||
|
// instead, so let the top menu fall back to Odoo's native hidden state.
|
||||||
|
@media (min-width: 769px) {
|
||||||
.o_menu_sections {
|
.o_menu_sections {
|
||||||
display: flex !important;
|
display: flex !important;
|
||||||
flex-grow: 1 !important;
|
flex-grow: 1 !important;
|
||||||
align-items: center !important;
|
align-items: center !important;
|
||||||
overflow: visible !important;
|
overflow: visible !important;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Explicitly override Odoo's internal enterprise variables
|
// Explicitly override Odoo's internal enterprise variables
|
||||||
.o_menu_sections .o_nav_entry, .o_menu_sections .dropdown-toggle {
|
.o_menu_sections .o_nav_entry, .o_menu_sections .dropdown-toggle {
|
||||||
|
|||||||
@ -5,10 +5,37 @@
|
|||||||
<xpath expr="//nav" position="inside">
|
<xpath expr="//nav" position="inside">
|
||||||
|
|
||||||
<t t-if="currentApp and currentApp.name === 'Education'">
|
<t t-if="currentApp and currentApp.name === 'Education'">
|
||||||
|
<!-- Mobile hamburger toggle: hidden by default, shown only below 768px (Odoo's own "md" breakpoint) -->
|
||||||
|
<!-- Centered: Odoo's own app-switcher icon (left) and systray (right)
|
||||||
|
stay visible on mobile natively, so the center is the open slot
|
||||||
|
once the brand name / section menu hide below 768px. -->
|
||||||
|
<div id="eduSidebarToggle"
|
||||||
|
onclick="document.querySelector('.o_sidebar_custom').classList.add('o_sidebar_open'); document.querySelector('.o_sidebar_backdrop').classList.add('o_sidebar_open');"
|
||||||
|
style="display:none; position:fixed; top:14px; left:50%; transform:translateX(-50%); z-index:111; width:42px; height:42px; border-radius:10px; background:rgba(0,0,0,0.25); color:#fff; align-items:center; justify-content:center; cursor:pointer;">
|
||||||
|
<i class="fa fa-bars" style="font-size:1.1rem;"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Backdrop: closes sidebar on outside tap, mobile only -->
|
||||||
|
<div class="o_sidebar_backdrop"
|
||||||
|
onclick="document.querySelector('.o_sidebar_custom').classList.remove('o_sidebar_open'); this.classList.remove('o_sidebar_open');"
|
||||||
|
style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.4); z-index:89;"/>
|
||||||
|
|
||||||
<div class="o_sidebar_custom d-flex flex-column position-fixed"
|
<div class="o_sidebar_custom d-flex flex-column position-fixed"
|
||||||
style="top: 70px; bottom: 0; left: 0; width: 260px; background: linear-gradient(135deg, #1f8f8f 0%, #144d4d 55%, #0d3d3d 100%); border-right: 1px solid rgba(255,255,255,0.1); z-index: 90; padding-top: 10px; overflow-y: auto; box-shadow: 2px 0 10px rgba(0,0,0,0.1); color: white;">
|
style="top: 70px; bottom: 0; left: 0; width: 260px; background: linear-gradient(135deg, #1f8f8f 0%, #144d4d 55%, #0d3d3d 100%); border-right: 1px solid rgba(255,255,255,0.1); z-index: 90; padding-top: 10px; overflow-y: auto; box-shadow: 2px 0 10px rgba(0,0,0,0.1); color: white;">
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* ── Mobile: off-canvas sidebar + visible hamburger/backdrop ── */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
#eduSidebarToggle { display: flex !important; }
|
||||||
|
.o_sidebar_custom {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
transition: transform 0.25s ease;
|
||||||
|
width: 80vw !important;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
.o_sidebar_custom.o_sidebar_open { transform: translateX(0); }
|
||||||
|
.o_sidebar_backdrop.o_sidebar_open { display: block !important; }
|
||||||
|
}
|
||||||
.o_sidebar_custom .sidebar-link {
|
.o_sidebar_custom .sidebar-link {
|
||||||
display: flex; align-items: center; padding: 8px 16px;
|
display: flex; align-items: center; padding: 8px 16px;
|
||||||
margin: 2px 8px; border-radius: 8px; color: rgba(255,255,255,0.9);
|
margin: 2px 8px; border-radius: 8px; color: rgba(255,255,255,0.9);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user