Szolgáltatások

A szolgáltatások hosszú élettartamú kódrészek, amelyek egy funkciót biztosítanak. Importálhatók komponensek által (useService-szel) vagy más szolgáltatások által. Továbbá, deklarálhatnak egy függőségi halmazt. Ebben az értelemben a szolgáltatások alapvetően egy DI függőség injektálási rendszer. Például a notification szolgáltatás lehetőséget biztosít egy értesítés megjelenítésére, vagy az rpc szolgáltatás a megfelelő módja annak, hogy kérést hajtsunk végre az Odoo szerver felé.

A következő példa regisztrál egy egyszerű szolgáltatást, amely 5 másodpercenként megjelenít egy értesítést:

import { registry } from "@web/core/registry";

const myService = {
    dependencies: ["notification"],
    start(env, { notification }) {
        let counter = 1;
        setInterval(() => {
            notification.add(`Tick Tock ${counter++}`);
        }, 5000);
    }
};

registry.category("services").add("myService", myService);

Induláskor a web kliens elindítja az összes szolgáltatást, amely jelen van a services regisztrációs táblában. Vegyük figyelembe, hogy a regisztrációs táblában használt név a szolgáltatás neve.

Megjegyzés

A legtöbb kód, amely nem komponens, csomagolva kell legyen egy szolgáltatásban, különösen, ha valamilyen mellékhatást fejt ki. Ez nagyon hasznos tesztelési célokra: a tesztek kiválaszthatják, mely szolgáltatások aktívak, így kisebb az esélye annak, hogy nem kívánt mellékhatások zavarják a tesztelt kódot.

Szolgáltatás definiálása

Egy szolgáltatásnak a következő interfészt kell megvalósítania:

dependencies

Opcionális karakterlánc lista. Ez a lista tartalmazza az összes függőséget (más szolgáltatásokat), amelyekre ennek a szolgáltatásnak szüksége van

start(env, deps)
Argumentum
  • env (Environment()) – az alkalmazás környezete

  • deps (Object()) – az összes kért függőség

Visszatérési érték

a szolgáltatás értéke vagy Promise<szolgáltatás értéke>

Ez a szolgáltatás fő definíciója. Visszaadhat egy értéket vagy egy ígéretet. Ebben az esetben a szolgáltatás betöltője egyszerűen megvárja, amíg az ígéret egy értékre oldódik fel, amely aztán a szolgáltatás értéke lesz.

Néhány szolgáltatás nem exportál semmilyen értéket. Lehet, hogy csak elvégzik a munkájukat anélkül, hogy más kód közvetlenül hívná őket. Ebben az esetben az értékük null lesz az env.services-ben.

async

Opcionális érték. Ha meg van adva, akkor true vagy egy karakterláncok listája kell legyen.

Néhány szolgáltatásnak aszinkron API-t kell biztosítania. Például az rpc szolgáltatás egy aszinkron függvény, vagy az orm szolgáltatás egy sor függvényt biztosít az Odoo szerver hívásához.

Ebben az esetben lehetséges, hogy a szolgáltatást használó komponensek megsemmisülnek az aszinkron függvényhívás vége előtt. A legtöbb esetben az aszinkron függvényhívást figyelmen kívül kell hagyni. Másképp cselekedni potenciálisan nagyon kockázatos, mert az alapul szolgáló komponens már nem aktív. Az async jelző egy módja annak, hogy ezt megtegyük: jelzi a szolgáltatás létrehozójának, hogy minden aszinkron hívást, amely a komponensekből érkezik, függőben kell hagyni, ha a komponens megsemmisül.

Szolgáltatás használata

Egy szolgáltatás, amely más szolgáltatásoktól függ és megfelelően deklarálta a dependencies-t, egyszerűen megkapja a megfelelő szolgáltatások hivatkozását a start metódus második argumentumában.

A useService hook a megfelelő módja annak, hogy egy szolgáltatást használjunk egy komponensben. Egyszerűen visszaad egy hivatkozást a szolgáltatás értékére, amelyet a komponens később használhat. Például:

import { rpc } from "@web/core/network/rpc";

class MyComponent extends Component {
  setup() {
    onWillStart(async () => {
      const result = await rpc(...);
    })
  }
}

Referencia lista

Technikai név

Rövid leírás

