Skip to content

Commit

Permalink
Fixed issue #14456: Regression: Feature for selecting which data colu…
Browse files Browse the repository at this point in the history
…msn to show was removed after Limesurvey 2.6 LTS
  • Loading branch information
ptelu committed May 31, 2019
1 parent 4824869 commit 1455c56
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 49 deletions.
38 changes: 32 additions & 6 deletions application/controllers/admin/responses.php
Expand Up @@ -424,18 +424,26 @@ public function browse($iSurveyId)
$aViewUrls = array('listResponses_view');
$model = SurveyDynamic::model($iSurveyId);


// Reset filters from stats
if (Yii::app()->request->getParam('filters') == "reset") {
Yii::app()->user->setState('sql_'.$iSurveyId, '');
}


// Page size
if (Yii::app()->request->getParam('pageSize')) {
Yii::app()->user->setState('pageSize', (int) Yii::app()->request->getParam('pageSize'));
}

// Model filters
if (isset($_SESSION['survey_' . $iSurveyId])) {
$sessionSurveyArray = App()->session->get('survey_' . $iSurveyId);
$visibleColumns = isset($sessionSurveyArray['filteredColumns']) ? $sessionSurveyArray['filteredColumns'] : null;
if (!empty($visibleColumns)){
$model->setAttributes($visibleColumns,false);
}

};
// Using safe search on dynamic column names would be far too much complex.
// So we pass over the safe validation and directly set attributes (second parameter of setAttributes to false).
// see: http://www.yiiframework.com/wiki/161/understanding-safe-validation-rules/
Expand All @@ -456,6 +464,15 @@ public function browse($iSurveyId)
}
}

// Checks if Columns have been filtered
$filterableColumnsExist = !empty(isset($_SESSION['survey_' . $iSurveyId]['filteredColumns']) ? $_SESSION['survey_' . $iSurveyId]['filteredColumns'] : null);
$filteredColumns = [];
if ($filterableColumnsExist) {
$filteredColumns = $_SESSION['survey_' . $iSurveyId]['filteredColumns'];
}
$aData['filterableColumnsExist'] = $filteredColumns;
$aData['filteredColumns'] = $filteredColumns;

// rendering
$aData['model'] = $model;
$aData['bHaveToken'] = $bHaveToken;
Expand All @@ -474,15 +491,24 @@ public function browse($iSurveyId)
* Saves the hidden columns for response browsing in the session
*
* @access public
* @param $iSurveyID : survey id
*
* @param $surveyid
*/

public function setHiddenColumns($iSurveyId)
public function setFilteredColumns($surveyid)
{
if (Permission::model()->hasSurveyPermission($iSurveyId, 'responses', 'read')) {
$aHiddenFields = explode('|', Yii::app()->request->getPost('aHiddenFields'));
$_SESSION['survey_'.$iSurveyId]['HiddenFields'] = $aHiddenFields;
if (Permission::model()->hasSurveyPermission($surveyid, 'responses', 'read')) {
$filteredColumns = [];
$columns = explode(',', Yii::app()->request->getPost('columns'));
foreach ($columns as $column){
if (!empty($column)){
$filteredColumns[] = $column;
}
}
$_SESSION['survey_'.$surveyid]['filteredColumns'] = $filteredColumns;
}
$this->getController()->redirect(["admin/responses", "sa"=>"browse", "surveyid"=>$surveyid]);

}


Expand Down
Expand Up @@ -8,7 +8,7 @@
?>

<!-- Massive actions widget : selector view -->
<div class="col-sm-4 pull-left dropup listActions" data-pk="<?php echo $this->pk;?>" data-grid-id="<?php echo $this->gridid;?>" id="<?php echo $this->dropupId;?>">
<div class="pull-left dropup listActions" data-pk="<?php echo $this->pk;?>" data-grid-id="<?php echo $this->gridid;?>" id="<?php echo $this->dropupId;?>">
<!-- Drop Up button selector -->
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<?php echo $this->dropUpText;?>
Expand Down
111 changes: 69 additions & 42 deletions application/views/admin/responses/listResponses_view.php
Expand Up @@ -70,6 +70,7 @@
// the massive actions dropup button
$massiveAction = App()->getController()->renderPartial('/admin/responses/massive_actions/_selector', array(), true, false);


// The first few colums are fixed.
// Specific columns at start
$aColumns = array(
Expand All @@ -92,75 +93,96 @@
array(
'header' => 'seed',
'name' => 'seed'
));
)
);

