Jelajahi Sumber

added test RefGraph

Piotr Labudda 8 tahun lalu
induk
melakukan
ea748885c6

+ 33 - 0
SE/se-lib/Route/RefGraph.php

@@ -0,0 +1,33 @@
+<?php
+
+Lib::loadClass('Api_WfsNs');
+
+class Route_RefGraph extends RouteBase {
+
+	function defaultAction() {
+		UI::layout([$this, 'defaultView']);
+	}
+	function defaultView() {
+		$namespace = V::get('namespace', '', $_GET);
+		if (!$namespace) throw new Exception("Missing namespace");
+		$primaryKey = V::get('primaryKey', '', $_GET);
+		if (!$primaryKey) throw new Exception("Missing primaryKey");
+		echo UI::h('script', [ 'src' => "static/cytoscape.min.js" ]);
+		echo UI::h('div', [ 'id' => "ref_graph_node", 'style' => "width:98%; height:500px; border:1px solid silver; margin:8px auto; padding:0" ], [
+			"Pobieranie danych..."
+		]);
+
+		echo UI::h('script', [ 'src' => "static/visjs/vis.min.js" ]);
+		echo UI::h('style', [ 'type' => "text/css", 'src' => "static/visjs/vis.min.css" ]);
+		UI::inlineJS(__FILE__ . '.view.js', [
+			// 'FUNCTION_FETCH_CHILDRENS' => 'refGraphFetchChildrens',
+			// 'FUNCTION_FETCH_PARENTS' => 'refGraphFetchParents',
+			'HTML_ID_REF_GRAPH' => 'ref_graph_node',
+			'TYPENAME' => Api_WfsNs::typeName($namespace),
+			'PRIMARY_KEY' => $primaryKey,
+			// 'JS_CHANNEL_UPDATE_NAME' => $jsFunction['JS_CHANNEL_UPDATE_NAME'],
+			'DBG' => (V::get('DBG', 0, $_GET, 'int') > 0),
+		]);
+	}
+
+}

+ 168 - 0
SE/se-lib/Route/RefGraph.php.view.js

