Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
ferrygun18
Contributor
5,032
In this quick tutorial, we will create an SAC Analytic App custom widget to visualize network graph force layout.

Network Graph


As highlighted in Fiori Design Guidelines, the network graph displays a large amount of data by highlighting the relationships between individual records. Records are displayed as nodes, and connectors (lines) show the relationships between them. Below is the screenshot of the network graph with force layout algorithms.


 

Prepare the Data


Let's prepare the data in CSV format. I am getting the data from the SAPUI5 sample Force-Based Layout with Static Nodes. Save it to "data.csv".
KEY,FROM,TO,TITLE,GROUP,STATUS,ICON,LABEL0,VALUE0,LABEL1,VALUE1
0,0,1,Iron Man,1,Error,sap-icon://key-user-settings,Release date,"May 2, 2008",Director,Jon Favreau
1,1,5,Iron Man 2,1,Error,sap-icon://key-user-settings,Release date,"May 7, 2010",Director,Jon Favreau
2,2,5,The Incredible Hulk,1,Error,sap-icon://theater,Release date,"June 13, 2008",Director,Louis Leterrier
3,3,5,Thor,1,Warning,sap-icon://wrenc,Release date,"May 6, 2011",Director,Kenneth Branagh
4,4,5,Captain America: The First Avenger,1,Success,sap-icon://unfavorite,Release date,"July 22, 2011",Director,Joe Johnston
5,5,6,Marvel's The Avengers,1,Error,sap-icon://text-color,Release date,"May 4, 2012",Director,Joss Whedon
6,5,7,Marvel's The Avengers,1,Error,sap-icon://text-color,Release date,"May 4, 2012",Director,Joss Whedon
7,5,8,Marvel's The Avengers,1,Error,sap-icon://text-color,Release date,"May 4, 2012",Director,Joss Whedon
8,5,19,Marvel's The Avengers,1,Error,sap-icon://text-color,Release date,"May 4, 2012",Director,Joss Whedon
9,6,10,Iron Man 3,2,Error,sap-icon://key-user-settings,Release date,"May 3, 2013",Director,Shane Black
10,7,10,Thor: The Dark World,2,Warning,sap-icon://wrench,Release date,"November 8, 2013",Director,Alan Taylor
11,8,10,Captain America: The Winter Soldier,2,Success,sap-icon://unfavorite,Release date,"April 4, 2014",Director,Anthony & Joe Russo
12,9,12,Doctor Strange,3,Error,sap-icon://activate,Release date,"November 4, 2016",Director,Scott Derrickson
13,10,12,Avengers: Age of Ultron,2,Error,sap-icon://text-color,Release date,"May 1, 2015",Director,Joss Whedon
14,10,13,Avengers: Age of Ultron,2,Error,sap-icon://text-color,Release date,"May 1, 2015",Director,Joss Whedon
15,10,14,Avengers: Age of Ultron,2,Error,sap-icon://text-color,Release date,"May 1, 2015",Director,Joss Whedon
16,10,19,Avengers: Age of Ultron,2,Error,sap-icon://text-color,Release date,"May 1, 2015",Director,Joss Whedon
17,,,Ant-Man and the Wasp,3,Error,sap-icon://chain-link,Release date,"July 6, 2018",Director,Peyton Reed
18,12,20,Thor: Ragnarok,3,Warning,sap-icon://wrench,Release date,"November 3, 2017",Director,Taika Waititi
19,13,11,Ant-Man,2,Error,sap-icon://chain-link,Release date,"July 17, 2015",Director,Peyton Reed
20,13,14,Ant-Man,2,Error,sap-icon://chain-link,Release date,"July 17, 2015",Director,Peyton Reed
21,14,16,Captain America: Civil War,3,Success,sap-icon://unfavorite,Release date,"May 6, 2016",Director,Anthony & Joe Russo
22,14,17,Captain America: Civil War,3,Success,sap-icon://unfavorite,Release date,"May 6, 2016",Director,Anthony & Joe Russo
23,15,18,Guardians of the Galaxy,2,Error,sap-icon://shield,Release date,"August 1, 2014",Director,James Gunn
24,16,20,Spider-Man: Homecoming,3,Error,sap-icon://tree,Release date,"July 7, 2017",Director,Jon Watts
25,17,20,Black Panther,3,Error,sap-icon://circle-task-2,Release date,"February 16, 2018",Director,Ryan Coogler
26,18,20,Guardians of the Galaxy Vol. 2,3,Error,sap-icon://shield,Release date,"May 5, 2017",Director,James Gunn
27,,,Avengers 4,3,Error,sap-icon://text-color,Release date,"May 3, 2019",Director,Anthony & Joe Russo
28,20,19,Avengers: Infinity War,3,Error,sap-icon://text-color,Release date,"April 27, 2018",Director,Anthony & Joe Russo

Expose the Data


