How to customize OJS3 frontend and how to suggest dev?

Hello,

I’m working in the IT department of the University of Bordeaux. We would have some questions and advices to customize OJS3 frontend.

At the University of Bordeaux, we host several journals in different scientific fields. We are still in version OJS 2.4.7.
The journals and the IT department choosed OJS after a benchmarking of several softwares because of these features, its open source philosophy and its network of very active users on the forums.
However, the display proposed in OJS version 2 did not satisfy them. The journals wished a more modern display of the style of Plos One journals and a personalized display per journal.
So, we made specific developments to meet their expectations, including integrating boostrap. This developments have not been made in accordance with PKP development rules, they are quite intrusive in the code and we couldn’t, for example, migrate to version 2.4.8 without overwriting the code we made. We acted this way because we knew that OJS3 will be released soon and will bring some solutions to our expectations.

I would like to explain you changes we made in OJS 2.4.7. and I would like to have some advices on how to integrate these changes in OJS3 in accordance with PKP development rules.
The main changes we made were to build a personal home page for each journal with personal menus and a personal article page.

For the home page, each journal wanted a personal display. Some of them, by highlighting covers of their 4 latest published articles, other with the 10 last articles of the last issue but also by adding graphics elements and other by displaying articles of their last issue but sorted by sections.

For the article page, they wanted a more modern display of the style of Plos One journals with several tabs (article, author, supplementary files, metrics) with title, type of article, Author(s), important article dates (Received, Accepted, Published), Abstract, References and the article body displayed with some features: references with a tooltip with details linked with the displayed metadatas references, a certain display to highlighting figures and tables.

To do that, we integrated bootsrap, created specific “js” and “css” files and changed the template article.tpl file.
We displayed some datas from metadatas as title, type of article, Author(s), Abstract, References. And we displayed article body by displaying content of HTML Galley. So we built this HTML Galley in the way we would like to display it without metadatas and with classes and features which will be defined in “js” and “css” files.
We wanted to display directly content of HTML galley in article page but for others galleys (as PDF and XML), we wanted to display a download link.

By studying OJS 3, I found it’s now possible to use the bootrap plugin which allows to create specific templates and looks by journal because templates overload default templates. And it’s exactly what we need!
I also read some similar threads such as this one:

