first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-06-08 17:09:23 -04:00
commit df3a033196
17887 changed files with 8637778 additions and 0 deletions
@@ -0,0 +1,140 @@
<?php
/**
* @file classes/components/listPanels/ContributorsListPanel.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2000-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class ContributorsListPanel
*
* @ingroup classes_components_list
*
* @brief A ListPanel component for viewing and editing contributors
*/
namespace PKP\components\listPanels;
use APP\core\Application;
use APP\submission\Submission;
use PKP\components\forms\publication\ContributorForm;
use PKP\context\Context;
class ContributorsListPanel extends ListPanel
{
public Submission $submission;
public Context $context;
public array $locales;
/** Whether the user can edit the current publication */
public bool $canEditPublication;
public function __construct(
string $id,
string $title,
Submission $submission,
Context $context,
array $locales,
array $items = [],
bool $canEditPublication = false
) {
parent::__construct($id, $title);
$this->submission = $submission;
$this->context = $context;
$this->locales = $locales;
$this->items = $items;
$this->canEditPublication = $canEditPublication;
}
/**
* @copydoc ListPanel::getConfig()
*/
public function getConfig()
{
$config = parent::getConfig();
// Remove some props not used in this list panel
unset($config['description']);
unset($config['expanded']);
unset($config['headingLevel']);
$config = array_merge(
$config,
[
'canEditPublication' => $this->canEditPublication,
'publicationApiUrlFormat' => $this->getPublicationUrlFormat(),
'form' => $this->getLocalizedForm(),
'items' => $this->items,
'i18nAddContributor' => __('grid.action.addContributor'),
'i18nConfirmDelete' => __('grid.action.deleteContributor.confirmationMessage'),
'i18nDeleteContributor' => __('grid.action.deleteContributor'),
'i18nEditContributor' => __('grid.action.edit'),
'i18nSetPrimaryContact' => __('author.users.contributor.setPrincipalContact'),
'i18nPrimaryContact' => __('author.users.contributor.principalContact'),
'i18nContributors' => __('submission.contributors'),
'i18nSaveOrder' => __('grid.action.saveOrdering'),
'i18nPreview' => __('contributor.listPanel.preview'),
'i18nPreviewDescription' => __('contributor.listPanel.preview.description'),
'i18nDisplay' => __('contributor.listPanel.preview.display'),
'i18nFormat' => __('contributor.listPanel.preview.format'),
'i18nAbbreviated' => __('contributor.listPanel.preview.abbreviated'),
'i18nPublicationLists' => __('contributor.listPanel.preview.publicationLists'),
'i18nFull' => __('contributor.listPanel.preview.full'),
]
);
return $config;
}
/**
* Get an example of the url to a publication's API endpoint,
* with a placeholder instead of the publication id, eg:
*
* http://example.org/api/v1/submissions/1/publications/__publicationId__
*/
protected function getPublicationUrlFormat(): string
{
return Application::get()->getRequest()->getDispatcher()->url(
Application::get()->getRequest(),
Application::ROUTE_API,
$this->context->getPath(),
'submissions/' . $this->submission->getId() . '/publications/__publicationId__'
);
}
/**
* Get the form data localized to the submission's locale
*/
protected function getLocalizedForm(): array
{
uksort($this->locales, fn ($a, $b) => $a === $this->submission->getData('locale') ? -1 : 1);
$apiUrl = Application::get()->getRequest()->getDispatcher()->url(
Application::get()->getRequest(),
Application::ROUTE_API,
$this->context->getPath(),
'submissions/' . $this->submission->getId() . '/publications/__publicationId__/contributors'
);
$form = $this->getForm($apiUrl);
$data = $form->getConfig();
$data['primaryLocale'] = $this->submission->getData('locale');
$data['visibleLocales'] = [$this->submission->getData('locale')];
return $data;
}
/**
* Get the contributor form
*/
protected function getForm(string $url): ContributorForm
{
return new ContributorForm(
$url,
$this->locales,
$this->submission,
$this->context
);
}
}
@@ -0,0 +1,53 @@
<?php
/**
* @file classes/components/listPanels/HighlightsListPanel.php
*
* Copyright (c) 2023 Simon Fraser University
* Copyright (c) 2023 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class HighlightsListPanel
*
* @ingroup classes_components_list
*
* @brief A ListPanel component for viewing and editing institutions
*/
namespace PKP\components\listPanels;
use PKP\components\forms\highlight\HighlightForm;
class HighlightsListPanel extends ListPanel
{
/** URL to the API endpoint where items can be retrieved */
public string $apiUrl = '';
/** Form for adding or editing a highlight */
public ?HighlightForm $form = null;
/** Query parameters to pass if this list executes GET requests */
public array $getParams = [];
/** Max number of items available to display in this list panel */
public int $itemsMax = 0;
public function getConfig(): array
{
$config = parent::getConfig();
$config = array_merge(
$config,
[
'apiUrl' => $this->apiUrl,
'form' => $this->form?->getConfig(),
'getParams' => $this->getParams,
'i18nAdd' => __('manager.highlights.add'),
'i18nConfirmDelete' => __('manager.highlights.confirmDelete'),
'i18nDelete' => __('manager.highlights.delete'),
'i18nEdit' => __('manager.highlights.edit'),
'i18nSaveOrder' => __('grid.action.saveOrdering'),
'itemsMax' => $this->itemsMax
]
);
return $config;
}
}
@@ -0,0 +1,103 @@
<?php
/**
* @file components/listPanels/ListPanel.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2000-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class ListPanel
*
* @ingroup classes_components_list
*
* @brief A base class for ListPanel components.
*/
namespace PKP\components\listPanels;
class ListPanel
{
/** @var string An optional description to add beneath the title */
public $description = '';
/** @var string An optional message to display when no items are in the list */
public $emptyLabel = '';
/** @var array Array of item ids that should be expanded on initial load */
public $expanded = [];
/** @var string The appropriate heading level for this component */
public $headingLevel = 'h2';
/** @var bool Should the sidebar be visible on initial load? */
public $isSidebarVisible = false;
/** @var string An ID for this component */
public $id = '';
/** @var array Items to display in the list */
public $items = [];
/** @var string Title (expects a translation key) */
public $title = '';
/**
* Initialize the form with config parameters
*
* @param string $id
* @param string $title
* @param array $args Configuration params
*/
public function __construct($id, $title, $args = [])
{
$this->id = $id;
$this->title = $title;
$this->set($args);
}
/**
* Set configuration data for the component
*
* @param array $args Configuration params
*
*/
public function set($args)
{
foreach ($args as $prop => $value) {
if (property_exists($this, $prop)) {
$this->{$prop} = $value;
}
}
return $this;
}
/**
* Convert the object into an assoc array ready to be json_encoded
* and passed to the UI component
*
* @return array Configuration data
*/
public function getConfig()
{
$config = [
'description' => $this->description,
'expanded' => $this->expanded,
'headingLevel' => $this->headingLevel,
'id' => $this->id,
'isSidebarVisible' => $this->isSidebarVisible,
'items' => $this->items,
'title' => $this->title,
];
if (strlen($this->emptyLabel)) {
$config['emptyLabel'] = $this->emptyLabel;
}
if (!empty($this->getParams)) {
$config['getParams'] = $this->getParams;
}
return $config;
}
}
@@ -0,0 +1,51 @@
<?php
/**
* @file classes/components/listPanels/PKPAnnouncementsListPanel.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2000-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PKPAnnouncementsListPanel
*
* @ingroup classes_components_list
*
* @brief A ListPanel component for viewing and editing email templates
*/
namespace PKP\components\listPanels;
class PKPAnnouncementsListPanel extends ListPanel
{
/** @var string URL to the API endpoint where items can be retrieved */
public $apiUrl = '';
/** @var int How many items to display on one page in this list */
public $count = 30;
/** @param \PKP\components\forms\announcement\PKPAnnouncementForm Form for adding or editing an email template */
public $form = null;
/** @var array Query parameters to pass if this list executes GET requests */
public $getParams = [];
/** @var int Max number of items available to display in this list panel */
public $itemsMax = 0;
/**
* @copydoc ListPanel::getConfig()
*/
public function getConfig()
{
return parent::getConfig() + [
'addAnnouncementLabel' => __('grid.action.addAnnouncement'),
'apiUrl' => $this->apiUrl,
'confirmDeleteMessage' => __('manager.announcements.confirmDelete'),
'count' => $this->count,
'deleteAnnouncementLabel' => __('manager.announcements.deleteAnnouncement'),
'editAnnouncementLabel' => __('manager.announcements.edit'),
'form' => $this->form->getConfig(),
'itemsMax' => $this->itemsMax,
];
}
}
@@ -0,0 +1,53 @@
<?php
/**
* @file classes/components/listPanels/PKPCounterReportsListPanel.php
*
* Copyright (c) 2024 Simon Fraser University
* Copyright (c) 2024 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PKPCounterReportsListPanel
*
* @ingroup classes_components_list
*
* @brief A ListPanel component for viewing, editing and downloading COUNTER R5 reports
*/
namespace PKP\components\listPanels;
use APP\components\forms\counter\CounterReportForm;
use PKP\sushi\CounterR5Report;
class PKPCounterReportsListPanel extends ListPanel
{
/** URL to the API endpoint where items can be retrieved */
public string $apiUrl = '';
/** Form for setting up and downloading a report*/
public ?CounterReportForm $form = null;
/** Query parameters to pass if this list executes GET requests */
public array $getParams = [];
/**
* @copydoc ListPanel::getConfig()
*/
public function getConfig(): array
{
$config = parent::getConfig();
$earliestDate = CounterR5Report::getEarliestDate();
$lastDate = CounterR5Report::getLastDate();
$config = array_merge(
$config,
[
'apiUrl' => $this->apiUrl,
'editCounterReportLabel' => __('manager.statistics.counterR5Report.settings'),
'form' => $this->form->getConfig(),
'usagePossible' => $lastDate > $earliestDate,
]
);
return $config;
}
}
@@ -0,0 +1,225 @@
<?php
/**
* @file classes/components/listPanels/PKPDoiListPanel.php
*
* Copyright (c) 2014-2020 Simon Fraser University
* Copyright (c) 2000-2020 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PKPDoiListPanel
*
* @ingroup classes_components_list
*
* @brief A ListPanel component for viewing and editing DOIs
*/
namespace PKP\components\listPanels;
use APP\core\Application;
use APP\template\TemplateManager;
use PKP\doi\Doi;
use PKP\plugins\Hook;
use PKP\submission\PKPSubmission;
abstract class PKPDoiListPanel extends ListPanel
{
/** @var string URL to the API endpoint where items can be retrieved */
public $apiUrl = '';
/** @var int How many items to display on one page in this list */
public $count = 30;
/** @var array Query parameters to pass if this list executes GET requests */
public $getParams = [];
/** @var int Max number of items available to display in this list panel */
public $itemsMax = 0;
/** @var boolean Should items be loaded after the component is mounted? */
public $lazyLoad = false;
/** @var string DOI prefix set in DOI settings */
public $doiPrefix = '';
public ?\stdClass $registrationAgencyInfo = null;
/** @var array Which publishing objects have DOIs enabled */
public array $enabledDoiTypes = [];
/** @var bool Whether to include a DOI per publication version */
public bool $versionDois = false;
/** @var string DOI API url for handling DOI operations */
public $doiApiUrl = '';
/** @var string PubObject type, e.g. 'submission' */
public string $itemType = '';
/**
* Convert the object into an assoc array ready to be json_encoded
* and passed to the UI component
*
* @return array Configuration data
*/
public function getConfig()
{
$config = parent::getConfig();
$config['apiUrl'] = $this->apiUrl;
$config['doiApiUrl'] = $this->doiApiUrl;
$config['count'] = $this->count;
$config['lazyLoad'] = $this->lazyLoad;
$config['itemsMax'] = $this->itemsMax;
$config['itemType'] = $this->itemType;
$config['enabledDoiTypes'] = $this->enabledDoiTypes;
$config['versionDois'] = $this->versionDois;
$config['registrationAgencyInfo'] = $this->registrationAgencyInfo;
$config['doiPrefix'] = $this->doiPrefix;
$config['filters'][] = [
'heading' => __('common.status'),
'filters' => [
[
'title' => __('manager.dois.status.needsDoi'),
'param' => 'hasDois',
'value' => '0'
],
[
'title' => __('manager.dois.filters.doiAssigned'),
'param' => 'hasDois',
'value' => '1',
],
],
];
$config['filters'][] = [
'heading' => __('manager.setup.dois.registration'),
'filters' => [
[
'title' => __('manager.dois.status.unregistered'),
'param' => 'unregistered',
'value' => 'true'
],
[
'title' => __('manager.dois.status.submitted'),
'param' => 'doiStatus',
'value' => Doi::STATUS_SUBMITTED
],
[
'title' => __('manager.dois.status.registered'),
'param' => 'doiStatus',
'value' => Doi::STATUS_REGISTERED
],
[
'title' => __('manager.dois.status.error.filterTitle'),
'param' => 'doiStatus',
'value' => Doi::STATUS_ERROR
],
[
'title' => __('manager.dois.status.stale'),
'param' => 'doiStatus',
'value' => Doi::STATUS_STALE
],
],
];
$config['publishedStatuses'] = [
'name' => 'status',
'published' => [PKPSubmission::STATUS_PUBLISHED],
'unpublished' => [PKPSubmission::STATUS_QUEUED, PKPSubmission::STATUS_SCHEDULED],
];
// Provide required locale keys
$request = Application::get()->getRequest();
$templateMgr = TemplateManager::getManager($request);
$templateMgr->setConstants([
'DOI_STATUS_SUBMITTED' => Doi::STATUS_SUBMITTED,
'DOI_STATUS_UNREGISTERED' => Doi::STATUS_UNREGISTERED,
'DOI_STATUS_REGISTERED' => Doi::STATUS_REGISTERED,
'DOI_STATUS_ERROR' => Doi::STATUS_ERROR,
'DOI_STATUS_STALE' => Doi::STATUS_STALE,
]);
$templateMgr->setLocaleKeys([
'publication.status.unpublished',
'publication.status.published',
'manager.dois.actions.deposit.label',
'manager.dois.actions.deposit.prompt',
'manager.dois.actions.markRegistered.label',
'manager.dois.actions.markRegistered.prompt',
'manager.dois.actions.markUnregistered.label',
'manager.dois.actions.markUnregistered.prompt',
'manager.dois.actions.markStale.label',
'manager.dois.actions.markStale.prompt',
'manager.dois.actions.export.label',
'manager.dois.actions.export.prompt',
'manager.dois.actions.assign.label',
'manager.dois.actions.assign.prompt',
'manager.dois.notification.exportSuccess',
'manager.dois.notification.markRegisteredSuccess',
'manager.dois.notification.markUnregisteredSuccess',
'manager.dois.notification.markStaleSuccess',
'manager.dois.registration.submittedDescription',
'manager.dois.registration.notSubmittedDescription',
'manager.dois.registration.viewError',
'manager.dois.registration.viewError.title',
'manager.dois.registration.viewRecord',
'manager.dois.registration.viewRecord.title',
'manager.dois.publicationStatus',
'manager.dois.registration.depositDois',
'manager.dois.status.needsDoi',
'manager.dois.status.unregistered',
'manager.dois.status.submitted',
'manager.dois.status.registered',
'manager.dois.status.error',
'manager.dois.status.stale',
'manager.dois.notification.assignDoisSuccess',
'manager.dois.notification.depositQueuedSuccess',
'manager.dois.actions.depositAll.label',
'manager.dois.actions.depositAll.prompt',
'manager.dois.registration.notPublishedDescription',
'manager.dois.update.partialFailure',
'manager.dois.actions.deposit.all',
'manager.dois.update.success',
'common.selectAll',
'common.selectNone',
'common.edit',
'common.save',
'common.type',
'common.status',
'common.description',
'list.expandAll',
'list.collapseAll',
'manager.dois.update.failedCreation',
'plugins.importexport.common.action.export',
'manager.dois.actions.description',
'manager.dois.title',
'manager.dois.actions.bulkActions',
'publication.version',
'doi.manager.versions.countStatement',
'doi.manager.versions.view',
'doi.manager.versions.modalTitle',
'manager.dois.help.statuses.title',
'manager.dois.status.needsDoi.description',
'manager.dois.status.unregistered.description',
'manager.dois.status.submitted.description',
'manager.dois.status.registered.description',
'manager.dois.status.error.description',
'manager.dois.status.stale.description',
'manager.dois.registration.manuallyMarkedRegistered',
'manager.dois.filters.doiAssigned',
'manager.dois.filters.doiAssigned.description',
'manager.dois.status.error.filterTitle',
]);
$this->setAppConfig($config);
Hook::call('DoiListPanel::setConfig', [&$config]);
// Check added here in case hook adds additional getParams
$config['getParams'] = empty($config['getParams']) ? new \stdClass() : $config['getParams'];
return $config;
}
/**
* Add any application-specific config to the list panel setup
*/
abstract protected function setAppConfig(array &$config): void;
}
@@ -0,0 +1,58 @@
<?php
/**
* @file classes/components/listPanels/PKPInstitutionsListPanel.php
*
* Copyright (c) 2022 Simon Fraser University
* Copyright (c) 2022 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PKPInstitutionsListPanel
*
* @ingroup classes_components_list
*
* @brief A ListPanel component for viewing and editing institutions
*/
namespace PKP\components\listPanels;
use PKP\components\forms\institution\PKPInstitutionForm;
class PKPInstitutionsListPanel extends ListPanel
{
/** URL to the API endpoint where items can be retrieved */
public string $apiUrl = '';
/** How many items to display on one page in this list */
public int $count = 30;
/** Form for adding or editing an institution */
public ?PKPInstitutionForm $form = null;
/**Query parameters to pass if this list executes GET requests */
public array $getParams = [];
/** Max number of items available to display in this list panel */
public int $itemsMax = 0;
/**
* @copydoc ListPanel::getConfig()
*/
public function getConfig(): array
{
$config = parent::getConfig();
$config = array_merge(
$config,
[
'addInstitutionLabel' => __('grid.action.addInstitution'),
'apiUrl' => $this->apiUrl,
'confirmDeleteMessage' => __('manager.institutions.confirmDelete'),
'count' => $this->count,
'deleteInstitutionLabel' => __('manager.institutions.deleteInstitution'),
'editInstitutionLabel' => __('manager.institutions.edit'),
'form' => $this->form->getConfig(),
'itemsMax' => $this->itemsMax
]
);
return $config;
}
}
@@ -0,0 +1,201 @@
<?php
/**
* @file components/listPanels/PKPSelectReviewerListPanel.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2000-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PKPSelectReviewerListPanel
*
* @ingroup classes_controllers_list
*
* @brief A class for loading a panel to select a reviewer.
*/
namespace PKP\components\listPanels;
use APP\facades\Repo;
use Illuminate\Support\Enumerable;
use PKP\user\Collector;
class PKPSelectReviewerListPanel extends ListPanel
{
/** @var string URL to the API endpoint where items can be retrieved */
public $apiUrl = '';
/** @var int Number of items to show at one time */
public $count = 30;
/** @var array List of user IDs already assigned as a reviewer to this review round */
public $currentlyAssigned = [];
/** @var array Query parameters to pass if this list executes GET requests */
public $getParams = [];
/** @var int Count of total items available for list */
public $itemsMax = 0;
/** @var string Name of the input field*/
public $selectorName = '';
/** @var array List of user IDs which may not be suitable for anonymous review because of existing access to author details */
public $warnOnAssignment = [];
/** @var Enumerable List of users who completed a review in the last round */
public Enumerable $lastRoundReviewers;
/**
* @copydoc ListPanel::set()
*/
public function set($args)
{
parent::set($args);
$this->currentlyAssigned = !empty($args['currentlyAssigned']) ? $args['currentlyAssigned'] : $this->currentlyAssigned;
$this->warnOnAssignment = !empty($args['warnOnAssignment']) ? $args['warnOnAssignment'] : $this->warnOnAssignment;
}
/**
* @copydoc ListPanel::getConfig()
*/
public function getConfig()
{
$config = parent::getConfig();
$config['apiUrl'] = $this->apiUrl;
$config['count'] = $this->count;
$config['currentlyAssigned'] = $this->currentlyAssigned;
$config['selectorName'] = $this->selectorName;
$config['warnOnAssignment'] = $this->warnOnAssignment;
$config['filters'] = [
[
'param' => 'reviewerRating',
'title' => __('reviewer.list.filterRating'),
'value' => 3,
'min' => 1,
'max' => 5,
'useStars' => true,
'valueLabel' => '{$value/5}',
],
[
'param' => 'reviewsCompleted',
'title' => __('reviewer.list.completedReviews'),
'value' => 10,
'min' => 0,
'max' => 20,
'valueLabel' => __('common.moreThan'),
],
[
'param' => 'daysSinceLastAssignment',
'title' => __('reviewer.list.daysSinceLastAssignmentDescription'),
'value' => [0, 365],
'min' => 0,
'max' => 365,
'filterType' => 'filter-slider-multirange',
'valueLabel' => __('common.range'),
'moreThanLabel' => __('common.moreThanOnly'),
'lessThanLabel' => __('common.lessThanOnly'),
],
[
'param' => 'reviewsActive',
'title' => __('reviewer.list.activeReviewsDescription'),
'value' => [0, 20],
'min' => 0,
'max' => 20,
'filterType' => 'filter-slider-multirange',
'valueLabel' => __('common.range'),
'moreThanLabel' => __('common.moreThanOnly'),
'lessThanLabel' => __('common.lessThanOnly'),
],
[
'param' => 'averageCompletion',
'title' => __('reviewer.list.averageCompletion'),
'value' => 75,
'min' => 0,
'max' => 75,
'valueLabel' => __('common.lessThan'),
],
];
if (!empty($this->lastRoundReviewers)) {
$config['lastRoundReviewers'] = Repo::user()
->getSchemaMap()
->summarizeManyReviewers($this->lastRoundReviewers)
->values()
->toArray();
}
if (!empty($this->getParams)) {
$config['getParams'] = $this->getParams;
}
$config['itemsMax'] = $this->itemsMax;
$config['activeReviewsCountLabel'] = __('reviewer.list.activeReviews');
$config['activeReviewsLabel'] = __('reviewer.list.activeReviewsDescription');
$config['assignedToLastRoundLabel'] = __('reviewer.list.assignedToLastRound');
$config['averageCompletionLabel'] = __('reviewer.list.averageCompletion');
$config['biographyLabel'] = __('reviewer.list.biography');
$config['cancelledReviewsLabel'] = __('reviewer.list.cancelledReviews');
$config['completedReviewsLabel'] = __('reviewer.list.completedReviews');
$config['currentlyAssignedLabel'] = __('reviewer.list.currentlyAssigned');
$config['daySinceLastAssignmentLabel'] = __('reviewer.list.daySinceLastAssignment');
$config['daysSinceLastAssignmentLabel'] = __('reviewer.list.daysSinceLastAssignment');
$config['daysSinceLastAssignmentDescriptionLabel'] = __('reviewer.list.daysSinceLastAssignmentDescription');
$config['declinedReviewsLabel'] = __('reviewer.list.declinedReviews');
$config['emptyLabel'] = __('reviewer.list.empty');
$config['gossipLabel'] = __('user.gossip');
$config['neverAssignedLabel'] = __('reviewer.list.neverAssigned');
$config['reassignLabel'] = __('reviewer.list.reassign');
$config['reassignWithNameLabel'] = __('reviewer.list.reassign.withName');
$config['reviewerRatingLabel'] = __('reviewer.list.reviewerRating');
$config['reviewInterestsLabel'] = __('reviewer.list.reviewInterests');
$config['selectReviewerLabel'] = __('editor.submission.selectReviewer');
$config['warnOnAssignmentLabel'] = __('reviewer.list.warnOnAssign');
$config['warnOnAssignmentUnlockLabel'] = __('reviewer.list.warnOnAssignUnlock');
return $config;
}
/**
* Helper method to get the items property according to the self::$getParams
*
* @param \APP\core\Request $request
*
* @return array
*/
public function getItems($request)
{
$reviewers = $this->_getCollector()->getMany();
$items = [];
$map = Repo::user()->getSchemaMap();
foreach ($reviewers as $reviewer) {
$items[] = $map->summarizeReviewer($reviewer);
}
return $items;
}
/**
* Helper method to get the itemsMax property according to self::$getParams
*
* @return int
*/
public function getItemsMax()
{
return $this->_getCollector()->offset(null)->limit(null)->getCount();
}
/**
* Helper method to compile initial params to get items
*/
protected function _getCollector(): Collector
{
return Repo::user()->getCollector()
->filterByContextIds([$this->getParams['contextId']])
->filterByWorkflowStageIds([$this->getParams['reviewStage']])
->filterByRoleIds([\PKP\security\Role::ROLE_ID_REVIEWER])
->includeReviewerData()
->offset(null)
->limit($this->count);
}
}
@@ -0,0 +1,288 @@
<?php
/**
* @file components/listPanels/PKPSubmissionsListPanel.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2000-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PKPSubmissionsListPanel
*
* @ingroup classes_components_list
*
* @brief A ListPanel component for displaying submissions in the dashboard
*/
namespace PKP\components\listPanels;
use APP\core\Application;
use APP\facades\Repo;
use APP\template\TemplateManager;
use PKP\components\forms\FieldAutosuggestPreset;
use PKP\components\forms\FieldSelectUsers;
use PKP\security\Role;
use PKP\submission\PKPSubmission;
use PKP\submission\reviewAssignment\ReviewAssignment;
use PKP\submission\reviewRound\ReviewRound;
abstract class PKPSubmissionsListPanel extends ListPanel
{
/** @var string URL to the API endpoint where items can be retrieved */
public $apiUrl = '';
/** @var int Number of items to show at one time */
public $count = 30;
/** @var array Query parameters to pass if this list executes GET requests */
public $getParams = [];
/** @var bool Should items be loaded after the component is mounted? */
public $lazyLoad = false;
/** @var int Count of total items available for list */
public $itemsMax = 0;
/** @var bool Whether to show assigned to editors filter */
public $includeAssignedEditorsFilter = false;
/** @var bool Whether to show categories filter */
public $includeCategoriesFilter = false;
/** @var array List of all available categories */
public $categories = [];
/**
* @copydoc ListPanel::getConfig()
*/
public function getConfig()
{
$request = Application::get()->getRequest();
$context = $request->getContext();
$config = parent::getConfig();
$config['apiUrl'] = $this->apiUrl;
$config['count'] = $this->count;
$config['getParams'] = $this->getParams;
$config['lazyLoad'] = $this->lazyLoad;
$config['itemsMax'] = $this->itemsMax;
// URL to add a new submission
if ($context->getData('disableSubmissions')) {
$config['allowSubmissions'] = false;
}
$config['addUrl'] = $request->getDispatcher()->url(
$request,
Application::ROUTE_PAGE,
null,
'submission'
);
// URL to view info center for a submission
$config['infoUrl'] = $request->getDispatcher()->url(
$request,
Application::ROUTE_COMPONENT,
null,
'informationCenter.SubmissionInformationCenterHandler',
'viewInformationCenter',
null,
['submissionId' => '__id__']
);
// URL to assign a participant
$config['assignParticipantUrl'] = $request->getDispatcher()->url(
$request,
Application::ROUTE_COMPONENT,
null,
'grid.users.stageParticipant.StageParticipantGridHandler',
'addParticipant',
null,
['submissionId' => '__id__', 'stageId' => '__stageId__']
);
$config['filters'] = [
[
'filters' => [
[
'param' => 'isOverdue',
'value' => true,
'title' => __('common.overdue'),
],
[
'param' => 'isIncomplete',
'value' => true,
'title' => __('submissions.incomplete'),
],
],
],
[
'heading' => __('settings.roles.stages'),
'filters' => $this->getWorkflowStages(),
],
[
'heading' => __('submission.list.activity'),
'filters' => [
[
'title' => __('submission.list.daysSinceLastActivity'),
'param' => 'daysInactive',
'value' => 30,
'min' => 1,
'max' => 180,
'filterType' => 'pkp-filter-slider',
]
]
]
];
if ($this->includeCategoriesFilter) {
$categoryFilter = [];
$categoryFilter = $this->getCategoryFilters($this->categories);
if ($categoryFilter) {
$config['filters'][] = $categoryFilter;
}
}
if ($this->includeAssignedEditorsFilter) {
$assignedEditorsField = new FieldSelectUsers('assignedTo', [
'label' => __('editor.submissions.assignedTo'),
'value' => [],
'apiUrl' => $request->getDispatcher()->url(
$request,
Application::ROUTE_API,
$context->getPath(),
'users',
null,
null,
['roleIds' => [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR]]
),
]);
$config['filters'][] = [
'filters' => [
[
'title' => __('editor.submissions.assignedTo'),
'param' => 'assignedTo',
'value' => [],
'filterType' => 'pkp-filter-autosuggest',
'component' => $assignedEditorsField->component,
'autosuggestProps' => $assignedEditorsField->getConfig(),
]
]
];
}
// Provide required constants
$templateMgr = TemplateManager::getManager($request);
$templateMgr->setConstants([
'STATUS_QUEUED' => PKPSubmission::STATUS_QUEUED,
'STATUS_PUBLISHED' => PKPSubmission::STATUS_PUBLISHED,
'STATUS_DECLINED' => PKPSubmission::STATUS_DECLINED,
'STATUS_SCHEDULED' => PKPSubmission::STATUS_SCHEDULED,
'WORKFLOW_STAGE_ID_SUBMISSION' => WORKFLOW_STAGE_ID_SUBMISSION,
'WORKFLOW_STAGE_ID_INTERNAL_REVIEW' => WORKFLOW_STAGE_ID_INTERNAL_REVIEW,
'WORKFLOW_STAGE_ID_EXTERNAL_REVIEW' => WORKFLOW_STAGE_ID_EXTERNAL_REVIEW,
'WORKFLOW_STAGE_ID_EDITING' => WORKFLOW_STAGE_ID_EDITING,
'WORKFLOW_STAGE_ID_PRODUCTION' => WORKFLOW_STAGE_ID_PRODUCTION,
'STAGE_STATUS_SUBMISSION_UNASSIGNED' => Repo::submission()::STAGE_STATUS_SUBMISSION_UNASSIGNED,
'REVIEW_ROUND_STATUS_PENDING_REVIEWERS' => ReviewRound::REVIEW_ROUND_STATUS_PENDING_REVIEWERS,
'REVIEW_ROUND_STATUS_REVIEWS_READY' => ReviewRound::REVIEW_ROUND_STATUS_REVIEWS_READY,
'REVIEW_ROUND_STATUS_REVIEWS_COMPLETED' => ReviewRound::REVIEW_ROUND_STATUS_REVIEWS_COMPLETED,
'REVIEW_ROUND_STATUS_REVIEWS_OVERDUE' => ReviewRound::REVIEW_ROUND_STATUS_REVIEWS_OVERDUE,
'REVIEW_ROUND_STATUS_REVISIONS_REQUESTED' => ReviewRound::REVIEW_ROUND_STATUS_REVISIONS_REQUESTED,
'REVIEW_ROUND_STATUS_REVISIONS_SUBMITTED' => ReviewRound::REVIEW_ROUND_STATUS_REVISIONS_SUBMITTED,
'REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW' => ReviewRound::REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW,
'REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW_SUBMITTED' => ReviewRound::REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW_SUBMITTED,
'REVIEW_ASSIGNMENT_STATUS_AWAITING_RESPONSE' => ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_AWAITING_RESPONSE,
'REVIEW_ASSIGNMENT_STATUS_RESPONSE_OVERDUE' => ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_RESPONSE_OVERDUE,
'REVIEW_ASSIGNMENT_STATUS_REVIEW_OVERDUE' => ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_REVIEW_OVERDUE,
'REVIEW_ASSIGNMENT_STATUS_ACCEPTED' => ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_ACCEPTED,
'REVIEW_ASSIGNMENT_STATUS_RECEIVED' => ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_RECEIVED,
'REVIEW_ASSIGNMENT_STATUS_COMPLETE' => ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_COMPLETE,
'REVIEW_ASSIGNMENT_STATUS_THANKED' => ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_THANKED,
'REVIEW_ASSIGNMENT_STATUS_CANCELLED' => ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_CANCELLED,
'REVIEW_ASSIGNMENT_STATUS_REQUEST_RESEND' => ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_REQUEST_RESEND,
'REVIEW_ROUND_STATUS_RECOMMENDATIONS_READY' => ReviewRound::REVIEW_ROUND_STATUS_RECOMMENDATIONS_READY,
'REVIEW_ROUND_STATUS_RECOMMENDATIONS_COMPLETED' => ReviewRound::REVIEW_ROUND_STATUS_RECOMMENDATIONS_COMPLETED,
]);
$templateMgr->setLocaleKeys([
'common.lastActivity',
'editor.submissionArchive.confirmDelete',
'submission.list.empty',
'submission.submit.newSubmissionSingle',
'submission.review',
'submissions.incomplete',
'submission.list.assignEditor',
'submission.list.copyeditsSubmitted',
'submission.list.currentStage',
'submission.list.discussions',
'submission.list.dualWorkflowLinks',
'submission.list.galleysCreated',
'submission.list.infoCenter',
'submission.list.reviewAssignment',
'submission.list.responseDue',
'submission.list.reviewCancelled',
'submission.list.reviewComplete',
'submission.list.reviewDue',
'submission.list.reviewerWorkflowLink',
'submission.list.reviewsCompleted',
'submission.list.revisionsSubmitted',
'submission.list.viewSubmission',
]);
return $config;
}
/**
* Compile the categories for passing as filters
*
* @param array $categories
*
* @return array
*/
public function getCategoryFilters($categories = [])
{
$request = Application::get()->getRequest();
if ($categories) {
// Use an autosuggest field if the list of categories is too long
if (count($categories) > 5) {
$autosuggestField = new FieldAutosuggestPreset('categoryIds', [
'label' => __('category.category'),
'value' => [],
'options' => array_map(function ($category) {
return [
'value' => (int) $category['id'],
'label' => $category['title'],
];
}, $categories),
]);
return [
'filters' => [
[
'title' => __('category.category'),
'param' => 'categoryIds',
'filterType' => 'pkp-filter-autosuggest',
'component' => 'field-autosuggest-preset',
'value' => [],
'autosuggestProps' => $autosuggestField->getConfig(),
]
],
];
}
return [
'heading' => __('category.category'),
'filters' => array_map(function ($category) {
return [
'param' => 'categoryIds',
'value' => (int) $category['id'],
'title' => $category['title'],
];
}, $categories),
];
}
return [];
}
}