preliminary support for home menu

This commit is contained in:
Géry Debongnie
2019-01-31 10:55:41 +01:00
parent 25da2b2230
commit bac075dbbd
7 changed files with 105 additions and 41 deletions
+6 -4
View File
@@ -26,11 +26,13 @@ body {
color: white; color: white;
display: flex; display: flex;
line-height: $navbar-height; line-height: $navbar-height;
font-size: 18px;
span.title { a.o_title {
font-size: 24px; padding: 10px 16px 16px 20px;
font-weight: bold; &:hover {
padding: 0 16px; background-color: #68465f;
}
} }
ul { ul {
+50 -27
View File
@@ -1,50 +1,69 @@
import { Widget } from "./core/widget"; import { Widget } from "./core/widget";
import { Navbar } from "./widgets/navbar";
import { ActionWidget } from "./services/action_manager";
import { INotification } from "./services/notifications";
import { Notification } from "./widgets/notification";
import { Env } from "./env"; import { Env } from "./env";
import { INotification } from "./services/notifications";
import { Action } from "./widgets/action";
import { HomeMenu } from "./widgets/home_menu";
import { Navbar } from "./widgets/navbar";
import { Notification } from "./widgets/notification";
const template = ` const template = `
<div class="o_web_client"> <div class="o_web_client">
<t t-widget="Navbar"/> <t t-widget="Navbar" t-props="{toggleHomeMenu:toggleHomeMenu,inMenu:state.inMenu}"/>
<div class="o_content" t-ref="content"/> <t t-if="state.inMenu">
<div class="o_notification_container"> <t t-widget="HomeMenu" t-props="{toggleHomeMenu:toggleHomeMenu}"/>
<t t-foreach="state.notifications" t-as="notif"> </t>
<t t-widget="Notification" t-props="notif"/> <t t-else="1">
</t> <t t-widget="Action" t-keep-alive="1"/>
</div> </t>
<div class="o_notification_container">
<t t-foreach="state.notifications" t-as="notif">
<t t-widget="Notification" t-props="notif"/>
</t>
</div>
</div> </div>
`; `;
interface State {
notifications: INotification[];
inMenu: boolean;
}
export class Root extends Widget<Env, {}> { export class Root extends Widget<Env, {}> {
name = "root"; name = "root";
template = template; template = template;
widgets = { Navbar, Notification }; widgets = { Navbar, Notification, HomeMenu, Action };
content: Widget<Env, {}> | null = null; content: Widget<Env, {}> | null = null;
state: { notifications: INotification[] } = { notifications: [] }; state: State = {
notifications: [],
inMenu: false
};
constructor(env: Env) {
super(env);
this.toggleHomeMenu = this.toggleHomeMenu.bind(this);
}
mounted() { mounted() {
this.env.actionManager.on("action_ready", this, this.setContentWidget); // this.env.actionManager.on("action_ready", this, this.setContentWidget);
this.env.notifications.on("notification_added", this, this.addNotif); this.env.notifications.on("notification_added", this, this.addNotif);
this.env.notifications.on("notification_removed", this, this.removeNotif); this.env.notifications.on("notification_removed", this, this.removeNotif);
const actionWidget = this.env.actionManager.getCurrentAction(); // const actionWidget = this.env.actionManager.getCurrentAction();
if (actionWidget) { // if (actionWidget) {
this.setContentWidget(actionWidget); // this.setContentWidget(actionWidget);
} // }
} }
async setContentWidget(actionWidget: ActionWidget) { // async setContentWidget(actionWidget: ActionWidget) {
const currentWidget = this.content; // const currentWidget = this.content;
const newWidget = new actionWidget.Widget(this, actionWidget.props); // const newWidget = new actionWidget.Widget(this, actionWidget.props);
await newWidget.mount(<HTMLElement>this.refs.content); // await newWidget.mount(<HTMLElement>this.refs.content);
if (currentWidget) { // if (currentWidget) {
currentWidget.destroy(); // currentWidget.destroy();
} // }
this.content = newWidget; // this.content = newWidget;
} // }
addNotif(notif: INotification) { addNotif(notif: INotification) {
const notifications = this.state.notifications.concat(notif); const notifications = this.state.notifications.concat(notif);
@@ -54,4 +73,8 @@ export class Root extends Widget<Env, {}> {
const notifs = this.state.notifications.filter(f => f.id !== notif.id); const notifs = this.state.notifications.filter(f => f.id !== notif.id);
this.updateState({ notifications: notifs }); this.updateState({ notifications: notifs });
} }
toggleHomeMenu() {
this.updateState({ inMenu: !this.state.inMenu });
}
} }
+14
View File
@@ -0,0 +1,14 @@
import { Widget } from "../core/widget";
import { Env } from "../env";
const template = `
<div class="o_content">
<span>MAIN ACTION</span>
<input/>
</div>
`;
export class Action extends Widget<Env, {}> {
name = "action";
template = template;
}
+13 -3
View File
@@ -3,8 +3,8 @@ import { Env, Menu } from "../env";
const template = ` const template = `
<div class="o_navbar"> <div class="o_navbar">
<span class="title">Odoo<t t-if="env.isMobile"> MOBILE</t></span> <a aria-label="Applications" class="o_title fa fa-th" href="#" title="Applications" accesskey="h" t-on-click="toggleHomeMenu"/>
<ul> <ul t-if="!props.inMenu">
<li t-foreach="env.menus" t-as="menu"> <li t-foreach="env.menus" t-as="menu">
<a t-att-href="getUrl(menu)"> <a t-att-href="getUrl(menu)">
<t t-esc="menu.title"/> <t t-esc="menu.title"/>
@@ -14,7 +14,12 @@ const template = `
</div> </div>
`; `;
export class Navbar extends Widget<Env, {}> { export interface Props {
toggleHomeMenu: () => void;
inMenu: boolean;
}
export class Navbar extends Widget<Env, Props> {
name = "navbar"; name = "navbar";
template = template; template = template;
@@ -22,4 +27,9 @@ export class Navbar extends Widget<Env, {}> {
const action_id = String(menu.actionID); const action_id = String(menu.actionID);
return this.env.router.formatURL("", { action_id }); return this.env.router.formatURL("", { action_id });
} }
toggleHomeMenu(ev: MouseEvent) {
ev.preventDefault();
this.props.toggleHomeMenu();
}
} }
+13
View File
@@ -0,0 +1,13 @@
import { Widget } from "../core/widget";
import { Env } from "../env";
const template = `
<div class="o_home_menu">
<span>HOME MENU</span>
</div>
`;
export class HomeMenu extends Widget<Env, {}> {
name = "home";
template = template;
}
@@ -2,7 +2,7 @@
exports[`can be rendered 1`] = ` exports[`can be rendered 1`] = `
"<div class=\\"o_navbar\\"> "<div class=\\"o_navbar\\">
<span class=\\"title\\">Odoo</span> <a aria-label=\\"Applications\\" class=\\"o_title fa fa-th\\" href=\\"#\\" title=\\"Applications\\" accesskey=\\"h\\"></a>
<ul> <ul>
</ul> </ul>
@@ -11,7 +11,7 @@ exports[`can be rendered 1`] = `
exports[`can render one menu item 1`] = ` exports[`can render one menu item 1`] = `
"<div class=\\"o_navbar\\"> "<div class=\\"o_navbar\\">
<span class=\\"title\\">Odoo</span> <a aria-label=\\"Applications\\" class=\\"o_title fa fa-th\\" href=\\"#\\" title=\\"Applications\\" accesskey=\\"h\\"></a>
<ul> <ul>
<li> <li>
<a href=\\"\\"> <a href=\\"\\">
@@ -24,7 +24,7 @@ exports[`can render one menu item 1`] = `
exports[`mobile mode: navbar is different 1`] = ` exports[`mobile mode: navbar is different 1`] = `
"<div class=\\"o_navbar\\"> "<div class=\\"o_navbar\\">
<span class=\\"title\\">Odoo MOBILE</span> <a aria-label=\\"Applications\\" class=\\"o_title fa fa-th\\" href=\\"#\\" title=\\"Applications\\" accesskey=\\"h\\"></a>
<ul> <ul>
</ul> </ul>
+6 -4
View File
@@ -1,5 +1,5 @@
import { Env } from "../../src/ts/env"; import { Env } from "../../src/ts/env";
import { Navbar } from "../../src/ts/widgets/navbar"; import { Navbar, Props } from "../../src/ts/widgets/navbar";
import { makeTestEnv, makeTestFixture } from "../helpers"; import { makeTestEnv, makeTestFixture } from "../helpers";
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -8,10 +8,12 @@ import { makeTestEnv, makeTestFixture } from "../helpers";
let fixture: HTMLElement; let fixture: HTMLElement;
let env: Env; let env: Env;
let props: Props;
beforeEach(() => { beforeEach(() => {
fixture = makeTestFixture(); fixture = makeTestFixture();
env = makeTestEnv(); env = makeTestEnv();
props = { inMenu: false, toggleHomeMenu: () => {} };
}); });
afterEach(() => { afterEach(() => {
@@ -23,21 +25,21 @@ afterEach(() => {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
test("can be rendered", async () => { test("can be rendered", async () => {
const navbar = new Navbar(env); const navbar = new Navbar(env, props);
await navbar.mount(fixture); await navbar.mount(fixture);
expect(fixture.innerHTML).toMatchSnapshot(); expect(fixture.innerHTML).toMatchSnapshot();
}); });
test("can render one menu item", async () => { test("can render one menu item", async () => {
env.menus.push({ title: "menu", actionID: 4 }); env.menus.push({ title: "menu", actionID: 4 });
const navbar = new Navbar(env); const navbar = new Navbar(env, props);
await navbar.mount(fixture); await navbar.mount(fixture);
expect(fixture.innerHTML).toMatchSnapshot(); expect(fixture.innerHTML).toMatchSnapshot();
}); });
test("mobile mode: navbar is different", async () => { test("mobile mode: navbar is different", async () => {
env.isMobile = true; env.isMobile = true;
const navbar = new Navbar(env); const navbar = new Navbar(env, props);
await navbar.mount(fixture); await navbar.mount(fixture);
expect(fixture.innerHTML).toMatchSnapshot(); expect(fixture.innerHTML).toMatchSnapshot();
}); });