Commit 59a37887 authored by Fintan Mc Gee's avatar Fintan Mc Gee

addded node attirbute list view

parent 92c144ba
......@@ -523,12 +523,19 @@ var updateNodePositions_cb = function (req, res) {
};
var updateNodeData_cb = function (req, res) {
sLog.debug_log("***********updatePositions" + JSON.stringify(req.body) + "\n\n");
sLog.debug_log("***********updateNodeData_cb" + JSON.stringify(req.body) + "\n\n");
sLog.debug_log("***********graphDB.userGraphs" + JSON.stringify(graphDB.userGraphs) + "\n\n");
req.body.nodeUids.forEach(function(nUid) {
graphObj.userGraphs[req.user.username].getLayerByName(req.body.nodeLayerName).setNodeProperty(nUid,req.body.nodePropName, req.body.nodePropValue);
});
if(req.body.nodePropObj) {
req.body.nodeUids.forEach(function (nUid) {
for(var key in req.body.nodePropObj) {
if(req.body.nodePropObj[key]) {
graphObj.userGraphs[req.user.username].getLayerByName(req.body.nodeLayerName).setNodeProperty(nUid, key, req.body.nodePropObj[key]);
}
}
})
}
res.json({msg:"Updated node property completed"});
};
......
......@@ -140,6 +140,7 @@
<script src="js/controllers/aspectSelectionController.js"></script>
<script src="js/controllers/sideMenuController.js"></script>
<script src="js/controllers/temporalLayeringController.js"></script>
<script src="js/controllers/attributeBarChartListController.js"></script>
<!-- Font-->
<!--Directives-->
......@@ -168,6 +169,7 @@
<script src="./js/directives/edgeHistogramDirective.js"></script>
<script src="./js/directives/svgLabelsDirective.js"></script>
<script src="./js/directives/temporalLayeringHistogramDirective.js"></script>
<script src="./js/directives/simpleAttributeBarChartDirective.js"></script>
<!--Services-->
<script src="./js/services/multiLayerGraphService.js"></script>
<script src="./js/services/dataService.js"></script>
......
......@@ -196,6 +196,13 @@
overflow-x: auto;
}
.bordered-graph-custom_size{
border-style: solid;
border-color: #787878;
overflow-y: auto;
overflow-x: auto;
}
.bordered-graph-list{
border-style: solid;
border-color: #787878;
......
<!--<H2 class="centered"><span>Node Link List View</span></H2>-->
<ng-include src="'./html/templates/topAspectDataToolBar.html'"></ng-include>
<div>
<ng-include src="'./html/templates/sideMenus.html'"></ng-include>
<div style="position:relative;display:inline-block;width: 95%;">
<div class="centeredDiv">
<div class="row">
<div class="col-sm-6">
<!--<div ng-controller="attributeBarChartListCtrl" ng-init="init()" style="overflow-y: scroll; height: 100%">-->
<div ng-controller="attributeBarChartListCtrl" ng-init="init()" style="overflow-y: scroll; height: 100%">
<div class="row">
<div class="col-sm-1"> </div>
<div class="col-sm-3">
<label>Attribute Name</label>
</div>
<div class="col-sm-1"> </div>
<div class="col-sm-3">
<select class="form-control" id="newListAttrib" ng-model="model.barChartAttribute">
<option ng-repeat="attributeName in model.availableAttributes" value="{{attributeName}}">{{attributeName}}</option>
</select>
</div>
<div class="col-sm-1"> </div>
<div class="col-sm-2">
<button class="btn btn-default" id="selectEdgeNodes" ng-click="addAttributeChart()">Add</button>
</div>
<div class="col-sm-1"> </div>
</div>
<div ng-repeat = "chart in model.chartlist" class="row" style="overflow: auto; height: 350px;">
<simple-attribute-Bar-Chart-Directive clickfunc="highlight" id = "{{chart.vegaEmbedId}}" labelfield="{{chart.label}}" attributefield = "{{chart.attributeField}}" height = "200" ></simple-attribute-Bar-Chart-Directive>
</div>
</div>
</div>
<div ng-controller="simpleNodeLinkCtrl" class="col-sm-6">
<div class="row" style="padding-bottom: 2px;">
<div class="col-sm-3">
</div>
<div class="col-sm-2">
<label>Node Link layer </label>
</div>
<div class="col-sm-4">
<select class="form-control" id="nodeLinkLayerName" ng-model="model.nodeLinkLayerName"
ng-change="changeNodeLinkLayer()">
<option ng-repeat="selectedNodeLinkLayer in model.availableLayers"
value="{{selectedNodeLinkLayer}}">{{selectedNodeLinkLayer}}
</option>
</select>
</div>
<div class="col-sm-3">
</div>
</div>
<div class="row">
<svg-directive class="bordered-graph-custom_size" givenId="nl-graph" width="0.475"></svg-directive>
</div>
</div>
<div id="tooltip"></div>
<div id="nodeInfo"></div>
</div>
</div>
</div>
</div>
\ No newline at end of file
<!--<H2 class="centered"><span>Node Link List View</span></H2>-->
<ng-include src="'./html/templates/topAspectDataToolBar.html'"></ng-include>
<div>
<ng-include src="'./html/templates/sideMenus.html'"></ng-include>
<div style="position:relative;display:inline-block;width: 95%;">
......
......@@ -71,6 +71,9 @@ angular.module(
$routeProvider.when('/nodeLinkList', {
templateUrl: 'html/partials/nodeLinkListView.html'
});
$routeProvider.when('/nodeLinkAttribute', {
templateUrl: 'html/partials/nodeLinkAttributeView.html'
});
$routeProvider.when('/logout', {
templateUrl: '/logout'
});
......
This diff is collapsed.
/**************************************3
* nodeInfor COntrollerController.js
* Functionality: SDispaly a nodes indivdual information, inclduing hyperlinks, and enable
* querying of back end edges
*
* Created By : Fintan McGee (LIST)
* Date: 17/11/2016
********************************/
angular.module('blizaarModule.controllers')
.controller('nodeInfoChartCtrl', ['$scope', 'multiLayerGraphService',
function ($scope, multiLayerGraphService) {
$scope.model = {};
$scope.getChartData = function(nodeId, layerName, fieldNames) {
};
$scope.initNodeInfo = function() {
// get the curretnly Selected node From the application controller;
if($scope.getSelectedNodeList) {
$scope.model.selectedNodes = $scope.getSelectedNodeList()
if( $scope.model.selectedNodes.length > 0){
$scope.model.selectedNode = $scope.model.selectedNodes[0];
}
}
if($scope.model.selectedNode) {
$scope.getNodeInfo()
}
};
$scope.getNodeInfo = function(inputDataFields) {
var dataFields = [];
if(!$scope.model.selectedNode) {
$scope.model.selectedNodeData = "No node Selected";
$scope.model.nodeHyperlinkData = "No Hyperlinks found";
return;
}
if(inputDataFields) {
dataFields = inputDataFields;
} else {
for(var fieldName in $scope.model.selectedNode) {
if(typeof($scope.model.selectedNode[fieldName]) !== "function" &&
typeof($scope.model.selectedNode[fieldName]) !== "object") {
if(fieldName.substr(0,4) != "BLZ_") {
dataFields.push(fieldName);
}
}
}
}
dataFields.sort();
$scope.model.selectedNodeData = "";
$scope.model.nodeHyperlinkData = "";
$scope.model.nodeHyperlinks = [];
dataFields.forEach(function(d){
$scope.model.selectedNodeData += d + ": " + multiLayerGraphService.getNodePropertyValue($scope.model.selectedNode["uid"],d,$scope.model.selectedNode["BLZ_layer"]) + "\n\n";
if(typeof($scope.model.selectedNode[d])=== "string") {
if ($scope.model.selectedNode[d].indexOf("http") > -1) {
$scope.model.nodeHyperlinks.push({name: d, link: multiLayerGraphService.getNodePropertyValue($scope.model.selectedNode["uid"],d,$scope.model.selectedNode["BLZ_layer"])});
$scope.model.nodeHyperlinkData += d + ": " + multiLayerGraphService.getNodePropertyValue($scope.model.selectedNode["uid"],d,$scope.model.selectedNode["BLZ_layer"])+ "\n";
}
}
});
};
$scope.convertIdsToActualNodes = function(idArray) {
var actualNodes = [],
sourceLayer =multiLayerGraphService.getGraph()
.getLayerByName($scope.model.selectedLayer);
idArray.forEach(function(nId) {
actualNodes.push(sourceLayer.node[nId]);
});
return actualNodes;
};
$scope.$on('refreshGraph', function(){
$scope.initNodeInfo();
// createChart();
});
$scope.$on('graphDataChanged', function(){
$scope.initNodeInfo();
// createChart();
});
}]);
\ No newline at end of file
/**************************************3
* attributeBarChartDirective.js
* Functionality: Builds an interactive barchart using vega-lite
* Inputs include. Can take in Height and width of barchart as parameters
* as well as the field to use as the X-axis labels
*
* Created By : Fintan McGee (LIST)
* Date: 17/11/2016
********************************/
/*global vegaEmbed */
angular.module('blizaarModule.directives')
.directive('simpleAttributeBarChartDirective', ['dataService', 'multiLayerGraphService', 'colorService',
function (dataService, multiLayerGraphService, colorService) {
"use strict";
return {
restrict: 'E',
replace: true,
template: '<div class ="centeredDiv" ></div>',
// controller:"ApplicationCtrl",
// defining a JSDoc object
// not for documentation purposes , but just to avoid webstorm reporting
// on an unresolved variable
/**
* @param scope angular scope variable
* @param element the element this directive is being attached to
* @param params parameters from HTML template/ partial.
* @param params.givenid a unique Id passed in form html
* @param params.width used to scale the view width
* @param params.height used to scale the view height
* @param params.labelfield used to specify which field is the label
* */
link: function (scope, element, params) {
var localSelectedLabelField = "";
var localBarchartAttribute ="";
var selectedSortOrder = "decending";
var labelIdMap = {};
var chartWidth = null;
var vegaEmbedString = "#ListBarVis";
if(params !== undefined && params.id !== undefined) {
vegaEmbedString = "#" +params.id;
}
if(params !== undefined && params.width !== undefined) {
chartWidth = parseInt(params.width);
}
var chartHeight = null;
if(params !== undefined && params.height !== undefined) {
chartHeight = parseInt(params.height);
}
if(params !== undefined && params.labelfield !== undefined) {
localSelectedLabelField= params.labelfield;
}
if(params !== undefined && params.attributefield !== undefined) {
localBarchartAttribute= params.attributefield;
}
var createChart = function() {
// building the vega lite data structure
if(!colorService.colorsCatMapForNode) {
//Color scheme has not been defined
// which means there is no data to draw so exit
return;
}
var nodeColorRange = colorService.colorsCatMapForNode.range();
var nodeColorCategories = multiLayerGraphService.getGraph().getLayerByName(scope.model.selectedLayer).getColorCategories();
var nodeColorAttribute = multiLayerGraphService.getGraph().getLayerByName(scope.model.selectedLayer).getColorCategoryField();
var barData = scope.getBarChartData(localBarchartAttribute, nodeColorAttribute, localSelectedLabelField);
if(barData.length) {
if (localSelectedLabelField !== "uid") {
labelIdMap = {};
barData.forEach(function (n) {
if (labelIdMap.hasOwnProperty(n[localSelectedLabelField])) {
// some times labels may be duplicates , so we add a suffix to distinguish them
// and maintain correct mapping
n[localSelectedLabelField] = "" + n[localSelectedLabelField] + "_" +n.uid;
}
labelIdMap[n[localSelectedLabelField]] = n.uid;
});
}
// defining a skeleton vega lite specification
// the visualization is built by vega lite based on this
var vlData = {
"$schema": "https://vega.github.io/schema/vega-lite/v2.0.json",
//"height": 200,
//autosize:{"type":"fit"},
"data": {
"name": "barData",
"values": barData
},
"mark": "bar",
"selection": {
"brush": {"type": "interval", "encodings": ["x"]}
},
"encoding": {
"x": {"field": localSelectedLabelField, "type": "nominal", "scale": {"rangeStep": 20}},
"y": {"field": localBarchartAttribute, "type": "quantitative"},
"color": {
"field": nodeColorAttribute,
"type": "nominal",
"scale": {
"domain": nodeColorCategories,
"range": nodeColorRange
}
}
}
};
if(chartHeight !== null) {
vlData.height = chartHeight;
}
if(chartWidth !== null) {
vlData.width = chartWidth;
}
var vegaView = null;
if (scope.model.selectedSortOrder !== "unsorted") {
vlData.encoding.x.sort = {
field: localBarchartAttribute,
order: scope.model.selectedSortOrder,
op: "min"
};
}
if(scope.model.attributeTypes ) {
if(scope.model.attributeTypes[localBarchartAttribute] === "categorical") {
//vlData.encoding.x.bin = {maxbins: 50};
vlData.encoding.x.field = localBarchartAttribute;
vlData.encoding.x.max = true;
vlData.encoding.y = {
"aggregate": "count",
"type": "nominal"
}
}
}
/**************************************3
* handleBrush
* Functionality: Gets brushed element information from vega lite chart when the brush is updated
* Items are identified by x axis label so if that is not "id" a look up is done
*
* Created By : Fintan McGee (LIST)
* Date: 17/11/2016
* // controller:"ApplicationCtrl",
// defining a JSDoc object
// not for documentation purposes , but just to avoid webstorm reporting
// on an unresolved variable
* @param evt the brush event
* @param data data associate wth the event
* @param data.intervals the intervals selected by the brush
*
********************************/
var handleBrush = function (evt, data) {
if (data) {
var ids = data.intervals[0].extent;
if(ids.length >3 ) {
console.log(JSON.stringify(data));
}
if (localSelectedLabelField !== "uid") {
// map labels to node IDs
var originalIds = [];
ids.forEach(function (n) {
originalIds.push(labelIdMap[n]);
});
ids = originalIds;
}
// just use the ids
if (scope.replaceNodesSelection ) {
//we have ids now we build an array of actual nodes form the currently
// selected actual node items
// and pass it the relevant function in the application controller
scope.replaceNodesSelection(scope.convertIdsToActualNodes(ids),false,scope.model.selectAcrossAllLayers);
}
}
};
// Alternate Approach to Loading Vega lite
// By compiling it into full vega
// This gives builds schema spec for
// adding more complex functionality
// not useful now , but may be later
// var vegaSpec = vl.compile(vlData).spec;
// vegaSpec.signals.push(newSignal);
// var runtime = vega.parse(vegaSpec); // may throw an Error if parsing fails
// vegaView = new vega.View(runtime)
// //.logLevel(vega.Warn) // set view logging level
// .renderer('svg') // set renderer (canvas or svg)
// .initialize('#barVis') // initialize view within parent DOM container
// .hover() // enable hover encode set processing
// .run(); //update and render the view
// vegaView.addSignalListener("brush_tuple", handleBrush);
// console.log("Vega Built")
// embed the chart in the page
vegaEmbed(vegaEmbedString, vlData, {
actions: false,
renderer: "canvas"
}).then(function (data1) {
vegaView = data1.view;
vegaView.hover().run(); // .enable hover event processing
// add a listener to identify brushed items
// noinspection Annotator
vegaView.addSignalListener("brush_tuple", handleBrush);
});
}
};
// update the barchart when configuration changes
scope.$watch('model.barChartAttribute', function() {
createChart();
});
scope.$watch('model.selectedSortOrder', function() {
createChart();
});
scope.$watch('model.selectedLayer', function() {
createChart();
});
scope.$on('graphDataChanged', function(){
createChart();
});
}
};
}]);
\ No newline at end of file
module.exports = {
db_txn_url: ":7474/db/data/transaction/commit",
db_login_url:":7474/user/neo4j",
......
......@@ -2577,16 +2577,23 @@ var MultiLayerGraph = function (nodes, links, layerName) {
return labelFound;
}
// coppys all distinct attibutes for source to target without overwiritng existing ones.
// retuns a simple objet containin all ne values
g.copyDistinctNodeAttributes= function(sourceUId, targetUId) {
var sourceNode = g.node[sourceUId],
targetNode = g.node[targetUId];
var updateObj = {};
if(sourceNode && targetNode) {
for(var nodeAttrib in sourceNode) {
if(!targetNode.hasOwnProperty(nodeAttrib)) {
targetNode[nodeAttrib] = sourceNode[nodeAttrib];
updateObj[nodeAttrib] = sourceNode[nodeAttrib];
}
}
}
return updateObj;
}
......@@ -3301,6 +3308,7 @@ var MultiLayerGraph = function (nodes, links, layerName) {
}
};
g.getLinkProperty =function(uid,propName) {
if(g.isLocalLayerProperty(propName)) {
return g.link[uid][propName];
......@@ -3361,6 +3369,7 @@ var MultiLayerGraph = function (nodes, links, layerName) {
layer.buildNodeLookUp();
layer.buildLinkLookUp();
});
}
g.setUID();
g.buildNodeLookUp();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment