[UI] generic_picker merged the pre_picker into the picker - WIP

pull/4024/head
mokaddem 2019-01-10 14:40:30 +01:00
parent 8f53a73761
commit 5b7fff5df2
5 changed files with 219 additions and 68 deletions

View File

@ -3292,19 +3292,6 @@ class EventsController extends AppController
$this->set('count', $count);
}
public function genericPicker() {
$this->set('options', array());
$this->set('items', array('item1', 'item2', 'item3'));
$this->render('/Elements/generic_picker');
}
public function genericPrePicker() {
$this->set('choices', array(
'Tag Collections' => "/tags/selectTag/4/collections/attribute",
'All Tags' => "/tags/selectTag/4/all/attribute"
));
$this->render('/Elements/generic_pre_picker');
}
public function addTag($id = false, $tag_id = false)
{
if (!$this->request->is('post')) {

View File

@ -106,18 +106,22 @@ class GalaxiesController extends AppController
)));
}
$choices = array();
$choices[__('All clusters')] = "/galaxies/selectCluster/" . h($target_id) . '/' . h($target_type) . '/0';
$items = array();
$items[__('All clusters')] = "/galaxies/selectCluster/" . h($target_id) . '/' . h($target_type) . '/0';
foreach ($galaxies as $galaxy) {
if ($galaxy['Galaxy']['id'] != -1) {
$choices[h($galaxy['Galaxy']['name'])] = "/galaxies/selectCluster/" . h($target_id) . '/' . h($target_type) . '/' . h($galaxy['Galaxy']['id']);
$items[h($galaxy['Galaxy']['name'])] = "/galaxies/selectCluster/" . h($target_id) . '/' . h($target_type) . '/' . h($galaxy['Galaxy']['id']);
} else { // attackMatrix
$items[h($galaxy['Galaxy']['name'])] = array(
'functionName' => "getMitreMatrixPopup('" . h($target_id) . "/" . h($target_type) . "')",
'isPill' => true
);
// getMitreMatrixPopup('echo h($target_id) . "/" . h($target_type);')
}
}
$this->set('choices', $choices);
$this->render('/Elements/generic_pre_picker');
$this->set('items', $items);
$this->render('/Elements/generic_picker');
}
public function selectGalaxyNamespace($target_id, $target_type='event')
@ -128,14 +132,17 @@ class GalaxiesController extends AppController
'group' => array('namespace')
));
$choices = array();
$choices[__('All namespaces')] = "/galaxies/selectGalaxy/" . h($target_id) . '/' . h($target_type) . '/0';
$items = array();
$items[__('All namespaces')] = "/galaxies/selectGalaxy/" . h($target_id) . '/' . h($target_type) . '/0';
foreach ($namespaces as $namespace) {
$choices[h($namespace)] = "/galaxies/selectGalaxy/" . h($target_id) . '/' . h($target_type) . '/' . h($namespace);
$items[h($namespace)] = "/galaxies/selectGalaxy/" . h($target_id) . '/' . h($target_type) . '/' . h($namespace);
}
$this->set('choices', $choices);
$this->render('/Elements/generic_pre_picker');
$this->set('items', $items);
$this->set('options', array( // set chosen (select picker) options
'multiple' => 0,
));
$this->render('/Elements/generic_picker');
}
public function selectCluster($target_id, $target_type = 'event', $selectGalaxy = false)
@ -201,10 +208,8 @@ class GalaxiesController extends AppController
$this->set('items', $items);
$this->set('options', array( // set chosen (select picker) options
'select_options' => array(
'multiple' => true,
),
'functionName' => $onClickForm,
'multiple' => -1,
));
$this->render('ajax/cluster_choice');
}

View File