Write an R script with Plumber library to expose the data as an REST API, so we can call it from the SAC custom widget app.
suppressMessages(library(plumber))
suppressMessages(library(dplyr))
suppressMessages(library(tidyr))
suppressMessages(library(sqldf))
suppressMessages(library(rlist))

#' @filter cors
cors <- function(req, res) {
res$setHeader("Access-Control-Allow-Origin", "*")
if (req$REQUEST_METHOD == "OPTIONS") {
res$setHeader("Access-Control-Allow-Methods","*")
res$setHeader("Access-Control-Allow-Headers", req$HTTP_ACCESS_CONTROL_REQUEST_HEADERS)
res$status <- 200
return(list())
} else {
plumber::forward()
}
}

#* @param df data frame of variables
#* @get /hierarchy
#* @serializer unboxedJSON
function() {
tryCatch({

data <- read.csv("data.csv")
dataset <- sqldf("SELECT * FROM data")
totalrow = nrow(dataset)
print(totalrow)

node <- list()
line <- list()
group <- list()

count_node <-1
count <- 1

# Getting nodes
for(REC in 1:totalrow) {
KEY <- dataset[REC,"KEY"]
FROM <- dataset[REC,"FROM"]
TO <- dataset[REC,"TO"]
TITLE <- dataset[REC,"TITLE"]
GROUP <- dataset[REC, "GROUP"]
STATUS <- dataset[REC, "STATUS"]
ICON <- dataset[REC, "ICON"]
LABEL0 <- dataset[REC, "LABEL0"]
VALUE0 <- dataset[REC, "VALUE0"]
LABEL1 <- dataset[REC, "LABEL1"]
VALUE1 <- dataset[REC, "VALUE1"]

# Get attributes
attr1 <- list()
attr1 <- c(attr1, label=LABEL0)
attr1 <- c(attr1, value=VALUE0)

attr2 <- list()
attr2 <- c(attr2, label=LABEL1)
attr2 <- c(attr2, value=VALUE1)

attrF <- list()
attrF <- c(attrF, list(attr1))
attrF <- c(attrF, list(attr2))

data <- list()
data <- c(data, key=count_node-1)
data <- c(data, title=TITLE)
data <- c(data, group=GROUP)
data <- c(data, status=STATUS)
data <- c(data, icon=ICON)
data <- c(data, attributes=list(attrF))

if(REC > 1) {
x <- list.find(node, title==TITLE, 1)

if(length(x) == 0 ) {
node[count_node] <- list(data)
count_node <- count_node + 1
}
} else {
node[count_node] <- list(data)
count_node <- count_node + 1
}

# Get lines
if(!is.na(FROM)) {
data_line <- list()
data_line <- c(data_line, from=FROM)
data_line <- c(data_line, to=TO)
line[count] <- list(data_line)
count <- count + 1
}
}

#group
group1 <- list()
group1 <- c(group1, key=1)
group1 <- c(group1, title="Phase One")
group1 <- list(group1)

group2 <- list()
group2 <- c(group2, key=2)
group2 <- c(group2, title="Phase Two")
group2 <- list(group2)

group3 <- list()
group3 <- c(group3, key=3)
group3 <- c(group3, title="Phase Three")
group3 <- list(group3)

group <- list()
group <- c(group, group1)
group <- c(group, group2)
group <- c(group, group3)

# Getting final result
dataF <- list()
dataF <- c(dataF, nodes=list(node))
dataF <- c(dataF, lines=list(line))
dataF <- c(dataF, groups=list(group))

list(dataF)
}, error = function(err){
print(err)
list(err)
})
}

Let's execute the script to get the result.



SAC Analytic App Custom Widget


Finally, we'll create a custom widget with SAPUI5 library sap.ui.core.mvc.XMLView and  sap.suite.ui.commons.networkgraph.Graph. For more detailed steps how to create, you can refer to the blog in the "Reference" section.

On onInit() function, we execute the Ajax "GET" to request the data from the REST API.
onInit: function() {
var this_ = this;

if (that._firstConnection === 0) {

that._firstConnection = 1;

$.ajax({
url: 'http://127.0.0.1:8856/hierarchy', //R Plumber REST API URL
type: 'GET',
async: true,
timeout: 0,
contentType: 'application/json',
success: function(data) {
var oGraph,
oModel = new JSONModel(data[0]);
oModel.setSizeLimit(Number.MAX_SAFE_INTEGER);

this_.getView().setModel(oModel, that.widgetName);

this_.oModelSettings = new JSONModel({
maxIterations: 200,
maxTime: 500,
initialTemperature: 200,
coolDownStep: 1
});
this_.getView().setModel(this_.oModelSettings, "settings");

this_.oGraph = this_.byId("graph_" + widgetName);
this_.oGraph._fZoomLevel = 0.75;
},
error: function(e) {
console.log("error: " + e);
console.log(e);
}
});
}
}

Create an Analytic app, load the widget and run it. You should see the output as shown below.


 

References



 

 

 

 

 
3 Comments
Labels in this area