cookie

sütik olvasása vagy módosítása

hatás

grafikus hatások megjelenítése

http

alacsony szintű http hívások végrehajtása

értesítés

értesítések megjelenítése

útválasztó

a böngésző URL kezelése

rpc

kérések küldése a szerverre

görgető

horgony elemek kattintásainak kezelése

cím

az ablak címének olvasása vagy módosítása

felhasználó

bizonyos információkat nyújt a jelenlegi felhasználóval kapcsolatban

Áttekintés

  • Technikai név: cookie

  • Függőségek: nincsenek

Lehetőséget biztosít a sütik kezelésére. Például:

cookieService.setCookie("hello", "odoo");

API

current

Objektum, amely minden sütit és annak értékét képviseli, ha van (vagy üres string)

setCookie(name[, value, ttl])
Argumentum
  • name (string()) – a süti neve, amelyet be kell állítani

  • value (any()) – opcionális. Ha meg van adva, a süti erre az értékre lesz beállítva

  • ttl (number()) – opcionális. az idő másodpercben, mielőtt a süti törlődik (alapértelmezett=1 év)

Beállítja a name sütit a value értékre ttl maximális élettartammal

deleteCookie(name)
Argumentum
  • name (string()) – a süti neve

Törli a name sütit.

Hatás szolgáltatás

Áttekintés

  • Technikai név: effect

  • Függőségek: Nincsenek

A hatások grafikai elemek, amelyek ideiglenesen megjelenhetnek az oldal tetején, általában azért, hogy visszajelzést adjanak a felhasználónak arról, hogy valami érdekes történt.

Jó példa erre a szivárványember:

A szivárványember hatás

Így jeleníthető meg:

const effectService = useService("effect");
effectService.add({
  type: "rainbow_man", // can be omitted, default type is already "rainbow_man"
  message: "Boom! Team record for the past 30 days.",
});

Figyelem

A useEffect hook nem kapcsolódik a hatás szolgáltatáshoz.

API

effectService.add(options)
Argumentum
  • options (object()) – a hatás beállításai. Ezek továbbítva lesznek az alapul szolgáló hatás komponenshez.

Egy hatás megjelenítése.

A beállításokat az alábbiak határozzák meg:

interface EffectOptions {
  // The name of the desired effect
  type?: string;
  [paramName: string]: any;
}

Elérhető hatások

Jelenleg az egyetlen hatás a szivárványember.

RainbowMan
effectService.add({ type: "rainbow_man" });

Név

Típus

Leírás

params.Component

owl.Component?

A Component osztály példányosítása a RainbowMan belsejében (ez helyettesíti az üzenetet).

params.props

object?={}

Ha a params.Component meg van adva, annak props értékei ezzel az argumentummal adhatók át.

params.message

string?="Well Done!"

Az üzenet az értesítés, amit a rainbowman tart.

Ha a felhasználó számára le vannak tiltva a hatások, a rainbowman nem jelenik meg, és egy egyszerű értesítés jelenik meg helyette.

Ha a hatások engedélyezve vannak és a params.Component meg van adva, a params.message nem kerül felhasználásra.

Az üzenet egy egyszerű szöveg vagy egy html-t reprezentáló szöveg (előnyben részesítse a params.Component használatát, ha interakciókat szeretne a DOM-ban).

params.messageIsHtml

boolean?=false

Állítsa igazra, ha az üzenet html-t reprezentál, így helyesen kerül beillesztésre a DOM-ba.

params.img_url

string?=/web/static/img/smile.svg

A kép URL-je, amelyet a szivárvány belsejében kell megjeleníteni.

params.fadeout

("slow"|"medium"|"fast"|"no")?="medium"

Késleltetés a szivárványember eltűnéséhez.

"fast" will make rainbowman dissapear quickly.

"medium" and "slow" will wait little longer before disappearing (can be used when params.message is longer).

"no" will keep rainbowman on screen until user clicks anywhere outside rainbowman.

Hogyan lehet hatást hozzáadni

A hatások egy effects nevű nyilvántartásban vannak tárolva. Új hatásokat adhat hozzá egy név és egy függvény megadásával.

const effectRegistry = registry.category("effects");
effectRegistry.add("rainbow_man", rainbowManEffectFunction);

A függvénynek a következő API-t kell követnie:

