diff --git a/QuickSubmitForm.php b/QuickSubmitForm.php index 60aeb4f..1d86d50 100644 --- a/QuickSubmitForm.php +++ b/QuickSubmitForm.php @@ -17,6 +17,7 @@ use APP\core\Application; use APP\facades\Repo; use APP\journal\Journal; +use APP\issue\enums\IssueSelection; use APP\plugins\importexport\quickSubmit\classes\form\SubmissionMetadataForm; use APP\publication\Publication; use APP\submission\Submission; @@ -27,7 +28,6 @@ use PKP\core\Core; use PKP\core\PKPRequest; use PKP\core\PKPString; -use PKP\db\DAORegistry; use PKP\facades\Locale; use PKP\form\Form; use PKP\form\validation\FormValidatorUrl; @@ -259,17 +259,34 @@ public function validate($callHooks = true) } // Validate Issue if Published is selected - // if articleStatus == 1 => should have issueId + // if articleStatus set to 1, it can be issue as continuous publication + // or have valid issue selected if ($this->getData('articleStatus') == 1) { - if ($this->getData('issueId') <= 0) { - $this->addError('issueId', __('plugins.importexport.quickSubmit.selectIssue')); + if (in_array($this->getData('issueId'), IssueSelection::unselectableOptionsValue())) { + $this->addError('issueId', __('publication.invalidIssue')); $this->errorFields['issueId'] = 1; + } + + $futureIssueIds = Repo::issue() + ->getCollector() + ->filterByContextIds([$this->_submission->getData('contextId')]) + ->filterByPublished(false) + ->getIds() + ->toArray(); + + // if issue is future issue and published is not selected, + // we don't need to validate datePublished + if (in_array((int) $this->getData('issueId'), $futureIssueIds) && !$this->getData('published')) { + return $this->isValid(); + } - return false; + if (!$this->getData('datePublished')) { + $this->addError('datePublished', __('validator.required')); + $this->errorFields['datePublished'] = 1; } } - return true; + return $this->isValid(); } /** @@ -373,7 +390,8 @@ public function readInputData() 'sectionId', 'submissionId', 'articleStatus', - 'locale' + 'locale', + 'published', ]); } @@ -443,13 +461,20 @@ public function execute(...$functionParams) } if ($this->getData('articleStatus') == 1) { + + $publication->setData('published', $this->getData('published') ?? false); $publication->setData('copyrightYear', $this->getData('copyrightYear')); $publication->setData('copyrightHolder', $this->getData('copyrightHolder'), null); $publication->setData('licenseUrl', $this->getData('licenseUrl')); $publication->setData('pages', $this->getData('pages')); - $publication->setData('datePublished', $this->getData('datePublished')); + $publication->setData('datePublished', $this->getData('datePublished') ?? null); $publication->setData('accessStatus', Submission::ARTICLE_ACCESS_ISSUE_DEFAULT); - $publication->setData('issueId', (int) $this->getData('issueId')); + $publication->setData( + 'issueId', + (int) $this->getData('issueId') === IssueSelection::NO_ISSUE->value + ? null + : (int) $this->getData('issueId') + ); // If other articles in this issue have a custom sequence, put this at the end $otherSubmissionsInSection = Repo::submission() @@ -489,10 +514,16 @@ public function execute(...$functionParams) public function getIssueOptions(Journal $journal): array { $issuesPublicationDates = []; + $issuesPublicationDates[IssueSelection::NO_ISSUE->value] = date( + PKPString::convertStrftimeFormat(Config::getVar('general', 'date_format_short')), + strtotime(Core::getCurrentDate()) + ); + + $futureIssues = []; $issueOptions = []; $journalId = $journal->getId(); - - $issueOptions[-1] = '------ ' . __('editor.issues.futureIssues') . ' ------'; + $issueOptions[IssueSelection::NO_ISSUE->value] = IssueSelection::NO_ISSUE->getLabel(); + $issueOptions[IssueSelection::FUTURE_ISSUES->value] = IssueSelection::FUTURE_ISSUES->getLabel(); $issues = Repo::issue() ->getCollector() ->filterByContextIds([$journalId]) @@ -501,10 +532,11 @@ public function getIssueOptions(Journal $journal): array ->getMany(); foreach ($issues as $issue) { + $futureIssues[] = $issue->getId(); $issueOptions[$issue->getId()] = $issue->getIssueIdentification(); $issuesPublicationDates[$issue->getId()] = date(PKPString::convertStrftimeFormat(Config::getVar('general', 'date_format_short')), strtotime(Core::getCurrentDate())); } - $issueOptions[-2] = '------ ' . __('editor.issues.currentIssue') . ' ------'; + $issueOptions[IssueSelection::CURRENT_ISSUE->value] = IssueSelection::CURRENT_ISSUE->getLabel(); $issues = array_values( Repo::issue() ->getCollector() @@ -520,7 +552,7 @@ public function getIssueOptions(Journal $journal): array $issuesPublicationDates[$issues[0]->getId()] = date(PKPString::convertStrftimeFormat(Config::getVar('general', 'date_format_short')), strtotime($issues[0]->getDatePublished())); array_shift($issues); } - $issueOptions[-3] = '------ ' . __('editor.issues.backIssues') . ' ------'; + $issueOptions[IssueSelection::BACK_ISSUES->value] = IssueSelection::BACK_ISSUES->getLabel(); foreach ($issues as $issue) { $issueOptions[$issue->getId()] = $issue->getIssueIdentification(); $issuesPublicationDates[$issue->getId()] = date(PKPString::convertStrftimeFormat(Config::getVar('general', 'date_format_short')), strtotime($issues[0]->getDatePublished())); @@ -528,6 +560,7 @@ public function getIssueOptions(Journal $journal): array $templateMgr = TemplateManager::getManager($this->_request); $templateMgr->assign('issuesPublicationDates', json_encode($issuesPublicationDates)); + $templateMgr->assign('futureIssues', json_encode($futureIssues)); return $issueOptions; } diff --git a/cypress/tests/functional/QuickSubmit.cy.js b/cypress/tests/functional/QuickSubmit.cy.js index 51d24d4..bed7907 100644 --- a/cypress/tests/functional/QuickSubmit.cy.js +++ b/cypress/tests/functional/QuickSubmit.cy.js @@ -37,8 +37,9 @@ describe('Quick Submit plugin tests', function() { // Schedule for publication cy.get('input#articlePublished').click(); cy.get('select#issueId').select('Vol. 1 No. 2 (2014)'); + cy.get('input[id^="datePublished-"]:visible').clear(); cy.get('input[id^="datePublished-"]:visible').type('2020-01-01', {delay: 0}); - cy.get('input[id^="licenseUrl"]').click(); // Take focus out of datepicker + cy.get('input[id^="datePublished-"]:visible').blur(); // Take focus out of datepicker // Add a galley cy.get('a[id^="component-grid-articlegalleys-articlegalleygrid-addGalley-button-"]').click(); diff --git a/js/QuickSubmitFormHandler.js b/js/QuickSubmitFormHandler.js index 10ac057..0e3620e 100644 --- a/js/QuickSubmitFormHandler.js +++ b/js/QuickSubmitFormHandler.js @@ -35,8 +35,11 @@ this.parent($form, options); this.callbackWrapper(this.updateSchedulePublicationDiv_()); + + $('#publishedOption').hide(); + $('#publishedOption').find('input[name="published"]').attr('checked', false); - $('#locale, #sectionId').change(function() { + $('#locale, #sectionId').on('change', function() { // Trick the form not to validate missing data before submitting $('input,textarea,select').filter('[required]').each(function() { $(this).removeAttr('required'); @@ -51,9 +54,11 @@ }); }; + $.pkp.classes.Helper.inherits( - $.pkp.plugins.importexport.quickSubmit.js.QuickSubmitFormHandler, - $.pkp.controllers.form.FormHandler); + $.pkp.plugins.importexport.quickSubmit.js.QuickSubmitFormHandler, + $.pkp.controllers.form.FormHandler + ); /** @@ -64,7 +69,9 @@ $.pkp.plugins.importexport.quickSubmit.js.QuickSubmitFormHandler.prototype. updateSchedulePublicationDiv_ = function() { - $('input[type=radio][name=articleStatus]').change(function() { + var self = this; + + $('input[type=radio][name=articleStatus]').on('change', function() { if ($(this).is(':checked') && this.value == '0') { $('#schedulePublicationDiv').hide(); } else if ($(this).is(':checked') && this.value == '1') { @@ -76,22 +83,57 @@ $('input[type=radio][name=articleStatus]').trigger('change'); - $('#issueId').change(function() { + $('input[name="published"]').on('change', function() { var val, array; val = /** @type {string} */ $('#issuesPublicationDates').val(); array = JSON.parse(val); - if (!array[$('#issueId').val()]) { + if ($(this).is(':checked')) { + self.displayDatePublished_($('#issueId').val(), array); + } else { + $('input[name="datePublished"]').prop('required', false) + $('#schedulingInformationDatePublished').hide(); + } + }); + + $('#issueId').on('change', function() { + $('#publishedOption').find('input[name="published"]').attr('checked', false); + $('#schedulingInformationDatePublished').find('input[name="datePublished"]').prop('required', false); + + var val, array, futureIssues, issueId; + val = /** @type {string} */ $('#issuesPublicationDates').val(); + array = JSON.parse(val); + futureIssues = JSON.parse($('#futureIssues').val()); + issueId = parseInt($('#issueId').val()); + + if (issueId === 0) { + self.displayDatePublished_(issueId, array); + } else if (!array[issueId]) { + $('input[name="datePublished"]').prop('required', false); $('#schedulingInformationDatePublished').hide(); } else { - $('input[name="datePublished"]'). - datepicker('setDate', array[$('#issueId').val()]); - $('#ui-datepicker-div').hide(); - $('#schedulingInformationDatePublished').show(); + if (futureIssues.includes(issueId)) { + $('input[name="datePublished"]').prop('required', false); + $('#schedulingInformationDatePublished').hide(); + } else { + self.displayDatePublished_(issueId, array); + } } + + futureIssues.includes(issueId) + ? $('#publishedOption').show() + : $('#publishedOption').hide(); }); $('#issueId').trigger('change'); }; + $.pkp.plugins.importexport.quickSubmit.js.QuickSubmitFormHandler.prototype.displayDatePublished_ = function(issueId, issuesPublicationDates) { + $('input[name="datePublished"]').prop('required', true); + $('input[name="datePublished"]').datepicker('setDate', issuesPublicationDates[issueId]); + $('input[name="datePublished"]').val(issuesPublicationDates[issueId]); + $('#ui-datepicker-div').hide(); + $('#schedulingInformationDatePublished').show(); + }; + /** @param {jQuery} $ jQuery closure. */ }(jQuery)); diff --git a/templates/index.tpl b/templates/index.tpl index eef2692..54bce0d 100644 --- a/templates/index.tpl +++ b/templates/index.tpl @@ -36,6 +36,9 @@ {if $issuesPublicationDates} {fbvElement type="hidden" id="issuesPublicationDates" value=$issuesPublicationDates} {/if} + {if $futureIssues} + {fbvElement type="hidden" id="futureIssues" value=$futureIssues} + {/if} {csrf} {include file="controllers/notification/inPlaceNotification.tpl" notificationId="quickSubmitFormNotification"} @@ -87,6 +90,12 @@ {/fbvFormSection} {/fbvFormArea} + {fbvFormArea id="publishedOption" title="manager.setup.continuousPublication"} + {fbvFormSection for="published" list="true"} + {fbvElement type="checkbox" name="published" id="published" checked=false label="publication.publish.continuousPublication.label" translate="true"} + {/fbvFormSection} + {/fbvFormArea} + {fbvFormArea id="pagesInformation" title="editor.issues.pages"} {fbvFormSection for="customExtras"} {fbvElement type="text" id="pages" label="editor.issues.pages" value=$pages inline=true size=$fbvStyles.size.MEDIUM}