チャプター2:ダッシュボードを作成¶
このチュートリアルの最初の部分では、ほとんどのフクロウのアイデアを紹介しました。 Web クライアントで使用されているように Odoo JavaScript フレームワーク全体について学ぶ時が来ました。
始めるには、実行中の Odoo サーバーと開発環境のセットアップが必要です。 練習問題に入る前に、この tutorial <tutorials/discover_js_framework/setup>`で説明されているすべてのステップに従っていることを確認してください。 この章では、`awesome_dashboard addonが提供する空のダッシュボードから始めます。 Odoo JavaScriptフレームワークを使用して、機能を徐々に追加します。
目標

章の各演習の解決策は、 official Odoo tutorials repository にホストされています。
1. 新しいレイアウト¶
Odoo ウェブクライアントのほとんどの画面は、共通のレイアウト:コントロールパネルを上に使用します。 ボタンの下にメインゾーンがあります これは Layout コンポーネント を使用して行われ、@web/search/layout
で利用できます。
Update the
AwesomeDashboard
component located inawesome_dashboard/static/src/
to use theLayout
component. You can use{controlPanel: {} }
for thedisplay
props of theLayout
component.Layout`に`className`プロパティを追加する: `className
'o_dashboard h-100'"`.o_dashboard
の背景色をグレー(または好きな色)に設定するdashboard.scss
ファイルを追加します
http://localhost:8069/webを開き、 Awesome Dashboard アプリを開き、結果を確認します。

関連項目
例: クライアントアクション と template でレイアウトを使用する
理論: サービス¶
実際には、すべてのコンポーネント(ルートコンポーネントを除く)はいつでも破壊され、別のコンポーネントに置き換えられる(またはそうでない)ことがあります。 これは、各コンポーネントの内部状態が持続しないことを意味します。 これは多くの場合は問題ありませんが、データを保持したい場合は確かにあります。 たとえば、チャンネルを表示するたびにすべてのディスカッションメッセージが再読み込みされることはありません。
また、コンポーネントではないコードを書く必要がある場合もあります。 多分、すべてのバーコードを処理する何か、またはユーザー構成(コンテキストなど)を管理する何か。
Odoo フレームワークは、 :ref:`service <frontend/services>`のアイデアを定義します。 これは状態や関数をエクスポートする永続的なコードです 各サービスは他のサービスに依存し、コンポーネントはサービスをインポートすることができます。
以下の例では、5秒ごとに通知を表示するシンプルなサービスを登録します。
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);
サービスは、任意のコンポーネントからアクセスできます。共有状態を維持するためのサービスがあるとします。
import { registry } from "@web/core/registry";
const sharedStateService = {
start(env) {
let state = {};
return {
getValue(key) {
return state[key];
},
setValue(key, value) {
state[key] = value;
},
};
},
};
registry.category("services").add("shared_state", sharedStateService);
次に、任意のコンポーネントが次のように実行できます。
import { useService } from "@web/core/utils/hooks";
setup() {
this.sharedState = useService("shared_state");
const value = this.sharedState.getValue("somekey");
// do something with value
}
3. ダッシュボード項目を追加¶
では、コンテンツを改善しましょう。
デフォルトのスロットを素敵なカードレイアウトで表示する汎用の
DashboardItem
コンポーネントを作成します。 デフォルトは1
で、オプションのsize
数値プロパティを使用します。幅は(18*size)rem
にハードコードする必要があります。ダッシュボードに2枚のカードを追加します。1枚はサイズがなく、もう1枚は2枚です。

関連項目
4. サーバーを呼び出し、統計情報を追加します¶
ダッシュボードにいくつかのダッシュボード項目を追加して、*実際の*ビジネスデータを表示することでダッシュボードを改善しましょう。 awesome_dashboard
addon は、興味深い情報を返すための /awesome_dashboard/statistics
ルートを提供します。
To call a specific controller, we need to use the rpc function.
It only exports a single function that perform the request: rpc(route, params, settings)
.
A basic request could look like this:
import { rpc } from "@web/core/network/rpc";
// ...
setup() {
onWillStart(async () => {
const result = await rpc("/my/controller", {a: 1, b: 2});
})
// ...
}
ダッシュボード`を更新して、`rpc`関数を使用し、統計ルート
/awesome_dashboard/statistics`を呼び出します。ダッシュボードにいくつかのカードを表示します。
Number of new orders this month
今月の新規注文合計
今月の平均Tシャツの注文数
キャンセルされた注文の月数
「新規」から「送信」または「キャンセル」への注文の平均時間

