[REF] web: refactor notification system
This commit does some improvements on notification system: - move notification handling logic in service - remove use of __destroy - simplify types closes odoo-dev/odoo#955 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
committed by
Aaron Bohy
parent
85dfc9cf49
commit
d1b260b424
@@ -1,62 +1,25 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { Notification as NotificationComponent } from "./notification";
|
||||
import { Notification } from "./notification";
|
||||
|
||||
const { Component, tags } = owl;
|
||||
|
||||
export class NotificationContainer extends Component {
|
||||
setup() {
|
||||
this.notifications = [];
|
||||
this.props.bus.on("ADD", this, this.add);
|
||||
this.props.bus.on("REMOVE", this, this.remove);
|
||||
}
|
||||
__destroy() {
|
||||
this.props.bus.off("ADD", this, this.add);
|
||||
this.props.bus.off("REMOVE", this, this.remove);
|
||||
super.__destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} params
|
||||
* @param {number} params.id
|
||||
* @param {{
|
||||
* name: string;
|
||||
* icon?: string;
|
||||
* primary?: boolean;
|
||||
* onClick: () => void
|
||||
* }[]} params.buttons
|
||||
* @param {string} params.className
|
||||
* @param {string} params.message
|
||||
* @param {boolean} params.messageIsHtml
|
||||
* @param {() => void} params.onClose
|
||||
* @param {string} params.title
|
||||
* @param {"warning" | "danger" | "success" | "info"} params.type
|
||||
*/
|
||||
add(params) {
|
||||
const { id, ...props } = params;
|
||||
this.notifications.push({ id, props });
|
||||
this.render();
|
||||
}
|
||||
/**
|
||||
* @param {number} id
|
||||
*/
|
||||
remove(id) {
|
||||
const index = this.notifications.findIndex((n) => n.id === id);
|
||||
if (index > -1) {
|
||||
this.notifications.splice(index, 1);
|
||||
this.render();
|
||||
}
|
||||
// this works, but then this component cannot be unmounted, then
|
||||
// remounted. would need a destroyed hook different from willunmount
|
||||
this.props.bus.on("UPDATE", this, this.render);
|
||||
}
|
||||
}
|
||||
|
||||
NotificationContainer.template = tags.xml`
|
||||
<div class="o_notification_manager">
|
||||
<t t-foreach="notifications" t-as="notification" t-key="notification.id">
|
||||
<NotificationComponent
|
||||
<t t-foreach="props.notifications" t-as="notification" t-key="notification.id">
|
||||
<Notification
|
||||
t-props="notification.props"
|
||||
t-transition="o_notification_fade"
|
||||
t-on-close="remove(notification.id)"
|
||||
t-on-close="notification.close()"
|
||||
/>
|
||||
</t>
|
||||
</div>`;
|
||||
NotificationContainer.components = { NotificationComponent };
|
||||
NotificationContainer.components = { Notification };
|
||||
|
||||
@@ -8,50 +8,65 @@ const { EventBus } = owl.core;
|
||||
|
||||
const AUTOCLOSE_DELAY = 4000;
|
||||
|
||||
/**
|
||||
* @typedef {Object} NotificationButton
|
||||
* @property {string} name
|
||||
* @property {string} [icon]
|
||||
* @property {boolean} [primary]
|
||||
* @property {() => void} onClick
|
||||
*
|
||||
* @typedef {Object} NotificationOptions
|
||||
* @property {string} [title]
|
||||
* @property {"warning" | "danger" | "success" | "info"} [type]
|
||||
* @property {boolean} [sticky]
|
||||
* @property {string} [className]
|
||||
* @property {() => void} [onClose]
|
||||
* @property {NotificationButton} [buttons]
|
||||
*/
|
||||
|
||||
export const notificationService = {
|
||||
start() {
|
||||
let notifId = 0;
|
||||
let notifications = [];
|
||||
const bus = new EventBus();
|
||||
|
||||
registry.category("main_components").add("NotificationContainer", {
|
||||
Component: NotificationContainer,
|
||||
props: { bus },
|
||||
props: { bus, notifications },
|
||||
});
|
||||
|
||||
return {
|
||||
bus,
|
||||
/**
|
||||
* @param {string} message
|
||||
* @param {Object} [options]
|
||||
* @param {{
|
||||
* name: string;
|
||||
* icon?: string;
|
||||
* primary?: boolean;
|
||||
* onClick: () => void
|
||||
* }[]} [options.buttons]
|
||||
* @param {string} [options.className]
|
||||
* @param {boolean} [options.messageIsHtml]
|
||||
* @param {() => void} [options.onClose]
|
||||
* @param {boolean} [options.sticky]
|
||||
* @param {string} [options.title]
|
||||
* @param {"warning" | "danger" | "success" | "info"} [options.type]
|
||||
*/
|
||||
add(message, options = {}) {
|
||||
const notif = Object.assign({}, options, {
|
||||
id: ++notifId,
|
||||
message,
|
||||
});
|
||||
const sticky = notif.sticky;
|
||||
delete notif.sticky;
|
||||
bus.trigger("ADD", notif);
|
||||
if (!sticky) {
|
||||
browser.setTimeout(() => bus.trigger("REMOVE", notif.id), AUTOCLOSE_DELAY);
|
||||
}
|
||||
return () => {
|
||||
bus.trigger("REMOVE", notif.id);
|
||||
};
|
||||
},
|
||||
};
|
||||
/**
|
||||
* @param {string} message
|
||||
* @param {NotificationOptions} [options]
|
||||
*/
|
||||
function add(message, options = {}) {
|
||||
const id = ++notifId;
|
||||
const props = Object.assign({}, options, { message });
|
||||
const sticky = props.sticky;
|
||||
delete props.sticky;
|
||||
const closeFn = () => close(id);
|
||||
const notification = {
|
||||
id,
|
||||
props,
|
||||
close: closeFn,
|
||||
};
|
||||
notifications.push(notification);
|
||||
bus.trigger("UPDATE");
|
||||
if (!sticky) {
|
||||
browser.setTimeout(closeFn, AUTOCLOSE_DELAY);
|
||||
}
|
||||
return closeFn;
|
||||
}
|
||||
|
||||
function close(id) {
|
||||
const index = notifications.findIndex((n) => n.id === id);
|
||||
if (index > -1) {
|
||||
notifications.splice(index, 1);
|
||||
bus.trigger("UPDATE");
|
||||
}
|
||||
}
|
||||
|
||||
return { add };
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user