@@ -0,0 +1,168 @@
+// @require variables:
+if ('undefined' === typeof HTML_ID_REF_GRAPH) throw "Missing HTML_ID_REF_GRAPH";
+if ('undefined' === typeof TYPENAME) throw "Missing TYPENAME";
+if ('undefined' === typeof PRIMARY_KEY) throw "Missing PRIMARY_KEY";
+// if ('undefined' === typeof FUNCTION_FETCH_CHILDRENS) throw "Missing FUNCTION_FETCH_CHILDRENS";
+// if ('undefined' === typeof FUNCTION_FETCH_PARENTS) throw "Missing FUNCTION_FETCH_PARENTS";
+// if ('undefined' === typeof JS_CHANNEL_UPDATE_NAME) throw "Missing JS_CHANNEL_UPDATE_NAME";
+var DBG = DBG || 0;
+
+var nodes = null; // [ { id: '', label: '' }, ... ]
+var edges = null; // [ { id: '', from: '', to: '' }, ... ]
+var network = null; // graph object
+
+(function () {
+	var form = document.getElementById('wfs_request')
+	var featureTypeName = TYPENAME
+	var wfsParams = {
+		resolve: 'all',
+		resolveDepth: 3,
+		primaryKey: PRIMARY_KEY,
+	}
+	if(DBG)console.log('p5WFS_GetFeature', featureTypeName, wfsParams)
+	p5WFS_GetFeature(featureTypeName, wfsParams).then(function (features) {
+		if(DBG)console.log('features', features)
+		updateWfsResponse(features, featureTypeName)
+	}).catch(function (e) {
+		if(DBG)console.warn(e)
+		p5UI__notifyAjaxCallback({ type: 'error', msg: e })
+	})
+})();
+
+function updateWfsResponse(features, featureTypeName) {
+	if(DBG)console.log('updateWfsResponse', { features: features, featureTypeName: featureTypeName })
+	if (network !== null) {
+		network.destroy();
+		network = null;
+	}
+
+	// var _edgeIdAutoIncrement = 0
+	var _todoGraphData = [ { nodes: [], edges: [] } ]; // data by levels
+	parseResponseRec(_todoGraphData, features, featureTypeName)
+
+	var _graphData = {
+		nodes: new vis.DataSet(),
+		edges: new vis.DataSet(),
+	};
+	_todoGraphData.forEach(function (levelData) {
+		if (levelData.nodes && levelData.nodes.length) {
+			levelData.nodes.forEach(function (node) {
+				try {
+					_graphData.nodes.add(node)
+				} catch (e) {
+					if(DBG)console.log('_graphData.nodes.add error:', e);
+				}
+			})
+		}
+		if (levelData.edges && levelData.edges.length) {
+			levelData.edges.forEach(function (edge) {
+				try {
+					_graphData.edges.add(edge)
+				} catch (e) {
+					if(DBG)console.log('_graphData.edges.add error:', e);
+				}
+			})
+		}
+	})
+
+	// create a network
+	var container = document.getElementById(HTML_ID_REF_GRAPH)
+	container.style.height = '' + (window.innerHeight - 40) + 'px'
+	var directionInput = 'LR'
+	var options = {
+		layout: {
+			hierarchical: {
+				direction: directionInput,
+				levelSeparation: 500,
+				nodeSpacing: 200,
+				sortMethod: 'directed'
+				// hierarchical.enabled	Boolean	false	Toggle the usage of the hierarchical layout system. If this option is not defined, it is set to true if any of the properties in this object are defined.
+				// hierarchical.levelSeparation	Number	150	The distance between the different levels.
+				// hierarchical.nodeSpacing	Number	100	Minimum distance between nodes on the free axis. This is only for the initial layout. If you enable physics, the node distance there will be the effective node distance.
+				// hierarchical.treeSpacing	Number	200	Distance between different trees (independent networks). This is only for the initial layout. If you enable physics, the repulsion model will denote the distance between the trees.
+				// hierarchical.blockShifting	Boolean	true	Method for reducing whitespace. Can be used alone or together with edge minimization. Each node will check for whitespace and will shift it's branch along with it for as far as it can, respecting the nodeSpacing on any level. This is mainly for the initial layout. If you enable physics, they layout will be determined by the physics. This will greatly speed up the stabilization time though!
+				// hierarchical.edgeMinimization	Boolean	true	Method for reducing whitespace. Can be used alone or together with block shifting. Enabling block shifting will usually speed up the layout process. Each node will try to move along its free axis to reduce the total length of it's edges. This is mainly for the initial layout. If you enable physics, they layout will be determined by the physics. This will greatly speed up the stabilization time though!
+				// hierarchical.parentCentralization	Boolean	true	When true, the parents nodes will be centered again after the the layout algorithm has been finished.
+				// hierarchical.direction	String	'UD'	The direction of the hierarchical layout. The available options are: UD, DU, LR, RL. To simplify: up-down, down-up, left-right, right-left.
+				// hierarchical.sortMethod	String	'hubsize'	The algorithm used to ascertain the levels of the nodes based on the data. The possible options are: hubsize, directed.
+        //
+				// Hubsize takes the nodes with the most edges and puts them at the top. From that the rest of the hierarchy is evaluated.
+        //
+				// Directed adheres to the to and from data of the edges. A --> B so B is a level lower than A.
+			}
+		}
+	};
+	if(DBG)console.log('_graphData', _graphData)
+	network = new vis.Network(container, _graphData, options); // graphData: { nodes: [], edges: [] }
+
+	// add event listeners
+	network.on('select', function (params) {
+		if(DBG)console.log('Selection: ', params.nodes)
+		// document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
+	});
+}
+
+function parseResponseRec(_todoGraphData, json, typeName, parentNodeId, level) { // @used global _edgeIdAutoIncrement
+	var level = level || 0
+	var parentNodeId = parentNodeId || null
+	if(DBG)console.log('DBG::parseResponseRec', {json:json, typeName:typeName, parentNodeId:parentNodeId, isString: p5Utils__isString(json), isArray: p5Utils__isArray(json), isObject: p5Utils__isObject(json)});
+	if (p5Utils__isArray(json)) {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec isArray');
+		// TODO: create named group
+		var isXlinkList = (json.length > 0 && p5Utils__isString(json[0]))
+		json.forEach(function (subJson) {
+			if (isXlinkList) {
+				parseResponseXlinkListRec(_todoGraphData, subJson, typeName, parentNodeId, level)
+			} else {
+				parseResponseRec(_todoGraphData, subJson, typeName, parentNodeId, level)
+			}
+		})
+	} else if (p5Utils__isObject(json)) {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec isObject');
+		var objectName = typeName.substr(typeName.indexOf(':') + 1)
+		var nodeId = objectName + '.' + json.ID // TODO: primaryKey?
+		{
+			// _todoGraphData.nodes.add({ id: nodeId, label: nodeId })
+			if (!_todoGraphData[level]) _todoGraphData[level] = { nodes: [], edges: [] }
+			_todoGraphData[level].nodes.push({ id: nodeId, label: nodeId, group: objectName })
+			if (parentNodeId) {
+				// _graphData.edges.add({ id: parentNodeId+nodeId, from: parentNodeId, to: nodeId })
+				_todoGraphData[level].edges.push({ id: parentNodeId+nodeId, from: parentNodeId, to: nodeId })
+			}
+		}
+		Object.keys(json).filter(function (fieldName) {
+			return (fieldName.indexOf(':') > -1)
+		})
+		.forEach(function (fieldName) {
+			var value = json[fieldName]
+			parseResponseRec(_todoGraphData, value, fieldName, nodeId, level + 1)
+		})
+	} else if (p5Utils__isString(json)) {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec isString');
+	} else {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec is not string, not array and not object');
+	}
+}
+function parseResponseXlinkListRec(_todoGraphData, json, typeName, parentNodeId, level) {
+	if(DBG)console.log('DBG::parseResponseRec:XlinkList', {json:json, typeName:typeName, parentNodeId:parentNodeId, isString: p5Utils__isString(json), isArray: p5Utils__isArray(json), isObject: p5Utils__isObject(json)});
+	if (p5Utils__isString(json)) { // xlink "https://biuro.biall-net.pl/wfs/default_db/BI_audit_ENERGA_RUM_KONTRAHENCI#BI_audit_ENERGA_RUM_KONTRAHENCI.9233",
+		var nodeId = json.substr(json.indexOf('#') + 1)
+		var objectName = typeName
+		{
+			// _graphData.nodes.add({ id: nodeId, label: nodeId })
+			if (!_todoGraphData[level]) _todoGraphData[level] = { nodes: [], edges: [] }
+			_todoGraphData[level].nodes.push({ id: nodeId, label: nodeId, group: objectName })
+			if (parentNodeId) {
+				// _graphData.edges.add({ id: parentNodeId+nodeId, from: parentNodeId, to: nodeId })
+				_todoGraphData[level].edges.push({ id: parentNodeId+nodeId, from: parentNodeId, to: nodeId })
+			}
+		}
+	} else if (p5Utils__isObject(json)) {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec isObject - fetch more xlink object');
+	} else {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec:XlinkList is not string and not object');
+	}
+}
+
+// global['FUNCTION_FETCH_CHILDRENS'] = 'refGraphFetchChildrens'
+// global['FUNCTION_FETCH_PARENTS'] = 'refGraphFetchParents'

