Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pkp/pkp-lib#2612 Submission filtering #2704

Merged
merged 7 commits into from
Aug 21, 2017
7 changes: 6 additions & 1 deletion api/v1/_submissions/PKPBackendSubmissionsHandler.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ public function getSubmissions($slimRequest, $response, $args) {
foreach ($params as $param => $val) {
switch ($param) {

// Always convert status to array
// Always convert status and stageIds to array
case 'status':
case 'stageIds':
if (is_string($val) && strpos($val, ',') > -1) {
$val = explode(',', $val);
} elseif (!is_array($val)) {
Expand Down Expand Up @@ -119,6 +120,10 @@ public function getSubmissions($slimRequest, $response, $args) {
case 'orderDirection':
$params[$param] = $val === 'ASC' ? $val : 'DESC';
break;

case 'isIncomplete':
case 'isOverdue':
$params[$param] = true;
}
}

Expand Down
9 changes: 7 additions & 2 deletions classes/services/PKPSubmissionService.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public function getSubmissionList($contextId, $args = array()) {
'searchPhrase' => null,
'count' => 20,
'offset' => 0,
'isIncomplete' => false,
'isOverdue' => false,
);

$args = array_merge($defaultArgs, $args);
Expand All @@ -64,6 +66,9 @@ public function getSubmissionList($contextId, $args = array()) {
->orderBy($args['orderBy'], $args['orderDirection'])
->assignedTo($args['assignedTo'])
->filterByStatus($args['status'])
->filterByStageIds($args['stageIds'])
->filterByIncomplete($args['isIncomplete'])
->filterByOverdue($args['isOverdue'])
->searchPhrase($args['searchPhrase']);

\HookRegistry::call('Submission::getSubmissionList::queryBuilder', array(&$submissionListQB, $contextId, $args));
Expand Down Expand Up @@ -508,7 +513,7 @@ public function toArrayStageDetails($submission, $stageIds = null) {
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO');
$reviewRound = $reviewRoundDao->getLastReviewRoundBySubmissionId($submission->getId(), $stageId);
if ($reviewRound) {
$stage['statusId'] = $reviewRound->getStatus();
$stage['statusId'] = $reviewRound->determineStatus();
$stage['status'] = __($reviewRound->getStatusKey());

// Revision files in this round.
Expand Down Expand Up @@ -562,7 +567,7 @@ public function toArrayReviewRounds($submission) {
'id' => $reviewRound->getId(),
'round' => $reviewRound->getRound(),
'stageId' => $reviewRound->getStageId(),
'statusId' => $reviewRound->getStatus(),
'statusId' => $reviewRound->determineStatus(),
'status' => __($reviewRound->getStatusKey()),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ abstract class PKPSubmissionListQueryBuilder extends BaseQueryBuilder {
/** @var array list of statuses */
protected $statuses = null;

/** @var array list of stage ids */
protected $stageIds = null;

/** @var int user ID */
protected $assigneeId = null;

Expand All @@ -43,6 +46,12 @@ abstract class PKPSubmissionListQueryBuilder extends BaseQueryBuilder {
/** @var bool whether to return only a count of results */
protected $countOnly = null;

/** @var bool whether to return only incomplete results */
protected $isIncomplete = false;

/** @var bool whether to return only submissions with overdue review assignments */
protected $isOverdue = false;

/**
* Constructor
*
Expand Down Expand Up @@ -88,6 +97,45 @@ public function filterByStatus($statuses) {
return $this;
}

/**
* Set stage filter
*
* @param int|array $stageIds
*
* @return \OJS\Services\QueryBuilders\SubmissionListQueryBuilder
*/
public function filterByStageIds($stageIds) {
if (!is_null($stageIds) && !is_array($stageIds)) {
$stageIds = array($stageIds);
}
$this->stageIds = $stageIds;
return $this;
}

/**
* Set incomplete submissions filter
*
* @param boolean $isIncomplete
*
* @return \OJS\Services\QueryBuilders\SubmissionListQueryBuilder
*/
public function filterByIncomplete($isIncomplete) {
$this->isIncomplete = $isIncomplete;
return $this;
}

/**
* Set overdue submissions filter
*
* @param boolean $isOverdue
*
* @return \OJS\Services\QueryBuilders\SubmissionListQueryBuilder
*/
public function filterByOverdue($isOverdue) {
$this->isOverdue = $isOverdue;
return $this;
}

/**
* Limit results to a specific user's submissions
*
Expand Down Expand Up @@ -153,6 +201,33 @@ public function get() {
$q->whereIn('s.status', $this->statuses);
}

// stage ids
if (!is_null($this->stageIds)) {
$q->whereIn('s.stage_id', $this->stageIds);
}

// incomplete submissions
if ($this->isIncomplete) {
$q->where('s.submission_progress', '>', 0);
}

// overdue submisions
if ($this->isOverdue) {
$q->leftJoin('review_assignments as raod', 'raod.submission_id', '=', 's.submission_id')
->leftJoin('review_rounds as rr', function($table) {
$table->on('rr.submission_id', '=', 's.submission_id');
$table->on('raod.review_round_id', '=', 'rr.review_round_id');
});
// Only get overdue assignments on active review rounds
import('lib.pkp.classes.submission.reviewRound.ReviewRound');
$q->where('rr.status', '!=', REVIEW_ROUND_STATUS_RESUBMITTED);
$q->where('rr.status', '!=', REVIEW_ROUND_STATUS_SENT_TO_EXTERNAL);
$q->where('rr.status', '!=', REVIEW_ROUND_STATUS_ACCEPTED);
$q->where('rr.status', '!=', REVIEW_ROUND_STATUS_DECLINED);
$q->where('raod.date_due', '<', \Core::getCurrentDate(strtotime('tomorrow')));
$q->where('raod.date_response_due', '<', \Core::getCurrentDate(strtotime('tomorrow')));
}

// assigned to
if (!is_null($this->assigneeId) && ($this->assigneeId !== -1)) {
$assigneeId = $this->assigneeId;
Expand Down
2 changes: 1 addition & 1 deletion classes/submission/reviewRound/ReviewRound.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public function determineStatus() {
* @return int
*/
function getStatusKey($isAuthor = false) {
switch ($this->getStatus()) {
switch ($this->determineStatus()) {
case REVIEW_ROUND_STATUS_REVISIONS_REQUESTED:
return 'editor.submission.roundStatus.revisionsRequested';
case REVIEW_ROUND_STATUS_REVISIONS_SUBMITTED:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<?php
/**
* @file controllers/list/submissions/SubmissionsListHandler.inc.php
* @file controllers/list/submissions/PKPSubmissionsListHandler.inc.php
*
* Copyright (c) 2014-2017 Simon Fraser University
* Copyright (c) 2000-2016 John Willinsky
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be 2017?

* Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
*
* @class SubmissionsListHandler
* @class PKPSubmissionsListHandler
* @ingroup classes_controllers_list
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is ingroup classes?

*
* @brief Instantiates and manages a UI component to list submissions.
Expand All @@ -15,7 +15,7 @@
import('lib.pkp.classes.db.DBResultRange');
import('lib.pkp.classes.submission.Submission');

class SubmissionsListHandler extends ListHandler {
abstract class PKPSubmissionsListHandler extends ListHandler {

/**
* Count of items to retrieve in initial page/request
Expand Down Expand Up @@ -97,6 +97,27 @@ public function getConfig() {

$config['getParams'] = $this->_getParams;

$config['filters'] = array(
'attention' => array(
'filters' => array(
array(
'param' => 'isOverdue',
'val' => true,
'title' => __('common.overdue'),
),
array(
'param' => 'isIncomplete',
'val' => true,
'title' => __('submissions.incomplete'),
),
),
),
'stageIds' => array(
'heading' => __('settings.roles.stages'),
'filters' => $this->getWorkflowStages(),
),
);

// Load grid localisation files
AppLocale::requireComponents(LOCALE_COMPONENT_PKP_GRID);
AppLocale::requireComponents(LOCALE_COMPONENT_PKP_SUBMISSION);
Expand Down Expand Up @@ -159,4 +180,11 @@ public function getItems() {
->get('submission')
->getSubmissionList($contextId, $params);
}

/**
* Get an array of workflow stages supported by the current app
*
* @return array
*/
abstract function getWorkflowStages();
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*
* @brief A list handler for selecting submissions
*/
import('lib.pkp.controllers.list.submissions.SubmissionsListHandler');
import('controllers.list.submissions.SubmissionsListHandler');

class SelectSubmissionsListHandler extends SubmissionsListHandler {

Expand All @@ -23,15 +23,15 @@ class SelectSubmissionsListHandler extends SubmissionsListHandler {
public $_inputName = 'selectedSubmissions';

/**
* @see SubmissionsListHandler
* @copydoc SubmissionsListHandler
*/
public function init( $args = array() ) {
parent::init($args);
$this->_inputName = isset($args['inputName']) ? $args['inputName'] : $this->_inputName;
}

/**
* @see SubmissionsListHandler
* @copydoc SubmissionsListHandler
*/
public function getConfig() {
$config = parent::getConfig();
Expand Down
5 changes: 4 additions & 1 deletion js/controllers/list/ListPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ export default {
* Update filter parameters
*/
updateFilter: function(params) {
this.filterParams = params;
this.filterParams = {};
this.$nextTick(function() {
this.filterParams = params;
});
},

/**
Expand Down
51 changes: 48 additions & 3 deletions js/controllers/list/ListPanelFilter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,34 @@ export default {
},
methods: {
/**
* Emit an event to filter items in the list panel
* Check if a filter is currently active
*/
filterList: function(data) {
this.$emit('filterList', data);
isFilterActive: function(type, val) {
return this.activeFilters.filter(filter => {
return filter.type === type && filter.val === val;
}).length
},

/**
* Add a filter
*/
filterBy: function(type, val) {
if (this.isFilterActive(type, val)) {
this.clearFilter(type, val);
return;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is happening here: when a filter that is active is added, it will be removed? :-\

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a toggle feature. Click once to activate it. If you click on the filter again, you deactivate it.

this.activeFilters.push({type: type, val: val});
this.filterList(this.compileFilterParams());
},

/**
* Remove a filter
*/
clearFilter: function(type, val) {
this.activeFilters = this.activeFilters.filter(filter => {
return filter.type !== type || filter.val !== val;
});
this.filterList(this.compileFilterParams());
},

/**
Expand All @@ -37,6 +61,27 @@ export default {
this.activeFilters = [];
this.filterList({});
},

/**
* Compile active filters into filter parameters
*/
compileFilterParams: function() {
let params = {};
for (var filter of this.activeFilters) {
if (params[filter.type] === undefined) {
params[filter.type] = [];
}
params[filter.type].push(filter.val);
}
return params;
},

/**
* Emit an event to filter items in the list panel
*/
filterList: function(data) {
this.$emit('filterList', data);
},
},
mounted: function() {
/**
Expand Down
Loading