mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
implement store, refactoring
This commit is contained in:
@@ -1,105 +0,0 @@
|
||||
import { IAjax } from "./ajax";
|
||||
import { Type } from "../core/component";
|
||||
import { EventBus } from "../core/event_bus";
|
||||
import { Registry } from "../core/registry";
|
||||
import { Widget } from "../widgets/widget";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export type ActionRequest = string | number;
|
||||
|
||||
export type Context = { [key: string]: any };
|
||||
|
||||
export interface CommonActionInfo {
|
||||
id: number;
|
||||
context: Context;
|
||||
title: string;
|
||||
target: "current" | "new";
|
||||
}
|
||||
|
||||
export type ActionWidget = Type<Widget<{}, {}>>;
|
||||
|
||||
export interface ClientActionInfo extends CommonActionInfo {
|
||||
type: "client";
|
||||
name: string;
|
||||
Widget: ActionWidget;
|
||||
}
|
||||
|
||||
export interface ActWindowInfo extends CommonActionInfo {
|
||||
type: "act_window";
|
||||
view: string;
|
||||
}
|
||||
|
||||
export interface ActionDescription {
|
||||
id: number;
|
||||
type: "ir.actions.act_window" | "ir.actions.client";
|
||||
target: "current";
|
||||
}
|
||||
|
||||
export type ActionInfo = ClientActionInfo | ActWindowInfo;
|
||||
export type ActionStack = ActionInfo[];
|
||||
|
||||
export type ActionEvent = "action_stack_updated";
|
||||
|
||||
type Callback = (stack: ActionStack) => void;
|
||||
|
||||
export interface IActionManager {
|
||||
doAction(request: ActionRequest): void;
|
||||
on(event: ActionEvent, owner: any, callback: Callback): void;
|
||||
getStack(): ActionStack;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Action Manager
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class ActionManager extends EventBus implements IActionManager {
|
||||
registry: Registry<ActionWidget>;
|
||||
ajax: IAjax;
|
||||
stack: ActionStack;
|
||||
|
||||
constructor(registry: Registry<ActionWidget>, ajax: IAjax) {
|
||||
super();
|
||||
this.registry = registry;
|
||||
this.ajax = ajax;
|
||||
this.stack = [];
|
||||
}
|
||||
|
||||
doAction(request: ActionRequest) {
|
||||
if (typeof request === "number") {
|
||||
this.loadAction(request);
|
||||
// this is an action ID
|
||||
let name = request === 131 ? "discuss" : "crm";
|
||||
let title =
|
||||
request === 131 ? "Discuss" : request === 250 ? "Notes" : "CRM";
|
||||
let Widget = this.registry.get(name);
|
||||
this.stack = [
|
||||
{
|
||||
id: 1,
|
||||
context: {},
|
||||
target: "current",
|
||||
type: "client",
|
||||
name,
|
||||
title,
|
||||
Widget: Widget
|
||||
}
|
||||
];
|
||||
this.trigger("action_stack_updated", this.stack);
|
||||
}
|
||||
}
|
||||
|
||||
private loadAction(id: number) {
|
||||
this.ajax.rpc({
|
||||
route: "web/action/load",
|
||||
params: {
|
||||
action_id: id
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getStack(): ActionStack {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
import { EventBus } from "../core/event_bus";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export interface RPCModelQuery {
|
||||
model: string;
|
||||
method: string;
|
||||
args?: any[];
|
||||
kwargs?: { [key: string]: any };
|
||||
context?: { [key: string]: any };
|
||||
}
|
||||
|
||||
export interface RPCControllerQuery {
|
||||
route: string;
|
||||
params: { [key: string]: any };
|
||||
}
|
||||
|
||||
export type RPCQuery = RPCModelQuery | RPCControllerQuery;
|
||||
|
||||
type AjaxStatus = "loading" | "notloading";
|
||||
|
||||
export interface IAjax {
|
||||
rpc(rpc: RPCQuery): Promise<any>;
|
||||
on(event: "rpc_status", owner: any, callback: (status: AjaxStatus) => void);
|
||||
}
|
||||
|
||||
interface RequestParameters {
|
||||
route: string;
|
||||
params: { [key: string]: any };
|
||||
}
|
||||
|
||||
export type FetchMethod = (route: string, params: any) => Promise<any>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Ajax
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class Ajax extends EventBus implements IAjax {
|
||||
fetch: FetchMethod;
|
||||
counter: number = 0;
|
||||
|
||||
constructor(fetch: FetchMethod) {
|
||||
super();
|
||||
this.fetch = fetch;
|
||||
}
|
||||
|
||||
async rpc(rpc: RPCQuery): Promise<any> {
|
||||
const request = this.prepareRequest(rpc);
|
||||
if (this.counter === 0) {
|
||||
this.trigger("rpc_status", "loading");
|
||||
}
|
||||
this.counter++;
|
||||
const result = await this.fetch(request.route, request.params);
|
||||
this.counter--;
|
||||
if (this.counter === 0) {
|
||||
this.trigger("rpc_status", "notloading");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private prepareRequest(query: RPCQuery): RequestParameters {
|
||||
let route: string;
|
||||
let params = "params" in query ? query.params : {};
|
||||
if ("route" in query) {
|
||||
route = query.route;
|
||||
} else if ("model" in query && "method" in query) {
|
||||
route = `/web/dataset/call_kw/${query.model}/${query.method}`;
|
||||
params.args = query.args || [];
|
||||
params.model = query.model;
|
||||
params.method = query.method;
|
||||
params.kwargs = Object.assign(params.kwargs || {}, query.kwargs);
|
||||
params.kwargs.context =
|
||||
query.context || params.context || params.kwargs.context;
|
||||
} else {
|
||||
throw new Error("Invalid Query");
|
||||
}
|
||||
|
||||
// doing this remove empty keys, and undefined stuff
|
||||
const sanitizedParams = JSON.parse(JSON.stringify(params));
|
||||
return { route, params: sanitizedParams };
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import { EventBus as Bus } from "../core/event_bus";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export interface INotification {
|
||||
id: number;
|
||||
title: string;
|
||||
message: string;
|
||||
type: "notification" | "warning";
|
||||
sticky: boolean;
|
||||
}
|
||||
|
||||
export interface INotificationManager {
|
||||
add(notif: Partial<INotification>): number;
|
||||
close(id: number): void;
|
||||
on(
|
||||
event: "notification_added",
|
||||
owner: any,
|
||||
callback: (notif: INotification) => void
|
||||
): void;
|
||||
on(
|
||||
event: "notification_closed",
|
||||
owner: any,
|
||||
callback: (id: number) => void
|
||||
): void;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Notification Manager
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class NotificationManager extends Bus implements INotificationManager {
|
||||
nextID = 1;
|
||||
|
||||
add(notif: Partial<INotification>): number {
|
||||
const id = this.nextID++;
|
||||
const defaultVals = {
|
||||
title: "",
|
||||
message: "",
|
||||
type: "notification",
|
||||
sticky: false
|
||||
};
|
||||
const notification = Object.assign(defaultVals, notif, { id });
|
||||
this.trigger("notification_added", notification);
|
||||
if (!notification.sticky) {
|
||||
setTimeout(() => this.close(id), 2500);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
close(id: number) {
|
||||
this.trigger("notification_closed", id);
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import { EventBus, Callback } from "../core/event_bus";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types and helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export type Query = { [key: string]: string };
|
||||
|
||||
function clearSlashes(s: string): string {
|
||||
return s.replace(/\/$/, "").replace(/^\//, "");
|
||||
}
|
||||
|
||||
export type RouterEvent = "query_changed";
|
||||
|
||||
export interface IRouter {
|
||||
navigate(query: Query): void;
|
||||
on(event: RouterEvent, owner: any, callback: Callback): void;
|
||||
getQuery(): Query;
|
||||
formatURL(path: string, query: Query): string;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Router
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class Router extends EventBus implements IRouter {
|
||||
currentQuery: Query;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.currentQuery = this.getQuery();
|
||||
window.onhashchange = () => {
|
||||
this.currentQuery = this.getQuery();
|
||||
this.trigger("query_changed", this.currentQuery);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Query} query
|
||||
*/
|
||||
navigate(query: Query) {
|
||||
const url = this.formatURL("", query);
|
||||
window.history.replaceState(null, document.title, url);
|
||||
}
|
||||
|
||||
formatQuery(query: Query): string {
|
||||
let parts: string[] = [];
|
||||
for (let key in query) {
|
||||
parts.push(`${key}=${query[key]}`);
|
||||
}
|
||||
return parts.join("&");
|
||||
}
|
||||
|
||||
formatURL(path: string, query: Query): string {
|
||||
let url = clearSlashes(path);
|
||||
return `/${url}#${this.formatQuery(query)}`;
|
||||
}
|
||||
|
||||
getQuery(): Query {
|
||||
const query = {};
|
||||
for (let part of window.location.hash.slice(1).split("&")) {
|
||||
let [key, value] = part.split("=");
|
||||
query[key] = value;
|
||||
}
|
||||
return query;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user