作成するアプリケーションは以下のように動作します。
Oracle JET Cookbookで紹介されているDiagramのBasicを実装しています。
以下より実装手順を説明します。
Oracle JET CookbookではJSON形式のファイルdiagramDataSample.jsonをデータソースとしています。Oracle APEXのアプリケーションでは、データベースの表をデータソースとして使用します。このJSONデータは後ほど、データ・ロード定義を作成する際にサンプルとして使うため、手元のPCにファイルとしてダウンロードしておきます。
diagramDataSample.jsonにはグラフのノードの配列である属性nodesとリンク(またはエッジ)の配列である属性linksの2種類の配列が含まれています。ノードの配列は表DG_BASIC_NODES、リンクの配列は表DG_BASIC_LINKSへ保存します。
以下のクイックSQLのモデルより、表DG_BASIC_NODESと表DG_BASIC_LINKSを作成します。設定にpk: noneを指定し、主キー列IDの生成を抑止します。その上で列idを定義しています。クイックSQLでは列idはつねにNUMBER型かつ主キーとしてDDLが生成されます。pk:none以外で自動的にID列を生成すると、主キーの値が自動採番される設定になります。列idを記述している場合は主キーとなりますが、自動採番の設定はされません。
# prefix: dg_basic
# pk: none
nodes
id
category num /nn
links
id
category num /nn
start_node /fk nodes
end_node /fk nodes
ノードのidの値はN0,N1,N2といった形式、リンクのidはL0,L1,L2といった形式で数値ではありません。列IDのデータ型については、クイックSQLから生成されたDDLを編集することで対応します。
SQLの生成、SQLスクリプトを保存、レビューおよび実行を順次実施します。
スクリプト・エディタが開いたら、表DG_BASIC_NODESの列ID、表DG_BASIC_LINKSの列ID、START_NODDE、END_NODEのデータ型をVARCHAR2(4)に変更します。
DDLの変更後スクリプトを実行し、ふたつの表を作成します。アプリケーションの作成は行ません。
ダイアグラムを組み込むAPEXのアプリケーションを作成します。
アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。アプリケーションの名前をJET Diagram Basicとします。
アプリケーションの作成をクリックします。
diagramDataSample.jsonを表DG_BASIC_NODESにロードする際に使用する、データ・ロード定義を作成します。
共有コンポーネントのデータ・ロード定義を開きます。
作成済みのデータ・ロード定義が一覧されます。作成をクリックします。
データ・ロードの作成として最初からを選択します。
次へ進みます。
データ・ロード定義の名前はGraph Nodesとします。ターゲット・タイプは表、表名としてDG_BASIC_NODESを選択します。
次へ進みます。
サンプル・データのソース・タイプとしてファイルのアップロードを選択し、すでにダウンロードしているdiagramDataSample.jsonをサンプル・ファイルとして選択します。
次へ進みます。
ウィザードによるデータ・ロード定義では、行セレクタを指定できません。(今回の場合では、属性nodesかlinksのどちらかを選択できない。)そのため、ここでは列のマッピングはそのままにしておきます。
データ・ロードの作成をクリックします。
データ・ロード定義Graph Nodesが作成されます。設定を調整するためにGraph Nodesを開きます。
静的IDをgraph_nodesからGRAPH_NODESに変更します。PL/SQLのコード中で使用するIDは大文字にしたいという理由なので、必ずしも必要な作業ではありません。設定のロード・メソッドを置換に変更します。
データ・プロファイルの編集をクリックします。
データ・プロファイルの行セレクタとしてnodesを設定します。列IDの主キーをNoからYesに変更しておきます。この主キーの設定はロード・メソッドがマージのときに使用されます。今回は置換を選択しているため、この設定は必ずしも必要ではありません。
以上で変更の適用をクリックします。
変更の適用をクリックし、データ・ロード定義の編集画面を閉じます。
データ・ロードの作成として最初からを選択します。
次へ進みます。
データ・ロード定義の名前はGraph Linksとします。ターゲット・タイプは表、表名としてDG_BASIC_LINKSを選択します。
次へ進みます。
サンプル・データのソース・タイプとしてファイルのアップロードを選択し、サンプル・ファイルとしてdiagramDataSample.jsonを選択します。
次へ進みます。
ソース列END(Varchar2(50))のマップ先としてEND_NODE(Varchar2)を指定します。次に、ソース列START_(Varchar2(50))のマップ先としてSTART_NODE(Varchar2)を指定します。
データ・ロードの作成をクリックします。
静的IDをgraph_linksからGRAPH_LINKSに変更します。必ずしも必要な作業ではありません。設定のロード・メソッドを置換に変更します。
データ・プロファイルの編集をクリックします。
データ・プロファイルの行セレクタがlinksであることを確認します。ロード・メソッドは置換なので必ずしも必要ではありませんが、列IDの主キーをYesに変更しておきます。
変更の適用をクリックします。
変更の適用をクリックし、データ・ロード定義の編集画面を閉じます。
以上でデータ・ロード定義の作成は完了です。
ページ・デザイナでページホームを開きます。
Breadcrumb BarにあるJET Diagram Basicを削除します。JET Diagram Basicの上でコンテキスト・メニューを表示させ、削除を実行します。
表DG_BASIC_NODESを操作する対話グリッドを作成します。
Body以下にリージョンを作成します。
識別のタイトルはNodes、タイプとして対話グリッドを選択します。ソースの表名としてDG_BASIC_NODESを選択します。
対話グリッドでは編集対象の表の主キーは通常は非表示、更新は不可です。表DG_BASIC_NODESの列IDは主キーですが、表示も更新も行えるように、ROWID列を含めるにチェックを入れ、対話グリッドがROWIDを主キーとして扱うように指示します。
識別のタイプをテキスト・フィールドに変更し、ヘッダーとしてIDを設定します。検証の必須の値をオン、ソースの主キーはオフにします。
対話グリッドの属性を開き、編集の有効をオンにします。空の場合に行を追加はオフにします。対話グリッドがあまり大きく表示されないように、ヘッダーの固定をリージョンとして、固定のレポートの高さを300ピクセルに制限します。
リージョンNodes上でコンテキスト・メニューを表示させ、重複を実行します。
作成された対話グリッドの識別のタイトルをLinksに、ソースの表名をDG_BASIC_LINKSに変更します。
表DG_BASIC_LINKSを操作する対話グリッドも完成しました。
表DG_BASIC_NODESとDG_BASIC_LINKSに初期データを投入するボタンを作成します。
識別のボタン名はINIT、ラベルはInitとします。対話グリッドNodesの上に配置します。外観のテンプレート・オプションのWidthをStretchに変更し、画面の横幅いっぱいにボタンを表示させます。
動作のアクションはデフォルトのページの送信のまま変更しません。
左ペインでプロセス・ビューを開き、ボタンINITを押した時に実行するプロセスを作成します。
表DG_BASIC_NODESへのデータ・ロードと表DG_BASIC_LINKSへのデータ・ロードをそれぞれ実行する必要があることから、最初に実行チェーンを作成して、その下にデータ・ロードを行なうプロセスを作成します。
識別の名前は初期化、タイプとして実行チェーンを選択します。設定のバックグラウンドで実行はオフとします。
サーバー側の条件のボタン押下時としてINITを選択します。
作成した実行チェーン上でコンテキスト・メニューを表示させ、子プロセスの追加を実行します。
参照制約の設定より、最初にノードの情報をロードします。
識別の名前はノード、タイプとしてデータのロードを選択します。実行チェーンは初期化になります。設定のデータ・ロード定義としてGraph Nodesを選択し、ソース・データ型にSQL Queryを選んで、SQL問合せに以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
select | |
apex_web_service.make_rest_request_b( | |
p_url => 'https://www.oracle.com/webfolder/technetwork/jet/cookbook/dataVisualizations/diagram/resources/diagramDataSample.json' | |
,p_http_method => 'GET' | |
) as blob_content | |
from dual; |
プロセスノードを重複させ、リンクをロードするプロセスとして設定します。
プロセスノード上でコンテキスト・メニューを表示させ、重複を実行します。
作成されたプロセスの識別の名前をリンクに、設定のデータ・ロード定義をGraph Linksに変更します。
表DB_BASIC_LINKSを操作する対話グリッドは表DB_BASIC_NODESの対話グリッドを重複させて作成しています。この場合、データベースを操作する行の自動処理のプロセスが作成されません。
プロセスNodes - 対話グリッド・データの保存上でコンテキスト・メニューを表示させ、重複を実行します。
アプリケーションを実行しボタンInitをクリックし、データ・ロードを実行します。
表DG_BASIC_NODESに9行、表DB_BASIC_LINKSに8行データがロードされました。
ノードが削除されると参照制約の設定により、そのノードを起点または終点としたリンクも削除されます。そのため、ノードの変更が発生した後に、リンクの対話グリッドをリフレッシュする必要があります。
対話グリッドNodesに動的アクションを作成します。
動的アクションの識別の名前はonSave Nodesとします。タイミングのイベントとして保存[対話グリッド]を選択します。
TRUEアクションとしてリフレッシュを選択し、影響を受ける要素の選択タイプとしてリージョン、リージョンとしてLinksを指定します。
ダイアグラムを表示するリージョンを作成します。
識別のタイトルはDiagramとします。タイプとして静的コンテンツを選択します。ボタンINITと対話グリッドの間にリージョンを配置します。
ソースのHTMLコードとして以下を記述します。Oracle JET Cookbookのdemo.htmlからPanningとZoomingの設定を切り替えるラジオボタンを除いています。これらはAPEXのページ・アイテムを使って実装します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="diagram-container"> | |
<oj-diagram | |
id="diagram1" | |
animation-on-data-change="auto" | |
panning="[[panningValue]]" | |
zooming="[[zoomingValue]]" | |
min-zoom=".5" | |
max-zoom="2" | |
node-data="[[nodeDataProvider]]" | |
link-data="[[linkDataProvider]]" | |
layout="[[layoutFunc]]" | |
aria-label="This is a simple diagram that shows how to render Nodes and Links"> | |
<template slot="nodeTemplate" data-oj-as="node"> | |
<oj-diagram-node | |
label="[[node.data.id]]" | |
short-desc='[["Node " + node.data.id + ", Category " + node.data.category]]' | |
icon.color="[[colorHandler.getValue(node.data.category)]]" | |
icon.width="50" | |
icon.height="50"> | |
</oj-diagram-node> | |
</template> | |
<template slot="linkTemplate" data-oj-as="link"> | |
<oj-diagram-link | |
start-node="[[link.data.start]]" | |
end-node="[[link.data.end]]" | |
short-desc='[["Link " + link.data.id + ", Category " + link.data.category + ", connects " + link.data.start + " to " + link.data.end]]' | |
color="[[colorHandler.getValue(link.data.category)]]" | |
start-connector-type="none" | |
end-connector-type="arrow"> | |
</oj-diagram-link> | |
</template> | |
</oj-diagram> | |
</div> |
余計な装飾を除くため、外観のテンプレートとしてBlank with Attributes (No Grid)を選択します。
PanningとZoomingを設定するページ・アイテムを配置するリージョンを作成します。
識別のタイトルはControls、タイプは静的コンテンツです。外観のテンプレートとしてBlank with Attributesを選択します。ボタンINITの下、リージョンDiagramの上に配置します。
このリージョンに自動でPanningを行うか決めるページ・アイテムP1_PANNINGを作成します。
タイプとしてラジオ・グループを選択します。ラベルはPanningとします。設定の列の数は2とします。
LOVのタイプとして静的値を選択します。静的値としてnoneとautoを設定します(スクリーンショットは後に添付します)。追加値の表示、NULL値の表示はともにオフです。
デフォルトのタイプに静的を選び、静的値としてnoneを設定します。
ページ・アイテムP1_PANNINGの設定は以上です。
ZoomingについてはPanningと設定はほぼ変わらないため、ページ・アイテムP1_PANNINGを重複させて作成します。
ページ・アイテムP1_PANNING上でコンテキスト・メニューを表示させ、重複を実行します。
作成されたページ・アイテムの識別の名前をP1_ZOOMINGに、ラベルをZoomingに変更します。ページ・アイテムP1_PANNINGの右隣に配置するため、レイアウトの新規行の開始をオフにします。
ダイアグラムとして表示するグラフのデータは、Ajaxコールバックを呼び出して取得します。
プロセス・ビューを開き、Ajaxコールバックにプロセスを作成します。Ajaxコールバックは、表DG_BASIC_NODESとDG_BASIC_LINKSの内容をそれぞれJSONの配列として含む、JSONオブジェクトを返します。
識別の名前はGET_DATA、タイプとしてコードを実行を選択します。ソースのPL/SQLコードとして以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
l_response clob; | |
begin | |
select json_object( | |
key 'nodes' value ( | |
select json_arrayagg( | |
json_object( | |
key 'id' value id | |
,key 'category' value category | |
) | |
) from dg_basic_nodes | |
) | |
,key 'links' value ( | |
select json_arrayagg( | |
json_object( | |
key 'id' value id | |
,key 'category' value category | |
,key 'start' value start_node | |
,key 'end' value end_node | |
) | |
) from dg_basic_links | |
) | |
) into l_response | |
from dual; | |
htp.p(l_response); | |
end; |
ダイアグラムの表示にはDemoCircleLayout.jsおよびDemoLayoutSupport.jsが必要です。
https://www.oracle.com/webfolder/technetwork/jet/cookbook/dataVisualizations/diagram/layouts/DemoCircleLayout.jshttps://www.oracle.com/webfolder/technetwork/jet/cookbook/dataVisualizations/diagram/layouts/DemoLayoutSupport.js
この2つのファイルを手元のPCにダウンロードし、APEXアプリケーションに静的アプリケーション・ファイルとしてアップロードします。
共有コンポーネントの静的アプリケーション・ファイルを開きます。
ファイルの作成をクリックします。
ディレクトリとしてlayoutsを指定し、ファイルをドラッグ・アンド・ドロップの領域にすでにダウンロードしてあるDemoLayoutSupport.jsを選択します。
作成をクリックします。
変更の保存をクリックするとminifyされたファイルが作成されます。ブレッドクラムの静的アプリケーション・ファイルをクリックしして、ファイルの一覧画面へ戻ります。
同様の手順にて静的アプリケーション・ファイルとしてDemoCircleLayout.jsを作成します。
最終的に静的アプリケーション・ファイルとして、DemoCircleLayouot.js、DemoLayoutSupport.jsと、双方のMinifyされたファイルDemoCircleLayouot.min.js、DemoLayoutSupport.min.jsが作成されます。
このJavaScriptファイルをロードする際に置換文字列#APP_FILES#がうまく使えません。#APP_FILES#はホスト名などを含まない相対パスに置換されますが、Oracle JETのコンポーネントはAPEXの外にあるため、これらのファイルはホスト名も含む絶対パスで指定する必要があります。
APEX_UTIL.HOST_URL('APEX_PATH')で取得されるURLをJavaScriptから参照できるように、アプリケーション・アイテムAPEX_PATHを作成し、APEX_UTIL.HOST_URL('APEX_PATH')が返す値を設定します。
共有コンポーネントのアプリケーション・アイテムを開きます。
作成済みのアプリケーション・アイテムが一覧されます。作成をクリックします。
名前としてAPEX_PATHを設定し、アプリケーション・アイテムの作成をクリックします。
デフォルトの有効範囲はアプリケーション、セキュリティのセッション・ステート保護は制限付き - ブラウザからの設定不可です。
アプリケーション・アイテムAPEX_PATHが作成されます。
共有コンポーネントのアプリケーションの計算を開きます。
作成済みのアプリケーションの計算が一覧されます。作成をクリックします。
計算アイテムとしてAPEX_PATHを選択します。頻度の計算ポイントはデフォルトの新規インスタンス(新規セッション)開始時を選択します。すでにAPEXアプリケーションが開始している場合、ページ・アイテムAPEX_PATHに値を設定するには、一旦サインアウトして再度サインインする必要があります。
計算の計算タイプに式を選択し、計算として以下を記述します。
APEX_UTIL.HOST_URL('APEX_PATH')
以上で、計算の作成をクリックします。
アプリケーションの計算としてAPEX_PATHが作成されます。
ページ・デザイナでホーム・ページを開きます。
ページ・プロパティのJavaScriptのファイルURLに以下を記述します。
[require jet]
ファンクションおよびグローバル変数の宣言に以下を記述します。
var diagram;
ページ・ロード時に実行に以下を記述します。ダイアグラムのモデルとなるクラスDiagramModelと、ダイアグラムを更新するapex.actionのupdate-diagramを定義しています。内容は概ねOracle JET Cookbookのdemo.jsを踏襲しています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
requirejs.config({ | |
paths: { | |
'diagramLayouts': "&APEX_PATH!RAW.#APP_FILES#layouts", | |
} | |
}); | |
require(["require", "exports", "knockout", "ojs/ojbootstrap", "diagramLayouts/DemoCircleLayout", "ojs/ojarraydataprovider", "ojs/ojattributegrouphandler", "ojs/ojknockout", "ojs/ojdiagram"], function (require, exports, ko, ojbootstrap_1, layout, ArrayDataProvider, ojattributegrouphandler_1) { | |
"use strict"; | |
class DiagramModel { | |
/* | |
* Diagramで表示するデータを更新する。 | |
*/ | |
update(data) { | |
this.nodeDataProvider(new ArrayDataProvider(data.nodes, { | |
keyAttributes: "id", | |
})); | |
this.linkDataProvider(new ArrayDataProvider(data.links, { | |
keyAttributes: "id", | |
})); | |
} | |
constructor() { | |
// this.data = JSON.parse(jsonData); | |
this.colorHandler = new ojattributegrouphandler_1.ColorAttributeGroupHandler(); | |
this.layoutFunc = layout.circleLayoutWithLayoutArgs(150); | |
this.panningValue = ko.observable(apex.items.P1_PANNING.value); | |
this.zoomingValue = ko.observable(apex.items.P1_ZOOMING.value); | |
/* | |
* this.nodeDataProvider, linkDataProviderはknockoutのobservableArrayに変更し、 | |
* データはコンストラクタの外から設定する。 | |
*/ | |
this.nodeDataProvider = ko.observableArray(); | |
this.linkDataProvider = ko.observableArray(); | |
} | |
} | |
(0, ojbootstrap_1.whenDocumentReady)().then(() => { | |
diagram = new DiagramModel(); | |
ko.applyBindings(diagram, document.getElementById('diagram-container')); | |
/* ページ・ロード時の表示 */ | |
apex.actions.invoke("update-diagram"); | |
}); | |
}); | |
/* | |
* Diagramを更新する。 | |
*/ | |
apex.actions.add([ | |
{ | |
name: "update-diagram", | |
action: () => { | |
apex.server.process ( "GET_DATA", {}, | |
{ | |
success: (data) => { | |
// console.log(data); | |
diagram.update(data); | |
} | |
} | |
); | |
} | |
} | |
]); |
CSSのファイルURLに以下を指定します。
#JET_CSS_DIRECTORY#redwood/oj-redwood-notag-min.css
対話グリッドでデータを変更し保存したときに、ダイアグラムを更新します。
対話グリッドNodesはすでに動的アクションが作成済みなので、TRUEアクションを追加します。
作成したTRUEアクションとしてJavaScriptコードの実行を選択し、設定のコードとして以下の1行を記述します。
apex.actions.invoke("update-diagram");
対話グリッドLinksを更新したときにもダイアグラムが更新されるように、動的アクションを作成します。
識別の名前はonSave Linksとします。タイミングのイベントとして保存[対話グリッド]を選択し、選択タイプはリージョン、リージョンとしてLinksを指定します。
apex.actions.invoke("update-diagram");
識別の名前はonChange Panning、タイミングのイベントはデフォルトの変更です。
TRUEアクションとしてJavaScriptコードの実行を選択し、設定のコードとして以下の1行を記述します。
diagram.panningValue($v(this.triggeringElement));
Zoomingの変更をダイアグラムに通知します。ページ・アイテムP1_ZOOMINGに動的アクションを作成します。
識別の名前はonChange Zooming、タイミングのイベントはデフォルトの変更です。