関連項目
5. ネットワーク通話のキャッシュ、サービスの作成¶
ブラウザの開発ツールの Network タブを開くと、 クライアントアクションが表示されるたびに、/awesome_dashboard/statistics
の呼び出しが行われます。 これは、Dashboard
コンポーネントがマウントされるたびに、onWillStart
フックが呼び出されるためです。 しかし、この場合、私たちは最初にそれを行うことを好むでしょう。 ですから、実際には`ダッシュボード`コンポーネントの外側にある状態を維持する必要があります。 これはサービスのための素敵なユースケースです!
awesome_dashboard.statistics
サービスを登録してインポートします。呼び出された関数`loadStatistics`を提供し、実際のrpcを実行し、常に同じ情報を返す必要があります。
統計をキャッシュすることを可能にする`@web/core/utils/functions`の`memoize <https://github.com/odoo/odoo/blob/1f4e583ba20a01f4c44b0a4ada42c4d3bb074273/ addons/web/static/src/core/utils/functions.js#L11>`_ utility関数`@web/core/utils/functions`を使います。
ダッシュボード
コンポーネントでこのサービスを使用します。期待どおりに動作することを確認してください。
6. 円グラフを表示¶
誰もがチャート(!)が好きなので、私たちのダッシュボードで円グラフを追加しましょう。 S/M/L/XL/XXLというサイズごとに販売されているTシャツの比率が表示されます。
この課題では、Chart.js を使用します。グラフビューで使用されているチャートライブラリです。 ただし、デフォルトではロードされていないため、アセットバンドルに追加するか、遅延ロードする必要があります。 ユーザーがチャートjsコードを必要としない場合は、毎回チャートjsコードをロードする必要がないため、遅延ロードは通常より良いです。
PieChart
コンポーネントを作成します。onWillStart
メソッドでチャートをロードします。loadJs 関数を使用して、/web/static/lib/Chart/Chart.js
をロードできます。DashboardItem
内のPieChart
コンポーネントを使用して、販売されている各Tシャツの枚数をそれぞれのサイズで表示する 円グラフ を表示します(この情報は/statistics
ルートで利用可能です)。size
プロパティを使うと、大きく見えるようになります。うまくいくようにしよう!