<newEffectFunction>(env, params)
Argumentum
  • env (Env()) – a szolgáltatás által kapott környezet

  • params (object()) – a szolgáltatás add függvényéből kapott paraméterek.

Visszatérési érték

({Component, props} | void) Egy komponens és annak tulajdonságai vagy semmi.

Ennek a függvénynek létre kell hoznia egy komponenst, és vissza kell adnia azt. Ez a komponens a hatás komponens konténerében van elhelyezve.

Példa

Tegyük fel, hogy szeretnénk hozzáadni egy hatást, amely szépia megjelenést ad az oldalnak.

import { registry } from "@web/core/registry";
import { Component, xml } from "@odoo/owl";

class SepiaEffect extends Component {
  static template = xml`
    <div style="
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        pointer-events: none;
        background: rgba(124,87,0, 0.4);
    "></div>
  `;
}

export function sepiaEffectProvider(env, params = {}) {
    return {
        Component: SepiaEffect,
    };
}

const effectRegistry = registry.category("effects");
effectRegistry.add("sepia", sepiaEffectProvider);

Ezután hívja meg valahol, ahol szeretné, és látni fogja az eredményt. Itt a webclient.js-ben van meghívva, hogy mindenhol látható legyen a példa kedvéért.

const effectService = useService("effect");
effectService.add({ type: "sepia" });
Odoo szépia színben

Http szolgáltatás

Áttekintés

  • Technikai név: http

  • Függőségek: Nincsenek

Míg az odoo-ban a kliens és a szerver közötti interakciók többsége RPC (XMLHTTPRequest), néha alacsonyabb szintű vezérlésre lehet szükség a kérések felett.

Ez a szolgáltatás lehetőséget biztosít get és post http kérések küldésére.

API

async get(route[, readMethod = "json"])
Argumentum
  • route (string()) – az URL, ahová a kérést küldeni kell

  • readMethod (string()) – the response content type. Can be „text”, „json”, „formData”, „blob”, „arrayBuffer”.

Visszatérési érték

a kérés eredménye a readMethod argumentumban meghatározott formátumban.

Get kérés küldése.

async post(route[, params = {}, readMethod = "json"])
Argumentum
  • route (string()) – az URL, ahová a kérést küldeni kell

  • params (object()) – kulcs-érték adatok, amelyeket a kérés form adatrészében kell beállítani

  • readMethod (string()) – the response content type. Can be „text”, „json”, „formData”, „blob”, „arrayBuffer”.

Visszatérési érték

a kérés eredménye a readMethod argumentumban meghatározott formátumban.

Post kérés küldése.

Példa

const httpService = useService("http");
const data = await httpService.get("https://something.com/posts/1");
// ...
await httpService.post("https://something.com/posts/1", { title: "new title", content: "new content" });

Értesítési szolgáltatás

Áttekintés

  • Technikai név: notification

  • Függőségek: Nincsenek

A notification szolgáltatás lehetővé teszi értesítések megjelenítését a képernyőn.

const notificationService = useService("notification");
notificationService.add("I'm a very simple notification");

API

add(message[, options])
Argumentum
  • message (string()) – a megjelenítendő értesítési üzenet

  • options (object()) – az értesítés beállításai

Visszatérési érték

egy függvény az értesítés bezárásához

Értesítést jelenít meg.

A beállításokat az alábbiak határozzák meg:

Név

Típus

Leírás

title

karakterlánc

Adjon címet az értesítéshez

típus

figyelmeztetés | veszély | siker | információ

Megváltoztatja a háttérszínt a típusnak megfelelően

ragadós

logikai

Azt jelzi, hogy az értesítés megmaradjon-e, amíg el nem utasítják

osztályNév

karakterlánc

további css osztály, amely hozzáadódik az értesítéshez

bezáráskor

függvény

visszahívás, amely végrehajtásra kerül, amikor az értesítés bezárul

gombok

button[] (lásd alább)

a megjelenítendő gombok listája az értesítésben

autocloseDelay

szám

duration in milliseconds before the notification is closed automatically

A gombok a következőképpen vannak meghatározva:

Név

Típus

Leírás

name

karakterlánc

A gomb szövege

kattintáskor

függvény

visszahívás, amely végrehajtódik, amikor a gombot megnyomják

