From 2f403077e4a7afa06aa6dac0f08622903ae90233 Mon Sep 17 00:00:00 2001 From: Jhon Date: Tue, 19 Mar 2024 13:30:29 -0400 Subject: [PATCH 01/12] WIP: Creation of annotations page Signed-off-by: Jhon --- HypothesisPlugin.php | 11 +++ classes/HypothesisDAO.php | 23 +++++ pages/annotations/AnnotationsHandler.php | 120 +++++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 classes/HypothesisDAO.php create mode 100644 pages/annotations/AnnotationsHandler.php diff --git a/HypothesisPlugin.php b/HypothesisPlugin.php index 0e41043..4a7e003 100644 --- a/HypothesisPlugin.php +++ b/HypothesisPlugin.php @@ -25,6 +25,7 @@ function register($category, $path, $mainContextId = null) { if (parent::register($category, $path, $mainContextId)) { Hook::add('ArticleHandler::download',array(&$this, 'callback')); Hook::add('TemplateManager::display', array(&$this, 'callbackTemplateDisplay')); + Hook::add('LoadHandler', [$this, 'addAnnotationsHandler']); return true; } return false; @@ -79,6 +80,16 @@ function changePdfjsPath($output, $templateMgr) { return $newOutput; } + public function addAnnotationsHandler($hookName, $args) + { + $page = $args[0]; + if ($page == 'annotations') { + define('HANDLER_CLASS', 'APP\plugins\generic\hypothesis\pages\annotations\AnnotationsHandler'); + return true; + } + return false; + } + /** * Get the display name of this plugin * @return string diff --git a/classes/HypothesisDAO.php b/classes/HypothesisDAO.php new file mode 100644 index 0000000..0773626 --- /dev/null +++ b/classes/HypothesisDAO.php @@ -0,0 +1,23 @@ +where('submission_id', $submissionId) + ->select('current_publication_id') + ->first(); + $currentPublicationId = get_object_vars($result)['current_publication_id']; + + $result = DB::table('publications') + ->where('publication_id', $currentPublicationId) + ->select('date_published') + ->first(); + + return get_object_vars($result)['date_published']; + } +} \ No newline at end of file diff --git a/pages/annotations/AnnotationsHandler.php b/pages/annotations/AnnotationsHandler.php new file mode 100644 index 0000000..0b3787e --- /dev/null +++ b/pages/annotations/AnnotationsHandler.php @@ -0,0 +1,120 @@ +addPolicy(new ContextRequiredPolicy($request)); + $this->addPolicy(new OpsServerMustPublishPolicy($request)); + + return parent::authorize($request, $args, $roleAssignments); + } + + public function index($args, $request) { + $plugin = PluginRegistry::getPlugin('generic', 'hypothesisplugin'); + $context = $request->getContext(); + + $paginationParams = $this->getPaginationParams($args, $request, $context); + $pubIdPlugins = PluginRegistry::loadCategory('pubIds', true, $context->getId()); + + $templateMgr = TemplateManager::getManager($request); + $templateMgr->assign($paginationParams); + $templateMgr->assign('pubIdPlugins', $pubIdPlugins); + $templateMgr->assign('journal', $context); + + $jsUrl = $request->getBaseUrl() . '/' . $plugin->getPluginPath() . '/js/load.js'; + $templateMgr->addJavascript('AnnotationsPage', $jsUrl, ['contexts' => 'frontend']); + + return $templateMgr->display($plugin->getTemplateResource('annotationsPage.tpl')); + } + + private function getPaginationParams($args, $request, $context): array { + $page = isset($args[0]) ? (int) $args[0] : 1; + $itemsPerPage = $context->getData('itemsPerPage') ? $context->getData('itemsPerPage') : (int) Config::getVar('interface', 'items_per_page'); + $offset = $page > 1 ? ($page - 1) * $itemsPerPage : 0; + + $orderBy = ($request->getUserVar('orderBy') ?? self::ORDER_BY_LAST_ANNOTATION); + $submissionsAnnotations = $this->getSubmissionsAnnotations($context->getId(), $orderBy); + $pageAnnotations = array_slice($submissionsAnnotations, $offset, $itemsPerPage); + + $total = count($submissionsAnnotations); + $showingStart = $offset + 1; + $showingEnd = min($offset + $itemsPerPage, $offset + count($pageAnnotations)); + $nextPage = $total > $showingEnd ? $page + 1 : null; + $prevPage = $showingStart > 1 ? $page - 1 : null; + + foreach ($pageAnnotations as $submissionAnnotation) { + $submissionAnnotation->submission = Repo::submission()->get($submissionAnnotation->submissionId); + } + + return [ + 'submissionsAnnotations' => $pageAnnotations, + 'orderBy' => $orderBy, + 'showingStart' => $showingStart, + 'showingEnd' => $showingEnd, + 'total' => $total, + 'nextPage' => $nextPage, + 'prevPage' => $prevPage + ]; + } + + private function getSubmissionsAnnotations($contextId, $orderBy) { + $cacheManager = CacheManager::getManager(); + $cache = $cacheManager->getFileCache( + $contextId, + 'submissions_annotations', + [$this, 'cacheDismiss'] + ); + + $submissionsAnnotations = $cache->getContents(); + + if (is_null($submissionsAnnotations)){ + $cache->flush(); + $hypothesisHandler = new HypothesisHandler(); + $cache->setEntireCache($hypothesisHandler->getSubmissionsAnnotations($contextId)); + $submissionsAnnotations = $cache->getContents(); + } + + $orderingFunction = $orderBy.'Ordering'; + usort($submissionsAnnotations, [$this, $orderingFunction]); + + return $submissionsAnnotations; + } + + public function lastAnnotationOrdering($submissionAnnotationsA, $submissionAnnotationsB) { + $lastAnnotationA = $submissionAnnotationsA->annotations[0]; + $lastAnnotationB = $submissionAnnotationsB->annotations[0]; + + if($lastAnnotationA->dateCreated == $lastAnnotationB->dateCreated) return 0; + + return ($lastAnnotationA->dateCreated < $lastAnnotationB->dateCreated) ? 1 : -1; + } + + public function datePublishedOrdering($submissionAnnotationsA, $submissionAnnotationsB) { + $hypothesisDao = new HypothesisDAO(); + $datePublishedA = $hypothesisDao->getDatePublished($submissionAnnotationsA->submissionId); + $datePublishedB = $hypothesisDao->getDatePublished($submissionAnnotationsB->submissionId); + + if($datePublishedA == $datePublishedB) return 0; + + return ($datePublishedA < $datePublishedB) ? 1 : -1; + } + + function cacheDismiss() { + return null; + } +} From 4179b0cdaec6df96b0ac38ef4c2687efcb76b383 Mon Sep 17 00:00:00 2001 From: Jhon Date: Tue, 19 Mar 2024 15:47:14 -0400 Subject: [PATCH 02/12] Finishes implementing annotations page Signed-off-by: Jhon --- classes/Annotation.php | 22 ++++ classes/HypothesisHandler.php | 131 +++++++++++++++++++++++ classes/SubmissionAnnotations.php | 26 +++++ js/load.js | 35 ++++++ locale/en/locale.po | 24 +++++ locale/es/locale.po | 24 +++++ locale/pt_BR/locale.po | 24 +++++ locale/pt_PT/locale.po | 24 +++++ pages/annotations/AnnotationsHandler.php | 10 +- styles/annotationsPage.css | 77 +++++++++++++ templates/annotationsPage.tpl | 66 ++++++++++++ templates/submissionAnnotations.tpl | 67 ++++++++++++ 12 files changed, 528 insertions(+), 2 deletions(-) create mode 100644 classes/Annotation.php create mode 100644 classes/HypothesisHandler.php create mode 100644 classes/SubmissionAnnotations.php create mode 100644 js/load.js create mode 100644 styles/annotationsPage.css create mode 100644 templates/annotationsPage.tpl create mode 100644 templates/submissionAnnotations.tpl diff --git a/classes/Annotation.php b/classes/Annotation.php new file mode 100644 index 0000000..b72e58b --- /dev/null +++ b/classes/Annotation.php @@ -0,0 +1,22 @@ +user = $user; + $this->dateCreated = $dateCreated; + $this->target = $target; + $this->content = $content; + } + + public static function __set_state($dump) { + $obj = new Annotation($dump['user'], $dump['dateCreated'], $dump['target'], $dump['content']); + return $obj; + } +} diff --git a/classes/HypothesisHandler.php b/classes/HypothesisHandler.php new file mode 100644 index 0000000..dbb95d2 --- /dev/null +++ b/classes/HypothesisHandler.php @@ -0,0 +1,131 @@ +getCollector() + ->filterByContextIds([$contextId]) + ->getMany(); + + $groupsRequests = $this->getSubmissionsGroupsRequests($submissions, $contextId); + $submissionsAnnotations = []; + foreach ($groupsRequests as $groupRequest) { + $groupResponse = $this->getRequestAnnotations($groupRequest); + if (!is_null($groupResponse) && $groupResponse['total'] > 0) { + $submissionsAnnotations = array_merge( + $submissionsAnnotations, + $this->groupSubmissionsAnnotations($groupResponse) + ); + } + } + + return $submissionsAnnotations; + } + + private function getSubmissionsGroupsRequests($submissions, $contextId) { + $requests = []; + $requestPrefix = $currentRequest = "https://hypothes.is/api/search?limit=200&group=__world__"; + $maxRequestLength = 4094; + + foreach ($submissions as $submission) { + $submissionRequestParams = $this->getSubmissionRequestParams($submission, $contextId); + + if(!is_null($submissionRequestParams)) { + if(strlen($currentRequest.$submissionRequestParams) < $maxRequestLength) { + $currentRequest .= $submissionRequestParams; + } + else { + $requests[] = $currentRequest; + $currentRequest = $requestPrefix . $submissionRequestParams; + } + } + } + + return $requests; + } + + private function getSubmissionRequestParams($submission, $contextId) { + $submissionRequestParams = ""; + $publication = $submission->getCurrentPublication(); + + if(is_null($publication)) + return null; + + $galleys = $publication->getData('galleys'); + foreach ($galleys as $galley) { + $galleyDownloadURL = $this->getGalleyDownloadURL($galley, $contextId); + if(!is_null($galleyDownloadURL)) + $submissionRequestParams .= "&uri={$galleyDownloadURL}"; + } + + return $submissionRequestParams; + } + + private function getRequestAnnotations($requestURL) { + $ch = curl_init($requestURL); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + $output = curl_exec($ch); + if(!$output || substr($output, 1, 8) != '"total":') return null; + + return json_decode($output, true); + } + + private function groupSubmissionsAnnotations($groupResponse) { + $submissionsAnnotations = []; + + foreach ($groupResponse['rows'] as $annotationResponse) { + $urlBySlash = explode("/", $annotationResponse['links']['incontext']); + $submissionId = (int) $urlBySlash[count($urlBySlash) - 3]; + + if(!array_key_exists($submissionId, $submissionsAnnotations)) { + $submissionsAnnotations[$submissionId] = new SubmissionAnnotations($submissionId); + } + + $annotation = $this->getAnnotation($annotationResponse); + $submissionsAnnotations[$submissionId]->addAnnotation($annotation); + } + + return $submissionsAnnotations; + } + + private function getAnnotation($annotationResponse): Annotation { + $user = substr($annotationResponse['user'], 5, strlen($annotationResponse['user']) - 17); + $dateCreated = $annotationResponse['created']; + $content = $annotationResponse['text']; + + $target = ""; + if(isset($annotationResponse['target'][0]['selector'])) { + foreach ($annotationResponse['target'][0]['selector'] as $selector) { + if($selector['type'] == 'TextQuoteSelector') { + $target = $selector['exact']; + break; + } + } + } + + return new Annotation($user, $dateCreated, $target, $content); + } + + public function getGalleyDownloadURL($galley, $contextId) { + $request = Application::get()->getRequest(); + $indexUrl = $request->getIndexUrl(); + $context = Application::getContextDAO()->getById($contextId); + $contextPath = $context->getPath(); + + $submissionFile = $galley->getFile(); + if(is_null($submissionFile)) + return null; + + $submissionId = $submissionFile->getData('submissionId'); + $assocId = $submissionFile->getData('assocId'); + $submissionFileId = $submissionFile->getId(); + + return $indexUrl . "/$contextPath/preprint/download/$submissionId/$assocId/$submissionFileId"; + } +} \ No newline at end of file diff --git a/classes/SubmissionAnnotations.php b/classes/SubmissionAnnotations.php new file mode 100644 index 0000000..edb70aa --- /dev/null +++ b/classes/SubmissionAnnotations.php @@ -0,0 +1,26 @@ +submissionId = $submissionId; + $this->annotations = []; + } + + public static function __set_state($dump) { + $obj = new SubmissionAnnotations($dump['submissionId']); + $obj->annotations = $dump['annotations']; + return $obj; + } + + public function addAnnotation(Annotation $annotation) { + $this->annotations[] = $annotation; + } +} \ No newline at end of file diff --git a/js/load.js b/js/load.js new file mode 100644 index 0000000..299015d --- /dev/null +++ b/js/load.js @@ -0,0 +1,35 @@ +let maxCharNumber = 300; +let annotationTargets = document.querySelectorAll('.annotation_target > blockquote'); +let annotationContents = document.querySelectorAll('.annotation_content > blockquote'); + +annotationTargets.forEach(target => { + addReadMoreLogic(target); +}); + +annotationContents.forEach(content => { + addReadMoreLogic(content); +}); + +function addReadMoreLogic(element) { + if(element.textContent.length <= maxCharNumber) { + let readMoreBtn = element.nextElementSibling; + readMoreBtn.style.display = "none"; + } + else { + let trimmedText = element.textContent.trim(); + let textToDisplay = trimmedText.slice(0, maxCharNumber); + let textMore = trimmedText.slice(maxCharNumber); + element.innerHTML = `${textToDisplay}...${textMore}`; + } +} + +function toggleReadMore(btn){ + let parent = btn.parentElement; + parent.querySelector('.dots').classList.toggle('hide'); + parent.querySelector('.more').classList.toggle('hide'); + if(btn.classList.contains('read_more')) + btn.nextElementSibling.classList.remove('hide'); + else + btn.previousElementSibling.classList.remove('hide'); + btn.classList.add('hide'); +} \ No newline at end of file diff --git a/locale/en/locale.po b/locale/en/locale.po index 1d54807..0b73707 100644 --- a/locale/en/locale.po +++ b/locale/en/locale.po @@ -16,3 +16,27 @@ msgstr "Hypothes.is Plugin" msgid "plugins.generic.hypothesis.description" msgstr "This plugin enables Hypothes.is integration into OJS article views for reader annotation and commenting." + +msgid "plugins.generic.hypothesis.annotation" +msgstr "annotation" + +msgid "plugins.generic.hypothesis.annotations" +msgstr "annotations" + +msgid "plugins.generic.hypothesis.annotationsPage" +msgstr "Annotations" + +msgid "plugins.generic.hypothesis.annotationsPageNumber" +msgstr "Annotations - Page {$pageNumber}" + +msgid "plugins.generic.hypothesis.noSubmissionsWithAnnotations" +msgstr "There are no annotated submissions" + +msgid "plugins.generic.hypothesis.orderBy" +msgstr "Order by:" + +msgid "plugins.generic.hypothesis.orderBy.datePublished" +msgstr "Date published" + +msgid "plugins.generic.hypothesis.orderBy.lastAnnotation" +msgstr "Date of last annotation" diff --git a/locale/es/locale.po b/locale/es/locale.po index 7ffe464..8f8aed4 100644 --- a/locale/es/locale.po +++ b/locale/es/locale.po @@ -18,3 +18,27 @@ msgstr "" msgid "plugins.generic.hypothesis.name" msgstr "Módulo Hypothes.is" + +msgid "plugins.generic.hypothesis.annotation" +msgstr "annotación" + +msgid "plugins.generic.hypothesis.annotations" +msgstr "anotaciones" + +msgid "plugins.generic.hypothesis.annotationsPage" +msgstr "Anotaciones" + +msgid "plugins.generic.hypothesis.annotationsPageNumber" +msgstr "Anotaciones - Página {$pageNumber}" + +msgid "plugins.generic.hypothesis.noSubmissionsWithAnnotations" +msgstr "No hay envíos anotados" + +msgid "plugins.generic.hypothesis.orderBy" +msgstr "Ordenar por:" + +msgid "plugins.generic.hypothesis.orderBy.datePublished" +msgstr "Fecha de publicación" + +msgid "plugins.generic.hypothesis.orderBy.lastAnnotation" +msgstr "Fecha de la última annotación" diff --git a/locale/pt_BR/locale.po b/locale/pt_BR/locale.po index 7339509..ccec324 100644 --- a/locale/pt_BR/locale.po +++ b/locale/pt_BR/locale.po @@ -18,3 +18,27 @@ msgstr "" msgid "plugins.generic.hypothesis.name" msgstr "Plugin Hypothes.is" + +msgid "plugins.generic.hypothesis.annotation" +msgstr "anotação" + +msgid "plugins.generic.hypothesis.annotations" +msgstr "anotações" + +msgid "plugins.generic.hypothesis.annotationsPage" +msgstr "Anotações" + +msgid "plugins.generic.hypothesis.annotationsPageNumber" +msgstr "Anotações - Página {$pageNumber}" + +msgid "plugins.generic.hypothesis.noSubmissionsWithAnnotations" +msgstr "Não há submissões com anotações" + +msgid "plugins.generic.hypothesis.orderBy" +msgstr "Ordenar por:" + +msgid "plugins.generic.hypothesis.orderBy.datePublished" +msgstr "Data de postagem" + +msgid "plugins.generic.hypothesis.orderBy.lastAnnotation" +msgstr "Data da última anotação" \ No newline at end of file diff --git a/locale/pt_PT/locale.po b/locale/pt_PT/locale.po index df28e3b..78e8938 100644 --- a/locale/pt_PT/locale.po +++ b/locale/pt_PT/locale.po @@ -16,3 +16,27 @@ msgstr "Plugin Hypothes.is" msgid "plugins.generic.hypothesis.description" msgstr "Este plugin permite a integração do Hypothes.is nas visualizações de artigo do OJS permitindo anotações e comentários dos leitores." + +msgid "plugins.generic.hypothesis.annotation" +msgstr "anotação" + +msgid "plugins.generic.hypothesis.annotations" +msgstr "anotações" + +msgid "plugins.generic.hypothesis.annotationsPage" +msgstr "Anotações" + +msgid "plugins.generic.hypothesis.annotationsPageNumber" +msgstr "Anotações - Página {$pageNumber}" + +msgid "plugins.generic.hypothesis.noSubmissionsWithAnnotations" +msgstr "Não há submissões com anotações" + +msgid "plugins.generic.hypothesis.orderBy" +msgstr "Ordenar por:" + +msgid "plugins.generic.hypothesis.orderBy.datePublished" +msgstr "Data de postagem" + +msgid "plugins.generic.hypothesis.orderBy.lastAnnotation" +msgstr "Data da última anotação" \ No newline at end of file diff --git a/pages/annotations/AnnotationsHandler.php b/pages/annotations/AnnotationsHandler.php index 0b3787e..abb9f22 100644 --- a/pages/annotations/AnnotationsHandler.php +++ b/pages/annotations/AnnotationsHandler.php @@ -1,5 +1,7 @@ $showingEnd, 'total' => $total, 'nextPage' => $nextPage, - 'prevPage' => $prevPage + 'prevPage' => $prevPage, + 'authorUserGroups' => Repo::userGroup()->getCollector() + ->filterByRoleIds([\PKP\security\Role::ROLE_ID_AUTHOR]) + ->filterByContextIds([$context->getId()]) + ->getMany()->remember(), ]; } diff --git a/styles/annotationsPage.css b/styles/annotationsPage.css new file mode 100644 index 0000000..a799c8e --- /dev/null +++ b/styles/annotationsPage.css @@ -0,0 +1,77 @@ +#orderSubmissions { + margin-bottom: 1rem; +} + +#selectOrderSubmissions { + background: #FFF; + border: 1px solid rgba(0,0,0,0.4); + border-radius: 3px; + font-size: 0.93rem; + height: calc(2.143rem - 2px); +} + +.submission_annotations { + background-color: #fafaf8; + padding: 10px 15px; + border-radius: 3px; +} + +.submission_annotations > .title { + font-size: 16px; + line-height: 20px; + font-weight: 700; +} + +.meta { + padding-top: 5px; + font-size: 14px; + line-height: 20px; +} + +.meta > .authors { + padding-right: 5em; +} + +.meta > .published, .meta > .doi { + color: rgba(0,0,0,0.54); +} + +.annotation { + background-color: #FFF; + font-size: 14px; + margin: 10px 0 0 15px; + padding: 14px; + border-radius: 3px; + box-shadow: 0px 2px 3px 0 rgba(0,0,0,0.2); +} + +.annotation_header span { + color: rgba(0,0,0,0.54); + margin-left: 8px; + float: right; +} + +.annotation_target { + font-style: italic; + margin: 1em 0; + padding: 0 1em; + color: rgba(0,0,0,0.54); +} + +.annotation_target blockquote, .annotation_content blockquote { + margin-bottom: 4px; +} + +.read_more, .read_less { + padding: 3px 6px; + border: 1px solid #007bff; + border-radius: 14px; + color: #007bff; + background-color: #FFF; + line-height: 20px; + font-weight: 700; +} + +.hide { + display: none; +} \ No newline at end of file diff --git a/templates/annotationsPage.tpl b/templates/annotationsPage.tpl new file mode 100644 index 0000000..c2cbcbf --- /dev/null +++ b/templates/annotationsPage.tpl @@ -0,0 +1,66 @@ +{capture assign="pageTitle"} + {if $prevPage} + {translate key="plugins.generic.hypothesis.annotationsPageNumber" pageNumber=$prevPage+1} + {else} + {translate key="plugins.generic.hypothesis.annotationsPage"} + {/if} +{/capture} + +{include file="frontend/components/header.tpl" pageTitleTranslated=$pageTitle} + +
+

{$pageTitle|escape}

+ + {if empty($submissionsAnnotations)} +

{translate key="plugins.generic.hypothesis.noSubmissionsWithAnnotations"}

+ {else} +
+ + +
+ +
    + {foreach from=$submissionsAnnotations item="submissionAnnotations"} +
  • + {include file="../../../plugins/generic/hypothesis/templates/submissionAnnotations.tpl"} +
  • + {/foreach} +
+ + {* Pagination *} + {if $prevPage > 1} + {capture assign=prevUrl}{url router=$smarty.const.ROUTE_PAGE page="annotations" path=$prevPage params=['orderBy' => $orderBy]}{/capture} + {elseif $prevPage === 1} + {capture assign=prevUrl}{url router=$smarty.const.ROUTE_PAGE page="annotations" params=['orderBy' => $orderBy]}{/capture} + {/if} + {if $nextPage} + {capture assign=nextUrl}{url router=$smarty.const.ROUTE_PAGE page="annotations" path=$nextPage params=['orderBy' => $orderBy]}{/capture} + {/if} + {include + file="frontend/components/pagination.tpl" + prevUrl=$prevUrl + nextUrl=$nextUrl + showingStart=$showingStart + showingEnd=$showingEnd + total=$total + } + {/if} +
+ +{include file="frontend/components/footer.tpl"} + + diff --git a/templates/submissionAnnotations.tpl b/templates/submissionAnnotations.tpl new file mode 100644 index 0000000..9257d7f --- /dev/null +++ b/templates/submissionAnnotations.tpl @@ -0,0 +1,67 @@ +{assign var="preprint" value=$submissionAnnotations->submission} +{assign var="annotations" value=$submissionAnnotations->annotations} + +
+ +
+
+ {$preprint->getCurrentPublication()->getAuthorString($authorUserGroups)|escape} +
+ + {* DOI *} + {foreach from=$pubIdPlugins item=pubIdPlugin} + {if $pubIdPlugin->getPubIdType() != 'doi'} + {continue} + {/if} + {assign var=pubId value=$preprint->getCurrentPublication()->getStoredPubId($pubIdPlugin->getPubIdType())} + {if $pubId} + {assign var="doiUrl" value=$pubIdPlugin->getResolvingURL($currentServer->getId(), $pubId)|escape} +
+ {capture assign=translatedDOI}{translate key="doi.readerDisplayName"}{/capture} + {translate key="semicolon" label=$translatedDOI} + + + {$doiUrl} + + +
+ {/if} + {/foreach} + +
+ {translate key="submission.dates" submitted=$preprint->getDateSubmitted()|date_format:$dateFormatShort published=$preprint->getDatePublished()|date_format:$dateFormatShort} +
+
+ + {foreach from=$annotations item="annotation"} +
+
+ {$annotation->user|escape} + {$annotation->dateCreated|date_format:$dateFormatLong} +
+ {if not empty($annotation->target)} +
+
{$annotation->target|escape}
+ + +
+ {/if} + +
{$annotation->content|escape}
+ + +
+
+ {/foreach} +
From 850d40d77b6e6cbc85cb7f5c304ca536e5e1224a Mon Sep 17 00:00:00 2001 From: Jhon Date: Tue, 19 Mar 2024 18:50:58 -0400 Subject: [PATCH 03/12] WIP: Adding of annotations viewers Signed-off-by: Jhon --- HypothesisPlugin.php | 17 +++++++++++++---- templates/addAnnotationViewers.tpl | 10 ++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 templates/addAnnotationViewers.tpl diff --git a/HypothesisPlugin.php b/HypothesisPlugin.php index 4a7e003..3a6c0ed 100644 --- a/HypothesisPlugin.php +++ b/HypothesisPlugin.php @@ -23,9 +23,10 @@ class HypothesisPlugin extends GenericPlugin { */ function register($category, $path, $mainContextId = null) { if (parent::register($category, $path, $mainContextId)) { - Hook::add('ArticleHandler::download',array(&$this, 'callback')); + Hook::add('ArticleHandler::download', array(&$this, 'callback')); Hook::add('TemplateManager::display', array(&$this, 'callbackTemplateDisplay')); - Hook::add('LoadHandler', [$this, 'addAnnotationsHandler']); + Hook::add('Templates::Preprint::Details', array($this, 'addAnnotationNumberViewers')); + Hook::add('LoadHandler', array($this, 'addAnnotationsHandler')); return true; } return false; @@ -80,8 +81,16 @@ function changePdfjsPath($output, $templateMgr) { return $newOutput; } - public function addAnnotationsHandler($hookName, $args) - { + public function addAnnotationNumberViewers($hookName, $args) { + $templateMgr = $args[1]; + $output = &$args[2]; + + $output .= $templateMgr->fetch($this->getTemplateResource('addAnnotationViewers.tpl')); + + return false; + } + + public function addAnnotationsHandler($hookName, $args) { $page = $args[0]; if ($page == 'annotations') { define('HANDLER_CLASS', 'APP\plugins\generic\hypothesis\pages\annotations\AnnotationsHandler'); diff --git a/templates/addAnnotationViewers.tpl b/templates/addAnnotationViewers.tpl new file mode 100644 index 0000000..4c1dabd --- /dev/null +++ b/templates/addAnnotationViewers.tpl @@ -0,0 +1,10 @@ + + \ No newline at end of file From dee5524eac8d664c301defd9ddcaf256f379e944 Mon Sep 17 00:00:00 2001 From: Jhon Date: Wed, 20 Mar 2024 17:40:24 -0400 Subject: [PATCH 04/12] Renames HypothesisHandler to HypothesisHelper Signed-off-by: Jhon --- classes/{HypothesisHandler.php => HypothesisHelper.php} | 2 +- pages/annotations/AnnotationsHandler.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename classes/{HypothesisHandler.php => HypothesisHelper.php} (99%) diff --git a/classes/HypothesisHandler.php b/classes/HypothesisHelper.php similarity index 99% rename from classes/HypothesisHandler.php rename to classes/HypothesisHelper.php index dbb95d2..fd158f3 100644 --- a/classes/HypothesisHandler.php +++ b/classes/HypothesisHelper.php @@ -7,7 +7,7 @@ use APP\plugins\generic\hypothesis\classes\Annotation; use APP\plugins\generic\hypothesis\classes\SubmissionAnnotations; -class HypothesisHandler { +class HypothesisHelper { public function getSubmissionsAnnotations($contextId) { $submissions = Repo::submission()->getCollector() ->filterByContextIds([$contextId]) diff --git a/pages/annotations/AnnotationsHandler.php b/pages/annotations/AnnotationsHandler.php index abb9f22..675256b 100644 --- a/pages/annotations/AnnotationsHandler.php +++ b/pages/annotations/AnnotationsHandler.php @@ -10,7 +10,7 @@ use PKP\cache\CacheManager; use PKP\security\authorization\ContextRequiredPolicy; use APP\security\authorization\OpsServerMustPublishPolicy; -use APP\plugins\generic\hypothesis\classes\HypothesisHandler; +use APP\plugins\generic\hypothesis\classes\HypothesisHelper; use APP\plugins\generic\hypothesis\classes\HypothesisDAO; class AnnotationsHandler extends Handler { @@ -90,8 +90,8 @@ private function getSubmissionsAnnotations($contextId, $orderBy) { if (is_null($submissionsAnnotations)){ $cache->flush(); - $hypothesisHandler = new HypothesisHandler(); - $cache->setEntireCache($hypothesisHandler->getSubmissionsAnnotations($contextId)); + $hypothesisHelper = new HypothesisHelper(); + $cache->setEntireCache($hypothesisHelper->getSubmissionsAnnotations($contextId)); $submissionsAnnotations = $cache->getContents(); } From 61dec744f8948d84eae11062c9153a2386601a86 Mon Sep 17 00:00:00 2001 From: Jhon Date: Wed, 20 Mar 2024 19:08:06 -0400 Subject: [PATCH 05/12] WIP: Add annotation viewers to frontend pages Signed-off-by: Jhon --- HypothesisPlugin.php | 43 +++++++++++++++++++++++++++--- controllers/HypothesisHandler.php | 19 +++++++++++++ js/addAnnotationViewers.js | 34 +++++++++++++++++++++++ styles/annotationViewer.css | 20 ++++++++++++++ templates/addAnnotationViewers.tpl | 10 ------- 5 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 controllers/HypothesisHandler.php create mode 100644 js/addAnnotationViewers.js create mode 100644 styles/annotationViewer.css delete mode 100644 templates/addAnnotationViewers.tpl diff --git a/HypothesisPlugin.php b/HypothesisPlugin.php index 3a6c0ed..e6441a1 100644 --- a/HypothesisPlugin.php +++ b/HypothesisPlugin.php @@ -16,6 +16,8 @@ use PKP\plugins\GenericPlugin; use PKP\plugins\Hook; +use APP\core\Application; +use APP\template\TemplateManager; class HypothesisPlugin extends GenericPlugin { /** @@ -25,8 +27,12 @@ function register($category, $path, $mainContextId = null) { if (parent::register($category, $path, $mainContextId)) { Hook::add('ArticleHandler::download', array(&$this, 'callback')); Hook::add('TemplateManager::display', array(&$this, 'callbackTemplateDisplay')); - Hook::add('Templates::Preprint::Details', array($this, 'addAnnotationNumberViewers')); + Hook::add('TemplateManager::display', [$this, 'addAnnotationNumberViewers']); Hook::add('LoadHandler', array($this, 'addAnnotationsHandler')); + Hook::add('LoadComponentHandler', array($this, 'setupHypothesisHandler')); + + $this->addHandlerURLToJavaScript(); + return true; } return false; @@ -82,11 +88,22 @@ function changePdfjsPath($output, $templateMgr) { } public function addAnnotationNumberViewers($hookName, $args) { - $templateMgr = $args[1]; - $output = &$args[2]; + $templateMgr = $args[0]; + $template = $args[1]; + $pagesToInsert = [ + 'frontend/pages/indexServer.tpl' + ]; - $output .= $templateMgr->fetch($this->getTemplateResource('addAnnotationViewers.tpl')); + if (in_array($template, $pagesToInsert)) { + $request = Application::get()->getRequest(); + $jsUrl = $request->getBaseUrl() . '/' . $this->getPluginPath() . '/js/addAnnotationViewers.js'; + $styleUrl = $request->getBaseUrl() . '/' . $this->getPluginPath() . '/styles/annotationViewer.css'; + + $templateMgr->addJavascript('AddAnnotationViewers', $jsUrl, ['contexts' => 'frontend']); + $templateMgr->addStyleSheet('AnnotationViewerStyleSheet', $styleUrl, ['contexts' => 'frontend']); + } + return false; } @@ -99,6 +116,24 @@ public function addAnnotationsHandler($hookName, $args) { return false; } + public function setupHypothesisHandler($hookName, $args) { + $component = &$args[0]; + if ($component == 'plugins.generic.hypothesis.controllers.HypothesisHandler') { + return true; + } + return false; + } + + public function addHandlerURLToJavaScript() + { + $request = Application::get()->getRequest(); + $templateMgr = TemplateManager::getManager($request); + $handlerUrl = $request->getDispatcher()->url($request, Application::ROUTE_COMPONENT, null, 'plugins.generic.hypothesis.controllers.HypothesisHandler'); + $data = ['hypothesisHandlerUrl' => $handlerUrl]; + + $templateMgr->addJavaScript('HypothesisHandler', 'app = ' . json_encode($data) . ';', ['contexts' => 'frontend', 'inline' => true]); + } + /** * Get the display name of this plugin * @return string diff --git a/controllers/HypothesisHandler.php b/controllers/HypothesisHandler.php new file mode 100644 index 0000000..d25bef7 --- /dev/null +++ b/controllers/HypothesisHandler.php @@ -0,0 +1,19 @@ +get($galleyId); + $fileId = $galley->getFile()->getId(); + + $galleyDownloadUrl = str_replace('view', 'download', $galleyUrl); + $galleyDownloadUrl .= "/$fileId"; + + return json_encode($galleyDownloadUrl); + } +} \ No newline at end of file diff --git a/js/addAnnotationViewers.js b/js/addAnnotationViewers.js new file mode 100644 index 0000000..59fe320 --- /dev/null +++ b/js/addAnnotationViewers.js @@ -0,0 +1,34 @@ + +function insertAfter(newNode, referenceNode) { + referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); +} + +function createAnnotationViewerNode(galleyUrl, message) { + var viewerLi = document.createElement('li'); + viewerLi.classList.add('annotation_viewer'); + var viewer = document.createElement('a'); + viewer.href = galleyUrl; + viewer.textContent = message; + + viewerLi.appendChild(viewer); + return viewerLi; +} + +async function addAnnotationViewers() { + let galleyLinks = document.getElementsByClassName('obj_galley_link'); + + for (let galleyLink of galleyLinks) { + let galleyUrl = galleyLink.href; + let galleyDownloadUrl = await $.get( + app.hypothesisHandlerUrl + 'get-galley-download-url', + { + galleyUrl: galleyUrl + } + ); + let viewerNode = createAnnotationViewerNode(JSON.parse(galleyDownloadUrl), '1 annotation'); + insertAfter(viewerNode, galleyLink.parentNode); + } +} + + +$(document).ready(addAnnotationViewers); \ No newline at end of file diff --git a/styles/annotationViewer.css b/styles/annotationViewer.css new file mode 100644 index 0000000..7108a9a --- /dev/null +++ b/styles/annotationViewer.css @@ -0,0 +1,20 @@ +.obj_article_details .galleys_links li { + margin-right: 0.25em; +} + +.annotation_viewer { + margin: 0.5em 0 1em; +} + +.annotation_viewer > a { + padding: 4px 8px; + border: 1px solid rgba(0,0,0,0.54); + border-radius: 15px; + color: rgba(0,0,0,0.54); + line-height: 20px; + font-size: 14px; +} + +.annotation_viewer > a:hover { + color: rgba(0,0,0,0.54); +} \ No newline at end of file diff --git a/templates/addAnnotationViewers.tpl b/templates/addAnnotationViewers.tpl deleted file mode 100644 index 4c1dabd..0000000 --- a/templates/addAnnotationViewers.tpl +++ /dev/null @@ -1,10 +0,0 @@ - - \ No newline at end of file From c1625f048a0fe38fccd8f8a77dfef6c619b460c8 Mon Sep 17 00:00:00 2001 From: Jhon Date: Thu, 21 Mar 2024 15:01:56 -0400 Subject: [PATCH 06/12] Finishes adding of annotations viewer number for OPS pages Signed-off-by: Jhon --- HypothesisPlugin.php | 4 +++- controllers/HypothesisHandler.php | 19 ++++++++++++++++--- js/addAnnotationViewers.js | 14 ++++++++++---- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/HypothesisPlugin.php b/HypothesisPlugin.php index e6441a1..c0f55ad 100644 --- a/HypothesisPlugin.php +++ b/HypothesisPlugin.php @@ -91,7 +91,9 @@ public function addAnnotationNumberViewers($hookName, $args) { $templateMgr = $args[0]; $template = $args[1]; $pagesToInsert = [ - 'frontend/pages/indexServer.tpl' + 'frontend/pages/indexServer.tpl', + 'frontend/pages/preprint.tpl', + 'frontend/pages/preprints.tpl' ]; if (in_array($template, $pagesToInsert)) { diff --git a/controllers/HypothesisHandler.php b/controllers/HypothesisHandler.php index d25bef7..cf533a5 100644 --- a/controllers/HypothesisHandler.php +++ b/controllers/HypothesisHandler.php @@ -4,16 +4,29 @@ use APP\facades\Repo; class HypothesisHandler extends Handler { - public function getGalleyDownloadUrl($args, $request) { + public function getAnnotationViewerData($args, $request) { $galleyUrl = $args['galleyUrl']; $explodedUrl = explode('/', $galleyUrl); $galleyId = (int) end($explodedUrl); + $galley = Repo::galley()->get($galleyId); - $fileId = $galley->getFile()->getId(); + if(!$galley) { + return json_encode(null); + } + $fileId = $galley->getFile()->getId(); $galleyDownloadUrl = str_replace('view', 'download', $galleyUrl); $galleyDownloadUrl .= "/$fileId"; + + $response = file_get_contents("https://hypothes.is/api/search?limit=0&group=__world__&uri={$galleyDownloadUrl}"); + $response = json_decode($response, true); + + if ($response['total'] > 0) { + $suffix = ($response['total'] == 1 ? 'annotation' : 'annotations'); + $message = $response['total'] . ' ' . __("plugins.generic.hypothesis.$suffix"); + return json_encode(['message' => $message]); + } - return json_encode($galleyDownloadUrl); + return json_encode(null); } } \ No newline at end of file diff --git a/js/addAnnotationViewers.js b/js/addAnnotationViewers.js index 59fe320..5a8849f 100644 --- a/js/addAnnotationViewers.js +++ b/js/addAnnotationViewers.js @@ -19,14 +19,20 @@ async function addAnnotationViewers() { for (let galleyLink of galleyLinks) { let galleyUrl = galleyLink.href; - let galleyDownloadUrl = await $.get( - app.hypothesisHandlerUrl + 'get-galley-download-url', + let viewerData = await $.get( + app.hypothesisHandlerUrl + 'get-annotation-viewer-data', { galleyUrl: galleyUrl } ); - let viewerNode = createAnnotationViewerNode(JSON.parse(galleyDownloadUrl), '1 annotation'); - insertAfter(viewerNode, galleyLink.parentNode); + + viewerData = JSON.parse(viewerData); + if (viewerData !== null) { + galleyUrl = galleyUrl + '?hasAnnotations=true'; + galleyLink.href = galleyUrl; + let viewerNode = createAnnotationViewerNode(galleyUrl, viewerData['message']); + insertAfter(viewerNode, galleyLink.parentNode); + } } } From 376b87300c525895e3d8805403d26838348a4f84 Mon Sep 17 00:00:00 2001 From: Jhon Date: Thu, 21 Mar 2024 16:43:15 -0400 Subject: [PATCH 07/12] Improves performance of annotation viewers adding Signed-off-by: Jhon --- controllers/HypothesisHandler.php | 15 +++++--------- js/addAnnotationViewers.js | 34 +++++++++++++++++++++++-------- styles/annotationViewer.css | 14 +++++++++++-- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/controllers/HypothesisHandler.php b/controllers/HypothesisHandler.php index cf533a5..317bb9b 100644 --- a/controllers/HypothesisHandler.php +++ b/controllers/HypothesisHandler.php @@ -18,15 +18,10 @@ public function getAnnotationViewerData($args, $request) { $galleyDownloadUrl = str_replace('view', 'download', $galleyUrl); $galleyDownloadUrl .= "/$fileId"; - $response = file_get_contents("https://hypothes.is/api/search?limit=0&group=__world__&uri={$galleyDownloadUrl}"); - $response = json_decode($response, true); - - if ($response['total'] > 0) { - $suffix = ($response['total'] == 1 ? 'annotation' : 'annotations'); - $message = $response['total'] . ' ' . __("plugins.generic.hypothesis.$suffix"); - return json_encode(['message' => $message]); - } - - return json_encode(null); + return json_encode([ + 'downloadUrl' => $galleyDownloadUrl, + 'annotationMsg' => __('plugins.generic.hypothesis.annotation'), + 'annotationsMsg' => __('plugins.generic.hypothesis.annotations') + ]); } } \ No newline at end of file diff --git a/js/addAnnotationViewers.js b/js/addAnnotationViewers.js index 5a8849f..e02ed01 100644 --- a/js/addAnnotationViewers.js +++ b/js/addAnnotationViewers.js @@ -3,12 +3,12 @@ function insertAfter(newNode, referenceNode) { referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); } -function createAnnotationViewerNode(galleyUrl, message) { +function createAnnotationViewerNode(galleyId) { var viewerLi = document.createElement('li'); viewerLi.classList.add('annotation_viewer'); + viewerLi.classList.add('hidden_viewer'); var viewer = document.createElement('a'); - viewer.href = galleyUrl; - viewer.textContent = message; + viewer.id = 'annotation_viewer_link-' + galleyId; viewerLi.appendChild(viewer); return viewerLi; @@ -19,20 +19,38 @@ async function addAnnotationViewers() { for (let galleyLink of galleyLinks) { let galleyUrl = galleyLink.href; + let explodedUrl = galleyUrl.split('/'); + let galleyId = explodedUrl[explodedUrl.length - 1]; + let viewerNode = createAnnotationViewerNode(galleyId); + insertAfter(viewerNode, galleyLink.parentNode); + let viewerData = await $.get( app.hypothesisHandlerUrl + 'get-annotation-viewer-data', { galleyUrl: galleyUrl } ); - viewerData = JSON.parse(viewerData); + if (viewerData !== null) { - galleyUrl = galleyUrl + '?hasAnnotations=true'; - galleyLink.href = galleyUrl; - let viewerNode = createAnnotationViewerNode(galleyUrl, viewerData['message']); - insertAfter(viewerNode, galleyLink.parentNode); + $.get( + 'https://hypothes.is/api/search?limit=0&group=__world__&uri=' + viewerData['downloadUrl'], + function(response) { + if (response['total'] > 0) { + const viewerButton = document.getElementById('annotation_viewer_link-' + galleyId); + const viewerLi = viewerButton.parentNode; + const suffix = (response['total'] == 1) ? viewerData['annotationMsg'] : viewerData['annotationsMsg']; + viewerButton.textContent = response['total'] + ' ' + suffix; + + const galleyLink = viewerLi.previousElementSibling.getElementsByTagName('a')[0]; + galleyLink.href = galleyLink.href + '?hasAnnotations=true'; + viewerButton.href = galleyLink.href; + viewerLi.classList.remove('hidden_viewer'); + } + } + ); } + } } diff --git a/styles/annotationViewer.css b/styles/annotationViewer.css index 7108a9a..dd0294d 100644 --- a/styles/annotationViewer.css +++ b/styles/annotationViewer.css @@ -2,8 +2,18 @@ margin-right: 0.25em; } -.annotation_viewer { - margin: 0.5em 0 1em; +.obj_article_details .galleys_links .annotation_viewer { + margin-top: 0.5em; +} + +.obj_article_summary .galleys_links .annotation_viewer { + margin: 0; +} + +.annotation_viewer.hidden_viewer { + visibility: hidden; + width: 0; + height: 0; } .annotation_viewer > a { From d58b7283d1947add6bdbc8749f6dacae08cb2ce9 Mon Sep 17 00:00:00 2001 From: Jhon Date: Thu, 21 Mar 2024 18:36:39 -0400 Subject: [PATCH 08/12] Performs major integrations with OJS Signed-off-by: Jhon --- HypothesisPlugin.php | 8 +++- classes/HypothesisHelper.php | 20 ++++---- pages/annotations/AnnotationsHandler.php | 12 +++-- styles/annotationsPage.css | 6 ++- templates/submissionAnnotations.tpl | 61 +++++++++++++----------- 5 files changed, 65 insertions(+), 42 deletions(-) diff --git a/HypothesisPlugin.php b/HypothesisPlugin.php index c0f55ad..993cd8f 100644 --- a/HypothesisPlugin.php +++ b/HypothesisPlugin.php @@ -93,9 +93,13 @@ public function addAnnotationNumberViewers($hookName, $args) { $pagesToInsert = [ 'frontend/pages/indexServer.tpl', 'frontend/pages/preprint.tpl', - 'frontend/pages/preprints.tpl' + 'frontend/pages/preprints.tpl', + 'frontend/pages/sections.tpl', + 'frontend/pages/indexJournal.tpl', + 'frontend/pages/article.tpl', + 'frontend/pages/issue.tpl' ]; - + if (in_array($template, $pagesToInsert)) { $request = Application::get()->getRequest(); diff --git a/classes/HypothesisHelper.php b/classes/HypothesisHelper.php index fd158f3..b2cb077 100644 --- a/classes/HypothesisHelper.php +++ b/classes/HypothesisHelper.php @@ -20,7 +20,7 @@ public function getSubmissionsAnnotations($contextId) { if (!is_null($groupResponse) && $groupResponse['total'] > 0) { $submissionsAnnotations = array_merge( $submissionsAnnotations, - $this->groupSubmissionsAnnotations($groupResponse) + $this->groupSubmissionsAnnotations($groupResponse, $contextId) ); } } @@ -59,7 +59,7 @@ private function getSubmissionRequestParams($submission, $contextId) { $galleys = $publication->getData('galleys'); foreach ($galleys as $galley) { - $galleyDownloadURL = $this->getGalleyDownloadURL($galley, $contextId); + $galleyDownloadURL = $this->getGalleyDownloadURL($contextId, $submission, $galley); if(!is_null($galleyDownloadURL)) $submissionRequestParams .= "&uri={$galleyDownloadURL}"; } @@ -76,12 +76,13 @@ private function getRequestAnnotations($requestURL) { return json_decode($output, true); } - private function groupSubmissionsAnnotations($groupResponse) { + private function groupSubmissionsAnnotations($groupResponse, $contextId) { $submissionsAnnotations = []; foreach ($groupResponse['rows'] as $annotationResponse) { $urlBySlash = explode("/", $annotationResponse['links']['incontext']); - $submissionId = (int) $urlBySlash[count($urlBySlash) - 3]; + $submissionBestId = (int) $urlBySlash[count($urlBySlash) - 3]; + $submissionId = Repo::submission()->getByBestId($submissionBestId, $contextId)->getId(); if(!array_key_exists($submissionId, $submissionsAnnotations)) { $submissionsAnnotations[$submissionId] = new SubmissionAnnotations($submissionId); @@ -112,20 +113,21 @@ private function getAnnotation($annotationResponse): Annotation { return new Annotation($user, $dateCreated, $target, $content); } - public function getGalleyDownloadURL($galley, $contextId) { + public function getGalleyDownloadURL($contextId, $submission, $galley) { $request = Application::get()->getRequest(); $indexUrl = $request->getIndexUrl(); $context = Application::getContextDAO()->getById($contextId); $contextPath = $context->getPath(); + $submissionType = (Application::getName() == 'ojs2' ? 'article' : 'preprint'); $submissionFile = $galley->getFile(); if(is_null($submissionFile)) return null; - $submissionId = $submissionFile->getData('submissionId'); - $assocId = $submissionFile->getData('assocId'); - $submissionFileId = $submissionFile->getId(); + $submissionBestId = $submission->getBestId(); + $galleyBestId = $galley->getBestGalleyId(); + $fileId = $submissionFile->getId(); - return $indexUrl . "/$contextPath/preprint/download/$submissionId/$assocId/$submissionFileId"; + return $indexUrl . "/$contextPath/$submissionType/download/$submissionBestId/$galleyBestId/$fileId"; } } \ No newline at end of file diff --git a/pages/annotations/AnnotationsHandler.php b/pages/annotations/AnnotationsHandler.php index 675256b..70bac28 100644 --- a/pages/annotations/AnnotationsHandler.php +++ b/pages/annotations/AnnotationsHandler.php @@ -5,11 +5,11 @@ use APP\handler\Handler; use PKP\plugins\PluginRegistry; use APP\template\TemplateManager; +use APP\core\Application; use PKP\config\Config; use APP\facades\Repo; use PKP\cache\CacheManager; use PKP\security\authorization\ContextRequiredPolicy; -use APP\security\authorization\OpsServerMustPublishPolicy; use APP\plugins\generic\hypothesis\classes\HypothesisHelper; use APP\plugins\generic\hypothesis\classes\HypothesisDAO; @@ -21,7 +21,12 @@ class AnnotationsHandler extends Handler { public function authorize($request, &$args, $roleAssignments) { $this->addPolicy(new ContextRequiredPolicy($request)); - $this->addPolicy(new OpsServerMustPublishPolicy($request)); + + if (Application::getName() == 'ojs2') { + $this->addPolicy(new \APP\security\authorization\OjsJournalMustPublishPolicy($request)); + } else { + $this->addPolicy(new \APP\security\authorization\OpsServerMustPublishPolicy($request)); + } return parent::authorize($request, $args, $roleAssignments); } @@ -36,7 +41,8 @@ public function index($args, $request) { $templateMgr = TemplateManager::getManager($request); $templateMgr->assign($paginationParams); $templateMgr->assign('pubIdPlugins', $pubIdPlugins); - $templateMgr->assign('journal', $context); + $templateMgr->assign('context', $context); + $templateMgr->assign('application', Application::getName()); $jsUrl = $request->getBaseUrl() . '/' . $plugin->getPluginPath() . '/js/load.js'; $templateMgr->addJavascript('AnnotationsPage', $jsUrl, ['contexts' => 'frontend']); diff --git a/styles/annotationsPage.css b/styles/annotationsPage.css index a799c8e..4ea94ae 100644 --- a/styles/annotationsPage.css +++ b/styles/annotationsPage.css @@ -16,12 +16,16 @@ border-radius: 3px; } -.submission_annotations > .title { +.submission_annotations .title { font-size: 16px; line-height: 20px; font-weight: 700; } +.submission_annotations .title a { + text-decoration: none; +} + .meta { padding-top: 5px; font-size: 14px; diff --git a/templates/submissionAnnotations.tpl b/templates/submissionAnnotations.tpl index 9257d7f..71c41e7 100644 --- a/templates/submissionAnnotations.tpl +++ b/templates/submissionAnnotations.tpl @@ -1,11 +1,16 @@ -{assign var="preprint" value=$submissionAnnotations->submission} +{assign var="submission" value=$submissionAnnotations->submission} {assign var="annotations" value=$submissionAnnotations->annotations}
- {$preprint->getCurrentPublication()->getAuthorString($authorUserGroups)|escape} + {$submission->getCurrentPublication()->getAuthorString($authorUserGroups)|escape}
- {* DOI *} - {foreach from=$pubIdPlugins item=pubIdPlugin} - {if $pubIdPlugin->getPubIdType() != 'doi'} - {continue} - {/if} - {assign var=pubId value=$preprint->getCurrentPublication()->getStoredPubId($pubIdPlugin->getPubIdType())} - {if $pubId} - {assign var="doiUrl" value=$pubIdPlugin->getResolvingURL($currentServer->getId(), $pubId)|escape} -
- {/if} - {/foreach} + {if $application == 'ops'} + {* DOI *} + {foreach from=$pubIdPlugins item=pubIdPlugin} + {if $pubIdPlugin->getPubIdType() != 'doi'} + {continue} + {/if} + {assign var=pubId value=$submission->getCurrentPublication()->getStoredPubId($pubIdPlugin->getPubIdType())} + {if $pubId} + {assign var="doiUrl" value=$pubIdPlugin->getResolvingURL($context->getId(), $pubId)|escape} +
+ {capture assign=translatedDOI}{translate key="doi.readerDisplayName"}{/capture} + {translate key="semicolon" label=$translatedDOI} + + + {$doiUrl} + + +
+ {/if} + {/foreach} -
- {translate key="submission.dates" submitted=$preprint->getDateSubmitted()|date_format:$dateFormatShort published=$preprint->getDatePublished()|date_format:$dateFormatShort} -
+
+ {translate key="submission.dates" submitted=$submission->getDateSubmitted()|date_format:$dateFormatShort published=$submission->getDatePublished()|date_format:$dateFormatShort} +
+ {/if}
{foreach from=$annotations item="annotation"} From 926b46c4eeba072ea22d1f6584dbddfa36a138f3 Mon Sep 17 00:00:00 2001 From: Jhon Date: Fri, 22 Mar 2024 11:45:34 -0400 Subject: [PATCH 09/12] Open Hypothesis sidebar automatically when PDF has annotations Signed-off-by: Jhon --- HypothesisPlugin.php | 18 ++++++++++++++++++ templates/hypothesisConfig.tpl | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 templates/hypothesisConfig.tpl diff --git a/HypothesisPlugin.php b/HypothesisPlugin.php index 993cd8f..7b06b2a 100644 --- a/HypothesisPlugin.php +++ b/HypothesisPlugin.php @@ -72,6 +72,7 @@ function callbackTemplateDisplay($hookName, $args) { // template path contains the plugin path, and ends with the tpl file if ( (strpos($template, $plugin) !== false) && ( (strpos($template, ':'.$submissiontpl, -1 - strlen($submissiontpl)) !== false) || (strpos($template, ':'.$issuetpl, -1 - strlen($issuetpl)) !== false))) { $templateMgr->registerFilter("output", array($this, 'changePdfjsPath')); + $templateMgr->registerFilter("output", array($this, 'addHypothesisConfig')); } return false; } @@ -87,6 +88,23 @@ function changePdfjsPath($output, $templateMgr) { return $newOutput; } + /** + * Adds Hypothesis tab configuration so sidebar opens automatically when PDF has annotations + * @param $output string + * @param $templateMgr TemplateManager + * @return $string + */ + public function addHypothesisConfig($output, $templateMgr) { + if (preg_match('/]+id="pdfCanvasContainer/', $output, $matches, PREG_OFFSET_CAPTURE)) { + $posMatch = $matches[0][1]; + $config = $templateMgr->fetch($this->getTemplateResource('hypothesisConfig.tpl')); + + $output = substr_replace($output, $config, $posMatch, 0); + $templateMgr->unregisterFilter('output', array($this, 'addHypothesisConfig')); + } + return $output; + } + public function addAnnotationNumberViewers($hookName, $args) { $templateMgr = $args[0]; $template = $args[1]; diff --git a/templates/hypothesisConfig.tpl b/templates/hypothesisConfig.tpl new file mode 100644 index 0000000..9f00b33 --- /dev/null +++ b/templates/hypothesisConfig.tpl @@ -0,0 +1,16 @@ + From 396a7773a170ab356a0b22774d76aa2b1c266a6b Mon Sep 17 00:00:00 2001 From: Jhon Date: Fri, 22 Mar 2024 14:30:24 -0400 Subject: [PATCH 10/12] Adds scheduled task to update cache Signed-off-by: Jhon --- HypothesisPlugin.php | 7 +++++ classes/HypothesisHelper.php | 13 ++++++--- classes/tasks/UpdateAnnotationsCache.php | 36 ++++++++++++++++++++++++ js/addAnnotationViewers.js | 2 +- scheduledTasks.xml | 10 +++++++ 5 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 classes/tasks/UpdateAnnotationsCache.php create mode 100644 scheduledTasks.xml diff --git a/HypothesisPlugin.php b/HypothesisPlugin.php index 7b06b2a..6410ab7 100644 --- a/HypothesisPlugin.php +++ b/HypothesisPlugin.php @@ -30,6 +30,7 @@ function register($category, $path, $mainContextId = null) { Hook::add('TemplateManager::display', [$this, 'addAnnotationNumberViewers']); Hook::add('LoadHandler', array($this, 'addAnnotationsHandler')); Hook::add('LoadComponentHandler', array($this, 'setupHypothesisHandler')); + Hook::add('AcronPlugin::parseCronTab', [$this, 'addTasksToCrontab']); $this->addHandlerURLToJavaScript(); @@ -148,6 +149,12 @@ public function setupHypothesisHandler($hookName, $args) { return false; } + public function addTasksToCrontab($hookName, $args) { + $taskFilesPath = &$args[0]; + $taskFilesPath[] = $this->getPluginPath() . DIRECTORY_SEPARATOR . 'scheduledTasks.xml'; + return false; + } + public function addHandlerURLToJavaScript() { $request = Application::get()->getRequest(); diff --git a/classes/HypothesisHelper.php b/classes/HypothesisHelper.php index b2cb077..2d443e0 100644 --- a/classes/HypothesisHelper.php +++ b/classes/HypothesisHelper.php @@ -4,6 +4,7 @@ use APP\facades\Repo; use APP\core\Application; +use APP\submission\Submission; use APP\plugins\generic\hypothesis\classes\Annotation; use APP\plugins\generic\hypothesis\classes\SubmissionAnnotations; @@ -11,6 +12,7 @@ class HypothesisHelper { public function getSubmissionsAnnotations($contextId) { $submissions = Repo::submission()->getCollector() ->filterByContextIds([$contextId]) + ->filterByStatus([Submission::STATUS_PUBLISHED]) ->getMany(); $groupsRequests = $this->getSubmissionsGroupsRequests($submissions, $contextId); @@ -59,9 +61,12 @@ private function getSubmissionRequestParams($submission, $contextId) { $galleys = $publication->getData('galleys'); foreach ($galleys as $galley) { - $galleyDownloadURL = $this->getGalleyDownloadURL($contextId, $submission, $galley); - if(!is_null($galleyDownloadURL)) - $submissionRequestParams .= "&uri={$galleyDownloadURL}"; + if ($galley->getFileType() == 'application/pdf') { + $galleyDownloadURL = $this->getGalleyDownloadURL($contextId, $submission, $galley); + if (!is_null($galleyDownloadURL)) { + $submissionRequestParams .= "&uri={$galleyDownloadURL}"; + } + } } return $submissionRequestParams; @@ -81,7 +86,7 @@ private function groupSubmissionsAnnotations($groupResponse, $contextId) { foreach ($groupResponse['rows'] as $annotationResponse) { $urlBySlash = explode("/", $annotationResponse['links']['incontext']); - $submissionBestId = (int) $urlBySlash[count($urlBySlash) - 3]; + $submissionBestId = $urlBySlash[count($urlBySlash) - 3]; $submissionId = Repo::submission()->getByBestId($submissionBestId, $contextId)->getId(); if(!array_key_exists($submissionId, $submissionsAnnotations)) { diff --git a/classes/tasks/UpdateAnnotationsCache.php b/classes/tasks/UpdateAnnotationsCache.php new file mode 100644 index 0000000..c37bfec --- /dev/null +++ b/classes/tasks/UpdateAnnotationsCache.php @@ -0,0 +1,36 @@ +getIds([ + 'isEnabled' => true, + ]); + + foreach ($contextIds as $contextId) { + $cacheManager = CacheManager::getManager(); + $cache = $cacheManager->getFileCache( + $contextId, + 'submissions_annotations', + [$this, 'cacheDismiss'] + ); + + $cache->flush(); + $hypothesisHelper = new HypothesisHelper(); + $cache->setEntireCache($hypothesisHelper->getSubmissionsAnnotations($contextId)); + } + + return true; + } + + function cacheDismiss() { + return null; + } +} diff --git a/js/addAnnotationViewers.js b/js/addAnnotationViewers.js index e02ed01..c812e3b 100644 --- a/js/addAnnotationViewers.js +++ b/js/addAnnotationViewers.js @@ -15,7 +15,7 @@ function createAnnotationViewerNode(galleyId) { } async function addAnnotationViewers() { - let galleyLinks = document.getElementsByClassName('obj_galley_link'); + let galleyLinks = document.getElementsByClassName('obj_galley_link pdf'); for (let galleyLink of galleyLinks) { let galleyUrl = galleyLink.href; diff --git a/scheduledTasks.xml b/scheduledTasks.xml new file mode 100644 index 0000000..f17624a --- /dev/null +++ b/scheduledTasks.xml @@ -0,0 +1,10 @@ + + + + + + + Updates the cache of submissions with annotations. + + + \ No newline at end of file From 9d67d3c900727a6022daa5506e3c26a6d2ff7050 Mon Sep 17 00:00:00 2001 From: Jhon Date: Fri, 22 Mar 2024 16:31:09 -0400 Subject: [PATCH 11/12] Ads styling for subtitles in annotations page Signed-off-by: Jhon --- styles/annotationsPage.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/styles/annotationsPage.css b/styles/annotationsPage.css index 4ea94ae..fee6002 100644 --- a/styles/annotationsPage.css +++ b/styles/annotationsPage.css @@ -26,6 +26,14 @@ text-decoration: none; } +.submission_annotations .title .subtitle { + display: block; + margin-top: 0.25em; + margin-bottom: 0.25em; + font-weight: 400; + color: rgba(0,0,0,0.54); +} + .meta { padding-top: 5px; font-size: 14px; From 33f68b6f28ff1b51e8a931187926228833f1718c Mon Sep 17 00:00:00 2001 From: Jhon Date: Wed, 18 Dec 2024 16:25:10 -0400 Subject: [PATCH 12/12] Fixes bug while retrieving annotations for annotations page Signed-off-by: Jhon --- classes/HypothesisHelper.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/classes/HypothesisHelper.php b/classes/HypothesisHelper.php index 2d443e0..4187427 100644 --- a/classes/HypothesisHelper.php +++ b/classes/HypothesisHelper.php @@ -49,6 +49,10 @@ private function getSubmissionsGroupsRequests($submissions, $contextId) { } } + if ($currentRequest != $requestPrefix) { + $requests[] = $currentRequest; + } + return $requests; }