diff --git a/.github/actions/tests.sh b/.github/actions/tests.sh
index fe3d231..1daf8b2 100755
--- a/.github/actions/tests.sh
+++ b/.github/actions/tests.sh
@@ -2,7 +2,5 @@
set -e
-npx cypress run --spec "cypress/tests/data/10-ApplicationSetup/*.cy.js,cypress/tests/data/60-content/VkarbasizaedSubmission.cy.js"
-
-npx cypress run --config specPattern=plugins/themes/pragma/cypress/tests/functional
-
+echo "Run cypress tests"
+npx cypress run --config '{"specPattern":["plugins/themes/pragma/cypress/tests/functional/*.cy.js"]}'
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 73b586d..aa0d739 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -28,4 +28,4 @@ jobs:
branch: main
repository: pkp
plugin: true
-
+ dataset_inject: true
diff --git a/PragmaThemePlugin.inc.php b/PragmaThemePlugin.inc.php
index 9303acf..a6e84c3 100644
--- a/PragmaThemePlugin.inc.php
+++ b/PragmaThemePlugin.inc.php
@@ -3,8 +3,8 @@
/**
* @file plugins/themes/pragma/PragmaThemePlugin.inc.php
*
- * Copyright (c) 2014-2022 Simon Fraser University
- * Copyright (c) 2003-2022 John Willinsky
+ * Copyright (c) 2014-2025 Simon Fraser University
+ * Copyright (c) 2003-2025 John Willinsky
* Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
*
* @class PragmaThemePlugin
@@ -16,144 +16,150 @@
use APP\facades\Repo;
use APP\issue\Collector;
use APP\services\NavigationMenuService;
+use PKP\config\Config;
+use PKP\navigationMenu\NavigationMenuItem;
use PKP\plugins\ThemePlugin;
-class PragmaThemePlugin extends ThemePlugin {
-
- public function init() {
- /* Additional theme options */
- // Change theme primary color
- $this->addOption('baseColour', 'FieldColor', array(
- 'label' => __('plugins.themes.default.option.colour.label'),
- 'default' => '#A8DCDD',
- ));
-
- // Add usage stats display options
- $this->addOption('displayStats', 'FieldOptions', [
- 'type' => 'radio',
- 'label' => __('plugins.themes.pragma.option.displayStats.label'),
- 'options' => [
- [
- 'value' => 'none',
- 'label' => __('plugins.themes.pragma.option.displayStats.none'),
- ],
- [
- 'value' => 'bar',
- 'label' => __('plugins.themes.pragma.option.displayStats.bar'),
- ],
- [
- 'value' => 'line',
- 'label' => __('plugins.themes.pragma.option.displayStats.line'),
- ],
- ],
- 'default' => 'none',
- ]);
-
- $baseColour = $this->getOption('baseColour');
-
- $additionalLessVariables = [];
- if ($baseColour !== '#A8DCDD') {
- $additionalLessVariables[] = '@primary-colour:' . $baseColour . ';';
- $additionalLessVariables[] = '@secondary-colour: darken(@primary-colour, 50%);';
- }
-
- // Update contrast colour based on primary colour
- if ($this->isColourDark($this->getOption('baseColour'))) {
- $additionalLessVariables[] = '
+
+class PragmaThemePlugin extends ThemePlugin
+{
+ public function init()
+ {
+ /* Additional theme options */
+ // Change theme primary color
+ $this->addOption('baseColour', 'FieldColor', [
+ 'label' => __('plugins.themes.default.option.colour.label'),
+ 'default' => '#A8DCDD',
+ ]);
+
+ // Add usage stats display options
+ $this->addOption('displayStats', 'FieldOptions', [
+ 'type' => 'radio',
+ 'label' => __('plugins.themes.pragma.option.displayStats.label'),
+ 'options' => [
+ [
+ 'value' => 'none',
+ 'label' => __('plugins.themes.pragma.option.displayStats.none'),
+ ],
+ [
+ 'value' => 'bar',
+ 'label' => __('plugins.themes.pragma.option.displayStats.bar'),
+ ],
+ [
+ 'value' => 'line',
+ 'label' => __('plugins.themes.pragma.option.displayStats.line'),
+ ],
+ ],
+ 'default' => 'none',
+ ]);
+
+ $baseColour = $this->getOption('baseColour');
+
+ $additionalLessVariables = [];
+ if ($baseColour !== '#A8DCDD') {
+ $additionalLessVariables[] = '@primary-colour:' . $baseColour . ';';
+ $additionalLessVariables[] = '@secondary-colour: darken(@primary-colour, 50%);';
+ }
+
+ // Update contrast colour based on primary colour
+ if ($this->isColourDark($this->getOption('baseColour'))) {
+ $additionalLessVariables[] = '
@contrast-colour: rgba(255, 255, 255, 0.95);
@secondary-contrast-colour: rgba(255, 255, 255, 0.75);
@tertiary-contrast-colour: rgba(255, 255, 255, 0.65);
';
- }
-
- $themeUrl = $this->getPluginPath();
- $additionalLessVariables[] = "@themeUrl: '$themeUrl';";
-
- // Add navigation menu areas for this theme
- $this->addMenuArea(array('primary', 'user'));
-
- // Adding styles (JQuery UI, Bootstrap, Tag-it)
- $this->addStyle('app-css', 'resources/dist/app.min.css');
- $this->addStyle('stylesheet', 'resources/less/import.less');
- $this->modifyStyle('stylesheet', array('addLessVariables' => join("\n", $additionalLessVariables)));
-
- // Adding scripts (JQuery, Popper, Bootstrap, JQuery UI, Tag-it, Theme's JS)
- $this->addScript('app-js', 'resources/dist/app.min.js');
-
- // Styles for HTML galleys
- $this->addStyle('htmlGalley', 'resources/less/import.less', array('contexts' => 'htmlGalley'));
- $this->modifyStyle('htmlGalley', array('addLessVariables' => join("\n", $additionalLessVariables)));
-
- HookRegistry::add('TemplateManager::display', array($this, 'addSiteWideData'));
- HookRegistry::add('TemplateManager::display', array($this, 'addIndexJournalData'));
- HookRegistry::add('TemplateManager::display', array($this, 'checkCurrentPage'));
- }
-
- /**
- * Get the display name of this theme
- * @return string
- */
- public function getDisplayName() {
- return __('plugins.themes.pragma.name');
- }
-
- /**
- * Get the description of this plugin
- * @return string
- */
- public function getDescription() {
- return __('plugins.themes.pragma.description');
- }
-
- /**
- * @param $hookname string
- * @param $args array
- */
- public function addSiteWideData($hookname, $args) {
- $templateMgr = $args[0];
-
- $request = $this->getRequest();
- $journal = $request->getJournal();
- $baseColour = $this->getOption('baseColour');
-
- if (!defined('SESSION_DISABLE_INIT')) {
-
- // Check locales
- if ($journal) {
- $locales = $journal->getSupportedLocaleNames();
- } else {
- $locales = $request->getSite()->getSupportedLocaleNames();
- }
-
- // Load login form
- $loginUrl = $request->url(null, 'login', 'signIn');
- if (Config::getVar('security', 'force_login_ssl')) {
- $loginUrl = PKPString::regexp_replace('/^http:/', 'https:', $loginUrl);
- }
-
- $orcidImageUrl = $this->getPluginPath() . '/templates/images/orcid.png';
-
- if ($request->getContext()) {
- $templateMgr->assign('pragmaHomepageImage', $journal->getLocalizedSetting('homepageImage'));
- }
-
- $templateMgr->assign(array(
- 'languageToggleLocales' => $locales,
- 'loginUrl' => $loginUrl,
- 'orcidImageUrl' => $orcidImageUrl,
- 'baseColour' => $baseColour,
- ));
- }
- }
-
- /**
- * @param $hookname string
- * @param $args array
- */
- public function addIndexJournalData($hookname, $args) {
- $templateMgr = $args[0];
- $template = $args[1];
-
- if ($template !== 'frontend/pages/indexJournal.tpl') return false;
+ }
+
+ $themeUrl = $this->getPluginPath();
+ $additionalLessVariables[] = "@themeUrl: '$themeUrl';";
+
+ // Add navigation menu areas for this theme
+ $this->addMenuArea(['primary', 'user']);
+
+ // Adding styles (JQuery UI, Bootstrap, Tag-it)
+ $this->addStyle('app-css', 'resources/dist/app.min.css');
+ $this->addStyle('stylesheet', 'resources/less/import.less');
+ $this->modifyStyle('stylesheet', ['addLessVariables' => join("\n", $additionalLessVariables)]);
+
+ // Adding scripts (JQuery, Popper, Bootstrap, JQuery UI, Tag-it, Theme's JS)
+ $this->addScript('app-js', 'resources/dist/app.min.js');
+
+ // Styles for HTML galleys
+ $this->addStyle('htmlGalley', 'resources/less/import.less', ['contexts' => 'htmlGalley']);
+ $this->modifyStyle('htmlGalley', ['addLessVariables' => join("\n", $additionalLessVariables)]);
+
+ HookRegistry::add('TemplateManager::display', [$this, 'addSiteWideData']);
+ HookRegistry::add('TemplateManager::display', [$this, 'addIndexJournalData']);
+ HookRegistry::add('TemplateManager::display', [$this, 'checkCurrentPage']);
+ }
+
+ /**
+ * Get the display name of this theme
+ * @return string
+ */
+ public function getDisplayName(): string
+ {
+ return __('plugins.themes.pragma.name');
+ }
+
+ /**
+ * Get the description of this plugin
+ * @return string
+ */
+ public function getDescription(): string
+ {
+ return __('plugins.themes.pragma.description');
+ }
+
+ /**
+ * @param $hookname string
+ * @param $args array
+ */
+ public function addSiteWideData($hookname, $args)
+ {
+ $templateMgr = $args[0];
+
+ $request = $this->getRequest();
+ $journal = $request->getJournal();
+ $baseColour = $this->getOption('baseColour');
+
+ if (!defined('SESSION_DISABLE_INIT')) {
+ // Check locales
+ if ($journal) {
+ $locales = $journal->getSupportedLocaleNames();
+ } else {
+ $locales = $request->getSite()->getSupportedLocaleNames();
+ }
+
+ // Load login form
+ $loginUrl = $request->url(null, 'login', 'signIn');
+ if (Config::getVar('security', 'force_login_ssl')) {
+ $loginUrl = preg_replace('/^http:/u', 'https:', $loginUrl);
+ }
+
+ if ($request->getContext()) {
+ $templateMgr->assign('pragmaHomepageImage', $journal->getLocalizedData('homepageImage'));
+ }
+
+ $templateMgr->assign([
+ 'languageToggleLocales' => $locales,
+ 'loginUrl' => $loginUrl,
+ 'baseColour' => $baseColour,
+ ]);
+ }
+ }
+
+ /**
+ * @param $hookname string
+ * @param $args array
+ */
+ public function addIndexJournalData($hookname, $args)
+ {
+ $templateMgr = $args[0];
+ $template = $args[1];
+
+ if ($template !== 'frontend/pages/indexJournal.tpl') {
+ return false;
+ }
$contextId = $this->getRequest()->getContext()->getId();
@@ -166,8 +172,8 @@ public function addIndexJournalData($hookname, $args) {
$currentIssue = Repo::issue()->getCurrent($contextId);
- // Exclude the current issue from the list
- $recentIssues = [];
+ // Exclude the current issue from the list
+ $recentIssues = [];
if ($currentIssue) {
foreach ($recentIssuesWithCurrent as $issue) {
if ($issue->getId() !== $currentIssue->getId()) {
@@ -176,70 +182,77 @@ public function addIndexJournalData($hookname, $args) {
}
}
- $templateMgr->assign('recentIssues', $recentIssues);
- }
-
-
- /**
- * @param $hookname string
- * @param $args array
- */
- public function checkCurrentPage($hookname, $args) {
- $templateMgr = $args[0];
- // TODO check the issue with multiple calls of the hook on settings/website
- if (!isset($templateMgr->registered_plugins["function"]["pragma_item_active"])) {
- $templateMgr->registerPlugin('function', 'pragma_item_active', array($this, 'isActiveItem'));
- }
-
- }
-
- /**
- * @param $params array
- * @param $smarty Smarty_Internal_Template
- * @return string
- */
- public function isActiveItem($params, $smarty) {
- $navigationMenuItem = $params['item'];
- $emptyMarker = '';
- $activeMarker = ' active';
-
- // Get URL of the current page
- $request = $this->getRequest();
- $currentUrl = $request->getCompleteUrl();
- $currentPage = $request->getRequestedPage();
-
- if (!($navigationMenuItem instanceof NavigationMenuItem && $navigationMenuItem->getIsDisplayed())) {
- if (is_string($navigationMenuItem)) {
- $navigationMenuItemIndex = preg_replace('/index$/', '', $navigationMenuItem);
- $navigationMenuItemSlash = preg_replace('/\/index$/', '', $navigationMenuItem);
- if ($navigationMenuItem == $currentUrl || $navigationMenuItemIndex == $currentUrl || $navigationMenuItemSlash == $currentUrl) {
- return $activeMarker;
- } else {
- return $emptyMarker;
- }
- } else {
- return $emptyMarker;
- }
- }
-
- // Do not add an active marker if it's a dropdown menu
- if ($navigationMenuItem->getIsChildVisible()) return $emptyMarker;
-
- // Retrieve URL and its components for a menu item
- $itemUrl = $navigationMenuItem->getUrl();
-
- // Check whether menu item points to the current page
- $context = $request->getContext();
- if ($context) {
- $currentIssue = Repo::issue()->getCurrent($context->getId());
- if ($navigationMenuItem->getType() === NavigationMenuService::NMI_TYPE_CURRENT) {
- $issue = $smarty->getTemplateVars('issue');
- if ($issue && ($issue->getId() === $currentIssue->getId()) && $currentPage == "issue") return $activeMarker;
- }
- }
-
- if ($currentUrl === $itemUrl) return $activeMarker;
-
- return $emptyMarker;
- }
+ $templateMgr->assign('recentIssues', $recentIssues);
+ }
+
+
+ /**
+ * @param $hookname string
+ * @param $args array
+ */
+ public function checkCurrentPage($hookname, $args)
+ {
+ $templateMgr = $args[0];
+ // TODO check the issue with multiple calls of the hook on settings/website
+ if (!isset($templateMgr->registered_plugins["function"]["pragma_item_active"])) {
+ $templateMgr->registerPlugin('function', 'pragma_item_active', [$this, 'isActiveItem']);
+ }
+ }
+
+ /**
+ * @param $params array
+ * @param $smarty Smarty_Internal_Template
+ * @return string
+ */
+ public function isActiveItem($params, $smarty)
+ {
+ $navigationMenuItem = $params['item'];
+ $emptyMarker = '';
+ $activeMarker = ' active';
+
+ // Get URL of the current page
+ $request = $this->getRequest();
+ $currentUrl = $request->getCompleteUrl();
+ $currentPage = $request->getRequestedPage();
+
+ if (!($navigationMenuItem instanceof NavigationMenuItem && $navigationMenuItem->getIsDisplayed())) {
+ if (is_string($navigationMenuItem)) {
+ $navigationMenuItemIndex = preg_replace('/index$/', '', $navigationMenuItem);
+ $navigationMenuItemSlash = preg_replace('/\/index$/', '', $navigationMenuItem);
+ if ($navigationMenuItem == $currentUrl || $navigationMenuItemIndex == $currentUrl || $navigationMenuItemSlash == $currentUrl) {
+ return $activeMarker;
+ } else {
+ return $emptyMarker;
+ }
+ } else {
+ return $emptyMarker;
+ }
+ }
+
+ // Do not add an active marker if it's a dropdown menu
+ if ($navigationMenuItem->getIsChildVisible()) {
+ return $emptyMarker;
+ }
+
+ // Retrieve URL and its components for a menu item
+ $itemUrl = $navigationMenuItem->getUrl();
+
+ // Check whether menu item points to the current page
+ $context = $request->getContext();
+ if ($context) {
+ $currentIssue = Repo::issue()->getCurrent($context->getId());
+ if ($navigationMenuItem->getType() === NavigationMenuService::NMI_TYPE_CURRENT) {
+ $issue = $smarty->getTemplateVars('issue');
+ if ($issue && ($issue->getId() === $currentIssue->getId()) && $currentPage == "issue") {
+ return $activeMarker;
+ }
+ }
+ }
+
+ if ($currentUrl === $itemUrl) {
+ return $activeMarker;
+ }
+
+ return $emptyMarker;
+ }
}
diff --git a/cypress/tests/functional/Pragma.cy.js b/cypress/tests/functional/Pragma.cy.js
index ad0a66f..a42b00d 100644
--- a/cypress/tests/functional/Pragma.cy.js
+++ b/cypress/tests/functional/Pragma.cy.js
@@ -10,7 +10,7 @@
describe('Theme plugin tests', function() {
const journalPath = 'publicknowledge';
const index = 'index.php';
- const path = '/' + index + '/' + journalPath;
+ const path = '/' + index + '/' + journalPath + '/en';
const date = new Date();
const day = date.getDate() + '';
@@ -37,7 +37,9 @@ describe('Theme plugin tests', function() {
it('Enables and selects the theme', function() {
cy.login('admin', 'admin', 'publicknowledge');
- cy.get('.app__nav a').contains('Website').click();
+ cy.get('nav').contains('Settings').click();
+ // Ensure submenu item click despite animation
+ cy.get('nav').contains('Website').click({ force: true });
cy.get('button[id="plugins-button"]').click();
// Find and enable the plugin
@@ -45,7 +47,7 @@ describe('Theme plugin tests', function() {
cy.get('div:contains(\'The plugin "Pragma Theme" has been enabled.\')');
cy.reload();
- // Select the Classic theme
+ // Select the Pragma theme
cy.get('button[id="appearance-button"]').click();
cy.get('select[id="theme-themePluginPath-control"]').select('pragma');
cy.get('#theme button').contains('Save').click();
@@ -53,14 +55,14 @@ describe('Theme plugin tests', function() {
});
it('Visits front-end theme pages', function() {
- cy.visit(' ');
+ cy.visit(path);
cy.visit(path + '/issue/current');
cy.visit(path + '/issue/archive');
cy.visit(path + '/issue/view/1');
cy.visit(path + '/article/view/1');
cy.visit(path + '/article/view/1/1');
cy.visit(path + '/about');
- cy.visit(path + '/about/editorialTeam');
+ cy.visit(path + '/about/editorialMasthead');
cy.visit(path + '/about/submissions');
cy.visit(path + '/about/contact');
cy.visit(path + '/about/privacy');
@@ -79,7 +81,7 @@ describe('Theme plugin tests', function() {
cy.get('#theme [role="status"]').contains('Saved');
// Populate journal summary
- cy.get('.app__navItem').contains('Journal').click();
+ cy.get('nav').contains('Journal').click();
cy.get('#masthead-button').click();
cy.setTinyMceContent('masthead-description-control-en', journalDescription);
cy.get('#masthead button').contains('Save').click();
@@ -106,31 +108,22 @@ describe('Theme plugin tests', function() {
cy.get('button').contains('OK').click();
});
cy.waitJQuery();
- cy.get('nav a').contains('Submissions').click();
- cy.get('button').contains('Archived').click();
- cy.get('.listPanel__item').first().within(() => {
- cy.get('.listPanel__item--submission__id').contains('1');
- cy.get('a span').contains('View').click();
- });
+ cy.visit('/index.php/publicknowledge/workflow/access/1');
cy.waitJQuery();
- cy.get('button').contains('Publication').click();
- cy.get('.pkpButton').contains('Create New Version').click();
- cy.get('#modals-container .pkpButton').contains('Yes').click();
- cy.wait(2000); // wait for a new version init
- cy.get('#issue-button').click();
+ cy.get(`[data-cy="active-modal"] nav a:contains('Issue')`).click();
cy.get('.pkpFormField--options__optionLabel').contains('First category').click();
- cy.get('#issue button').contains('Save').click();
- cy.get('#issue [role="status"]').contains('Saved');
+ cy.get('button').contains('Save').click();
+ cy.get('[role="status"]').contains('Saved');
- cy.get('#titleAbstract-button').click();
+ cy.get(`[data-cy="active-modal"] nav a:contains('Title & Abstract')`).click();
cy.getTinyMceContent('titleAbstract-title-control-en').then((content) => {
cy.setTinyMceContent('titleAbstract-title-control-en', content + ' - version 2');
});
- cy.get('#titleAbstract .pkpButton').contains('Save').click();
- cy.get('#titleAbstract [role="status"]').contains('Saved');
- cy.get('#publication .pkpButton').contains('Publish').click();
- cy.get('.pkp_modal .pkpButton').contains('Publish').click();
+ cy.get('button').contains('Save').click();
+ cy.get('[role="status"]').contains('Saved');
+ cy.get('button').contains('Publish').click();
+ cy.get('.pkpWorkflow__publishModal button').contains('Publish').click();
cy.wait(2000);
// Visit front-end pages
@@ -191,16 +184,16 @@ describe('Theme plugin tests', function() {
cy.get('#reviewerInterests input').type('psychotherapy,neuroscience,neurobiology', {delay: 0});
cy.get('button[type="submit"]').contains('Register').focus().click();
cy.get('a').contains('View Submissions').click();
- cy.url().should('include', 'submissions');
+ cy.url().should('include', 'dashboard');
});
- it('Log in/Log out', function() {
+ it('Log out/Log in', function() {
// Sign out
cy.visit(path + '/' + 'login/signOut');
cy.url().should('include', 'login');
- cy.get('#username').type(user.username, {delay: 0});
- cy.get('#password').type(user.username + user.username);
+ cy.get('#username').type('dbarnes', {delay: 0});
+ cy.get('#password').type('dbarnesdbarnes');
cy.get('button[type="submit"]').contains('Login').click();
- cy.url().should('include', 'submissions');
+ cy.url().should('include', 'dashboard');
});
});
diff --git a/index.php b/index.php
index 4364d8b..51ceb87 100644
--- a/index.php
+++ b/index.php
@@ -1,17 +1,17 @@
span {
+ display: block;
+ }
+
+ .name {
+ font-weight: bold;
+ }
+ }
+}
diff --git a/resources/less/pages/orcid.less b/resources/less/pages/orcid.less
new file mode 100644
index 0000000..e0ed717
--- /dev/null
+++ b/resources/less/pages/orcid.less
@@ -0,0 +1,18 @@
+/**
+ * @file less/pages/orcid.less
+ *
+ * Copyright (c) 2025 Simon Fraser University
+ * Copyright (c) 2025 John Willinsky
+ * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
+ *
+ * @brief Stylesheet for ORCID pages (orcidAbout.tpl, orcidVerify.tpl) and buttons
+ *
+ */
+
+.orcid_icon {
+ display: inline-block;
+ margin-left: 5px;
+ margin-right: 2px;
+ width: 24px;
+ height: 24px;
+}
diff --git a/templates/frontend/components/loginForm.tpl b/templates/frontend/components/loginForm.tpl
index 9d91c4e..f624d43 100644
--- a/templates/frontend/components/loginForm.tpl
+++ b/templates/frontend/components/loginForm.tpl
@@ -50,6 +50,30 @@
+
+ {* recaptcha spam blocker *}
+ {if $recaptchaPublicKey}
+
+ {/if}
+
+ {* altcha spam blocker *}
+ {if $altchaEnabled}
+
+
+
+ {/if}
+
diff --git a/templates/frontend/pages/announcement.tpl b/templates/frontend/pages/announcement.tpl
index 7e6c0e0..741da19 100644
--- a/templates/frontend/pages/announcement.tpl
+++ b/templates/frontend/pages/announcement.tpl
@@ -1,15 +1,15 @@
{**
* templates/frontend/pages/announcements.tpl
*
- * Copyright (c) 2014-2020 Simon Fraser University
- * Copyright (c) 2003-2020 John Willinsky
+ * Copyright (c) 2014-2025 Simon Fraser University
+ * Copyright (c) 2003-2025 John Willinsky
* Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
*
* @brief Display the page which represents a single announcement
*
* @uses $announcement Announcement The announcement to display
*}
-{include file="frontend/components/header.tpl" pageTitleTranslated=$announcement->getLocalizedTitle()|escape}
+{include file="frontend/components/header.tpl" pageTitleTranslated=$announcement->getLocalizedData('title')|escape}
@@ -19,17 +19,17 @@
{translate key="announcement.announcements"}
- {$announcement->getLocalizedTitle()|escape}
+ {$announcement->getLocalizedData('title')|escape}
- {$announcement->getDatePosted()|date_format:$dateFormatShort}
+ {$announcement->datePosted|date_format:$dateFormatShort}
- {if $announcement->getLocalizedDescription()}
- {$announcement->getLocalizedDescription()|strip_unsafe_html}
+ {if $announcement->getLocalizedData('description')}
+ {$announcement->getLocalizedData('description')|strip_unsafe_html}
{else}
- {$announcement->getLocalizedDescriptionShort()|strip_unsafe_html}
+ {$announcement->getLocalizedData('descriptionShort')|strip_unsafe_html}
{/if}
diff --git a/templates/frontend/pages/article.tpl b/templates/frontend/pages/article.tpl
index a810c62..710eb50 100644
--- a/templates/frontend/pages/article.tpl
+++ b/templates/frontend/pages/article.tpl
@@ -7,7 +7,7 @@
*
* @brief Display the page to view an article with all of it's details.
*
- * @uses $article Article This article
+ * @uses $article Submission This article
* @uses $publication Publication The publication being displayed
* @uses $firstPublication Publication The first published version of this article
* @uses $currentPublication Publication The most recently published version of this article
@@ -17,7 +17,7 @@
* @uses $primaryGalleys array List of article galleys that are not supplementary or dependent
* @uses $supplementaryGalleys array List of article galleys that are supplementary
*}
- {include file="frontend/components/header.tpl" pageTitleTranslated=$article->getLocalizedTitle()|escape}
+ {include file="frontend/components/header.tpl" pageTitleTranslated=$article->getLocalizedData('title')|escape}
diff --git a/templates/frontend/pages/editorialHistory.tpl b/templates/frontend/pages/editorialHistory.tpl
new file mode 100644
index 0000000..5debe48
--- /dev/null
+++ b/templates/frontend/pages/editorialHistory.tpl
@@ -0,0 +1,62 @@
+{**
+ * templates/frontend/pages/editorialHistory.tpl
+ *
+ * Copyright (c) 2025 Simon Fraser University
+ * Copyright (c) 2025 John Willinsky
+ * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
+ *
+ * @brief Display context's editorial history page.
+ *
+ *}
+{include file="frontend/components/header.tpl" pageTitle="common.editorialHistory"}
+
+
+
+
+
+
+ {translate key="common.editorialHistory.page"}
+
+
+
+
{translate key="common.editorialHistory.page.description"}
+ {foreach from=$mastheadRoles item="mastheadRole"}
+ {if array_key_exists($mastheadRole->id, $mastheadUsers)}
+
{$mastheadRole->getLocalizedData('name')|escape}
+
+ {foreach from=$mastheadUsers[$mastheadRole->id] item="mastheadUser"}
+
+ {strip}
+
+ {foreach name="services" from=$mastheadUser['services'] item="service"}
+ {translate key="common.fromUntil" from=$service['dateStart'] until=$service['dateEnd']}
+ {if !$smarty.foreach.services.last}{translate key="common.commaListSeparator"}{/if}
+ {/foreach}
+
+
+ {$mastheadUser['user']->getFullName()|escape}
+ {if $mastheadUser['user']->getData('orcid') && $mastheadUser['user']->hasVerifiedOrcid()}
+
+ getFullName()|escape}">
+ {$orcidIcon}
+
+
+ {/if}
+
+ {if !empty($mastheadUser['user']->getLocalizedData('affiliation'))}
+ {$mastheadUser['user']->getLocalizedData('affiliation')|escape}
+ {/if}
+ {/strip}
+
+ {/foreach}
+
+ {/if}
+ {/foreach}
+
+ {include file="frontend/components/editLink.tpl" page="management" op="settings" path="context" anchor="masthead" sectionTitleKey="common.editorialHistory"}
+ {$currentContext->getLocalizedData('editorialHistory')}
+
+
+
+
+{include file="frontend/components/footer.tpl"}
diff --git a/templates/frontend/pages/editorialMasthead.tpl b/templates/frontend/pages/editorialMasthead.tpl
new file mode 100644
index 0000000..55f7328
--- /dev/null
+++ b/templates/frontend/pages/editorialMasthead.tpl
@@ -0,0 +1,84 @@
+{**
+ * templates/frontend/pages/editorialMasthead.tpl
+ *
+ * Copyright (c) 2025 Simon Fraser University
+ * Copyright (c) 2025 John Willinsky
+ * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
+ *
+ * @brief Display context's editorial masthead page.
+ *
+ *}
+{include file="frontend/components/header.tpl" pageTitle="common.editorialMasthead"}
+
+
+
+
+
+
+ {translate key="common.editorialMasthead"}
+
+
+
+ {foreach from=$mastheadRoles item="mastheadRole"}
+ {if array_key_exists($mastheadRole->id, $mastheadUsers)}
+
{$mastheadRole->getLocalizedData('name')|escape}
+
+ {foreach from=$mastheadUsers[$mastheadRole->id] item="mastheadUser"}
+
+ {strip}
+ {translate key="common.fromUntil" from=$mastheadUser['dateStart'] until=""}
+
+ {$mastheadUser['user']->getFullName()|escape}
+ {if $mastheadUser['user']->getData('orcid') && $mastheadUser['user']->hasVerifiedOrcid()}
+
+ getFullName()|escape}">
+ {$orcidIcon}
+
+
+ {/if}
+
+ {if !empty($mastheadUser['user']->getLocalizedData('affiliation'))}
+ {$mastheadUser['user']->getLocalizedData('affiliation')|escape}
+ {/if}
+ {/strip}
+
+ {/foreach}
+
+ {/if}
+ {/foreach}
+
+ {capture assign=editorialHistoryUrl}{url page="about" op="editorialHistory" router=\PKP\core\PKPApplication::ROUTE_PAGE}{/capture}
+ {translate key="about.editorialMasthead.linkToEditorialHistory" url=$editorialHistoryUrl}
+
+
+
+ {if $reviewers->count()}
+
{translate key="common.editorialMasthead.peerReviewers"}
+
{translate key="common.editorialMasthead.peerReviewers.description" year=$previousYear}
+
+ {foreach from=$reviewers item="reviewer"}
+
+ {strip}
+
+ {$reviewer->getFullName()|escape}
+ {if $reviewer->getData('orcid') && $reviewer->hasVerifiedOrcid()}
+
+ getFullName()|escape}">
+ {$orcidIcon}
+
+
+ {/if}
+
+ {if !empty($reviewer->getLocalizedData('affiliation'))}
+ {$reviewer->getLocalizedData('affiliation')|escape}
+ {/if}
+ {/strip}
+
+ {/foreach}
+
+ {/if}
+
+
+
+
+{include file="frontend/components/footer.tpl"}
diff --git a/templates/frontend/pages/editorialTeam.tpl b/templates/frontend/pages/editorialTeam.tpl
deleted file mode 100755
index 8e59e66..0000000
--- a/templates/frontend/pages/editorialTeam.tpl
+++ /dev/null
@@ -1,30 +0,0 @@
-{**
- * templates/frontend/pages/editorialTeam.tpl
- *
- * Copyright (c) 2014-2020 Simon Fraser University
- * Copyright (c) 2003-2020 John Willinsky
- * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
- *
- * @brief Display the page to view the editorial team.
- *
- * @uses $currentContext Journal|Press The current journal or press
- *}
-{include file="frontend/components/header.tpl" pageTitle="about.editorialTeam"}
-
-
-
-
-
-
- {translate key="about.editorialTeam"}
-
- {include file="frontend/components/editLink.tpl" page="management" op="settings" path="context" anchor="masthead" sectionTitleKey="about.editorialTeam"}
-
-
- {$currentContext->getLocalizedSetting('editorialTeam')}
-
-
-
-
-
-{include file="frontend/components/footer.tpl"}
diff --git a/templates/frontend/pages/indexJournal.tpl b/templates/frontend/pages/indexJournal.tpl
index db1ddf7..7a5a5b7 100644
--- a/templates/frontend/pages/indexJournal.tpl
+++ b/templates/frontend/pages/indexJournal.tpl
@@ -60,14 +60,14 @@
{break}
{/if}
- {$announcement->getLocalizedTitle()|escape}
- {$announcement->getDatePosted()|date_format:$dateFormatLong}
- {$announcement->getLocalizedDescriptionShort()|strip_unsafe_html}
-
- {capture assign="announcementPageUrl"}{url router=$smarty.const.ROUTE_PAGE page="announcement" op="view" path=$announcement->getId()}{/capture}
- {translate key="common.more"}
-
-
+
{$announcement->getLocalizedData('title')|escape}
+
{$announcement->datePosted|date_format:$dateFormatLong}
+
{$announcement->getLocalizedData('descriptionShort')|strip_unsafe_html}
+
+ {capture assign="announcementPageUrl"}{url router=$smarty.const.ROUTE_PAGE page="announcement" op="view" path=$announcement->id}{/capture}
+ {translate key="common.more"}
+
+
{/foreach}
{if $numAnnouncementsHomepage > 1 && $announcements|@count > 1}
diff --git a/templates/frontend/pages/indexSite.tpl b/templates/frontend/pages/indexSite.tpl
index a7f443d..a947c29 100644
--- a/templates/frontend/pages/indexSite.tpl
+++ b/templates/frontend/pages/indexSite.tpl
@@ -33,7 +33,7 @@
{assign var="countItems" value=count($journals)}
{foreach from=$journals item=journal}
{capture assign="url"}{url journal=$journal->getPath()}{/capture}
- {assign var="thumb" value=$journal->getLocalizedSetting('journalThumbnail')}
+ {assign var="thumb" value=$journal->getLocalizedData('journalThumbnail')}
{assign var="description" value=$journal->getLocalizedDescription()}
{assign var="journalKey" value=$journalKey+1}
diff --git a/templates/frontend/pages/orcidAbout.tpl b/templates/frontend/pages/orcidAbout.tpl
new file mode 100644
index 0000000..4aadeb4
--- /dev/null
+++ b/templates/frontend/pages/orcidAbout.tpl
@@ -0,0 +1,45 @@
+{**
+ * templates/frontend/pages/orcidAbout.tpl
+ *
+ * Copyright (c) 2014-2024 Simon Fraser University
+ * Copyright (c) 2000-2024 John Willinsky
+ * Copyright (c) 2018-2019 University Library Heidelberg
+ * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
+ *
+ * Page template to display from the OrcidHandler to show information/overview about ORCID functionality for users.
+ *}
+{include file="frontend/components/header.tpl"}
+
+
+
+
+
+
+ {translate key="orcid.about.title"}
+
+
+
+
+
+ {translate key="orcid.about.orcidExplanation"}
+
+
{translate key="orcid.about.howAndWhy.title"}
+ {if $isMemberApi}
+
+ {translate key="orcid.about.howAndWhyMemberAPI"}
+
+ {else}
+
+ {translate key="orcid.about.howAndWhyPublicAPI"}
+
+ {/if}
+
{translate key="orcid.about.display.title"}
+
+ {translate key="orcid.about.display"}
+
+
+
+
+
+
+{include file="frontend/components/footer.tpl"}
diff --git a/templates/frontend/pages/orcidVerify.tpl b/templates/frontend/pages/orcidVerify.tpl
new file mode 100644
index 0000000..cde2178
--- /dev/null
+++ b/templates/frontend/pages/orcidVerify.tpl
@@ -0,0 +1,85 @@
+{**
+ * templates/frontend/pages/orcidVerify.tpl
+ *
+ * Copyright (c) 2014-2024 Simon Fraser University
+ * Copyright (c) 2000-2024 John Willinsky
+ * Copyright (c) 2018-2019 University Library Heidelberg
+ * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
+ *
+ * Page template to display from the OrcidHandler to show ORCID verification success or failure.
+ *}
+{include file="frontend/components/header.tpl"}
+
+
+
+
+
+
+ {translate key="orcid.verify.title"}
+
+
+
+ {if $verifySuccess}
+
+
+ {$orcidIcon}{$orcid|escape}
+
+
+
+ {translate key="orcid.verify.success"}
+
+ {if $sendSubmission}
+ {if $sendSubmissionSuccess}
+
+ {translate key="orcid.verify.sendSubmissionToOrcid.success"}
+
+ {else}
+
+ {translate key="orcid.verify.sendSubmissionToOrcid.failure"}
+
+ {/if}
+ {elseif $submissionNotPublished}
+ {translate key="orcid.verify.sendSubmissionToOrcid.notpublished"}
+ {/if}
+
+ {translate key="orcid.verify.success.redirect" contextName=$contextName}
+
+ {else}
+
+ {if $orcidAPIError}
+ {$orcidAPIError}
+ {/if}
+ {if $invalidClient}
+ {translate key="orcid.invalidClient"}
+ {elseif $duplicateOrcid}
+ {translate key="orcid.verify.duplicateOrcid"}
+ {elseif $denied}
+ {translate key="orcid.authDenied"}
+ {elseif $authFailure}
+ {translate key="orcid.authFailure"}
+ {else}
+ {translate key="orcid.verify.failure"}
+ {/if}
+
+ {translate key="orcid.failure.contact"}
+ {/if}
+
+
+
+
+
+{include file="frontend/components/footer.tpl"}
+
+{if $verifySuccess}
+
+
+{/if}
diff --git a/templates/frontend/pages/privacy.tpl b/templates/frontend/pages/privacy.tpl
index 475815b..456174c 100755
--- a/templates/frontend/pages/privacy.tpl
+++ b/templates/frontend/pages/privacy.tpl
@@ -20,7 +20,7 @@
- {$currentContext->getLocalizedSetting('privacyStatement')}
+ {$currentContext->getLocalizedData('privacyStatement')}
diff --git a/templates/frontend/pages/userLogin.tpl b/templates/frontend/pages/userLogin.tpl
index 27b132d..d785a89 100755
--- a/templates/frontend/pages/userLogin.tpl
+++ b/templates/frontend/pages/userLogin.tpl
@@ -69,12 +69,23 @@
{* recaptcha spam blocker *}
{if $recaptchaPublicKey}
-
-
-
-
-
Recaptcha response
+
+ {/if}
+
+ {* altcha spam blocker *}
+ {if $altchaEnabled}
+
+
{/if}
diff --git a/templates/frontend/pages/userLostPassword.tpl b/templates/frontend/pages/userLostPassword.tpl
index d93e7aa..aa34b50 100644
--- a/templates/frontend/pages/userLostPassword.tpl
+++ b/templates/frontend/pages/userLostPassword.tpl
@@ -37,6 +37,16 @@
+
+ {* altcha spam blocker *}
+ {if $altchaEnabled}
+
+
+
+ {/if}
+