+ 26 - 1
SE/se-lib/Route/WfsJsRequestPanel.php

@@ -17,6 +17,7 @@ class Route_WfsJsRequestPanel extends RouteBase {
 			$jsFunction = [];
 			$jsFunction['JS_FUNCTION_UPDATE_RESPONSE'] = 'updateWfsResponse';
 			$jsFunction['JS_FUNCTION_GET_SELECTED_FORMAT'] = 'getWfsResponseFormat';
+			$jsFunction['JS_CHANNEL_UPDATE_NAME'] = 'wfsPanel';
 
 
 			$exampleProcesyFltr = [
@@ -310,12 +311,36 @@ class Route_WfsJsRequestPanel extends RouteBase {
 				])),
 			]);
 			UI::endContainer();
+			echo UI::h('script', [ 'src' => 'static/postal.min.js' ]);
 			UI::inlineJS(__FILE__ . '.updateResponseView.js', [
 				// 'NODE_ID_TREE_VIEW_FROM_TEXT' => "wfsResponseTreeView",
 				'NODE_ID_TREE_VIEW_FROM_JSON' => "jsonResponseTreeView",
 				'NODE_ID_WFS_RESPONSE' => "wfsResponse",
 				'JS_FUNCTION_UPDATE_RESPONSE' => $jsFunction['JS_FUNCTION_UPDATE_RESPONSE'],
 				'JS_FUNCTION_GET_SELECTED_FORMAT' => $jsFunction['JS_FUNCTION_GET_SELECTED_FORMAT'],
+				'JS_CHANNEL_UPDATE_NAME' => $jsFunction['JS_CHANNEL_UPDATE_NAME'],
+			]);
+
+			echo UI::h('div', [ 'id' => "ref_graph_node", 'style' => "width:100%; height:300px; border:1px solid silver; margin:10px; padding:0" ]);
+
+			echo UI::h('script', [ 'src' => "static/visjs/vis.min.js" ]);
+			echo UI::h('style', [ 'type' => "text/css", 'src' => "static/visjs/vis.min.css" ]);
+
+			// echo UI::h('script', [ 'src' => "static/cytoscape.min.js" ]);
+			// echo UI::h('script', [ 'src' => "static/cola.min.js" ]);
+			// echo UI::h('script', [ 'src' => "static/cytoscape-cola.js" ]);
+			// UI::inlineJS(__FILE__ . '.refGraph-cytoscape-cola.js', [
+			UI::inlineJS(__FILE__ . '.refGraph.js', [
+				'FUNCTION_FETCH_CHILDRENS' => 'refGraphFetchChildrens',
+				'FUNCTION_FETCH_PARENTS' => 'refGraphFetchParents',
+				'HTML_ID_REF_GRAPH' => 'ref_graph_node',
+				// 'NODE_ID_TREE_VIEW_FROM_TEXT' => "wfsResponseTreeView",
+				// 'NODE_ID_TREE_VIEW_FROM_JSON' => "jsonResponseTreeView",
+				// 'NODE_ID_WFS_RESPONSE' => "wfsResponse",
+				// 'JS_FUNCTION_UPDATE_RESPONSE' => $jsFunction['JS_FUNCTION_UPDATE_RESPONSE'],
+				// 'JS_FUNCTION_GET_SELECTED_FORMAT' => $jsFunction['JS_FUNCTION_GET_SELECTED_FORMAT'],
+				'JS_CHANNEL_UPDATE_NAME' => $jsFunction['JS_CHANNEL_UPDATE_NAME'],
+				'DBG' => (V::get('DBG', 0, $_GET, 'int') > 0),
 			]);
 
 			echo UI::h('script', [], "
@@ -385,7 +410,7 @@ class Route_WfsJsRequestPanel extends RouteBase {
 					console.log('p5WFS_GetFeature', featureTypeName, wfsParams)
 					p5WFS_GetFeature(featureTypeName, wfsParams).then(function (features) {
 						console.log('features', features)
-						{$jsFunction['JS_FUNCTION_UPDATE_RESPONSE']}(features)
+						{$jsFunction['JS_FUNCTION_UPDATE_RESPONSE']}(features, featureTypeName)
 					}).catch(function (e) {
 						console.warn(e)
 						{$jsFunction['JS_FUNCTION_UPDATE_RESPONSE']}(''+e)

+ 169 - 0
SE/se-lib/Route/WfsJsRequestPanel.php.refGraph.js

@@ -0,0 +1,169 @@
+// @require variables:
+if ('undefined' === typeof HTML_ID_REF_GRAPH) throw "Missing HTML_ID_REF_GRAPH";
+if ('undefined' === typeof FUNCTION_FETCH_CHILDRENS) throw "Missing FUNCTION_FETCH_CHILDRENS";
+if ('undefined' === typeof FUNCTION_FETCH_PARENTS) throw "Missing FUNCTION_FETCH_PARENTS";
+if ('undefined' === typeof JS_CHANNEL_UPDATE_NAME) throw "Missing JS_CHANNEL_UPDATE_NAME";
+if ('undefined' === typeof postal) throw "Missing postal.js";
+if ('undefined' === typeof vis) throw "Missing vis.js";
+var DBG = DBG || false
+
+var nodes = null; // [ { id: '', label: '' }, ... ]
+var edges = null; // [ { id: '', from: '', to: '' }, ... ]
+var network = null; // graph object
+
+function _dataUpdatedCallback(data, envelope) {
+	console.log('refGraph:postal:updated', {data: data, envelope: envelope})
+
+	if (network !== null) {
+		network.destroy();
+		network = null;
+	}
+
+	// var _edgeIdAutoIncrement = 0
+	var _todoGraphData = [ { nodes: [], edges: [] } ]; // data by levels
+	parseResponseRec(_todoGraphData, data.response, data.typeName)
+
+	var _graphData = {
+		nodes: new vis.DataSet(),
+		edges: new vis.DataSet(),
+	};
+	_todoGraphData.forEach(function (levelData) {
+		if (levelData.nodes && levelData.nodes.length) {
+			levelData.nodes.forEach(function (node) {
+				try {
+					_graphData.nodes.add(node)
+				} catch (e) {
+					if(DBG)console.log('_graphData.nodes.add error:', e);
+				}
+			})
+		}
+		if (levelData.edges && levelData.edges.length) {
+			levelData.edges.forEach(function (edge) {
+				try {
+					_graphData.edges.add(edge)
+				} catch (e) {
+					if(DBG)console.log('_graphData.edges.add error:', e);
+				}
+			})
+		}
+	})
+
+	// create a network
+	var container = document.getElementById(HTML_ID_REF_GRAPH)
+	container.style.height = '' + (window.innerHeight - 40) + 'px'
+	var directionInput = 'LR'
+	var options = {
+		layout: {
+			hierarchical: {
+				direction: directionInput,
+				levelSeparation: 500,
+				nodeSpacing: 200,
+				sortMethod: 'directed'
+				// hierarchical.enabled	Boolean	false	Toggle the usage of the hierarchical layout system. If this option is not defined, it is set to true if any of the properties in this object are defined.
+				// hierarchical.levelSeparation	Number	150	The distance between the different levels.
+				// hierarchical.nodeSpacing	Number	100	Minimum distance between nodes on the free axis. This is only for the initial layout. If you enable physics, the node distance there will be the effective node distance.
+				// hierarchical.treeSpacing	Number	200	Distance between different trees (independent networks). This is only for the initial layout. If you enable physics, the repulsion model will denote the distance between the trees.
+				// hierarchical.blockShifting	Boolean	true	Method for reducing whitespace. Can be used alone or together with edge minimization. Each node will check for whitespace and will shift it's branch along with it for as far as it can, respecting the nodeSpacing on any level. This is mainly for the initial layout. If you enable physics, they layout will be determined by the physics. This will greatly speed up the stabilization time though!
+				// hierarchical.edgeMinimization	Boolean	true	Method for reducing whitespace. Can be used alone or together with block shifting. Enabling block shifting will usually speed up the layout process. Each node will try to move along its free axis to reduce the total length of it's edges. This is mainly for the initial layout. If you enable physics, they layout will be determined by the physics. This will greatly speed up the stabilization time though!
+				// hierarchical.parentCentralization	Boolean	true	When true, the parents nodes will be centered again after the the layout algorithm has been finished.
+				// hierarchical.direction	String	'UD'	The direction of the hierarchical layout. The available options are: UD, DU, LR, RL. To simplify: up-down, down-up, left-right, right-left.
+				// hierarchical.sortMethod	String	'hubsize'	The algorithm used to ascertain the levels of the nodes based on the data. The possible options are: hubsize, directed.
+        //
+				// Hubsize takes the nodes with the most edges and puts them at the top. From that the rest of the hierarchy is evaluated.
+        //
+				// Directed adheres to the to and from data of the edges. A --> B so B is a level lower than A.
+			}
+		}
+	};
+	console.log('_graphData', _graphData)
+	network = new vis.Network(container, _graphData, options); // graphData: { nodes: [], edges: [] }
+
+	// add event listeners
+	network.on('select', function (params) {
+		console.log('Selection: ', params.nodes)
+		// document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
+	});
+
+}
+
+var subscription = postal.subscribe({
+	channel: JS_CHANNEL_UPDATE_NAME,
+	topic: "updated",
+	callback: _dataUpdatedCallback
+});
+
+function parseResponseRec(_todoGraphData, json, typeName, parentNodeId, level) { // @used global _edgeIdAutoIncrement
+	var level = level || 0
+	var parentNodeId = parentNodeId || null
+	console.log('DBG::_todoGraphData level('+level+')', _todoGraphData);
+	if(DBG)console.log('DBG::parseResponseRec', {json:json, typeName:typeName, parentNodeId:parentNodeId, isString: p5Utils__isString(json), isArray: p5Utils__isArray(json), isObject: p5Utils__isObject(json)});
+	if (p5Utils__isArray(json)) {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec isArray');
+		// TODO: create named group
+		var isXlinkList = (json.length > 0 && p5Utils__isString(json[0]))
+		json.forEach(function (subJson) {
+			if (isXlinkList) {
+				parseResponseXlinkListRec(_todoGraphData, subJson, typeName, parentNodeId, level)
+			} else {
+				parseResponseRec(_todoGraphData, subJson, typeName, parentNodeId, level)
+			}
+		})
+	} else if (p5Utils__isObject(json)) {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec isObject');
+		var objectName = typeName.substr(typeName.indexOf(':') + 1)
+		var nodeId = objectName + '.' + json.ID // TODO: primaryKey?
+		{
+			// _todoGraphData.nodes.add({ id: nodeId, label: nodeId })
+			if (!_todoGraphData[level]) _todoGraphData[level] = { nodes: [], edges: [] }
+			_todoGraphData[level].nodes.push({ id: nodeId, label: nodeId, group: objectName })
+			if (parentNodeId) {
+				// _graphData.edges.add({ id: parentNodeId+nodeId, from: parentNodeId, to: nodeId })
+				_todoGraphData[level].edges.push({ id: parentNodeId+nodeId, from: parentNodeId, to: nodeId })
+			}
+		}
+		Object.keys(json).filter(function (fieldName) {
+			return (fieldName.indexOf(':') > -1)
+		})
+		.forEach(function (fieldName) {
+			var value = json[fieldName]
+			console.log('feature['+fieldName+'] = ', value)
+			parseResponseRec(_todoGraphData, value, fieldName, nodeId, level + 1)
+		})
+	} else if (p5Utils__isString(json)) {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec isString');
+	} else {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec is not string, not array and not object');
+	}
+}
+function parseResponseXlinkListRec(_todoGraphData, json, typeName, parentNodeId, level) {
+	console.log('DBG::_todoGraphData level('+level+')', _todoGraphData);
+	if(DBG)console.log('DBG::parseResponseRec:XlinkList', {json:json, typeName:typeName, parentNodeId:parentNodeId, isString: p5Utils__isString(json), isArray: p5Utils__isArray(json), isObject: p5Utils__isObject(json)});
+	if (p5Utils__isString(json)) { // xlink "https://biuro.biall-net.pl/wfs/default_db/BI_audit_ENERGA_RUM_KONTRAHENCI#BI_audit_ENERGA_RUM_KONTRAHENCI.9233",
+		var nodeId = json.substr(json.indexOf('#') + 1)
+		var objectName = typeName
+		{
+			// _graphData.nodes.add({ id: nodeId, label: nodeId })
+			if (!_todoGraphData[level]) _todoGraphData[level] = { nodes: [], edges: [] }
+			_todoGraphData[level].nodes.push({ id: nodeId, label: nodeId, group: objectName })
+			if (parentNodeId) {
+				// _graphData.edges.add({ id: parentNodeId+nodeId, from: parentNodeId, to: nodeId })
+				_todoGraphData[level].edges.push({ id: parentNodeId+nodeId, from: parentNodeId, to: nodeId })
+			}
+		}
+	} else if (p5Utils__isObject(json)) {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec isObject - fetch more xlink object');
+	} else {
+		if(DBG)console.log('TODO: Not implemented - parseResponseRec:XlinkList is not string and not object');
+	}
+}
+
+
+function refGraphFetchChildrens() {
+
+}
+function refGraphFetchParents() {
+
+}
+
+global['FUNCTION_FETCH_CHILDRENS'] = 'refGraphFetchChildrens'
+global['FUNCTION_FETCH_PARENTS'] = 'refGraphFetchParents'

+ 24 - 17
SE/se-lib/Route/WfsJsRequestPanel.php.updateResponseView.js

@@ -5,24 +5,31 @@ var NODE_ID_TREE_VIEW_FROM_JSON = NODE_ID_TREE_VIEW_FROM_JSON || null // 'NODE_I
 // 'JS_FUNCTION_UPDATE_RESPONSE' => "updateWfsResponse"
 // 'JS_FUNCTION_GET_SELECTED_FORMAT' => "getWfsResponseFormat"
 
-// Object.prototype.toString.call([]) // "[object Array]"
-// Object.prototype.toString.call('') // "[object String]"
-// Object.prototype.toString.call({}) // "[object Object]"
-// Object.prototype.toString.call(null) // "[object Null]"
-// Object.prototype.toString.call() // "[object Undefined]"
-function p5Utils_isString(arg) { return '[object String]' === Object.prototype.toString.call(arg); }
-function p5Utils_isArray(arg) { return '[object Array]' === Object.prototype.toString.call(arg); }
-function p5Utils_isObject(arg) { return '[object Object]' === Object.prototype.toString.call(arg); }
-
 // private var - global for this file
 var _RESPONSE_DATA = null
 
-function updateResponse(values) {
+function updateResponse(values, typeName) {
+	var typeName = typeName || null
 	if ('undefined' !== typeof values) _RESPONSE_DATA = values
 	var responseFormat = global[JS_FUNCTION_GET_SELECTED_FORMAT]() // json, text
-	console.warn('format: '+responseFormat+', _RESPONSE_DATA: '+_RESPONSE_DATA)
+	console.warn({format: responseFormat, _RESPONSE_DATA: _RESPONSE_DATA})
+
+	if (postal && JS_CHANNEL_UPDATE_NAME) {
+		if (p5Utils__isArray(_RESPONSE_DATA)) {
+			postal.publish({
+				channel: JS_CHANNEL_UPDATE_NAME,
+				topic: "updated",
+				data: {
+					response: _RESPONSE_DATA,
+					typeName: typeName,
+				}
+			});
+		}
+	} else {
+		console.warn("Missing postal or JS_CHANNEL_UPDATE_NAME", {postal: postal, JS_CHANNEL_UPDATE_NAME: JS_CHANNEL_UPDATE_NAME})
+	}
 
-	document.getElementById(NODE_ID_WFS_RESPONSE).innerHTML = (p5Utils_isString(_RESPONSE_DATA)) ? _RESPONSE_DATA : JSON.stringify(_RESPONSE_DATA, null, 2)
+	document.getElementById(NODE_ID_WFS_RESPONSE).innerHTML = (p5Utils__isString(_RESPONSE_DATA)) ? _RESPONSE_DATA : JSON.stringify(_RESPONSE_DATA, null, 2)
 	if (NODE_ID_TREE_VIEW_FROM_JSON) {
 		var treeViewNode = document.getElementById(NODE_ID_TREE_VIEW_FROM_JSON)
 		if (treeViewNode) treeViewNode.parentNode.removeChild(treeViewNode)
@@ -102,8 +109,8 @@ function shortValue(str, limit) {
 function parseJsonToTreeViewRec(json, node, xpath, name) {
 	var name = name || '';
 	var xpath = xpath || '/root';
-	if(DBG)console.warn('DBG::parseJsonToTreeViewRec(json, node, "'+xpath+'", "'+name+'")', { isString: p5Utils_isString(json), 'isArray': p5Utils_isArray(json), 'isObject': p5Utils_isObject(json), json: json, node: node });
-	if (p5Utils_isArray(json)) {
+	if(DBG)console.warn('DBG::parseJsonToTreeViewRec(json, node, "'+xpath+'", "'+name+'")', { isString: p5Utils__isString(json), 'isArray': p5Utils__isArray(json), 'isObject': p5Utils__isObject(json), json: json, node: node });
+	if (p5Utils__isArray(json)) {
 		var details = document.createElement('details')
 		details.setAttribute('title', 'xpath: '+xpath)
 		if ('/root' === xpath) details.setAttribute('open', 'open')
@@ -119,7 +126,7 @@ function parseJsonToTreeViewRec(json, node, xpath, name) {
 		json.forEach(function (subJson, idx) {
 			parseJsonToTreeViewRec(subJson, div, xpath+'['+idx+']')
 		})
-	} else if (p5Utils_isObject(json)) {
+	} else if (p5Utils__isObject(json)) {
 		var details = document.createElement('details')
 		details.setAttribute('title', 'xpath: '+xpath)
 		if ('/root' === xpath) details.setAttribute('open', 'open')
@@ -135,14 +142,14 @@ function parseJsonToTreeViewRec(json, node, xpath, name) {
 		Object.keys(json).forEach(function (fieldName) {
 			parseJsonToTreeViewRec(json[fieldName], div, xpath+'/'+fieldName, fieldName)
 		})
-	} else if (p5Utils_isString(json)) {
+	} else if (p5Utils__isString(json)) {
 		var div = document.createElement('div')
 		div.style.paddingLeft = '11px'
 		div.setAttribute('title', 'xpath: '+xpath+( name ? '/'+name : '' ))
 		node.appendChild(div)
 		div.appendChild(document.createTextNode( name ? '"'+name+'": "'+shortValue(json, 100)+'",' : '"'+json+'",' ));
 	} else {
-		if(DBG)console.warn('TODO: Not implemented - parseJsonToTreeViewRec(json, node)', { isString: p5Utils_isString(json), 'isArray': p5Utils_isArray(json), 'isObject': p5Utils_isObject(json), json: json });
+		if(DBG)console.warn('TODO: Not implemented - parseJsonToTreeViewRec(json, node)', { isString: p5Utils__isString(json), 'isArray': p5Utils__isArray(json), 'isObject': p5Utils__isObject(json), json: json });
 	}
 }
 

File diff ditekan karena terlalu besar
+ 7 - 0
SE/static/postal.min.js


File diff ditekan karena terlalu besar
+ 0 - 0
SE/static/visjs/vis.min.css


File diff ditekan karena terlalu besar
+ 24 - 0
SE/static/visjs/vis.min.js


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini