mirror of https://github.com/MISP/MISP
Merge pull request #4309 from mokaddem/extendedDistributionGraph
Improvement on distribution visualizationpull/4316/head
commit
ae2c513b62
|
@ -115,6 +115,7 @@ class ACLComponent extends Component
|
|||
'getEventGraphReferences' => array('*'),
|
||||
'getEventGraphTags' => array('*'),
|
||||
'getEventGraphGeneric' => array('*'),
|
||||
'genDistributionGraph' => array('*'),
|
||||
'getDistributionGraph' => array('*'),
|
||||
'getReferenceData' => array('*'),
|
||||
'getReferences' => array('*'),
|
||||
|
|
|
@ -868,6 +868,7 @@ class EventsController extends AppController
|
|||
$this->set('analysisLevels', $this->Event->analysisLevels);
|
||||
$this->set('distributionLevels', $this->Event->distributionLevels);
|
||||
$this->set('shortDist', $this->Event->shortDist);
|
||||
$this->set('distributionData', $this->genDistributionGraph(-1));
|
||||
if ($this->params['ext'] === 'csv') {
|
||||
App::uses('CsvExport', 'Export');
|
||||
$export = new CsvExport();
|
||||
|
@ -4667,8 +4668,7 @@ class EventsController extends AppController
|
|||
return new CakeResponse(array('body' => json_encode($json), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
|
||||
public function getDistributionGraph($id, $type = 'event')
|
||||
{
|
||||
private function genDistributionGraph($id, $type = 'event', $extended = 0) {
|
||||
$validTools = array('event');
|
||||
if (!in_array($type, $validTools)) {
|
||||
throw new MethodNotAllowedException(__('Invalid type.'));
|
||||
|
@ -4677,9 +4677,6 @@ class EventsController extends AppController
|
|||
$this->loadModel('Organisation');
|
||||
App::uses('DistributionGraphTool', 'Tools');
|
||||
$grapher = new DistributionGraphTool();
|
||||
$data = $this->request->is('post') ? $this->request->data : array();
|
||||
|
||||
$extended = isset($this->params['named']['extended']) ? 1 : 0;
|
||||
|
||||
$servers = $this->Server->find('list', array(
|
||||
'fields' => array('name'),
|
||||
|
@ -4692,6 +4689,13 @@ class EventsController extends AppController
|
|||
$item = utf8_encode($item);
|
||||
}
|
||||
});
|
||||
return $json;
|
||||
}
|
||||
|
||||
public function getDistributionGraph($id, $type = 'event')
|
||||
{
|
||||
$extended = isset($this->params['named']['extended']) ? 1 : 0;
|
||||
$json = $this->genDistributionGraph($id, $type, $extended);
|
||||
$this->response->type('json');
|
||||
return new CakeResponse(array('body' => json_encode($json), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
// construct distribution info
|
||||
$this->__json['distributionInfo'] = array();
|
||||
$sgs = $this->__eventModel->SharingGroup->fetchAllAuthorised($this->__user, 'name', 1);
|
||||
$this->__json['allSharingGroup'] = h(array_values($sgs));
|
||||
$sgs = $this->__eventModel->SharingGroup->fetchAllAuthorised($this->__user, 'simplified', 1);
|
||||
$this->__json['allSharingGroup'] = h($sgs);
|
||||
$distributionLevels = $this->__eventModel->distributionLevels;
|
||||
foreach ($distributionLevels as $key => $value) {
|
||||
$this->__json['distributionInfo'][$key] = array('key' => h($value), 'desc' => h($this->__eventModel->distributionDescriptions[$key]['formdesc']), 'value' => h($key));
|
||||
|
@ -59,6 +59,12 @@
|
|||
$this->__json['additionalDistributionInfo'][$distributionLevel] = array();
|
||||
}
|
||||
$this->__json['additionalDistributionInfo'][$distributionLevel][h($data)] = 0; // set-alike
|
||||
if ($distributionLevel == 4) {
|
||||
if (!isset($this->__json['sharingGroupRepartition'][h($data)])) {
|
||||
$this->__json['sharingGroupRepartition'][h($data)] = 0;
|
||||
}
|
||||
$this->__json['sharingGroupRepartition'][h($data)]++;
|
||||
}
|
||||
}
|
||||
|
||||
private function __addOtherDistributionInfo()
|
||||
|
@ -124,17 +130,28 @@
|
|||
|
||||
public function get_distributions_graph($id)
|
||||
{
|
||||
$event = $this->__get_event($id);
|
||||
$eventDist = $event['distribution'];
|
||||
$eventSGName = $event['SharingGroupName'];
|
||||
$this->__eventDistribution = $eventDist;
|
||||
$this->__eventSharingGroupName = $eventSGName;
|
||||
$this->__json['event'] = $this->init_array_distri();
|
||||
$this->__json['attribute'] = $this->init_array_distri();
|
||||
$this->__json['object'] = $this->init_array_distri();
|
||||
$this->__json['obj_attr'] = $this->init_array_distri();
|
||||
$this->__json['additionalDistributionInfo'] = $this->init_array_distri(array());
|
||||
$this->__json['sharingGroupRepartition'] = array();
|
||||
|
||||
$this->__addOtherDistributionInfo();
|
||||
|
||||
// transform set into array
|
||||
foreach (array_keys($this->__json['additionalDistributionInfo']) as $d) {
|
||||
$this->__json['additionalDistributionInfo'][$d] = array_keys($this->__json['additionalDistributionInfo'][$d]);
|
||||
}
|
||||
|
||||
if ($id === -1) {
|
||||
return $this->__json;
|
||||
}
|
||||
$event = $this->__get_event($id);
|
||||
$eventDist = $event['distribution'];
|
||||
$eventSGName = $event['SharingGroupName'];
|
||||
$this->__eventDistribution = $eventDist;
|
||||
$this->__eventSharingGroupName = $eventSGName;
|
||||
|
||||
if (empty($event)) {
|
||||
return $this->__json;
|
||||
|
@ -188,13 +205,8 @@
|
|||
|
||||
unset($this->__json['distributionInfo'][5]); // inherit event.
|
||||
|
||||
|
||||
$this->__addOtherDistributionInfo();
|
||||
|
||||
// transform set into array
|
||||
foreach (array_keys($this->__json['additionalDistributionInfo']) as $d) {
|
||||
$this->__json['additionalDistributionInfo'][$d] = array_keys($this->__json['additionalDistributionInfo'][$d]);
|
||||
}
|
||||
// transform set into array for SG (others are already done)
|
||||
$this->__json['additionalDistributionInfo'][4] = array_keys($this->__json['additionalDistributionInfo'][4]);
|
||||
|
||||
return $this->__json;
|
||||
}
|
||||
|
|
|
@ -214,6 +214,16 @@
|
|||
echo h($shortDist[$event['Event']['distribution']]);
|
||||
endif;
|
||||
?>
|
||||
<?php
|
||||
echo sprintf(
|
||||
'<it type="button" title="%s" class="%s" aria-hidden="true" style="font-size: x-small;" data-event-distribution="%s" data-event-distribution-name="%s" data-scope-id="%s"></it>',
|
||||
'Toggle advanced sharing network viewer',
|
||||
'fa fa-share-alt useCursorPointer distributionNetworkToggle',
|
||||
h($event['Event']['distribution']),
|
||||
$event['Event']['distribution'] == 4 ? h($event['SharingGroup']['name']) : h($shortDist[$event['Event']['distribution']]),
|
||||
h($event['Event']['id'])
|
||||
)
|
||||
?>
|
||||
</td>
|
||||
<td class="short action-links">
|
||||
<?php
|
||||
|
@ -239,5 +249,11 @@
|
|||
$('.select').on('change', function() {
|
||||
listCheckboxesChecked();
|
||||
});
|
||||
|
||||
$('.distributionNetworkToggle').each(function() {
|
||||
$(this).distributionNetwork({
|
||||
distributionData: <?php echo json_encode($distributionData); ?>,
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
<div class="spinner"></div>
|
||||
<div class="loadingText"><?php echo __('Loading');?></div>
|
||||
</div>
|
||||
<div id="eventdistri_graph" data-event-id="<?php echo h($event['Event']['id']); ?>" data-event-distribution="<?php echo h($event['Event']['distribution']); ?>" data-user-manipulation="<?php echo $mayModify || $isSiteAdmin ? 'true' : 'false'; ?>" data-extended="<?php echo $extended; ?>">
|
||||
|
||||
<div id="eventdistri_graph" data-event-id="<?php echo h($event['Event']['id']); ?>" data-event-distribution="<?php echo h($event['Event']['distribution']); ?>" data-event-distribution-text="<?php echo $event['Event']['distribution'] == 4 ? h($event['SharingGroup']['name']) : h($distributionLevels[$event['Event']['distribution']]); ?>" data-user-manipulation="<?php echo $mayModify || $isSiteAdmin ? 'true' : 'false'; ?>" data-extended="<?php echo $extended; ?>">
|
||||
<canvas id="distribution_graph_canvas" height="290px"width="400px"></canvas>
|
||||
</div>
|
||||
<div class="popupDistriSeparator"></div>
|
||||
|
|
|
@ -136,6 +136,12 @@
|
|||
});
|
||||
|
||||
</script>
|
||||
<?php
|
||||
echo $this->Html->script('vis');
|
||||
echo $this->Html->css('vis');
|
||||
echo $this->Html->css('distribution-graph');
|
||||
echo $this->Html->script('network-distribution-graph');
|
||||
?>
|
||||
|
||||
<input type="hidden" class="keyboardShortcutsConfig" value="/shortcuts/event_index.json" />
|
||||
<?php
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
echo $this->Html->css('query-builder.default');
|
||||
echo $this->Html->script('query-builder');
|
||||
echo $this->Html->css('attack_matrix');
|
||||
echo $this->Html->script('network-distribution-graph');
|
||||
?>
|
||||
<div class="events view">
|
||||
<?php
|
||||
|
@ -145,15 +146,24 @@
|
|||
'key' => __('Distribution'),
|
||||
'value_class' => ($event['Event']['distribution'] == 0) ? 'privateRedText' : '',
|
||||
'html' => sprintf(
|
||||
'%s %s',
|
||||
'%s %s %s %s',
|
||||
($event['Event']['distribution'] == 4) ?
|
||||
sprintf('<a href="%s%s">%s</a>', $baseurl . '/sharing_groups/view/', h($event['SharingGroup']['id']), h($event['SharingGroup']['name'])) :
|
||||
h($distributionLevels[$event['Event']['distribution']]),
|
||||
sprintf(
|
||||
'<span class="%s" data-object-id="%s" data-object-context="event" data-shown="false"></span><div style="display: none">%s</div>',
|
||||
'<span id="distribution_graph_bar" style="margin-left: 5px;" data-object-id="%s" data-object-context="event"></span>',
|
||||
h($event['Event']['id'])
|
||||
),
|
||||
sprintf(
|
||||
'<it class="%s" data-object-id="%s" data-object-context="event" data-shown="false"></it><div style="display: none">%s</div>',
|
||||
'useCursorPointer fa fa-info-circle distribution_graph',
|
||||
h($event['Event']['id']),
|
||||
$this->element('view_event_distribution_graph')
|
||||
),
|
||||
sprintf(
|
||||
'<it type="button" id="showAdvancedSharingButton" title="%s" class="%s" aria-hidden="true" style="margin-left: 5px;"></it>',
|
||||
'Toggle advanced sharing network viewer',
|
||||
'fa fa-share-alt useCursorPointer'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -497,6 +507,7 @@ $(document).ready(function () {
|
|||
$.get("/threads/view/<?php echo h($event['Event']['id']); ?>/true", function(data) {
|
||||
$("#discussions_div").html(data);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function enable_correlation_graph() {
|
||||
|
|
|
@ -2,6 +2,44 @@
|
|||
color: #333333;
|
||||
}
|
||||
|
||||
.eventgraph_header {
|
||||
background: #f9f9f9;
|
||||
box-shadow: 0px 0px 6px #B2B2B2;
|
||||
margin-bottom: 2px;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
select.center-in-network-header {
|
||||
margin-bottom: 0px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
input[type="text"].center-in-network-header {
|
||||
top: 5px;
|
||||
margin: 0px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
input[type="checkbox"].center-in-network-header {
|
||||
top: 0px;
|
||||
margin: 0px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
label.center-in-network-header {
|
||||
user-select: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.center-in-network-header {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
top: 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.loadingPopover {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
|
@ -105,3 +143,21 @@
|
|||
border-radius: 4px;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);
|
||||
}
|
||||
|
||||
.advancedSharingNetwork {
|
||||
position: fixed;
|
||||
top: 45px;
|
||||
right: 0px;
|
||||
height: 800px;
|
||||
width: 800px;
|
||||
background: #ffffffcc;;
|
||||
z-index: 1;
|
||||
border: 1px solid #0088cc;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.sharingNetworkOrgFinder {
|
||||
position: absolute !important;
|
||||
right: 30px !important;
|
||||
}
|
||||
|
|
|
@ -1,369 +1,455 @@
|
|||
var scope_id = $('#eventdistri_graph').data('event-id');
|
||||
var event_distribution = $('#eventdistri_graph').data('event-distribution');
|
||||
var event_distribution_text = $('#eventdistri_graph').data('event-distribution-text');
|
||||
var extended_text = $('#eventdistri_graph').data('extended') == 1 ? true : false;
|
||||
var spanOffset_orig = 15; // due to padding
|
||||
var payload = {};
|
||||
var distribution_chart;
|
||||
var distributionData;
|
||||
|
||||
function clickHandlerGraph(evt) {
|
||||
var firstPoint = distribution_chart.getElementAtEvent(evt)[0];
|
||||
var distribution_id;
|
||||
if (firstPoint) {
|
||||
var value = distribution_chart.data.datasets[firstPoint._datasetIndex].data[firstPoint._index];
|
||||
if (value == 0) {
|
||||
document.getElementById('attributesFilterField').value = "";
|
||||
filterAttributes('all', scope_id);
|
||||
} else {
|
||||
distribution_id = distribution_chart.data.distribution[firstPoint._index].value;
|
||||
var value_to_set = String(distribution_id);
|
||||
value_to_set += distribution_id == event_distribution ? '|' + '5' : '';
|
||||
value_to_set = value_to_set.split('|');
|
||||
var rules = {
|
||||
condition: 'AND',
|
||||
rules: [
|
||||
{
|
||||
field: 'distribution',
|
||||
value: value_to_set
|
||||
}
|
||||
]
|
||||
};
|
||||
performQuery(rules);
|
||||
}
|
||||
}
|
||||
var firstPoint = distribution_chart.getElementAtEvent(evt)[0];
|
||||
var distribution_id;
|
||||
if (firstPoint) {
|
||||
var value = distribution_chart.data.datasets[firstPoint._datasetIndex].data[firstPoint._index];
|
||||
if (value == 0) {
|
||||
document.getElementById('attributesFilterField').value = "";
|
||||
filterAttributes('all', scope_id);
|
||||
} else {
|
||||
distribution_id = distribution_chart.data.distribution[firstPoint._index].value;
|
||||
var value_to_set = String(distribution_id);
|
||||
value_to_set += distribution_id == event_distribution ? '|' + '5' : '';
|
||||
value_to_set = value_to_set.split('|');
|
||||
var rules = {
|
||||
condition: 'AND',
|
||||
rules: [
|
||||
{
|
||||
field: 'distribution',
|
||||
value: value_to_set
|
||||
}
|
||||
]
|
||||
};
|
||||
performQuery(rules);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generate_additional_info(info) {
|
||||
if (info.length == 0) {
|
||||
return "";
|
||||
} else {
|
||||
var to_ret = "\n\nInvolved:\n";
|
||||
var sel = document.createElement('select');
|
||||
sel.classList.add('distributionInfo');
|
||||
info.forEach(function(i) {
|
||||
var opt = document.createElement('option');
|
||||
opt.val = i;
|
||||
opt.innerHTML = i;
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
return to_ret += sel.outerHTML;
|
||||
}
|
||||
if (info.length == 0) {
|
||||
return "";
|
||||
} else {
|
||||
var to_ret = "\n\nInvolved:\n";
|
||||
var sel = document.createElement('select');
|
||||
sel.classList.add('distributionInfo');
|
||||
info.forEach(function(i) {
|
||||
var opt = document.createElement('option');
|
||||
opt.val = i;
|
||||
opt.innerHTML = i;
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
return to_ret += sel.outerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
function generate_pie_chart(data, placeholder) {
|
||||
var labels = Object.keys(data);
|
||||
var dough_data = labels.map(function(l) {
|
||||
return data[l];
|
||||
});
|
||||
|
||||
if (labels.length == 0) {
|
||||
return
|
||||
} else {
|
||||
var sgDistributionChart = new Chart(placeholder, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
data: dough_data,
|
||||
backgroundColor: labels.map(function(l) { return '#7a86e0'; })
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
title: {
|
||||
display: false
|
||||
},
|
||||
animation: {
|
||||
duration: 500
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function clickHandlerPbText(evt) {
|
||||
var distribution_id = evt.target.dataset.distribution;
|
||||
var value_to_set = String(distribution_id);
|
||||
var rules = {
|
||||
condition: 'AND',
|
||||
rules: [
|
||||
{
|
||||
field: 'distribution',
|
||||
value: [value_to_set]
|
||||
}
|
||||
]
|
||||
};
|
||||
performQuery(rules);
|
||||
var distribution_id = evt.target.dataset.distribution;
|
||||
var value_to_set = String(distribution_id);
|
||||
var rules = {
|
||||
condition: 'AND',
|
||||
rules: [
|
||||
{
|
||||
field: 'distribution',
|
||||
value: [value_to_set]
|
||||
}
|
||||
]
|
||||
};
|
||||
performQuery(rules);
|
||||
}
|
||||
function clickHandlerPb(evt) {
|
||||
var distribution_id = $(evt.target).data('distribution');
|
||||
var value_to_set = String(distribution_id);
|
||||
value_to_set = value_to_set.split('|')
|
||||
var rules = {
|
||||
condition: 'AND',
|
||||
rules: [
|
||||
{
|
||||
field: 'distribution',
|
||||
value: value_to_set
|
||||
}
|
||||
]
|
||||
};
|
||||
performQuery(rules);
|
||||
var distribution_id = $(evt.target).data('distribution');
|
||||
var value_to_set = String(distribution_id);
|
||||
value_to_set = value_to_set.split('|')
|
||||
var rules = {
|
||||
condition: 'AND',
|
||||
rules: [
|
||||
{
|
||||
field: 'distribution',
|
||||
value: value_to_set
|
||||
}
|
||||
]
|
||||
};
|
||||
performQuery(rules);
|
||||
}
|
||||
|
||||
function fill_distri_for_search(start_distri, end_distri) {
|
||||
var to_ret = "";
|
||||
for (var i=start_distri; i<end_distri; i++) {
|
||||
to_ret += String(i) + "|";
|
||||
to_ret += i==event_distribution ? "5|" : "";
|
||||
}
|
||||
to_ret += String(end_distri);
|
||||
to_ret += end_distri==event_distribution ? "|5" : "";
|
||||
return to_ret;
|
||||
var to_ret = "";
|
||||
for (var i=start_distri; i<end_distri; i++) {
|
||||
to_ret += String(i) + "|";
|
||||
to_ret += i==event_distribution ? "5|" : "";
|
||||
}
|
||||
to_ret += String(end_distri);
|
||||
to_ret += end_distri==event_distribution ? "|5" : "";
|
||||
return to_ret;
|
||||
}
|
||||
|
||||
function get_maximum_distribution(array) {
|
||||
var org = array[0];
|
||||
var community = array[1];
|
||||
var connected = array[2];
|
||||
var all = array[3];
|
||||
var sharing = array[4];
|
||||
if (all != 0) {
|
||||
return 3;
|
||||
} else if (connected != 0) {
|
||||
return 2;
|
||||
} else if (community != 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
var org = array[0];
|
||||
var community = array[1];
|
||||
var connected = array[2];
|
||||
var all = array[3];
|
||||
var sharing = array[4];
|
||||
if (all != 0) {
|
||||
return 3;
|
||||
} else if (connected != 0) {
|
||||
return 2;
|
||||
} else if (community != 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function get_minimum_distribution(array, event_dist) {
|
||||
var org = array[0];
|
||||
var community = array[1];
|
||||
var connected = array[2];
|
||||
var all = array[3];
|
||||
var sharing = array[4];
|
||||
if (connected != 0 && 3 == event_distribution) {
|
||||
return 2;
|
||||
} else if (community != 0 && 1 < event_distribution) {
|
||||
return 1;
|
||||
} else if (org != 0 && 0 < event_distribution) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
var org = array[0];
|
||||
var community = array[1];
|
||||
var connected = array[2];
|
||||
var all = array[3];
|
||||
var sharing = array[4];
|
||||
if (connected != 0 && 3 == event_distribution) {
|
||||
return 2;
|
||||
} else if (community != 0 && 1 < event_distribution) {
|
||||
return 1;
|
||||
} else if (org != 0 && 0 < event_distribution) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
function add_level_to_pb(distribution, additionalInfo, maxLevel) {
|
||||
var pb_container = document.getElementById('eventdistri_pb_container');
|
||||
var pb = document.getElementById('eventdistri_pb_background');
|
||||
document.getElementById('eventdistri_graph').style.left = spanOffset_orig + 'px'; // center graph inside the popover
|
||||
var pbStep = pb.clientWidth / 4.0;
|
||||
var pb_top = pb.offsetTop;
|
||||
var pb_container = document.getElementById('eventdistri_pb_container');
|
||||
var pb = document.getElementById('eventdistri_pb_background');
|
||||
document.getElementById('eventdistri_graph').style.left = spanOffset_orig + 'px'; // center graph inside the popover
|
||||
var pbStep = pb.clientWidth / 4.0;
|
||||
var pb_top = pb.offsetTop;
|
||||
|
||||
var spanOffset = spanOffset_orig;
|
||||
distribution = jQuery.extend({}, distribution); // deep clone distribution object
|
||||
for (var d in distribution) {
|
||||
d = parseInt(d);
|
||||
if (d == 4) { // skip sharing group
|
||||
continue;
|
||||
}
|
||||
// text
|
||||
var span = document.createElement('span');
|
||||
span.classList.add('useCursorPointer', 'pbDistributionText', 'badge');
|
||||
span.onclick = clickHandlerPbText;
|
||||
span.innerHTML = distribution[d].key;
|
||||
span.setAttribute('data-distribution', d);
|
||||
span.style.whiteSpace = 'pre-wrap';
|
||||
if (maxLevel == d+1) { // current event distribution
|
||||
span.style.fontSize = 'larger';
|
||||
span.style.top = d % 2 == 0 ? pb_top-37+'px' : pb_top+30+'px';
|
||||
span.style.boxShadow = '3px 3px 5px 1px rgba(0,0,0,0.6)';
|
||||
} else {
|
||||
span.style.opacity = '0.5';
|
||||
span.style.top = d % 2 == 0 ? pb_top-37+'px' : pb_top+30+'px';
|
||||
}
|
||||
pb_container.appendChild(span);
|
||||
if (d == Object.keys(distribution).length-2) { // last one, move a bit to the left. (-2 because sharing is not considered)
|
||||
span.style.left = (pbStep*(d+1))+spanOffset-span.clientWidth/2-35 + 'px';
|
||||
} else {
|
||||
span.style.left = (pbStep*(d+1))+spanOffset-span.clientWidth/2 + 'px';
|
||||
}
|
||||
var pop = $(span).popover({
|
||||
placement: d % 2 == 0 ? 'top' : 'bottom',
|
||||
trigger: 'click',
|
||||
content: '<b>Distribution description:</b> ' + distribution[d].desc + generate_additional_info(additionalInfo[d]),
|
||||
title: distribution[d].key,
|
||||
container: 'body',
|
||||
html: true,
|
||||
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title distributionInfo"></h3><div class="popover-content distributionInfo" style="white-space: pre-wrap"></div></div>'
|
||||
});
|
||||
var spanOffset = spanOffset_orig;
|
||||
distribution = jQuery.extend({}, distribution); // deep clone distribution object
|
||||
for (var d in distribution) {
|
||||
d = parseInt(d);
|
||||
if (d == 4) { // skip sharing group
|
||||
continue;
|
||||
}
|
||||
// text
|
||||
var span = document.createElement('span');
|
||||
span.classList.add('useCursorPointer', 'pbDistributionText', 'badge', 'toBeCleared');
|
||||
span.onclick = clickHandlerPbText;
|
||||
span.innerHTML = distribution[d].key;
|
||||
span.setAttribute('data-distribution', d);
|
||||
span.style.whiteSpace = 'pre-wrap';
|
||||
if (maxLevel == d+1) { // current event distribution
|
||||
span.style.fontSize = 'larger';
|
||||
span.style.top = d % 2 == 0 ? pb_top-37+'px' : pb_top+30+'px';
|
||||
span.style.boxShadow = '3px 3px 5px 1px rgba(0,0,0,0.6)';
|
||||
} else {
|
||||
span.style.opacity = '0.5';
|
||||
span.style.top = d % 2 == 0 ? pb_top-37+'px' : pb_top+30+'px';
|
||||
}
|
||||
pb_container.appendChild(span);
|
||||
if (d == Object.keys(distribution).length-2) { // last one, move a bit to the left. (-2 because sharing is not considered)
|
||||
span.style.left = (pbStep*(d+1))+spanOffset-span.clientWidth/2-35 + 'px';
|
||||
} else {
|
||||
span.style.left = (pbStep*(d+1))+spanOffset-span.clientWidth/2 + 'px';
|
||||
}
|
||||
var pop = $(span).popover({
|
||||
placement: d % 2 == 0 ? 'top' : 'bottom',
|
||||
trigger: 'click',
|
||||
content: '<b>Distribution description:</b> ' + distribution[d].desc + generate_additional_info(additionalInfo[d]),
|
||||
title: distribution[d].key,
|
||||
container: 'body',
|
||||
html: true,
|
||||
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title distributionInfo"></h3><div class="popover-content distributionInfo" style="white-space: pre-wrap"></div></div>'
|
||||
});
|
||||
|
||||
// tick
|
||||
var span = document.createElement('span');
|
||||
span.classList.add('pbDistributionTick');
|
||||
spanOffset += (pbStep*(d+1))+spanOffset > pb_container.clientWidth ? -3 : 0; // avoid the tick width to go further than the pb
|
||||
span.style.left = (pbStep*(d+1))+spanOffset + 'px';
|
||||
span.style.top = d % 2 == 0 ? pb_top-15+'px' : pb_top+0+'px';
|
||||
if (maxLevel == d+1) {
|
||||
span.style.opacity = '0.6';
|
||||
} else {
|
||||
span.style.opacity = '0.2';
|
||||
}
|
||||
pb_container.appendChild(span);
|
||||
}
|
||||
// tick
|
||||
var span = document.createElement('span');
|
||||
span.classList.add('pbDistributionTick', 'toBeCleared');
|
||||
spanOffset += (pbStep*(d+1))+spanOffset > pb_container.clientWidth ? -3 : 0; // avoid the tick width to go further than the pb
|
||||
span.style.left = (pbStep*(d+1))+spanOffset + 'px';
|
||||
span.style.top = d % 2 == 0 ? pb_top-15+'px' : pb_top+0+'px';
|
||||
if (maxLevel == d+1) {
|
||||
span.style.opacity = '0.6';
|
||||
} else {
|
||||
span.style.opacity = '0.2';
|
||||
}
|
||||
pb_container.appendChild(span);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function construct_piechart(data) {
|
||||
$('.toBeCleared').remove();
|
||||
|
||||
$(".loadingPopover").hide();
|
||||
|
||||
// DISTRIBUTION PROGRESSBAR
|
||||
$('#eventdistri_pb_invalid').tooltip();
|
||||
$('#eventdistri_pb').tooltip();
|
||||
$('#eventdistri_pb_min').tooltip();
|
||||
|
||||
$('#eventdistri_pb_invalid').click(function(evt) { clickHandlerPb(evt); });
|
||||
$('#eventdistri_pb').click(function(evt) { clickHandlerPb(evt); });
|
||||
$('#eventdistri_pb_min').click(function(evt) { clickHandlerPb(evt); });
|
||||
$('#eventdistri_sg_pb').click(function(evt) { clickHandlerPb(evt); });
|
||||
|
||||
// pb
|
||||
var event_dist, min_distri, max_distri;
|
||||
if (event_distribution == 4) { // if distribution is sharing group, overwrite default behavior
|
||||
var event_dist = 1;
|
||||
var min_distri = 0;
|
||||
var max_distri = 0;
|
||||
} else {
|
||||
var event_dist = event_distribution+1; // +1 to reach the first level
|
||||
var min_distri = get_minimum_distribution(data.event, event_dist)+1; // +1 to reach the first level
|
||||
var max_distri = get_maximum_distribution(data.event)+1; // +1 to reach the first level
|
||||
}
|
||||
add_level_to_pb(data.distributionInfo, data.additionalDistributionInfo, event_dist);
|
||||
|
||||
var bg_width_step = $('#eventdistri_pb_background').width()/4.0;
|
||||
$('#eventdistri_pb_min').width(bg_width_step*min_distri + 'px');
|
||||
$('#eventdistri_pb_min').data("distribution", fill_distri_for_search(0, min_distri-1));
|
||||
$('#eventdistri_pb_min').attr('aria-valuenow', min_distri*25);
|
||||
$('#eventdistri_pb_min').css("background", "#ffc107");
|
||||
|
||||
$('#eventdistri_pb').width((event_dist)*25+'%');
|
||||
$('#eventdistri_pb').data("distribution", fill_distri_for_search(0, event_dist-1));
|
||||
$('#eventdistri_pb').attr('aria-valuenow', (event_dist-min_distri)*25);
|
||||
$('#eventdistri_pb').css("background", "#28a745");
|
||||
|
||||
$('#eventdistri_pb_invalid').width((max_distri-event_dist)*25+'%');
|
||||
$('#eventdistri_pb_invalid').data("distribution", fill_distri_for_search(event_dist, max_distri-1));
|
||||
$('#eventdistri_pb_invalid').attr('aria-valuenow', (max_distri-event_dist)*25);
|
||||
$('#eventdistri_pb_invalid').css("background", "#dc3545");
|
||||
|
||||
// SHARING GROUPS
|
||||
var sgNum = data.additionalDistributionInfo[4].length;
|
||||
var sgPerc = (sgNum/data.allSharingGroup.length)*100;
|
||||
if (sgPerc > 0) {
|
||||
$('#eventdistri_sg_pb').width(sgPerc+'%');
|
||||
$('#eventdistri_sg_pb').tooltip({
|
||||
title: "Distribution among sharing group: "+(sgNum +' / '+ data.allSharingGroup.length)
|
||||
});
|
||||
$('#eventdistri_sg_pb').data("distribution", '4' + (event_distribution==4 ? '|5' : ''));
|
||||
$('#eventdistri_sg_pb').attr('aria-valuenow', sgPerc);
|
||||
$('#eventdistri_sg_pb').css("background", "#7a86e0");
|
||||
} else { // no sg, hide it and display
|
||||
$('#eventdistri_sg_pb_background').text("Event not distributed to any sharing group");
|
||||
}
|
||||
|
||||
$('.sharingGroup_pb_text').popover({
|
||||
placement: 'bottom',
|
||||
trigger: 'click',
|
||||
title: 'Sharing group',
|
||||
content: '<b>Distribution description:</b> ' + data.distributionInfo[4].desc + generate_additional_info(data.additionalDistributionInfo[4]) + '<div class="distributionInfo" style="height: 150px; width: 300px; position: relative; left: 25%;"><canvas class="distributionInfo" id="sg_distribution_graph_canvas" height="150px" width="300px"></canvas></div>',
|
||||
container: 'body',
|
||||
html: true,
|
||||
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title distributionInfo"></h3><div class="popover-content distributionInfo" style="white-space: pre-wrap"></div></div>'
|
||||
})
|
||||
.click(function() {
|
||||
generate_pie_chart(data.sharingGroupRepartition, document.getElementById('sg_distribution_graph_canvas'));
|
||||
});
|
||||
|
||||
// doughtnut
|
||||
var doughnutColors = ['#ff0000', '#ff9e00', '#957200', '#008000', 'rgb(122, 134, 224)'];
|
||||
var doughnut_dataset = [
|
||||
{
|
||||
label: "All",
|
||||
data: data.event,
|
||||
hidden: false,
|
||||
backgroundColor: doughnutColors
|
||||
},
|
||||
{
|
||||
label: "Attributes",
|
||||
data: data.attribute,
|
||||
hidden: false,
|
||||
backgroundColor: doughnutColors
|
||||
},
|
||||
{
|
||||
label: "Object attributes",
|
||||
data: data.obj_attr,
|
||||
hidden: false,
|
||||
backgroundColor: doughnutColors
|
||||
},
|
||||
|
||||
];
|
||||
var ctx = document.getElementById("distribution_graph_canvas");
|
||||
ctx.onclick = function(evt) { clickHandlerGraph(evt); };
|
||||
|
||||
var count = 0;
|
||||
for (var i=0, n=data.event.length; i < n; i++) {
|
||||
count += data.event[i];
|
||||
}
|
||||
if (count > 0) {
|
||||
distribution_chart = new Chart(ctx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: data.distributionInfo.map(function(elem, index) { return [elem.key]; }),
|
||||
distribution: data.distributionInfo,
|
||||
datasets: doughnut_dataset,
|
||||
},
|
||||
options: {
|
||||
title: {
|
||||
display: false
|
||||
},
|
||||
animation: {
|
||||
duration: 500
|
||||
},
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
label: function(item, data) {
|
||||
return data.datasets[item.datasetIndex].label
|
||||
+ " - " + data.labels[item.index]
|
||||
+ ": " + data.datasets[item.datasetIndex].data[item.index];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
var canvas = ctx;
|
||||
ctx = canvas.getContext("2d");
|
||||
ctx.font = "30px Comic Sans MS";
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillText("Event is empty", canvas.width/2, canvas.height/2);
|
||||
}
|
||||
|
||||
// create checkboxes
|
||||
var div = $('<div class="toBeCleared"></div>');
|
||||
div.addClass('distribution_checkboxes_dataset');
|
||||
var distri_graph = $('#eventdistri_graph');
|
||||
var distriOffset = distri_graph.offset();
|
||||
var distriHeight = distri_graph.height()/2;
|
||||
div.css({left: '50px'});
|
||||
for (var i in doughnut_dataset) {
|
||||
var item = doughnut_dataset[i];
|
||||
var label = $('<label></label>');
|
||||
label.addClass('useCursorPointer');
|
||||
label.css({'user-select': 'none'});
|
||||
var checkbox = $('<input type="checkbox">');
|
||||
checkbox.data('dataset-index', i);
|
||||
checkbox.prop('checked', true);
|
||||
checkbox.change(function(evt) {
|
||||
var clickedIndex = $(this).data('dataset-index');
|
||||
var isChecked = $(this).prop('checked');
|
||||
distribution_chart.config.data.datasets[clickedIndex].hidden = !isChecked;
|
||||
distribution_chart.update();
|
||||
});
|
||||
label.append(checkbox);
|
||||
label.append(item.label);
|
||||
div.append(label);
|
||||
}
|
||||
distri_graph.append(div);
|
||||
}
|
||||
|
||||
function fetchDistributionData(callback) {
|
||||
$.ajax({
|
||||
url: "/events/"+"getDistributionGraph"+"/"+scope_id+"/event.json",
|
||||
dataType: 'json',
|
||||
type: 'post',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify( payload ),
|
||||
processData: false,
|
||||
beforeSend: function (XMLHttpRequest) {
|
||||
$(".loadingPopover").show();
|
||||
},
|
||||
success: function( data, textStatus, jQxhr ){
|
||||
distributionData = data;
|
||||
if (callback !== undefined) {
|
||||
callback(data);
|
||||
}
|
||||
},
|
||||
error: function( jqXhr, textStatus, errorThrown ){
|
||||
console.log( errorThrown );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function drawBarChart(data) {
|
||||
var csv = "scope,val\n";
|
||||
var lineCount = 0;
|
||||
data.event.forEach(function(d, i) {
|
||||
var scope = data.distributionInfo[i].key;
|
||||
var val = d;
|
||||
csv += scope + "," + val + "\n";
|
||||
lineCount++;
|
||||
})
|
||||
sparklineBar('#distribution_graph_bar', csv, lineCount);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
var pop = $('.distribution_graph').popover({
|
||||
title: "<b>Distribution graph</b> [atomic event]",
|
||||
html: true,
|
||||
content: function() { return $('#distribution_graph_container').html(); },
|
||||
template : '<div class="popover" role="tooltip" style="z-index: 1;"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content" style="padding-left: '+spanOffset_orig+'px; padding-right: '+spanOffset_orig*2+'px;"></div></div>'
|
||||
});
|
||||
var rightBtn = '<div style="float:right;"><span type="button" id="reloadDistributionGraph" title="Reload Distribution Graph" class="fa fa-refresh useCursorPointer" aria-hidden="true" style="margin-left: 5px;" onclick="fetchDistributionData(function(data) { construct_piechart(data); });"></span></div>';
|
||||
var pop = $('.distribution_graph').popover({
|
||||
title: "<b>Distribution graph</b> [atomic event]" + rightBtn,
|
||||
html: true,
|
||||
content: function() { return $('#distribution_graph_container').html(); },
|
||||
template : '<div class="popover" role="tooltip" style="z-index: 1;"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content" style="padding-left: '+spanOffset_orig+'px; padding-right: '+spanOffset_orig*2+'px;"></div></div>'
|
||||
}).on('shown.bs.popover', function(e) {
|
||||
if (distributionData !== undefined) {
|
||||
construct_piechart(distributionData);
|
||||
} else {
|
||||
fetchDistributionData(function(data) {
|
||||
construct_piechart(data);
|
||||
});
|
||||
}
|
||||
}).on('hide.bs.popover', function(e) {
|
||||
});
|
||||
|
||||
$('body').on('mouseup', function(e) {
|
||||
if(!$(e.target).hasClass('distributionInfo') && !($(e.target).hasClass('pbDistributionText') || $(e.target).hasClass('sharingGroup_pb_text'))) {
|
||||
$('.pbDistributionText').popover('hide');
|
||||
$('.sharingGroup_pb_text').popover('hide');
|
||||
}
|
||||
});
|
||||
$('body').on('mouseup', function(e) {
|
||||
if(!$(e.target).hasClass('distributionInfo') && !($(e.target).hasClass('pbDistributionText') || $(e.target).hasClass('sharingGroup_pb_text'))) {
|
||||
$('.pbDistributionText').popover('hide');
|
||||
$('.sharingGroup_pb_text').popover('hide');
|
||||
}
|
||||
});
|
||||
|
||||
$('.distribution_graph').click(function() {
|
||||
if ($(this).data('shown') == 'true') {
|
||||
$(this).data('shown', 'false');
|
||||
return;
|
||||
} else {
|
||||
$(this).data('shown', 'true');
|
||||
}
|
||||
$.ajax({
|
||||
url: "/events/"+"getDistributionGraph"+"/"+scope_id+"/event.json",
|
||||
dataType: 'json',
|
||||
type: 'post',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify( payload ),
|
||||
processData: false,
|
||||
beforeSend: function (XMLHttpRequest) {
|
||||
$(".loadingPopover").show();
|
||||
},
|
||||
success: function( data, textStatus, jQxhr ){
|
||||
$(".loadingPopover").hide();
|
||||
|
||||
// DISTRIBUTION PROGRESSBAR
|
||||
$('#eventdistri_pb_invalid').tooltip();
|
||||
$('#eventdistri_pb').tooltip();
|
||||
$('#eventdistri_pb_min').tooltip();
|
||||
|
||||
$('#eventdistri_pb_invalid').click(function(evt) { clickHandlerPb(evt); });
|
||||
$('#eventdistri_pb').click(function(evt) { clickHandlerPb(evt); });
|
||||
$('#eventdistri_pb_min').click(function(evt) { clickHandlerPb(evt); });
|
||||
$('#eventdistri_sg_pb').click(function(evt) { clickHandlerPb(evt); });
|
||||
|
||||
// pb
|
||||
var event_dist, min_distri, max_distri;
|
||||
if (event_distribution == 4) { // if distribution is sharing group, overwrite default behavior
|
||||
var event_dist = 1;
|
||||
var min_distri = 0;
|
||||
var max_distri = 0;
|
||||
} else {
|
||||
var event_dist = event_distribution+1; // +1 to reach the first level
|
||||
var min_distri = get_minimum_distribution(data.event, event_dist)+1; // +1 to reach the first level
|
||||
var max_distri = get_maximum_distribution(data.event)+1; // +1 to reach the first level
|
||||
}
|
||||
add_level_to_pb(data.distributionInfo, data.additionalDistributionInfo, event_dist);
|
||||
|
||||
var bg_width_step = $('#eventdistri_pb_background').width()/4.0;
|
||||
$('#eventdistri_pb_min').width(bg_width_step*min_distri + 'px');
|
||||
$('#eventdistri_pb_min').data("distribution", fill_distri_for_search(0, min_distri-1));
|
||||
$('#eventdistri_pb_min').attr('aria-valuenow', min_distri*25);
|
||||
$('#eventdistri_pb_min').css("background", "#ffc107");
|
||||
|
||||
$('#eventdistri_pb').width((event_dist)*25+'%');
|
||||
$('#eventdistri_pb').data("distribution", fill_distri_for_search(0, event_dist-1));
|
||||
$('#eventdistri_pb').attr('aria-valuenow', (event_dist-min_distri)*25);
|
||||
$('#eventdistri_pb').css("background", "#28a745");
|
||||
|
||||
$('#eventdistri_pb_invalid').width((max_distri-event_dist)*25+'%');
|
||||
$('#eventdistri_pb_invalid').data("distribution", fill_distri_for_search(event_dist, max_distri-1));
|
||||
$('#eventdistri_pb_invalid').attr('aria-valuenow', (max_distri-event_dist)*25);
|
||||
$('#eventdistri_pb_invalid').css("background", "#dc3545");
|
||||
|
||||
// SHARING GROUPS
|
||||
var sgNum = data.additionalDistributionInfo[4].length;
|
||||
var sgPerc = (sgNum/data.allSharingGroup.length)*100;
|
||||
if (sgPerc > 0) {
|
||||
$('#eventdistri_sg_pb').width(sgPerc+'%');
|
||||
$('#eventdistri_sg_pb').tooltip({
|
||||
title: "Distribution among sharing group: "+(sgNum +' / '+ data.allSharingGroup.length)
|
||||
});
|
||||
$('#eventdistri_sg_pb').data("distribution", '4' + (event_distribution==4 ? '|5' : ''));
|
||||
$('#eventdistri_sg_pb').attr('aria-valuenow', sgPerc);
|
||||
$('#eventdistri_sg_pb').css("background", "#7a86e0");
|
||||
} else { // no sg, hide it and display
|
||||
$('#eventdistri_sg_pb_background').text("Event not distributed to any sharing group");
|
||||
}
|
||||
|
||||
$('.sharingGroup_pb_text').popover({
|
||||
placement: 'bottom',
|
||||
trigger: 'click',
|
||||
title: 'Sharing group',
|
||||
content: '<b>Distribution description:</b> ' + data.distributionInfo[4].desc + generate_additional_info(data.additionalDistributionInfo[4]),
|
||||
container: 'body',
|
||||
html: true,
|
||||
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title distributionInfo"></h3><div class="popover-content distributionInfo" style="white-space: pre-wrap"></div></div>'
|
||||
});
|
||||
|
||||
// doughtnut
|
||||
var doughnutColors = ['#ff0000', '#ff9e00', '#957200', '#008000', 'rgb(122, 134, 224)'];
|
||||
var doughnut_dataset = [
|
||||
{
|
||||
label: "All",
|
||||
data: data.event,
|
||||
hidden: false,
|
||||
backgroundColor: doughnutColors
|
||||
},
|
||||
{
|
||||
label: "Attributes",
|
||||
data: data.attribute,
|
||||
hidden: false,
|
||||
backgroundColor: doughnutColors
|
||||
},
|
||||
{
|
||||
label: "Object attributes",
|
||||
data: data.obj_attr,
|
||||
hidden: false,
|
||||
backgroundColor: doughnutColors
|
||||
},
|
||||
|
||||
];
|
||||
var ctx = document.getElementById("distribution_graph_canvas");
|
||||
ctx.onclick = function(evt) { clickHandlerGraph(evt); };
|
||||
distribution_chart = new Chart(ctx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: data.distributionInfo.map(function(elem, index) { return [elem.key]; }),
|
||||
distribution: data.distributionInfo,
|
||||
datasets: doughnut_dataset,
|
||||
},
|
||||
options: {
|
||||
title: {
|
||||
display: false
|
||||
},
|
||||
animation: {
|
||||
duration: 500
|
||||
},
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
label: function(item, data) {
|
||||
return data.datasets[item.datasetIndex].label
|
||||
+ " - " + data.labels[item.index]
|
||||
+ ": " + data.datasets[item.datasetIndex].data[item.index];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// create checkboxes
|
||||
var div = $('<div></div>');
|
||||
div.addClass('distribution_checkboxes_dataset');
|
||||
var distri_graph = $('#eventdistri_graph');
|
||||
var distriOffset = distri_graph.offset();
|
||||
var distriHeight = distri_graph.height()/2;
|
||||
div.css({left: '50px'});
|
||||
for (var i in doughnut_dataset) {
|
||||
var item = doughnut_dataset[i];
|
||||
var label = $('<label></label>');
|
||||
label.addClass('useCursorPointer');
|
||||
label.css({'user-select': 'none'});
|
||||
var checkbox = $('<input type="checkbox">');
|
||||
checkbox.data('dataset-index', i);
|
||||
checkbox.prop('checked', true);
|
||||
checkbox.change(function(evt) {
|
||||
var clickedIndex = $(this).data('dataset-index');
|
||||
var isChecked = $(this).prop('checked');
|
||||
distribution_chart.config.data.datasets[clickedIndex].hidden = !isChecked;
|
||||
distribution_chart.update();
|
||||
});
|
||||
label.append(checkbox);
|
||||
label.append(item.label);
|
||||
div.append(label);
|
||||
}
|
||||
distri_graph.append(div);
|
||||
},
|
||||
error: function( jqXhr, textStatus, errorThrown ){
|
||||
console.log( errorThrown );
|
||||
}
|
||||
});
|
||||
});
|
||||
fetchDistributionData(function(data) {
|
||||
drawBarChart(data);
|
||||
$('#showAdvancedSharingButton').distributionNetwork({
|
||||
event_distribution: event_distribution,
|
||||
distributionData: data,
|
||||
scope_id: scope_id
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3998,6 +3998,44 @@ function liveFilter() {
|
|||
}
|
||||
}
|
||||
|
||||
function sparklineBar(elemId, data, lineCount) {
|
||||
data = d3.csv.parse(data);
|
||||
var y_max = 0;
|
||||
data.forEach(function(e) {
|
||||
e = parseInt(e.val);
|
||||
y_max = e > y_max ? e : y_max;
|
||||
});
|
||||
var WIDTH = 50;
|
||||
var HEIGHT = 25;
|
||||
var DATA_COUNT = lineCount;
|
||||
var BAR_WIDTH = (WIDTH - DATA_COUNT) / DATA_COUNT;
|
||||
var x = d3.scale.linear().domain([0, DATA_COUNT]).range([0, WIDTH]);
|
||||
var y = d3.scale.linear().domain([0, y_max]).range([0, HEIGHT]);
|
||||
|
||||
var distributionGraphBarTooltip = d3.select("body").append("div")
|
||||
.attr("class", "distributionGraphBarTooltip")
|
||||
.style("opacity", 0);
|
||||
|
||||
var svg = d3.select(elemId).append('svg')
|
||||
.attr('width', WIDTH)
|
||||
.attr('height', HEIGHT)
|
||||
.append('g');
|
||||
svg.selectAll('.bar').data(data)
|
||||
.enter()
|
||||
.append('g')
|
||||
.attr('title', function(d, i) { return d.scope + ': ' + d.val })
|
||||
.attr('class', 'DGbar')
|
||||
.append('rect')
|
||||
.attr('class', 'bar')
|
||||
.attr('x', function(d, i) { return x(i); })
|
||||
.attr('y', function(d, i) { return HEIGHT - y(d.val); })
|
||||
.attr('width', BAR_WIDTH)
|
||||
.attr('height', function(d, i) { return y(d.val); })
|
||||
.attr('fill', '#3465a4');
|
||||
|
||||
$('.DGbar').tooltip({container: 'body'});
|
||||
}
|
||||
|
||||
function generic_picker_move(scope, direction) {
|
||||
if (direction === 'right') {
|
||||
$('#' + scope + 'Left option:selected').remove().appendTo('#' + scope + 'Right');
|
||||
|
|
|
@ -0,0 +1,585 @@
|
|||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
"use strict";
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery'], factory);
|
||||
} else if (window.jQuery && !window.jQuery.fn.DistributionNetwork) {
|
||||
factory(window.jQuery);
|
||||
}
|
||||
}
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
// DistributionNetwork object
|
||||
var DistributionNetwork = function(container, options) {
|
||||
this._default_options = {
|
||||
network_options: {
|
||||
width: '800px',
|
||||
height: '759px',
|
||||
layout: {randomSeed: 0},
|
||||
edges: {
|
||||
arrowStrikethrough: false,
|
||||
arrows: {
|
||||
to: {enabled: true, scaleFactor:1, type:'arrow'},
|
||||
},
|
||||
shadow: {
|
||||
enabled: true,
|
||||
size: 7,
|
||||
x: 3,
|
||||
y: 3
|
||||
}
|
||||
},
|
||||
physics:{
|
||||
barnesHut: {
|
||||
gravitationalConstant: -10000,
|
||||
centralGravity: 0.3,
|
||||
springLength: 150,
|
||||
springConstant: 0.02,
|
||||
damping: 0.09,
|
||||
avoidOverlap: 0
|
||||
},
|
||||
repulsion: {
|
||||
centralGravity: 0.2,
|
||||
springLength: 200,
|
||||
springConstant: 0.02,
|
||||
nodeDistance: 200,
|
||||
damping: 0.15
|
||||
},
|
||||
|
||||
solver: 'barnesHut'
|
||||
},
|
||||
nodes: {
|
||||
shadow: {
|
||||
enabled: true,
|
||||
size: 7,
|
||||
x: 3,
|
||||
y: 3
|
||||
}
|
||||
},
|
||||
groups: {
|
||||
'root': {
|
||||
shape: 'icon',
|
||||
icon: {
|
||||
face: 'FontAwesome',
|
||||
code: '\uf10c',
|
||||
color: '#000000',
|
||||
size: 50
|
||||
},
|
||||
font: {size: 30},
|
||||
color: '#000000',
|
||||
},
|
||||
'org-only': {
|
||||
shape: 'icon',
|
||||
icon: {
|
||||
face: 'FontAwesome',
|
||||
code: '\uf2c2',
|
||||
color: '#ff0000',
|
||||
size: 30
|
||||
},
|
||||
font: {
|
||||
size: 14, // px
|
||||
color: '#ff0000',
|
||||
background: 'rgba(255, 255, 255, 0.7)'
|
||||
},
|
||||
color: '#ff0000',
|
||||
},
|
||||
'root-this-community': {
|
||||
shape: 'icon',
|
||||
icon: {
|
||||
face: 'FontAwesome',
|
||||
code: '\uf1e1',
|
||||
color: '#ff9725',
|
||||
size: 70
|
||||
},
|
||||
font: {
|
||||
size: 18, // px
|
||||
color: '#ff9725',
|
||||
background: 'rgba(255, 255, 255, 0.7)'
|
||||
},
|
||||
color: '#ff9725',
|
||||
},
|
||||
'this-community': {
|
||||
font: {color: 'white'},
|
||||
color: '#ff9725',
|
||||
shape: 'box',
|
||||
margin: 3
|
||||
},
|
||||
'root-connected-community': {
|
||||
shape: 'icon',
|
||||
icon: {
|
||||
face: 'FontAwesome',
|
||||
code: '\uf0e8',
|
||||
color: '#9b6e1b',
|
||||
size: 70
|
||||
},
|
||||
font: {
|
||||
size: 18, // px
|
||||
color: '#9b6e1b',
|
||||
background: 'rgba(255, 255, 255, 0.7)'
|
||||
},
|
||||
color: '#9b6e1b',
|
||||
},
|
||||
'connected-community': {
|
||||
shape: 'image',
|
||||
image: '/img/orgs/MISP.png'
|
||||
},
|
||||
'web': {
|
||||
shape: 'icon',
|
||||
icon: {
|
||||
face: 'FontAwesome',
|
||||
code: '\uf0ac',
|
||||
color: '#007d20',
|
||||
size: 70
|
||||
},
|
||||
font: {
|
||||
size: 18, // px
|
||||
color: '#007d20',
|
||||
background: 'rgba(255, 255, 255, 0.7)'
|
||||
},
|
||||
color: '#007d20',
|
||||
},
|
||||
'root-sharing-group': {
|
||||
shape: 'icon',
|
||||
icon: {
|
||||
face: 'FontAwesome',
|
||||
code: '\uf0c0',
|
||||
color: '#1369a0',
|
||||
size: 70
|
||||
},
|
||||
font: {
|
||||
size: 18, // px
|
||||
color: '#1369a0',
|
||||
background: 'rgba(255, 255, 255, 0.7)'
|
||||
},
|
||||
color: '#1369a0',
|
||||
}
|
||||
}
|
||||
},
|
||||
EDGE_LENGTH_HUB: 300,
|
||||
};
|
||||
|
||||
this.container = $(container);
|
||||
this._validateOptions(options);
|
||||
|
||||
this.network_wrapper = false;
|
||||
this.options = $.extend({}, this._default_options, options);
|
||||
|
||||
this.event_distribution = this.options.event_distribution;
|
||||
this.scope_id = this.options.scope_id;
|
||||
this.distributionData = this.options.distributionData;
|
||||
this.network;
|
||||
this.nodes_distri;
|
||||
this.edges_distri;
|
||||
this.cacheAddedOrgName = {};
|
||||
|
||||
this._constructUI();
|
||||
this._registerListener();
|
||||
};
|
||||
|
||||
DistributionNetwork.prototype = {
|
||||
constructor: DistributionNetwork,
|
||||
|
||||
_validateOptions: function(options) {
|
||||
if (options.event_distribution === undefined) {
|
||||
// try to fetch is from the container
|
||||
var event_distribution = this.container.data('event-distribution');
|
||||
var event_distribution_name = this.container.data('event-distribution-name');
|
||||
if (event_distribution !== undefined && event_distribution_name !== undefined) {
|
||||
options.event_distribution = event_distribution;
|
||||
options.event_distribution_name = event_distribution_name;
|
||||
this._adjust_sharing_numbers(options)
|
||||
} else {
|
||||
throw "Event distribution or Org not set";
|
||||
}
|
||||
}
|
||||
|
||||
if (options.distributionData === undefined) {
|
||||
throw "Distribution data not set";
|
||||
}
|
||||
if (options.scope_id === undefined) {
|
||||
// try to fetch is from the container
|
||||
var scope_id = this.container.data('scope-id');
|
||||
if (scope_id !== undefined) {
|
||||
options.scope_id = scope_id;
|
||||
} else {
|
||||
throw "Scope id is not set";
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_adjust_sharing_numbers: function (options) {
|
||||
var sum = options.distributionData.event.reduce(function(pv, cv) { return pv + cv; }, 0);
|
||||
if (sum == 0) { // if event does not contain anything (or we don't know about its content)
|
||||
options.distributionData.event[options.event_distribution] = 1;
|
||||
}
|
||||
if (options.event_distribution == 4) {
|
||||
options.distributionData.additionalDistributionInfo[4].push(options.event_distribution_name);
|
||||
}
|
||||
},
|
||||
|
||||
_registerListener: function() {
|
||||
var that = this;
|
||||
this.container.click(function() {
|
||||
$('#sharingNetworkWrapper').toggle('slide', {direction: 'right'}, 300);
|
||||
that._construct_network();
|
||||
|
||||
$('body').off('keyup.distributionNetwork').on('keyup.distributionNetwork', function(e) {
|
||||
if (e.keyCode == 27) { // ESC
|
||||
$('body').off('keyup.distributionNetwork');
|
||||
that.dismissNetwork();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
dismissNetwork: function() {
|
||||
$('#sharingNetworkWrapper').hide('slide', {direction: 'right'}, 300);
|
||||
},
|
||||
|
||||
_constructUI: function() {
|
||||
var that = this;
|
||||
if ($('#sharingNetworkWrapper').length > 0) {
|
||||
return; // Wrapper already exists
|
||||
}
|
||||
|
||||
var allow_interactive_picking = $('#attributes_div table tr').length > 0;
|
||||
|
||||
var $div = '<div id="sharingNetworkWrapper" class="advancedSharingNetwork hidden">'
|
||||
+ '<div class="eventgraph_header" style="border-radius: 5px; display: flex;">'
|
||||
+ '<it class="fa fa-circle-o" style="margin: auto 10px; font-size: x-large"></it>'
|
||||
+ '<input type="text" id="sharingNetworkTargetId" class="center-in-network-header network-typeahead" style="width: 200px;" disabled></input>';
|
||||
if (allow_interactive_picking) {
|
||||
$div += '<div class="form-group" style="margin: auto 10px;"><div class="checkbox">'
|
||||
+ '<label style="user-select: none;"><input id="interactive_picking_mode" type="checkbox" title="Click on a element to see how it is distributed" style="margin-top: 4px;">Enable interactive picking mode</label>'
|
||||
+ '</div></div>'
|
||||
}
|
||||
$div += '<select type="text" id="sharingNetworkOrgFinder" class="center-in-network-header network-typeahead sharingNetworkOrgFinder" style="width: 200px;"></select>'
|
||||
+ '<button id="closeButton" type="button" class="close" style="margin: 1px 5px; right: 0px; position: absolute;">×</button>'
|
||||
+ '</div><div id="advancedSharingNetwork"></div></div>';
|
||||
$div = $($div);
|
||||
this.network_wrapper = $div;
|
||||
$div.find('#closeButton').click(function() {
|
||||
that.dismissNetwork();
|
||||
});
|
||||
$('body').append($div);
|
||||
},
|
||||
|
||||
_construct_network: function(target_distribution, scope_text, overwriteSg) {
|
||||
var that = this;
|
||||
if (this.network !== undefined) {
|
||||
this.network.destroy();
|
||||
this.cacheAddedOrgName = {};
|
||||
}
|
||||
if (scope_text == undefined) {
|
||||
scope_text = 'Event ' + this.options.scope_id;
|
||||
}
|
||||
$('#sharingNetworkTargetId').val(scope_text);
|
||||
|
||||
this.nodes_distri = new vis.DataSet([
|
||||
{id: 'root', group: 'root', label: scope_text, x: 0, y: 0, fixed: true, mass: 20},
|
||||
{id: this.distributionData.additionalDistributionInfo[0][0], label: this.distributionData.additionalDistributionInfo[0][0], group: 'org-only'},
|
||||
|
||||
]);
|
||||
this.edges_distri = new vis.DataSet([
|
||||
{from: 'root', to: this.distributionData.additionalDistributionInfo[0][0], length: 30, width: 3},
|
||||
]);
|
||||
if (target_distribution === undefined || target_distribution == 5) {
|
||||
target_distribution = this.event_distribution;
|
||||
}
|
||||
|
||||
if (target_distribution !== 0) {
|
||||
// Event always restrict propagation (sharing group is a special case)
|
||||
var temp_target_disti = target_distribution;
|
||||
if (target_distribution !== 4 && temp_target_disti >= this.event_distribution) {
|
||||
while (temp_target_disti >= this.event_distribution) {
|
||||
var toID = false;
|
||||
switch (temp_target_disti) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
toID = 'this-community';
|
||||
break;
|
||||
case 2:
|
||||
toID = 'connected-community';
|
||||
break;
|
||||
case 3:
|
||||
toID = 'all-community';
|
||||
break;
|
||||
case 4:
|
||||
toID = 'sharing-group';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
var edgeData = {from: 'root', to: toID, width: 3};
|
||||
if (temp_target_disti != this.event_distribution) {
|
||||
edgeData.label = 'X';
|
||||
edgeData.title = 'The distribution of the Event restricts the distribution level of this element';
|
||||
edgeData.font = {
|
||||
size: 50,
|
||||
color: '#ff0000',
|
||||
strokeWidth: 6,
|
||||
strokeColor: '#ff0000'
|
||||
};
|
||||
}
|
||||
if (toID !== false) {
|
||||
this.edges_distri.add(edgeData);
|
||||
}
|
||||
temp_target_disti--;
|
||||
}
|
||||
} else {
|
||||
switch (temp_target_disti) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
toID = 'this-community';
|
||||
break;
|
||||
case 2:
|
||||
toID = 'connected-community';
|
||||
break;
|
||||
case 3:
|
||||
toID = 'all-community';
|
||||
break;
|
||||
case 4:
|
||||
toID = 'sharing-group';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
var edgeData = {from: 'root', to: toID, width: 3};
|
||||
if (toID !== false) {
|
||||
this.edges_distri.add(edgeData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var nodesToAdd = [];
|
||||
var edgesToAdd = [];
|
||||
this.cacheAddedOrgName[this.distributionData.additionalDistributionInfo[0][0]] = 1;
|
||||
|
||||
// Community
|
||||
if (target_distribution >= 1 && target_distribution != 4
|
||||
&& (this.distributionData.event[1] > 0 || this.distributionData.event[2] > 0 || this.distributionData.event[3] > 0)
|
||||
) {
|
||||
nodesToAdd.push({id: 'this-community', label: 'This community', group: 'root-this-community'});
|
||||
this._inject_this_community_org(nodesToAdd, edgesToAdd, this.distributionData.additionalDistributionInfo[1], 'this-community', 'this-community');
|
||||
}
|
||||
// Connected Community
|
||||
if (target_distribution >= 2 && target_distribution != 4
|
||||
&& (this.distributionData.event[2] > 0 || this.distributionData.event[3] > 0)
|
||||
) {
|
||||
nodesToAdd.push({id: 'connected-community', label: 'Connected community', group: 'root-connected-community'});
|
||||
this.distributionData.additionalDistributionInfo[2].forEach(function(orgName) {
|
||||
if (orgName === 'This community') {
|
||||
edgesToAdd.push({from: 'connected-community', to: 'this-community', length: that.options.EDGE_LENGTH_HUB});
|
||||
} else {
|
||||
nodesToAdd.push({
|
||||
id: 'connected-community_' + orgName,
|
||||
label: orgName,
|
||||
group: 'connected-community'
|
||||
});
|
||||
edgesToAdd.push({from: 'connected-community', to: 'connected-community_' + orgName});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// All Community
|
||||
if (target_distribution >= 3 && target_distribution != 4
|
||||
&& this.distributionData.event[3] > 0
|
||||
) {
|
||||
nodesToAdd.push({id: 'all-community', label: 'All community', group: 'web'});
|
||||
this.distributionData.additionalDistributionInfo[3].forEach(function(orgName) {
|
||||
if (orgName === 'This community') {
|
||||
edgesToAdd.push({from: 'all-community', to: 'this-community', length: that.options.EDGE_LENGTH_HUB});
|
||||
} else if (orgName === 'All other communities') {
|
||||
edgesToAdd.push({from: 'all-community', to: 'connected-community', length: that.options.EDGE_LENGTH_HUB});
|
||||
}
|
||||
});
|
||||
}
|
||||
// Sharing Group
|
||||
if (this.distributionData.event[4] > 0) {
|
||||
this.distributionData.allSharingGroup.forEach(function(sg) {
|
||||
var sgName = sg.SharingGroup.name;
|
||||
if (overwriteSg === undefined) { // if overwriteSg not set, use the one from the event
|
||||
overwriteSg = that.distributionData.additionalDistributionInfo[4];
|
||||
}
|
||||
if (overwriteSg.indexOf(sgName) == -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nodesToAdd.push({
|
||||
id: 'sharing-group_' + sgName,
|
||||
label: sgName,
|
||||
group: 'root-sharing-group'
|
||||
});
|
||||
edgesToAdd.push({from: 'root', to: 'sharing-group_' + sgName, width: 3});
|
||||
sg.SharingGroupOrg.forEach(function(org) {
|
||||
var sgOrgName = org.Organisation.name;
|
||||
if (that.cacheAddedOrgName[sgOrgName] === undefined) {
|
||||
nodesToAdd.push({
|
||||
id: sgOrgName,
|
||||
label: sgOrgName,
|
||||
group: 'sharing-group'
|
||||
});
|
||||
that.cacheAddedOrgName[sgOrgName] = 1;
|
||||
}
|
||||
edgesToAdd.push({
|
||||
from: 'sharing-group_' + sgName,
|
||||
to: sgOrgName,
|
||||
arrows: {
|
||||
to: { enabled: false }
|
||||
},
|
||||
color: { opacity: 0.4 }
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var options = '<option></option>';
|
||||
$('#sharingNetworkOrgFinder').empty();
|
||||
Object.keys(this.cacheAddedOrgName).forEach(function(org) {
|
||||
options += '<option value="'+org+'">'+org+'</option>';
|
||||
});
|
||||
$('#sharingNetworkOrgFinder').append(options)
|
||||
.trigger('chosen:updated')
|
||||
.chosen({
|
||||
inherit_select_classes: true,
|
||||
no_results_text: "Focus to an organisation",
|
||||
placeholder_text_single: "Focus to an organisation",
|
||||
allow_single_deselect: true
|
||||
})
|
||||
.off('change')
|
||||
.on('change', function(evt, params) {
|
||||
if (this.value !== '') {
|
||||
if (that.nodes_distri.get(this.value) !== null) {
|
||||
that.network.focus(this.value, {animation: true});
|
||||
that.network.selectNodes([this.value]);
|
||||
}
|
||||
} else {
|
||||
that.network.fit({animation: true})
|
||||
}
|
||||
});
|
||||
|
||||
this.nodes_distri.add(nodesToAdd);
|
||||
this.edges_distri.add(edgesToAdd);
|
||||
var data = { nodes: this.nodes_distri, edges: this.edges_distri };
|
||||
this.network = new vis.Network(document.getElementById('advancedSharingNetwork'), data, this.options.network_options);
|
||||
|
||||
this.network.on("dragStart", function (params) {
|
||||
params.nodes.forEach(function(nodeId) {
|
||||
that.nodes_distri.update({id: nodeId, fixed: {x: false, y: false}});
|
||||
});
|
||||
});
|
||||
this.network.on("dragEnd", function (params) {
|
||||
params.nodes.forEach(function(nodeId) {
|
||||
that.nodes_distri.update({id: nodeId, fixed: {x: true, y: true}});
|
||||
});
|
||||
});
|
||||
|
||||
$('#interactive_picking_mode').off('change').on('change', function(e) {
|
||||
var target_id = $(this).val();
|
||||
if (this.checked) {
|
||||
that._toggleRowListener(true);
|
||||
} else {
|
||||
that._toggleRowListener(false);
|
||||
that._construct_network(this.event_distribution)
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_toggleRowListener: function(toAdd) {
|
||||
var that = this;
|
||||
if (toAdd) {
|
||||
var $table = $('#attributes_div table tr');
|
||||
if ($table.length == 0) {
|
||||
return;
|
||||
}
|
||||
$table.off('click.advancedSharing').on('click.advancedSharing', function() {
|
||||
var $row = $(this);
|
||||
var clicked_type = $row.attr('id').split('_')[0];
|
||||
var clicked_id = $row.attr('id').split('_')[1];
|
||||
var $dist_cell = $row.find('div').filter(function() {
|
||||
return $(this).attr('id') !== undefined && $(this).attr('id').includes(clicked_id+'_distribution');
|
||||
});
|
||||
|
||||
var distribution_value;
|
||||
var overwriteSg;
|
||||
switch ($dist_cell.text().trim()) {
|
||||
case 'Organisation':
|
||||
distribution_value = 0;
|
||||
break;
|
||||
case 'Community':
|
||||
distribution_value = 1;
|
||||
break;
|
||||
case 'Connected':
|
||||
distribution_value = 2;
|
||||
break;
|
||||
case 'All':
|
||||
distribution_value = 3;
|
||||
break;
|
||||
case 'Inherit':
|
||||
distribution_value = 5;
|
||||
if (that.event_distribution == 4) {
|
||||
overwriteSg = that.event_distribution_text.trim();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
distribution_value = 4;
|
||||
overwriteSg = $dist_cell.text().trim();
|
||||
break
|
||||
}
|
||||
that._construct_network(distribution_value, clicked_type+' '+clicked_id, [overwriteSg]);
|
||||
});
|
||||
} else {
|
||||
$('#attributes_div table tr').off('click.advancedSharing');
|
||||
}
|
||||
},
|
||||
|
||||
_inject_this_community_org: function(nodesToAdd, edgesToAdd, orgs, group, root) {
|
||||
var that = this;
|
||||
orgs.forEach(function(orgName) {
|
||||
if (that.cacheAddedOrgName[orgName] === undefined) {
|
||||
nodesToAdd.push({
|
||||
id: orgName,
|
||||
label: orgName,
|
||||
group: group
|
||||
});
|
||||
that.cacheAddedOrgName[orgName] = 1;
|
||||
}
|
||||
edgesToAdd.push({
|
||||
from: root,
|
||||
to: orgName,
|
||||
arrows: {
|
||||
to: { enabled: false }
|
||||
},
|
||||
color: { opacity: 0.4 }
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
$.distributionNetwork = DistributionNetwork;
|
||||
$.fn.distributionNetwork = function(option) {
|
||||
var pickedArgs = arguments;
|
||||
|
||||
return this.each(function() {
|
||||
var $this = $(this),
|
||||
inst = $this.data('distributionNetwork'),
|
||||
options = ((typeof option === 'object') ? option : {});
|
||||
if ((!inst) && (typeof option !== 'string')) {
|
||||
$this.data('distributionNetwork', new DistributionNetwork(this, options));
|
||||
} else {
|
||||
if (typeof option === 'string') {
|
||||
inst[option].apply(inst, Array.prototype.slice.call(pickerArgs, 1));
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.distributionNetwork.constructor = DistributionNetwork;
|
||||
}));
|
|
@ -1 +1 @@
|
|||
Subproject commit 469d17bceeed65373da3ac3b4f96600dfea8ca68
|
||||
Subproject commit 407f346eb8118d57b43035ef0da47e2ff77ed00e
|
Loading…
Reference in New Issue