Then I tried to integrate changes we made on “article_details.tpl” template of the boostrap plugin but I encountered some difficulties.

  1. We don’t find in OJS3 some functions of OJS2 to display HTML and PDF galleys the way we want (Content for HTML galley and download link for others galleys. Those missing functions are for example: isHTMLGalley(), getHTMLContents(), isPdfGalley(). Are those functions abandoned or not yet implemented ?
  2. We don’t find either in OJS3 some functions of OJS2 to display references one by one ($citationFactory->getCount(), $citation->getRawCitation()) and not like a unique string as the current function ($article->getCitations()). We want to display references one by one to apply to them a certain style and a certain processing of display by “js” and “css” files.
  3. We would like to display the accepted date of the article but there is no function to display it. We have added in OJS2 some code function to retrieve it:
    $authorSubmissionDao = DAORegistry::getDAO(‘AuthorSubmissionDAO’);
    $editorDecisions = $authorSubmissionDao->getEditorDecisions($article->getId(), $article->getCurrentRound());
    $lastDecision = count($editorDecisions) >= 1 ? $editorDecisions[count($editorDecisions) - 1] : null;
    $dateAccepted = $lastDecision[‘decision’] == 1 ? $lastDecision[‘dateDecided’] : null;
    Is it possible to integrate this code somewhere ?

We did some other changes we can discuss with you or suggest you. And we would like to know how to suggest PKP/OJS a new feature, a change or a modification? Is it by this forum or on github site? If it’s on github site, is there a guide which explains the steps to follow before suggesting some change or some code ?

If you want to have a look to our scholarly journals portal and of the looks of our journals, voilà the address:
http://open.u-bordeaux.fr/journals/

Thanks in advance for your answers.
Helene

Hi @hcl,

Congratulations on all the work on the OJS2 installation – it looks great!

Tagging @NateWr on this, as he’s our main front end guru. I’ll make some comments on the back-end aspects.

Overall some of our goals in rewriting OJS2 for the OJS3 release align well with your requirements – OJS2 (as you’ll be well aware) was difficult to give a modern appearance, and we had some improvements to make with regard to theming. Hopefully you’ll find some pleasant surprises in working with OJS3 that’ll make your work easier, and facilitate things like upgrades of installations with customizations. (Child themes are part of this – see GitHub - NateWr/defaultChild: An example child theme for OJS 3. as an example.) As much of this is new to OJS, though heavily inspired by other applications like Wordpress, we’d welcome feedback on the areas that give you trouble.

  1. We don’t find in OJS3 some functions of OJS2 to display HTML and PDF galleys the way we want (Content for HTML galley and download link for others galleys. Those missing functions are for example: isHTMLGalley(), getHTMLContents(), isPdfGalley(). Are those functions abandoned or not yet implemented ?

We don’t have specific HTML vs. PDF functions in OJS3 like we did before; we’re hoping to improve the breadth of formats supported using plugins. You can check file types by MIME type. Have a look at the plugins providing visualizations for the various file types, such as plugins/generic/pdfJsViewer for PDF galleys and plugins/generic/htmlArticleGalley for HTML galleys.

  1. We don’t find either in OJS3 some functions of OJS2 to display references one by one ($citationFactory->getCount(), $citation->getRawCitation()) and not like a unique string as the current function ($article->getCitations()). We want to display references one by one to apply to them a certain style and a certain processing of display by “js” and “css” files.

We’ve removed/deprecated the citation assistant tools – they weren’t being well maintained – and are favouring our XML publishing toolset using Open Typesetting Stack instead. I’d suggest exploring that; even if you decide not to use JATS XML in publishing your galleys (see this example article) you can interact more richly with article content once it’s been transformed into JATS. It’s (in my opinion) the best standard available for representing scholarly article content and I expect a lot of tools to gain traction for working with JATS XML.

  1. We would like to display the accepted date of the article but there is no function to display it. We have added in OJS2 some code function to retrieve it: (…)

The tools to get the acceptance date in OJS3 are similar. Try using the EditDecisionDAO.

We did some other changes we can discuss with you or suggest you. And we would like to know how to suggest PKP/OJS a new feature, a change or a modification? Is it by this forum or on github site? If it’s on github site, is there a guide which explains the steps to follow before suggesting some change or some code ?

We welcome those kinds of discussions both here and on github. If you expect to work directly with code, github provides great tools for managing contributions; if you want to discuss functionality at a high level, this forum might attract more community engagement. We often have conversations involving both tools, with links going back and forth between them. In general, it’s useful to split various conversations into different topics, so that the forum stays organized and approachable for users who share some but not all of your interests.

Regards,
Alec Smecher
Public Knowledge Project Team

Hi @hcl,

It sounds like you’ve found the theming API and know what you’re doing with it. If you haven’t yet seen the theming guide, you may find it useful:

https://www.gitbook.com/book/pkp/pkp-theming-guide/details

In particular, if you want to pass data to a template file that doesn’t already exist, here’s a quick example of how you can hook in before a template is loaded from a theme plugin:

https://pkp.gitbooks.io/pkp-theming-guide/content/en/advanced-custom-data.html

As you go about implementing your changes, I’d encourage you to especially look at the Child Theming API, which will allow you to isolate specific changes and hopefully help you maintain your customizations over time:

https://pkp.gitbooks.io/pkp-theming-guide/content/en/child-themes.html

And of course, feel free to reach out if you have any questions as you go along.

Hi,

Thanks for your both advices on the back-end and front-end aspects. And thanks for the link to the “PKP Theming Guide GitBook” which is very useful.

You’re right @NateWr, we’ve found the theming API and now we want to use it. And we want to pass data to a template file that doesn’t already exist.
I tested it by trying to get the acceptance date of the article.
I create a public function “loadTemplateData” in the CustomThemePlugin.inc.php file.
As @ctgraham has suggested, to get the acceptance date, I used the “EditDecisionDAO” as this:
$editDecisionDao = DAORegistry::getDAO(‘EditDecisionDAO’);
And then I need to use the getEditorDecisions function which takes at least the article Id as argument.
But how I get the article Id data in the loadTemplateData function ?

I have an other question related to customization. Has the Custom Locale Plugin been adapted for OJS3 ?

Thanks again for your answers.
Best regards.
Helene

Hi @hcl,

The article view page has an additional hook which contains the issue and article objects:

If you use that hook, you should be able to receive those as arguments in your custom theme function.

I’m not familiar with the Custom Locale Plugin. I’ve only worked with OJS 3 since joining PKP, but maybe someone else knows.

I @NateWr,
I don’t manage to receive arguments of article objects in my custom theme function.
Maybe I don’t do it the right way. I was also wondering if it was possible because the theme is called before the article page ?
Thanks, Helene

Hi @hcl,

Can you post the code you’re having trouble with?

I again @NateWr,
I tried several things in the CustomThemePlugin.inc.php file:

  • Add in the “init” function or in the new “loadTemplateData” function this line code:
    HookRegistry::call(‘ArticleHandler::view’, array(&$request, &$issue, &$article));
  • Add in the “init” function this line code:
    HookRegistry::register(‘ArticleHandler::view’,array(&$this, ‘articleView’));
    and then create an “articleView” function.
    Otherwise, I manage to do it in the article_details.tpl file where I can get the article Id ($article->getId()) but I would prefer to handle the code outside a template file.
    Thanks, Helene

Hi @hcl,

The HookRegistry::register approach sounds right. If you can share the code you’re using, I can work through it and see what’s not working.

I @NateWr,

I was out of the office for a few days. And it was apparently very helpful because I finally managed to do what I wanted to do.
And your advice also directed me to the right solution.
Here’s what I did.

I Added in the “init” function this line code:
HookRegistry::register(‘ArticleHandler::view’,array($this, ‘articleView’));

And I create the articleView function as follows:
public function articleView($hookName, $args) {
$templateMgr = TemplateManager::getManager($request);
$article =$args[2];
$editDecisionDao = DAORegistry::getDAO(‘EditDecisionDAO’);
$templateMgr->assign(‘editDecisionDao’, $editDecisionDao);
$editorDecisions = $editDecisionDao->getEditorDecisions($article->getId());
$lastDecision = count($editorDecisions) >= 1 ? $editorDecisions[count($editorDecisions) - 1] : null;
$dateAccepted = $lastDecision[‘decision’] == 1 ? $lastDecision[‘dateDecided’] : null;
$templateMgr->assign(‘dateAccepted’, $dateAccepted);
}

I had no need to use the following function in the init:
HookRegistry::register (‘TemplateManager::display’, array($this, ‘loadTemplateData’));

And I manage to get the article Id ($article->getId()) by initializing $article variable with the good argument (number 2). I think, at first I didn’t initialized the $article variable with the good argument number.

This allowed me to understand how to pass data to a template file in the theming API.

Thanks a lot for all your advices and your help.
Best regards.
Helene

Hi @hcl,

Glad you were able to get it working! It’s great to see people pushing what the theme api can do.

The ArticleHandler::view hook is a special hook specifically for the article view page. But not every template has it’s own special hook. So in those cases, you may need to use the TemplateManager::display hook to get into the template before it’s rendered.

Hi, I am using OJS 3.1. Could you please tell me the steps used to create this function (Accepted Date). What codes should I add and in which files. I tried doing these steps:

Copied this code in my theme’s javascript.js file

public function articleView($hookName, $args) {
$templateMgr = TemplateManager::getManager($request);
$article =$args[2];
$editDecisionDao = DAORegistry::getDAO(‘EditDecisionDAO’);
$templateMgr->assign(‘editDecisionDao’, $editDecisionDao);
$editorDecisions = $editDecisionDao->getEditorDecisions($article->getId());
$lastDecision = count($editorDecisions) >= 1 ? $editorDecisions[count($editorDecisions) - 1] : null;
$dateAccepted = $lastDecision[‘decision’] == 1 ? $lastDecision[‘dateDecided’] : null;
$templateMgr->assign(‘dateAccepted’, $dateAccepted);
}

and then copied in my theme’s inc.php file

HookRegistry::register(‘ArticleHandler::view’,array($this, ‘articleView’));

Finally added

{$article->getDateAccepted()|date_format}

in my theme’s template file, but it didnt show

Hi @varshilmehta,

The “public function articleView” must also be present in your theme’s inc.php file and not in your javascript.js file. This function is in PHP code and not in Javascript code.
And getDateAccepted is a variable and not a function that must be called like that and not with $article object.

Here is what you need to do:

  • Copy “HookRegistry::register” code in your theme’s inc.php file at the beginning of init function
  • Copy “public function articleView” in your theme’s inc.php file outside init function (for example after getDescription function)
  • Add for example the following code in your theme’s template file:
    {$dateAccepted|date_format:"%e %B %Y"}

I hope it will be helpful.
Best regards.
Helene

1 Like

It is still not showing up. I did exactly like you mentioned

In which template file do you display $dateAccepted variable ?

To verify if data of public function articleView is well called in your template file, can you add this code at the beginning of function articleView:
echo "function articleView</br>";

In my case, I added $dateAccepted variable in:
mytheme/templates/frontend/objects/article_details.tpl
and the value is displayed via this URL for example:
http://journals.sfu.ca/present3/index.php/demojournal/article/view/6

I have also added dateaccepted in my article_details.tpl
I have also added “function articleView
”; as per your suggestion and it is displaying on the top

It’s a good news.
In this kind of situation you have to progress step by step to see where it doesn’t work.
Modify the code of public function articleView as follows:

    public function articleView($hookName, $args) {
    echo "function articleView</br>";
    $templateMgr = TemplateManager::getManager($request);
    $article =$args[2];
    $articleId=$article->getId();
    echo "articleId: $articleId</br>";
    $editDecisionDao = DAORegistry::getDAO(‘EditDecisionDAO’);
    $templateMgr->assign(‘editDecisionDao’, $editDecisionDao);
    $editorDecisions = $editDecisionDao->getEditorDecisions($article->getId());
    $cEditorDecisions = count($editorDecisions);
    echo "cEditorDecisions: $cEditorDecisions</br>";
    echo "Start editorDecisions</br>";
    print_r($editorDecisions);
    echo "</br>End editorDecisions</br>";
    $lastDecision = count($editorDecisions) >= 1 ? $editorDecisions[count($editorDecisions) - 1] : null;
    $dateAccepted = $lastDecision[‘decision’] == 1 ? $lastDecision[‘dateDecided’] : null;
    echo "dateAccepted: $dateAccepted</br>";
    $templateMgr->assign(‘dateAccepted’, $dateAccepted);
    }

And have a look on what is displaying on the top.
You should have something like this:

    function articleView
    articleId: 1570
    cEditorDecisions: 4
    Start editorDecisions
    Array ( [0] => Array ( [editDecisionId] => 1397 ... [dateDecided] => 2017-01-14 17:57:01 ) )
    End editorDecisions
    dateAccepted: 2017-01-14 17:57:01

In editorDecisions Array, you should have a value for “dateDecided”

I just got
function articleView
articleId: 84

I think it is different for OJS 3.1

Hi @varshilmehta, finally did you get this?
I have tried everything I found in this forum (#3061, the plugin from Github and several ways to get the acceptance date to show up in article_details template) but I can not make it to work.

We are using a custom bootstrap 3 theme on a OJS 3.1 and so far I worked on BootstrapThreeThemePlugin.inc.php to load the articleView function, and the HookRegistry in the init fuction. Also I have tried several ways to call the variable $dateAccepted from the smarty template, but always get blank result.

As @hcl proposed, I modified the code of public function as follows:
18
And I get this at the top:
35

It looks like the variable $dateAccepted is not saving any value…

This is how I am trying to get the date in the smarty template “article-details.tpl”.
06

@asmecher, @bozana, could you help me please? Thanks :slight_smile:

Daniel
ICONO14