elsődleges

logikai

meghatározza, hogy a gombot elsődleges gombként kell-e formázni

Példák

Értesítés, amikor egy értékesítési üzlet létrejön, egy gombbal, amely egy jutalékoldalra vezet.

// in setup
this.notificationService = useService("notification");
this.actionService = useService("action");

// later
this.notificationService.add("You closed a deal!", {
  title: "Congrats",
  type: "success",
  buttons: [
      {
          name: "See your Commission",
          onClick: () => {
              this.actionService.doAction("commission_action");
          },
      },
  ],
});
Értesítés példája

Egy értesítés, amely egy másodperc után bezárul:

const notificationService = useService("notification");
const close = notificationService.add("I will be quickly closed");
setTimeout(close, 1000);

Router Szolgáltatás

Áttekintés

  • Technikai név: router

  • Függőségek: nincsenek

A router szolgáltatás három funkciót biztosít:

  • információ az aktuális útvonalról

  • egy mód az alkalmazás számára, hogy frissítse az URL-t az állapotától függően

  • figyeli minden hash változást, és értesíti az alkalmazás többi részét

API

current

Az aktuális útvonal a current kulccsal érhető el. Ez egy objektum a következő információkkal:

  • pathname (string): az aktuális hely útvonala (valószínűleg /web )

  • search (object): egy szótár, amely az URL keresési kulcsszavait (a querystringet) értékeikhez rendeli. Üres string az érték, ha nem adtak meg kifejezetten értéket

  • hash (object): ugyanaz, mint fent, de a hash-ben leírt értékekre.

Például:

// url = /web?debug=assets#action=123&owl&menu_id=174
const { pathname, search, hash } = env.services.router.current;
console.log(pathname); //   /web
console.log(search); //   { debug="assets" }
console.log(hash); //   { action:123, owl: "", menu_id: 174 }

Az URL frissítése a pushState metódussal történik:

pushState(hash: object[, replace?: boolean])
Argumentum
  • hash (Object()) – objektum, amely néhány kulcsot értékekhez rendel

  • replace (boolean()) – ha igaz, az URL lecserélődik, ellenkező esetben csak a hash kulcs/érték párok frissülnek.

Frissíti az URL-t a hash objektumból származó minden kulcs/érték párral. Ha egy érték üres karakterláncra van állítva, a kulcs hozzáadódik az url-hez bármilyen megfelelő érték nélkül.

Ha igaz, a replace argumentum azt jelzi a routernek, hogy az url hash-t teljesen le kell cserélni (így a hash objektumban nem szereplő értékek eltávolításra kerülnek).

Ez a metódushívás nem tölti újra az oldalt. Nem vált ki hashchange eseményt, sem ROUTE_CHANGE-t a main bus-ban. Ennek oka, hogy ez a metódus csak az url frissítésére szolgál. A metódust hívó kód felelőssége, hogy biztosítsa a képernyő frissítését is.

Például:

// url = /web#action_id=123
routerService.pushState({ menu_id: 321 });
// url is now /web#action_id=123&menu_id=321
routerService.pushState({ yipyip: "" }, replace: true);
// url is now /web#yipyip

Végül, a redirect metódus átirányítja a böngészőt egy megadott url-re:

redirect(url[, wait])
Argumentum
  • url (string()) – egy érvényes url

  • wait (boolean()) – ha igaz, várja meg, amíg a szerver készen áll, és utána irányítson át

Irányítsa át a böngészőt url-re. Ez a metódus újratölti az oldalt. A wait argumentum ritkán használt: hasznos lehet bizonyos esetekben, amikor tudjuk, hogy a szerver rövid ideig nem lesz elérhető, tipikusan közvetlenül egy kiegészítő frissítése vagy telepítése után.

Megjegyzés

A router szolgáltatás ROUTE_CHANGE eseményt bocsát ki a main bus-ban, valahányszor a jelenlegi útvonal megváltozott.

RPC szolgáltatás

Áttekintés

  • Technikai név: rpc

  • Függőségek: nincsenek

Az rpc szolgáltatás egyetlen aszinkron függvényt biztosít a szerverhez való kérések küldésére. Egy vezérlő meghívása nagyon egyszerű: az útvonalnak kell lennie az első argumentumnak, és opcionálisan egy params objektum adható meg második argumentumként.

