2023年9月1日金曜日

Oracle JETのPicto Chartを使って東京の最高気温を表示する

Oracle JETのCookbookではCalendarとなっていますが、Picto Chart(oj-picto-chart)を使ってカレンダー形式で東京の最高気温を表示してみます。

今までOracle JET Cookbookに載っているサンプルをOracle APEXに実装してきましたが、概ねOracle JET Cookbookによるビジュアリゼーション自体は変えていません。今回はOracle JET Cookbookのサンプルが扱っているデータが米国ニューヨーク市の2015年の気温で、少々面白くありません。そして、データを変更するには(色々とハードコードされていて)、コードの変更が必要でした。

それで今回はコードに手を加えて、指定した期間の東京の最高気温を表示するようにJET Picto Chartを実装しました。以下は、作成したアプリケーションによる最高気温の表示です。

2023年3月から8月までの東京都の最高気温をカレンダーに表示しています(取得できた履歴データが8月26日までなので、8月の表示は完全ではありません)。


Weather data by Open-Meteo.com

2022年3月から8月までの東京の最高気温の表示は以下なので、今年は暑いことがよくわかります。


Oracle JET Cookbookの以下の実装を元にしています。


最高気温のデータは、Open-Meteo.comのFree Weather APIを呼び出して取得しています。使用にあたっては、ライセンスおよびPricingについて、ご自身で確認していただくようお願いします。Terms & Privacyに説明がありますが、非商用であれば無料で利用できます。


以下より実装手順を説明します。

最初にOpen-Meteo.comを呼び出して取得した、最高気温のデータを保存する表HMT_TEMPERATURESを作成します。表の作成には、以下のクイックSQLのモデルを使用します。
# prefix: hmt
temperatures
    tag vc20 /nn
    date_rec date /nn
    temperature_2m_max num
SQLの作成、SQLスクリプトを保存、レビューおよび実行を順次実行します。表の作成までを行い、アプリケーションは作成しません。


続いてアプリケーション作成ウィザードを起動します。

アプリケーションの名前はJET Picto Chartとします。デフォルトで作成されているホーム・ページを削除し、表HMT_TEMPERATURESをソース表とした対話グリッドのページを追加します。


追加する対話グリッドのページは、ページ名をTemperatures、表またはビューとしてHMT_TEMPERATURESを指定します。今回は対話グリッドからデータを更新することは想定していませんが、編集を許可を選択しています。


以上でアプリケーションの作成を実行します。

作成されたアプリケーションのページ番号1、ページ名Temperaturesに今回の実装を行います。


アプリケーション定義を開き、置換文字列G_MONTHとして一度に表示する月数を設定します。今回は置換値に6を設定しています。


ページ・デザイナでページTemperaturesを開きます。

Breadcrumb BarにあるリージョンJET Picto Chartを削除します。JET Picto Chart上でコンテキスト・メニューを表示させ、削除を実行します。


主にOpen MeteoのAPI呼び出しの引数となる値を保持するページ・アイテムを作成します。これらのページ・アイテムを配置するリージョンを作成します。

識別のタイトルはMaximum Temperatures (2m)とし、タイプとして静的コンテンツを選択します。対話グリッドHmt Temperaturesの上に配置します。


作成したリージョンにページ・アイテムを作成します。

1度のAPI呼び出しで得られたデータにつけるタグを指定するページ・アイテムを作成します。

識別の名前はP1_TAG、タイプはテキスト・フィールド、ラベルはTagとします。デフォルトのタイプに静的を選び、静的値としてTokyo (2023)を設定します。


データの取得および表示を開始する年を指定するページ・アイテムを作成します。

識別の名前はP1_YEAR、タイプは選択リスト、ラベルはYearとします。ページ・アイテムP1_TAGの右隣に配置するため、レイアウトの新規行の開始はオフにします。検証の必須の値はオンです。

LOVのタイプにSQL問合せを選択し、SQL問合せとして以下を記述します。現在の年から過去30年を表示の対象として選択できます。

追加値の表示、NULL値の表示はオフとします。


デフォルトのタイプとして静的を選択し、静的値として2023を設定します。


データの取得および表示を開始する月を指定するページ・アイテムを作成します。これはページ・アイテムP1_YEARを重複させて作成します。

識別の名前をP1_MONTH、ラベルをMonth、LOVのSQL問合せを以下に変更します。


デフォルトの静的値は1に変更します。


観測地点の緯度を指定するページ・アイテムを作成します。

識別の名前をP1_LAT、タイプを数値フィールド、ラベルをLatitudeとします。レイアウトの新規行の開始はオフです。検証の必須の値はオンにします。