if (!$filterableColumnsExist || in_array('lastpage', $filterableColumnsExist ? $filteredColumns : [])) {
$aColumns[] = array(
'header'=>'lastpage',
'name'=>'lastpage',
'type'=>'number',
'filter'=>TbHtml::textField(
'header' => 'lastpage',
'name' => 'lastpage',
'type' => 'number',
'filter' => TbHtml::textField(
'SurveyDynamic[lastpage]',
$model->lastpage)
);
}
$filterableColumns[] = 'lastpage';

if (!$filterableColumnsExist || in_array(gT("completed"), $filterableColumnsExist ? $filteredColumns : [])) {
$aColumns[] = array(
'header'=>gT("completed"),
'name'=>'completed_filter',
'value'=>'$data->completed',
'type'=>'raw',
'filter'=>TbHtml::dropDownList(
'header' => gT("completed"),
'name' => 'completed_filter',
'value' => '$data->completed',
'type' => 'raw',
'filter' => TbHtml::dropDownList(
'SurveyDynamic[completed_filter]',
$model->completed_filter,
array(''=>gT('All'),'Y'=>gT('Yes'),'N'=>gT('No')))
array('' => gT('All'), 'Y' => gT('Yes'), 'N' => gT('No')))
);
}
$filterableColumns[] = gT("completed");

//add token to top of list if survey is not private
if ($bHaveToken)
{
//add token to top of list if survey is not private
if ($bHaveToken) {
if (!$filterableColumnsExist || in_array('token', $filterableColumnsExist ? $filteredColumns : [])) {
$aColumns[] = array(
'header'=>'token',
'name'=>'token',
'type'=>'raw',
'value'=>'$data->tokenForGrid',
'header' => 'token',
'name' => 'token',
'type' => 'raw',
'value' => '$data->tokenForGrid',

);
}
$filterableColumns[] = 'token';

if (!$filterableColumnsExist || in_array(gT("First name"), $filterableColumnsExist ? $filteredColumns : [])) {
$aColumns[] = array(
'header'=>gT("First name"),
'name'=>'tokens.firstname',
'id'=>'firstname',
'type'=>'raw',
'value'=>'$data->firstNameForGrid',
'filter'=>TbHtml::textField(
'header' => gT("First name"),
'name' => 'tokens.firstname',
'id' => 'firstname',
'type' => 'raw',
'value' => '$data->firstNameForGrid',
'filter' => TbHtml::textField(
'SurveyDynamic[firstname_filter]',
$model->firstname_filter)
);
}
$filterableColumns[] = gT("First name");

if (!$filterableColumnsExist || in_array(gT("Last name"), $filterableColumnsExist ? $filteredColumns : [])) {
$aColumns[] = array(
'header'=>gT("Last name"),
'name'=>'tokens.lastname',
'type'=>'raw',
'id'=>'lastname',
'value'=>'$data->lastNameForGrid',
'filter'=>TbHtml::textField(
'header' => gT("Last name"),
'name' => 'tokens.lastname',
'type' => 'raw',
'id' => 'lastname',
'value' => '$data->lastNameForGrid',
'filter' => TbHtml::textField(
'SurveyDynamic[lastname_filter]',
$model->lastname_filter)
);
}
$filterableColumns[] = gT("Last name");

if (!$filterableColumnsExist || in_array(gT("Email"), $filterableColumnsExist ? $filteredColumns : [])) {
$aColumns[] = array(
'header'=>gT("Email"),
'name'=>'tokens.email',
'id'=>'email',
'filter'=>TbHtml::textField(
'header' => gT("Email"),
'name' => 'tokens.email',
'id' => 'email',
'filter' => TbHtml::textField(
'SurveyDynamic[email_filter]',
$model->email_filter)
);
}
$filterableColumns[] = gT("Email");
}

if (!$filterableColumnsExist || in_array('startlanguage', $filterableColumnsExist ? $filteredColumns : [])) {
$aColumns[] = array(
'header'=>'startlanguage',
'name'=>'startlanguage',
'header' => 'startlanguage',
'name' => 'startlanguage',
);
}
$filterableColumns[] = 'startlanguage';

// The column model must be built dynamically, since the columns will differ from survey to survey, depending on the questions.
// All other columns are based on the questions.
Expand All @@ -176,17 +198,22 @@
/* Here we strip all tags, and separate with hr since we allow html (in popover), maybe use only viewHelper::purified ? But remind XSS. mantis #14301 */
$colTitle = viewHelper::getFieldText($fieldmap[$column->name],array('afterquestion'=>"<hr>",'separator'=>array('','<br>')));

$aColumns[]=
array(
'header' => '<div data-toggle="popover" data-trigger="hover focus" data-placement="bottom" title="'.$colName.'" data-content="'.CHtml::encode($colTitle).'" data-html="1" data-container="#responses-grid">'.$colName.' <br/> '.$colDetails.'</div>',
'headerHtmlOptions'=>array('style'=>'min-width: 350px;'),
if (!$filterableColumnsExist || in_array($colName . ': ' . $colDetails, $filterableColumnsExist ? $filteredColumns : [])) {
$aColumns[] = array(
'header' => '<div data-toggle="popover" data-trigger="hover focus" data-placement="bottom" title="' . $colName . '" data-content="' . CHtml::encode($colTitle) . '" data-html="1" data-container="#responses-grid">' . $colName . ' <br/> ' . $colDetails . '</div>',
'headerHtmlOptions' => array('style' => 'min-width: 350px;'),
'name' => $column->name,
'type' => 'raw',
'value' => '$data->getExtendedData("'.$column->name.'", "'.$language.'", "'.$base64jsonFieldMap.'")',
'value' => '$data->getExtendedData("' . $column->name . '", "' . $language . '", "' . $base64jsonFieldMap . '")',
);
}
$filterableColumns[] = $colName . ': ' . $colDetails;
}
}

// create a modal to filter all columns
$filterColumns = App()->getController()->renderPartial('/admin/responses/modal_subviews/filterColumns', array('filterableColumns' => $filterableColumns, 'filteredColumns' => $filteredColumns), true, false);

$this->widget('ext.LimeGridView.LimeGridView', array(
'dataProvider' => $model->search(),
'filter' => $model,
Expand All @@ -196,7 +223,7 @@
'ajaxUpdate' => 'responses-grid',
'ajaxType' => 'POST',
'afterAjaxUpdate'=>'js:function(id, data){ LS.resp.bindScrollWrapper(); onUpdateTokenGrid();$(".grid-view [data-toggle=\'popover\']").popover(); }',
'template' => "<div class='push-grid-pager'>{items}\n</div><div id='ListPager'><div class=\"col-sm-12\" id=\"massive-action-container\">$massiveAction</div><div class=\"col-sm-12 pager-container ls-ba \">{pager}</div><div class=\"col-sm-12 summary-container\">{summary}</div></div>",
'template' => "<div class='push-grid-pager'>{items}\n</div><div id='ListPager'><div class=\"col-sm-12\" id=\"massive-action-container\">$massiveAction$filterColumns</div><div class=\"col-sm-12 pager-container ls-ba \">{pager}</div><div class=\"col-sm-12 summary-container\">{summary}</div></div>",
'summaryText' => gT('Displaying {start}-{end} of {count} result(s).').' '. sprintf(gT('%s rows per page'),
CHtml::dropDownList(
'pageSize',
Expand Down
39 changes: 39 additions & 0 deletions application/views/admin/responses/modal_subviews/filterColumns.php
@@ -0,0 +1,39 @@
<?php
$surveyid = App()->request->getParam('surveyid');
$surveyColumns = isset($filterableColumns) ? $filterableColumns : null;
?>

<!-- Button trigger modal -->
<a class="btn btn-default" data-toggle="modal" data-target="#responses-column-filter-modal" id="responses-column-filter-button">
<span class="fa fa-columns"></span>
</a>

<!-- Modal -->
<div class="modal fade" id="responses-column-filter-modal" tabindex="-1" role="dialog" aria-labelledby="responses-column-filter-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form action="<?=App()->createUrl('/admin/responses/sa/setfilteredcolumns/', ['surveyid' => $surveyid])?>" class="pjax" method="POST">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="responses-column-filter-modal"><?php eT("Select columns") ?></h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="responses-column-filter-select"></label>
<select multiple name="columns" id="responses-column-filter-select" class="form-control">
<?php foreach ($surveyColumns as $surveyColumn): ?>
<option <?php echo in_array($surveyColumn, $filteredColumns) ? 'selected' : '' ?>><?php echo $surveyColumn ?></option>
<?php endforeach; ?>
</select>
<input type="hidden" name="surveyid" value="<?=$surveyid?>" />
<input type="hidden" name="<?=Yii::app()->request->csrfTokenName?>" value="<?=App()->request->csrfToken?>" />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><?php eT("Close"); ?></button>
<button type="submit" class="btn btn-primary"><?php eT('Ok'); ?></button>
</div>
</form>
</div>
</div>
</div>
6 changes: 6 additions & 0 deletions assets/scripts/admin/listresponse.js
Expand Up @@ -129,3 +129,9 @@ $(document).on('ready pjax:scriptcomplete',function(){
onDocumentReadyListresponse();
reinstallResponsesFilterDatePicker();
});

// hide Modal on submit for pjax preventDefault
$(document).on('click', '#responses-column-filter-modal :submit', function (e) {
$('#responses-column-filter-modal').modal('hide');
});

8 changes: 8 additions & 0 deletions assets/styles-public/browse.css
Expand Up @@ -30,9 +30,17 @@
text-align: left;
}

#responses-grid #responses-column-filter-select {
height: 200px;
}

#responses-grid #responses-column-filter-button {
margin-left: 3px;
}

/*!
* Style for browsing response : in jqgrid
* TODO: Is not in use anymore
*/

#gview_displayresponses th .qcode {
Expand Down

0 comments on commit 1455c56

Please sign in to comment.