@ -573,26 +573,31 @@ class TagsController extends AppController
throw new NotFoundException('You don\'t have permission to do that.');
}
$choices = array();
$items = array();
$favourites = $this->Tag->FavouriteTag->find('count', array('conditions' => array('FavouriteTag.user_id' => $this->Auth->user('id'))));
if ($favourites) {
$choices[__('Favourite Tags')] = "/tags/selectTag/" . h($id) . "/favourites/" . h($scope);
$items[__('Favourite Tags')] = "/tags/selectTag/" . h($id) . "/favourites/" . h($scope);
}
if ($scope !== 'tag_collection') {
$choices[__('Tag Collections')] = "/tags/selectTag/" . h($id) . "/collections/" . h($scope);
$items[__('Tag Collections')] = "/tags/selectTag/" . h($id) . "/collections/" . h($scope);
}
$choices[__('All Tags')] = "/tags/selectTag/" . h($id) . "/all/" . h($scope);
$items[__('All Tags')] = "/tags/selectTag/" . h($id) . "/all/" . h($scope);
$this->loadModel('Taxonomy');
$options = $this->Taxonomy->find('list', array('conditions' => array('enabled' => true), 'fields' => array('namespace'), 'order' => array('Taxonomy.namespace ASC')));
foreach ($options as $k => $option) {
$tags = $this->Taxonomy->getTaxonomyTags($k, false, true);
if (!empty($tags)) {
$choices[__('Taxonomy Library') . ":" . h($option)] = "/tags/selectTag/" . h($id) . "/" . h($k) . "/" . h($scope);
$items[__('Taxonomy Library') . ":" . h($option)] = "/tags/selectTag/" . h($id) . "/" . h($k) . "/" . h($scope);
}
}
$this->set('choices', $choices);
$this->render('/Elements/generic_pre_picker');
$this->set('items', $items);
$this->set('options', array( // set chosen (select picker) options
'select_options' => array(
'multiple' => 0,
),
));
$this->render('/Elements/generic_picker');
}
public function selectTag($id, $taxonomy_id, $scope = 'event', $filterData = '')
@ -716,10 +721,8 @@ class TagsController extends AppController
}
$this->set('items', $items);
$this->set('options', array( // set chosen (select picker) options
'select_options' => array(
'multiple' => true,
),
'functionName' => $onClickForm,
'multiple' => -1,
));
$this->render('ajax/select_tag');
}

View File

@ -2,10 +2,8 @@
/**
* Generic select picker
*/
// prevent exception if not set
$options = isset($options) ? $options : array();
$items = isset($items) ? $items : array();
/** Config **/
$select_threshold = 6; // threshold on which pills will be replace by a select (unused if multiple is > 1)
$defaults_options = array(
'select_options' => array(
// 'multiple' => '', // set to add possibility to pick multiple options in the select
@ -18,12 +16,25 @@
'disable_search_threshold' => 10,
'allow_single_deselect' => true,
),
'multiple' => 0,
'functionName' => '', // function to be called on submit
);
/** prevent exception if not set **/
$options = isset($options) ? $options : array();
$items = isset($items) ? $items : array();
// merge options with defaults
$defaults = array_replace_recursive($defaults_options, $options);
// enforce consistency
if ($defaults['multiple'] == 0) {
unset($defaults['select_options']['multiple']);
} else { // multiple enabled
$defaults['chosen_options']['max_selected_options'] = $defaults['multiple'] == -1 ? 'Infinity' : $defaults['multiple'];
$defaults['select_options']['multiple'] = '';
$select_threshold = 0;
}
$use_select = count($items) > $select_threshold;
function add_select_params($options) {
$select_html = '';
foreach ($options['select_options'] as $option => $value) {
@ -57,39 +68,166 @@
}
$option_html .= '>';
$option_html .= is_array($param)? h($name) : h($param);
// $option_html .= is_array($param)? h($name) : h($param);
$option_html .= h($name);
$option_html .= '</option>';
return $option_html;
}
function add_link_params($name, $param, $defaults = array()) {
$param_html = ' ';
if (is_array($param)) { // add data as param
if (isset($param['functionName'])) {
// $param_html .= 'onclick="' . $param['functionName'] . '" ';
$param_html .= 'onclick="execAndClose(this, ' . $param['functionName'] . ')" ';
} else { // fallback to default submit function
$param_html .= 'onclick="submitFunction(this, ' . $defaults['functionName'] . ')" ';
}
$additionalData = json_encode(array());
foreach ($param as $paramName => $paramValue) {
if ($paramName === 'additionalData') {
$additionalData = json_encode($param['additionalData']);
} else if ($paramName === 'value'){
$param_html .= 'value="' . h($paramValue) . '" ';
} else {
$param_html .= 'data-' . h($paramName). '="' . h($paramValue) . '" ';
}
}
$param_html .= ' data-additionaldata=' . $additionalData;
} else { // param is a simple endpoint from which fetch data
$param_html .= 'data-endpoint="' . h($param) . '" ';
$param_html .= 'onclick="fetchRequestedData(this)" ';
}
return $param_html;
}
?>
<div class="popover_choice generic_picker">
<div>
<select <?php echo h(add_select_params($defaults)); ?>>
<script>
function execAndClose(elem, alreadyExecuted) {
$(elem).closest('div.popover').prev().popover('destroy');
}
function setupChosen(id) {
var $elem = $('#'+id);
var chosen_options = <?php echo json_encode($defaults['chosen_options']); ?>;
$elem.chosen(chosen_options);
if (!$elem.prop('multiple')) { // not multiple, selection trigger next event
$elem.change(function(event, selected) {
select = this;
$select = $(select);
$select.data('endpoint', selected.selected);
fetchRequestedData($select);
});
}
}
// Used to keep the popover arrow at the correct place regardless of the popover content
function syncPopoverArrow($arrow, $wrapper, content) {
var ar_pos = $arrow.position();
$wrapper.html(content);
$wrapper.show();
// redraw popover
$arrow.css('top', ar_pos.top + 'px');
$arrow.css('left', ar_pos.left + 'px');
}
// can either call a function or fetch requested data
function fetchRequestedData(clicked) {
var $clicked = $(clicked);
var $wrapper = $clicked.closest('div').find('div.generic-picker-wrapper');
$.ajax({
dataType:"html",
async: true,
cache: false,
beforeSend: function() {
var loadingHtml = '<div style="height: 40px; width: 40px; left: 50%; position: relative;"><div class="spinner" style="height: 30px; width: 30px;"></div></div>';
var $arrow = $clicked.closest('div.popover').find('div.arrow');
syncPopoverArrow($arrow, $wrapper, loadingHtml)
},
success:function (data, textStatus) {
var $arrow = $clicked.closest('div.popover').find('div.arrow');
syncPopoverArrow($arrow, $wrapper, data)
},
error:function() {
$wrapper.html('<div class="alert alert-error" style="margin-bottom: 0px;">Something went wrong - the queried function returned an exception. Contact your administrator for further details (the exception has been logged).</div>');
},
url: $clicked.data('endpoint')
});
}
function submitFunction(clicked, callback) {
var $clicked = $(clicked);
var $select = $clicked.parent().find('select');
var selected, additionalData;
if ($select.length > 0) {
selected = $select.val();
additionalData = $select.find(":selected").data('additionaldata');
} else {
selected = $clicked.attr('value');
additionalData = $clicked.data('additionaldata');
}
callback(selected, additionalData);
}
</script>
<div class="generic_picker">
<?php if ($use_select): ?>
<?php
$select_id = h(uniqid()); // used to only register the listener on this select (allowing nesting)
$flag_addPills = false;
?>
<select id="<?php echo $select_id; ?>" style="height: 20px; margin-bottom: 0px;" <?php echo h(add_select_params($defaults)); ?>>
<option></option>
<?php
foreach ($items as $name => $param) {
echo add_option($name, $param);
if (isset($param['isPill']) && $param['isPill']) {
$flag_addPills = true;
continue;
} else {
echo add_option($name, $param);
}
}
?>
</select>
<button class="btn btn-primary" onclick="submitFunction(this, <?php echo $defaults['functionName']; ?>)">submit</button>
</div>
<!-- <div class="overlay_spacing" style="margin: 5px; margin-top: 10px;"> -->
<!-- </div> -->
<?php if ($defaults['multiple'] != 0): ?>
<button class="btn btn-primary" onclick="submitFunction(this, <?php echo $defaults['functionName']; ?>)">submit</button>
<?php endif; ?>
<?php if ($flag_addPills): // add forced pills ?>
<ul class="nav nav-pills">
<?php foreach ($items as $name => $param): ?>
<?php if (isset($param['isPill']) && $param['isPill']): ?>
<li>
<a href="#" data-toggle="pill" class="pill-pre-picker" <?php echo add_link_params($name, $param, $defaults); ?> >
<?php echo h($name); ?>
</a>
</li>
<?php endif; ?>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<script>
$(document).ready(function() {
setTimeout(function() { // let time for the popup to show
setupChosen("<?php echo $select_id; ?>");
}, 10);
});
</script>
<?php else: ?>
<ul class="nav nav-pills">
<?php foreach ($items as $name => $param): ?>
<li>
<a href="#" data-toggle="pill" class="pill-pre-picker" <?php echo add_link_params($name, $param, $defaults); ?> >
<?php echo h($name); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<div class='generic-picker-wrapper hidden'></div>
</div>
<script>
$('document').ready(function() {
var chosen_options = <?php echo json_encode($defaults['chosen_options']); ?>;
$(".generic_picker select").chosen(chosen_options);
})
function submitFunction(clicked, callback) {
var $clicked = $(clicked);
var $select = $clicked.parent().find('select');
var selected = $select.val();
var additionalData = $select.find(":selected").data('additionaldata');
callback(selected, additionalData);
}
</script>

View File

@ -895,17 +895,35 @@ a.proposal_link_red:hover {
}
a.pill-pre-picker {
background-color: #0000000f;
background-color: #fcfcfc;
font-weight: bold;
border: solid 1px #00000033;
}
.generic_picker {
margin: 10px;
display: inline-block;
}
.generic_picker ul.nav {
margin-bottom: 0px;
}
.generic-picker-wrapper {
/* background-color: #8a8a8a50; */
padding: 7px;
margin-top: 3px;
background-color: #65737e32;
border-radius: 7px;
}
.generic-picker-wrapper:before {
content: '';
margin-right: 5px;
margin-left: 2px;
border-left: 1px solid;
border-bottom: 1px solid;
height: 10px;
width: 5px;
display: inline-block;
float: left;
}
.gray_out {