diff --git a/.github/workflows/moodle-plugin-ci.yml b/.github/workflows/moodle-plugin-ci.yml index 9069f71..4632ec4 100644 --- a/.github/workflows/moodle-plugin-ci.yml +++ b/.github/workflows/moodle-plugin-ci.yml @@ -8,7 +8,7 @@ jobs: services: postgres: - image: postgres:13 + image: postgres:14 env: POSTGRES_USER: 'postgres' POSTGRES_HOST_AUTH_METHOD: 'trust' @@ -17,7 +17,7 @@ jobs: options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 mariadb: - image: mariadb:10 + image: mariadb:10.11 env: MYSQL_USER: 'root' MYSQL_ALLOW_EMPTY_PASSWORD: "true" @@ -31,6 +31,25 @@ jobs: fail-fast: false matrix: include: + - php: 8.4 + moodle-branch: MOODLE_500_STABLE + database: pgsql + - php: 8.4 + moodle-branch: MOODLE_500_STABLE + database: mariadb + - php: 8.4 + moodle-branch: MOODLE_500_STABLE + database: pgsql + - php: 8.4 + moodle-branch: MOODLE_500_STABLE + database: mariadb + - php: 8.4 + moodle-branch: MOODLE_500_STABLE + database: pgsql + - php: 8.4 + moodle-branch: MOODLE_500_STABLE + database: mariadb + - php: 8.3 moodle-branch: MOODLE_405_STABLE database: pgsql @@ -42,13 +61,13 @@ jobs: database: pgsql - php: 8.2 moodle-branch: MOODLE_405_STABLE - database: mariadb + database: mariadb - php: 8.1 moodle-branch: MOODLE_405_STABLE database: pgsql - php: 8.1 moodle-branch: MOODLE_405_STABLE - database: mariadb + database: mariadb - php: 8.3 moodle-branch: MOODLE_404_STABLE @@ -61,13 +80,13 @@ jobs: database: pgsql - php: 8.2 moodle-branch: MOODLE_404_STABLE - database: mariadb + database: mariadb - php: 8.1 moodle-branch: MOODLE_404_STABLE database: pgsql - php: 8.1 moodle-branch: MOODLE_404_STABLE - database: mariadb + database: mariadb - php: 8.2 moodle-branch: MOODLE_403_STABLE @@ -119,12 +138,14 @@ jobs: - php: 8.0 moodle-branch: MOODLE_401_STABLE database: mariadb + - php: 7.4 moodle-branch: MOODLE_401_STABLE database: pgsql - php: 7.4 moodle-branch: MOODLE_401_STABLE database: mariadb + steps: - name: Check out repository code uses: actions/checkout@v4 @@ -147,8 +168,7 @@ jobs: echo $(cd ci/bin; pwd) >> $GITHUB_PATH echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH sudo locale-gen en_AU.UTF-8 - # echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash + echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV - name: Install moodle-plugin-ci run: moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 @@ -213,3 +233,4 @@ jobs: - name: Mark cancelled jobs as failed. if: ${{ cancelled() }} run: exit 1 + diff --git a/README.md b/README.md index e2f78c2..a57fdbb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -PDF Annotation Tool for Moodle +[![Moodle Plugin CI](https://github.com/rwthmoodle/moodle-mod_pdfannotator/actions/workflows/moodle-plugin-ci.yml/badge.svg?branch=main)](https://github.com/rwthmoodle/moodle-mod_pdfannotator/actions/workflows/moodle-plugin-ci.yml) + +# PDF Annotation Tool for Moodle This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,4 +26,4 @@ Optionally Google Charts API can be used in download function to convert [LaTeX] - Unzip and copy "pdfannotator" folder into Moodle's "mod" folder - Visit admin page to install module -For further installation instructions please see: \ No newline at end of file +For further installation instructions please see: diff --git a/locallib.php b/locallib.php index ab02e55..44c7413 100644 --- a/locallib.php +++ b/locallib.php @@ -328,7 +328,8 @@ function pdfannotator_data_preprocessing($context, $textarea, $draftitemid = 0) * Same function as core, however we need to add files into the existing draft area! * Copied from hsuforum. */ -function pdfannotator_file_prepare_draft_area(&$draftitemid, $contextid, $component, $filearea, $itemid, array $options=null, $text=null) { +function pdfannotator_file_prepare_draft_area(&$draftitemid, $contextid, $component, $filearea, $itemid, ?array $options=null, + ?string $text=null) { global $CFG, $USER, $CFG, $DB; $options = (array)$options; @@ -869,7 +870,7 @@ function pdfannotator_set_mainfile($data) { } } -function pdfannotator_render_listitem_actions(array $actions = null) { +function pdfannotator_render_listitem_actions(?array $actions = null) { $menu = new action_menu(); $menu->attributes['class'] .= ' course-item-actions item-actions'; $hasitems = false; diff --git a/shared/locallib.js b/shared/locallib.js index e260d8f..aba838c 100644 --- a/shared/locallib.js +++ b/shared/locallib.js @@ -5,6 +5,8 @@ * */ +/* global MathJax, $ */ + function addDropdownNavigation(Y, __capabilities, __cmid) { // Select the general overview tab. @@ -84,17 +86,13 @@ function addDropdownNavigation(Y, __capabilities, __cmid) { } function renderMathJax(node) { - var counter = 0; - let mathjax = function (node) { - if (typeof (MathJax) !== "undefined") { - MathJax.Hub.Queue(['Typeset', MathJax.Hub, node]); - } else if (counter < 30) { - counter++; - setTimeout(mathjax, 100); - } else { - } - }; - mathjax(node); + if (window.MathJax && MathJax.typesetPromise) { + MathJax.typesetPromise([node]).catch(function (err) { + console.error('MathJax typeset failed: ', err); + }); + } else { + console.warn("MathJax not loaded yet."); + } } function fixCommentForm() { @@ -179,7 +177,7 @@ function makeFullScreen() { /** * Check just one checkbox under the comment form - * + * */ function checkOnlyOneCheckbox( Y ) { var radios = document.getElementsByClassName('pdfannotator-radio'); @@ -229,8 +227,8 @@ function checkOnlyOneCheckbox( Y ) { function setTimeoutNotification(){ setTimeout(function(){ let notificationpanel = document.getElementById("user-notifications"); - while (notificationpanel.hasChildNodes()) { + while (notificationpanel.hasChildNodes()) { notificationpanel.removeChild(notificationpanel.firstChild); - } + } }, 10000); } diff --git a/tests/behat/add_pdfannotator.feature b/tests/behat/add_pdfannotator.feature new file mode 100644 index 0000000..24f7ff4 --- /dev/null +++ b/tests/behat/add_pdfannotator.feature @@ -0,0 +1,35 @@ +@mod @mod_pdfannotator @_file_upload +Feature: Add a pdfannotator activity + In order to let the users use the pdfannotator in a course + As a teacher + I need to add a pdfannotator to a moodle course + + @javascript + Scenario: Add a pdfannotator to a course + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | Teacher | 1 | teacher1@example.com | + | student1 | Student | 1 | student1@example.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + | student1 | C1 | student | + And the following "user preferences" exist: + | user | preference | value | + | teacher1 | htmleditor | atto | + | student1 | htmleditor | atto | + And I log in as "teacher1" + And I am on "Course 1" course homepage with editing mode on + And I add a pdfannotator activity to course "Course 1" section "1" and I fill the form with: + | Name | Test pdf annotation | + | Description | Test pdf annotation description | + | Select a pdf-file | mod/pdfannotator/tests/fixtures/submission.pdf | + And I am on "Course 1" course homepage with editing mode on + And I log out + And I log in as "student1" + And I am on "Course 1" course homepage + And I follow "Test pdf annotation" + Then I should see "Test pdf annotation" diff --git a/tests/behat/annotate_pdfannotator.feature b/tests/behat/annotate_pdfannotator.feature new file mode 100644 index 0000000..a51be3c --- /dev/null +++ b/tests/behat/annotate_pdfannotator.feature @@ -0,0 +1,42 @@ +@mod @mod_pdfannotator @_file_upload @javascript +Feature: Annotate in a pdfannotator activity + In order to annotate in the pdfannotator in a course + As a student + I need to note questions and subscribe or unsubscribe to notificatoins + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | Teacher | 1 | teacher1@example.com | + | student1 | Student | 1 | student1@example.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + | student1 | C1 | student | + And the following "user preferences" exist: + | user | preference | value | + | teacher1 | htmleditor | atto | + | student1 | htmleditor | atto | + And I log in as "teacher1" + And I am on "Course 1" course homepage with editing mode on + And I add a pdfannotator activity to course "Course 1" section "1" and I fill the form with: + | Name | Test PDF annotation | + | Description | Test pdf annotation description | + | Select a pdf-file | mod/pdfannotator/tests/fixtures/submission.pdf | + And I am on "Course 1" course homepage with editing mode on + And I log out + + Scenario: Add a question to a pdfannotator + Given I am on the "Test PDF annotation" "mod_pdfannotator > View" page logged in as "student1" + And I click on "comment" "button" + And I wait "1" seconds + And I point at the pdfannotator canvas + And I wait "1" seconds + And I set the field with xpath "//div[@class='pdfannotator-comment-list']//textarea" to "This is a smurfing smurf" + And I click on "Create Annotation" "button" + And I wait until the page is ready + Then I should see "This is a smurfing smurf" + And I log out diff --git a/tests/behat/behat_mod_pdfannotator.php b/tests/behat/behat_mod_pdfannotator.php new file mode 100644 index 0000000..cebb6b8 --- /dev/null +++ b/tests/behat/behat_mod_pdfannotator.php @@ -0,0 +1,120 @@ +. + +/** + * Steps definitions related to mod_pdfannotator. + * + * @package mod_pdfannotator + * @category test + * @copyright 2019 HSR (http://www.hsr.ch) + * @author 2019 Huong Nguyen + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); + +use mod_pdfannotator\utils; +use Behat\Mink\Exception\ExpectationException as ExpectationException; +use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException; +use Behat\Gherkin\Node\TableNode as TableNode; + +/** + * Steps definitions related to mod_pdfannotator. + * + * @package pdfannotator + * @category test + * @copyright 2024 Luca Bösch + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_mod_pdfannotator extends behat_base { + + /** + * Convert page names to URLs for steps like 'When I am on the "[page name]" page'. + * + * Recognised page names are: + * | None so far! | | + * + * @param string $page name of the page, with the component name removed e.g. 'Admin notification'. + * @return moodle_url the corresponding URL. + * @throws Exception with a meaningful error message if the specified page cannot be found. + */ + protected function resolve_page_url(string $page): moodle_url { + switch ($page) { + default: + throw new Exception('Unrecognised pdfannotator page type "' . $page . '."'); + } + } + + /** + * Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'. + * + * Recognised page names are: + * | pagetype | name meaning | description | + * | View | Student Quiz name | The student quiz info page (view.php) | + * | Edit | Student Quiz name | The edit quiz page (edit.php) | + * | Statistics | Student Quiz name | The Statistics report page | + * | Ranking | Student Quiz name | The Ranking page | + * + * @param string $type identifies which type of page this is, e.g. 'View'. + * @param string $identifier identifies the particular page, e.g. 'Test student quiz'. + * @return moodle_url the corresponding URL. + * @throws Exception with a meaningful error message if the specified page cannot be found. + */ + protected function resolve_page_instance_url(string $type, string $identifier): moodle_url { + switch ($type) { + case 'View': + return new moodle_url('/mod/pdfannotator/view.php', + ['id' => $this->get_cm_by_pdfannotator_name($identifier)->id]); + + case 'Edit': + return new moodle_url('/course/modedit.php', + ['update' => $this->get_cm_by_pdfannotator_name($identifier)->id]); + + case 'Statistics': + return new moodle_url('/mod/pdfannotator/reportstat.php', + ['id' => $this->get_cm_by_pdfannotator_name($identifier)->id]); + + case 'Ranking': + return new moodle_url('/mod/pdfannotator/reportrank.php', + ['id' => $this->get_cm_by_pdfannotator_name($identifier)->id]); + + default: + throw new Exception('Unrecognised pdfannotator page type "' . $type . '."'); + } + } + + /** + * Get a pdfannotator by name. + * + * @param string $name pdfannotator name. + * @return stdClass the corresponding DB row. + */ + protected function get_pdfannotator_by_name(string $name): stdClass { + global $DB; + return $DB->get_record('pdfannotator', array('name' => $name), '*', MUST_EXIST); + } + + /** + * Get cmid from the pdfannotator name. + * + * @param string $name pdfannotator name. + * @return stdClass cm from get_coursemodule_from_instance. + */ + protected function get_cm_by_pdfannotator_name(string $name): stdClass { + $pdfannotator = $this->get_pdfannotator_by_name($name); + return get_coursemodule_from_instance('pdfannotator', $pdfannotator->id, $pdfannotator->course); + } +} diff --git a/tests/behat/behat_pdfannotator_editpdf.php b/tests/behat/behat_pdfannotator_editpdf.php new file mode 100644 index 0000000..9e7a250 --- /dev/null +++ b/tests/behat/behat_pdfannotator_editpdf.php @@ -0,0 +1,59 @@ +. + +/** + * Behat pdfannotator-related steps definitions. + * + * @package pdfannotator + * @category test + * @copyright 2021 Luca Bösch + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. + +require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); + +/** + * Steps definitions related with the pdfannotator. + * + * @package pdfannotator + * @category test + * @copyright 2021 Luca Bösch + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_pdfannotator_editpdf extends behat_base { + + /** + * Point at the pdfannotator pdf. + * + * @When /^I point at the pdfannotator canvas$/ + */ + public function i_point_at_the_pdfannotator_canvas() { + $node = $this->find('xpath', '//div[@id=\'pageContainer1\']'); + $this->execute('behat_general::i_click_on', [$node, 'NodeElement']); + } + + /** + * Point at the pdfannotator pdf. + * + * @When /^I click the pdfannotator public comment dropdown menu button$/ + */ + public function i_click_the_pdfannotator_public_comment_dropdown_menu_button() { + $node = $this->find('xpath', '//a[@id=\'dropdownMenuButton\']'); + $this->execute('behat_general::i_click_on', [$node, 'NodeElement']); + } +} diff --git a/tests/fixtures/submission.pdf b/tests/fixtures/submission.pdf new file mode 100644 index 0000000..576d378 Binary files /dev/null and b/tests/fixtures/submission.pdf differ