import { rpc } from "@web/core/network/rpc";

 // somewhere else, in an async function:
 const result = await rpc("/my/route", { some: "value" });

Megjegyzés

Vegye figyelembe, hogy az rpc szolgáltatás alacsony szintű szolgáltatásnak minősül. Csak Odoo vezérlőkkel való interakcióra kell használni. A modellekkel való munkához (ami messze a legfontosabb felhasználási eset) inkább az orm szolgáltatást kell használni.

API

rpc(route, params, settings)
Argumentum
  • route (string()) – a kérés által célzott útvonal

  • params (Object()) – (opcionális) a szervernek küldött paraméterek

  • settings (Object()) – (opcionális) kérés beállításai (lásd alább)

A settings objektum tartalmazhatja:

  • xhr, amelynek egy XMLHTTPRequest objektumnak kell lennie. Ebben az esetben az rpc metódus egyszerűen ezt fogja használni egy új létrehozása helyett. Ez hasznos, amikor az XMLHTTPRequest API fejlett funkcióihoz férünk hozzá.

  • silent (boolean) Ha true-ra van állítva, a web kliens nem ad visszajelzést arról, hogy van egy függőben lévő rpc.

Az rpc szolgáltatás a szerverrel egy XMLHTTPRequest objektum használatával kommunikál, amely az application/json tartalomtípusra van konfigurálva. Így egyértelmű, hogy a kérés tartalmának JSON sorosíthatónak kell lennie. Minden, e szolgáltatás által végzett kérés a POST http metódust használja.

A szerver hibák valójában egy http 200 kóddal térnek vissza. Azonban az rpc szolgáltatás ezeket hibaként fogja kezelni.

Hibakezelés

Egy rpc két fő okból hibásodhat meg:

  • vagy az odoo szerver hibát ad vissza (ezt szerver hibának nevezzük). Ebben az esetben a http kérés 200-as http kóddal tér vissza, DE egy válaszobjektummal, amely tartalmaz egy error kulcsot.

  • vagy valamilyen más hálózati hiba van

Amikor egy rpc meghibásodik, akkor:

  • az rpc-t képviselő ígéret elutasításra kerül, így a hívó kód összeomlik, hacsak nem kezeli a helyzetet

  • egy RPC_ERROR esemény kerül kiváltásra a fő alkalmazás buszon. Az esemény terhelése tartalmazza a hiba okának leírását:

    Ha szerverhiba történt (a szerver kód kivételt dobott). Ebben az esetben az esemény terhelése egy objektum lesz a következő kulcsokkal:

    • type = 'server'

    • message(string)

    • code(number)

    • name(string) (opcionális, a hibaszolgáltatás használja, hogy megfelelő párbeszédablakot keressen a hiba kezelésekor)

    • subType(string) (opcionális, gyakran a párbeszédablak címének meghatározására használják)

    • data(object) (opcionális objektum, amely különböző kulcsokat tartalmazhat, többek között debug : a fő hibakeresési információ, a hívási veremmel)

    Ha hálózati hiba lép fel, akkor a hiba leírása egyszerűen egy objektum {type: 'network'}. Amikor hálózati hiba történik, egy értesítés jelenik meg, és a szervert rendszeresen megkeresik, amíg nem válaszol. Az értesítés bezárul, amint a szerver válaszol.

Scroller szolgáltatás

Áttekintés

  • Technikai név: scroller

  • Függőségek: nincsenek

Amikor a felhasználó rákattint egy horgonyra a web kliensben, ez a szolgáltatás automatikusan a célpontra görget (ha megfelelő).

The service adds an event listener to get click’s on the document. The service checks if the selector contained in its href attribute is valid to distinguish anchors and Odoo actions (e.g. <a href="#target_element"></a>). It does nothing if it is not the case.

Egy SCROLLER:ANCHOR_LINK_CLICKED esemény kerül kiváltásra a fő alkalmazás buszon, ha a kattintás úgy tűnik, hogy egy elemre irányul. Az esemény tartalmaz egy egyedi eseményt, amely az element egyezést és annak id-ját referenciaként tartalmazza. Ez lehetővé teheti más részek számára, hogy kezeljék a horgonyokkal kapcsolatos viselkedést. Az eredeti esemény is meg van adva, mivel szükség lehet annak megakadályozására. Ha az eseményt nem akadályozzák meg, akkor a felhasználói felület a cél elemre görget.