デフォルトのタイプとして静的を選択し、静的値として東京の緯度である35.6895を設定します。


観測地点の経度を指定するページ・アイテムを作成します。これはページ・アイテムP1_LATを重複させて作成します。

識別の名前をP1_LON、ラベルをLongitude、デフォルトの静的値を東京の緯度である139.6917を設定します。


タイムゾーンを指定するページ・アイテムを作成します。

識別の名前をP1_TIMEZONE、タイプをテキスト・フィールド、ラベルをTimezoneとします。レイアウトの新規行の開始はオフです。検証の必須の値はオンにします。

デフォルトのタイプとして静的を選択し、静的値としてAsia/Tokyoを設定します。


ページ・アイテムP1_LAT、P1_LON、P1_TIMEZONEは観測地点のマスター・データを準備してポップアップLOVを使うと、もっと扱いやすい実装が可能です。今回は主に東京のデータを取得することを前提として、このような実装は省略しています。

Open-Meteo.comにAPIを発行してデータを取得し、表HMT_TEMPERATURESに保存するボタンを作成します。

識別のボタン名はLOAD、ラベルはLoad from Open-Meteo.comとします。外観のテンプレート・オプションのWidthとしてStretchを選択します。

動作のアクションはデフォルトのページの送信から変更しません。


プロセス・ビューを開き、ボタンを押した時に実行されるプロセスを作成します。

識別の名前はLoad from Open-Meteo.comとします。タイプとしてコードを実行を選びます。ソースのPL/SQLコードに以下を記述します。

サーバー側の条件のボタン押下時としてLOADを選択します。


対話グリッドHmt Tempereturesの属性を開き、ヘッダーの固定としてリージョンを選択します。固定のレポートの高さを300ピクセルとして、対話グリッドの高さを制限します。


以上でアプリケーションを実行し、ボタンLoad from Open-Meteo.comをクリックします。最高気温のデータが読み込まれることを確認します。


プロセス・ビューを開き、Picto Chartに読み込むデータを作成するプロセスをAjaxコールバックとして作成します。

識別の名前はGET_DATA、タイプはコードを実行、ソースのPL/SQLコードとして以下を記述します。



レンダリング・ビューを開き、Oracle JETのPicto Chartを表示するリージョンを作成します。

識別のタイトルはTemperatures、タイプとして動的コンテンツを選択します。リージョンMaximum Temperatures (2m)と対話グリッドHmt Temperaturesの間に配置します。

ソースのCLOBを返すPL/SQLファンクション本体として以下を記述します。

余計な装飾を省くため、外観のテンプレートとして、Blank with Attributes (No Grid)を選択します。


ページ・プロパティのJavaScriptのファイルURLに以下を記述します。

[require jet]

ページ・ロード時の実行に以下を記述します。

CSSのファイルURLに以下を記述します。

#JET_CSS_DIRECTORY#redwood/oj-redwood-notag-min.css

インラインは、Oracle JET Cookbookにdemo.cssとして記載されている内容を元に、若干の変更を加えています。
.demo-datavisualizations-blockcalendar-wordspacing {
    word-spacing: 0.375rem;
}

.demo-datavisualizations-blockcalendar-style {
    height: 3.125rem;
    max-width: 67.5rem;
}


以上でアプリケーションは完成です。アプリケーションを実行すると、記事の先頭にある画面が表示されます。

対話グリッドからのデータの修正は想定していないため、動的アクションは作成しません。

今回のAPEXアプリケーションではOracle JETのチャートとなるHTMLは、動的コンテンツとしてPL/SQLコードによって生成しています。動的コンテンツのリージョンには遅延ロードのオプションがあります。今回の実装で遅延ロードをオンにすると、チャートが描画されなくなります。これはHTMLがすべて生成される前に、以下のハンドラが呼び出されるためです。
(0, ojbootstrap_1.whenDocumentReady)().then(() => {
        apex.server.process ( "GET_DATA", {
                pageItems: ["P1_TAG","P1_YEAR","P1_MONTH"]
            },
            {
                success: (data) =>  {
                    ko.applyBindings(new PictoChartModel(data), document.getElementById("chart-container"));
                }
            }
        );
    });
動的イベントのリフレッシュ後のタイミングで上記のハンドラを呼び出すと正常に動くかもしれませんが、そもそもknockoutによりチャートの描画は非同期になっています。動的コンテンツの遅延ロードの設定は2重の遅延ロードになるため、設定は不要です。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/jet-picto-chart.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。

完