7. 実際の耐用年数の更新¶
データの読み込みをキャッシュに移動したので、更新はありません。 しかし、私たちは速い移動データを見ているので、定期的に(例えば、10分ごとに)新鮮なデータをリロードしたいと思います。
これは統計サービスに`setTimeout`または`setInterval`を使って実装するのはとても簡単です。 ただし、ここでは難しい部分です:ダッシュボードが現在表示されている場合は、すぐに更新する必要があります。
これを行うには、 reactive
オブジェクトを使用できます。これは、 useState
が返すプロキシと同じですが、どのコンポーネントにもリンクされていません。 コンポーネントはその変更を受け取るために useState
を実行できます。
統計情報サービスを更新して、10分ごとにデータを再読み込みします(テストするには10秒を代わりに使用してください)
reactive オブジェクトを返すように修正します。データをリロードする場合は、その場所でリアクティブオブジェクトを更新する必要があります。
Dashboard
コンポーネントがuseState
で使用できるようになりました。
関連項目
8. ダッシュボードを読み込んでいます¶
私たちのダッシュボードはかなり大きくなってきており、一部のユーザーにとってのみ関心があると考えてみましょう。 その場合、私たちのダッシュボードと関連するすべての資産を遅延ロードすることは意味があります。 コードを読み込むのにかかる費用は実際に見たいときだけです
これを行う一つの方法は、 LazyComponent
(`@web/core/assets`から) をコンポーネントを表示する前にアセットバンドルをロードする中間として使用することです。
Example
example_action.js
:
export class ExampleComponentLoader extends Component {
static components = { LazyComponent };
static template = xml`
<LazyComponent bundle="'example_module.example_assets'" Component="'ExampleComponent'" />
`;
}
registry.category("actions").add("example_module.example_action", ExampleComponentLoader);
9. ダッシュボードを一般的にする¶
これまでのところ、私たちは素晴らしい作業ダッシュボードを持っていますが、現在はダッシュボードテンプレートでハードコードされています。 ダッシュボードをカスタマイズしたい場合はどうなりますか? ユーザーによってはニーズが異なり、他のデータを見たいユーザーもいるかもしれません。
次のステップは、ダッシュボードを一般的にすることです。テンプレート内のコンテンツをハードコーディングする代わりに。 ダッシュボードの項目のリストを繰り返すだけです しかし、ダッシュボードアイテムの表示方法、登録方法、受信するデータなど、多くの質問が出てきます。 このようなシステムを設計するには、さまざまなトレードオフがあります。
このチュートリアルでは、ダッシュボード項目は以下の構造を持つオブジェクトであると言います。
const item = {
id: "average_quantity",
description: "Average amount of t-shirt",
Component: StandardItem,
// size and props are optionals
size: 3,
props: (data) => ({
title: "Average amount of t-shirt by order this month",
value: data.average_quantity
}),
};
description
の値は、ユーザーがダッシュボードに追加できる項目の名前を表示するために、後で練習するときに役立ちます。 size`番号は任意で、表示されるダッシュボードアイテムのサイズを簡単に説明します。 最後に、 `props
関数は任意です。指定しない場合は、 statistics
オブジェクトをデータとして渡します。 しかし、定義されている場合は、コンポーネントの特定の props を計算するために使用されます。
目標は、ダッシュボードの内容を次のスニペットに置き換えることです。
<t t-foreach="items" t-as="item" t-key="item.id">
<DashboardItem size="item.size || 1">
<t t-set="itemProp" t-value="item.props ? item.props(statistics) : {'data': statistics}"/>
<t t-component="item.Component" t-props="itemProp" />
</DashboardItem>
</t>
上記の例では、動的コンポーネントと動的プロップの 2 つの高度な機能を備えています。
現在、アイテムコンポーネントには2種類あります:タイトルと数字のあるナンバーカード。 パイカードにラベルと円グラフが付いています
NumberCard
とPieChartCard
の 2 つのコンポーネントを作成し、実装します。dashboard_items.js
ファイルを作成し、アイテムのリストを定義してエクスポートします。NumberCard
とPieChartCard
を使用して現在のダッシュボードを再作成します。ダッシュボード
コンポーネント内のアイテムのリストをインポートし、コンポーネントに追加し、テンプレートを更新して上記のようにt-foreach
を使用します。setup() { this.items = items; }
ダッシュボードテンプレートは一般的です!
10. ダッシュボードを拡張可能にする¶
ただし、アイテムリストの内容はまだハードコードされています。レジストリを使用して修正してみましょう:
リストをエクスポートする代わりに、
awesome_dashboard
レジストリにすべてのダッシュボード項目を登録します`ダッシュボード`コンポーネントに`awesome_dashboard`レジストリのすべての項目をインポートします
ダッシュボードは簡単に拡張可能になりました。 ダッシュボードに新しいアイテムを登録したい他のOdooアドオンは、レジストリに追加するだけです。
11. ダッシュボードアイテムの追加と削除¶
ダッシュボードをカスタマイズ可能にする方法を見てみましょう。 簡単にするために、ユーザーダッシュボードの設定をローカルストレージに保存し、永続化します。 でも今のところはサーバーを扱う必要はない
ダッシュボードの設定は、削除されたアイテムIDのリストとして保存されます。
コントロールパネルにギアアイコンを表示するボタンを追加し、設定ボタンであることを示します。
そのボタンをクリックするとダイアログが開きます。
このダイアログには、すべての既存のダッシュボードアイテムのリストが表示され、それぞれにチェックボックスが表示されます。
フッターに`Apply`ボタンがあります。クリックすると、チェックされていない全てのアイテムIDのリストが作成されます。
その値をローカルストレージに保存したいと考えています。
また、構成からアイテムの id を削除することで、
Dashboard
コンポーネントを変更して、現在のアイテムをフィルタリングします。

12.さらに進む¶
以下は、時間があればやってみることができるいくつかの小さな改善点のリストです:
アプリケーションが translated (
env._t
) であることを確認してください。円グラフのセクションをクリックすると、対応するサイズの注文がすべてリスト表示されます。
ダッシュボードの内容をユーザー設定のサーバーに保存します!
モバイルモードでは、各カードの幅が100%かかる必要があります。