API

A következő értékek találhatók a fentebb ismertetett anchor-link-clicked egyedi eseményben.

Név

Típus

Leírás

elem

HTMLElement | null

A href által megcélzott horgony elem

azonosító

string

A href-ben található azonosító

eredetiEv

Esemény

Az eredeti kattintási esemény

Megjegyzés

A görgető szolgáltatás egy SCROLLER:ANCHOR_LINK_CLICKED eseményt bocsát ki a main bus-on. A görgető szolgáltatás alapértelmezett görgetési viselkedésének elkerülése érdekében használja a preventDefault()-ot az eseményen, amelyet a hallgatónak ad, így helyesen megvalósíthatja saját viselkedését a hallgatóból.

Cím Szolgáltatás

Áttekintés

  • Technikai név: title

  • Függőségek: nincsenek

The title service offers a simple API that allows to read/modify the document title. For example, if the current document title is „Odoo”, we can change it to „Odoo 15 - Apple” by using the following command:

// in some component setup method
const titleService = useService("title");

titleService.setParts({ odoo: "Odoo 15", fruit: "Apple" });

API

A title szolgáltatás a következő interfészt kezeli:

interface Parts {
    [key: string]: string | null;
}

Minden kulcs a cím egy részének azonosítóját képviseli, és minden érték az a sztring, amely megjelenik, vagy null, ha eltávolították.

Az API-ja a következő:

current

Ez egy sztring, amely a jelenlegi címet képviseli. A következő módon van felépítve: value_1 - ... - value_n, ahol minden value_i egy (nem null) érték, amely a Parts objektumban található (amit a getParts függvény ad vissza).

getParts()
Visszatérési érték

A jelenlegi Parts objektum részei, amelyet a cím szolgáltatás tart fenn

setParts(parts)
Argumentum
  • parts (Parts()) – objektum, amely a szükséges változást képviseli

A setParts metódus lehetővé teszi több címrész hozzáadását/cseréjét/törlését. Egy rész (egy érték) törlése azzal történik, hogy a hozzá tartozó kulcs értékét null-ra állítjuk.

Megjegyzendő, hogy csak egyetlen részt lehet módosítani anélkül, hogy a többi részt érintenénk. Például, ha a cím a következő részekből áll:

{ odoo: "Odoo", action: "Import" }

ahol a current érték Odoo - Import , akkor

setParts({
  action: null,
});

a cím Odoo-ra változik.

Felhasználói szolgáltatás

Áttekintés

  • Technikai név: user

  • Függőségek: rpc

A user szolgáltatás számos adatot és néhány segédfüggvényt biztosít a csatlakoztatott felhasználóval kapcsolatban.

API

Név

Típus

Leírás

context

Objektum

A felhasználói kontextus

adatbázis

Objektum

Információ az adatbázisról

home_action_id

(szám | hamis)

A felhasználó kezdőlapjaként használt művelet azonosítója

isAdmin

boolean

A felhasználó adminisztrátor-e (a base.group_erp_manager csoport vagy szuperfelhasználó)

isSystem

boolean

A felhasználó része-e a rendszer csoportnak (base.group_system)

lang

string

használt nyelv

name

string

A felhasználó neve

partnerId

number

A felhasználó partner példányának azonosítója

tz

string

A felhasználó időzónája

userId

number

A felhasználó azonosítója

userName

string

A felhasználó alternatív beceneve

updateContext(update)
Argumentum
  • update (object()) – az objektum, amellyel a kontextust frissíteni kell

frissítse a felhasználói kontextust a megadott objektummal.

userService.updateContext({ isFriend: true })
removeFromContext(key)
Argumentum
  • key (string()) – a célzott attribútum kulcsa

távolítsa el az értéket a megadott kulccsal a felhasználói kontextusból

userService.removeFromContext("isFriend")
hasGroup(group)
Argumentum
  • group (string()) – a keresett csoport xml_id-ja

Visszatérési érték

Promise<boolean> a felhasználó a csoportban van-e

ellenőrizze, hogy a felhasználó tagja-e egy csoportnak

const isInSalesGroup = await userService.hasGroup("sale.group_sales")