Merge pull request #4309 from mokaddem/extendedDistributionGraph

Improvement on distribution visualization
pull/4316/head
Alexandre Dulaunoy 2019-03-15 16:05:17 +01:00 committed by GitHub
commit ae2c513b62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1172 additions and 356 deletions

View File

@ -115,6 +115,7 @@ class ACLComponent extends Component
'getEventGraphReferences' => array('*'),
'getEventGraphTags' => array('*'),
'getEventGraphGeneric' => array('*'),
'genDistributionGraph' => array('*'),
'getDistributionGraph' => array('*'),
'getReferenceData' => array('*'),
'getReferences' => array('*'),

View File

@ -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'));
}

View File

@ -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;
}

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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() {

View File

@ -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;
}

View File

@ -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
});
});
});

View File

@ -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');

View File

@ -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