mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
preliminary support for home menu
This commit is contained in:
@@ -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
@@ -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 });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user