Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add worlimit indicator for essays and quiz sites #12

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 8 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,14 @@ jobs:
fail-fast: false
matrix:
include:
- {moodle-branch: 'MOODLE_39_STABLE', php: '7.2', node: '16.14.2', database: 'mariadb'}
- {moodle-branch: 'MOODLE_39_STABLE', php: '7.2', node: '16.14.2', database: 'pgsql'}
- {moodle-branch: 'MOODLE_39_STABLE', php: '7.3', node: '16.14.2', database: 'mariadb'}
- {moodle-branch: 'MOODLE_39_STABLE', php: '7.3', node: '16.14.2', database: 'pgsql'}
- {moodle-branch: 'MOODLE_39_STABLE', php: '7.4', node: '16.14.2', database: 'mariadb'}
- {moodle-branch: 'MOODLE_39_STABLE', php: '7.4', node: '16.14.2', database: 'pgsql'}
- {moodle-branch: 'MOODLE_310_STABLE', php: '7.4', node: '16.14.2', database: 'mariadb'}
- {moodle-branch: 'MOODLE_310_STABLE', php: '7.4', node: '16.14.2', database: 'pgsql'}
- {moodle-branch: 'MOODLE_311_STABLE', php: '7.4', node: '16.14.2', database: 'mariadb'}
- {moodle-branch: 'MOODLE_311_STABLE', php: '7.4', node: '16.14.2', database: 'pgsql'}
- {moodle-branch: 'MOODLE_311_STABLE', php: '8.0', node: '16.14.2', database: 'mariadb'}
- {moodle-branch: 'MOODLE_311_STABLE', php: '8.0', node: '16.14.2', database: 'pgsql'}
- {moodle-branch: 'master', php: '7.4', node: '16.14.2', database: 'mariadb'}
- {moodle-branch: 'master', php: '7.4', node: '16.14.2', database: 'pgsql'}
- {moodle-branch: 'master', php: '8.0', node: '16.14.2', database: 'mariadb'}
- {moodle-branch: 'master', php: '8.0', node: '16.14.2', database: 'pgsql'}
- {moodle-branch: 'MOODLE_311_STABLE', php: '7.4', node: '14.18.0', database: 'mariadb'}
- {moodle-branch: 'MOODLE_311_STABLE', php: '7.4', node: '14.18.0', database: 'pgsql'}
- {moodle-branch: 'MOODLE_311_STABLE', php: '8.0', node: '14.18.0', database: 'mariadb'}
- {moodle-branch: 'MOODLE_311_STABLE', php: '8.0', node: '14.18.0', database: 'pgsql'}
- {moodle-branch: 'MOODLE_400_STABLE', php: '7.4', node: '14.18.0', database: 'mariadb'}
- {moodle-branch: 'MOODLE_400_STABLE', php: '7.4', node: '14.18.0', database: 'pgsql'}
- {moodle-branch: 'MOODLE_400_STABLE', php: '8.0', node: '14.18.0', database: 'mariadb'}
- {moodle-branch: 'MOODLE_400_STABLE', php: '8.0', node: '14.18.0', database: 'pgsql'}

steps:
- name: Check out repository code
Expand Down
8 changes: 4 additions & 4 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## [1.1.2] - 2022-03-19
## [1.1.2] - 2022-05-11
### Changed
- Stylesheet for fix ui for atto in Moodle 4.0
- Fix behat test to support Moodle 4.0
- Moodle 3.11+ required
- Added wordlimit indicator for assignments and quizs

## [1.1.0] - 2022-02-01
### Changed
Expand All @@ -11,7 +11,7 @@
### Added
- Add stylesheets for bottom toolbar

### Changed
### Changed
- Update the release workflow to new one with token
- Fix screen reader only view on question editor

Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ Add "real time" words count to Moodle Atto editor, By enable this Atto plugin th
The count is change will the user type or change the Atto editor content.

You can see examples in the screenshots bellow.

## Requirements
- Moodle 2.7 or later.
- Moodle 3.11 or later.

## Installation
1. Add the plugin to /lib/editor/atto/plugins
Expand All @@ -16,12 +17,15 @@ You can see examples in the screenshots bellow.
## Records
Thanks to the Hebrew University Of Jerusalem that sponsor this plugin development.
![Hebrew University Of Jerusalem](https://moodle.org/pluginfile.php/50/local_plugins/plugin_description/2743/logo-ltr.png)

## Author
Avi Levy ([email protected])
![SysBind](https://moodle.org/pluginfile.php/50/local_plugins/plugin_description/2743/Sysbind-Moodle-Partner-Landscape.png)
## License ##
André Menrath ([email protected])

## License ##
2021 SysBind
2022 University of Graz

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 the Free Software
Expand Down
2 changes: 0 additions & 2 deletions classes/privacy/provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@

namespace atto_wordcount\privacy;

defined('MOODLE_INTERNAL') || die();

/**
* Privacy Subsystem for atto_wordcount implementing null_provider.
*
Expand Down
131 changes: 131 additions & 0 deletions classes/wordlimit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* atto_wordcount extensions for fetching wordlimits.
*
* @package atto_wordcount
* @copyright 2022 André Menrath <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace atto_wordcount;

/**
* Collection of functions thich get the wordlimit for the text written in atto if it is set.
*
* @copyright 2022 André Menrath <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class wordlimit {

/**
* Get the wordlimit for an onlinesubmission in an essay.
*
* @param string $assignmentid the instance-id of the assignment
* @return string $wordlimit
*/
protected static function get_wordlimit_for_onlinesubmission($assignmentid) {
// Get settings from onlinepage submission plugin: Check if the wordlimit is enabled.
global $DB;
$wordlimitenabled = $DB->get_record(
'assign_plugin_config',
array(
'assignment' => $assignmentid,
'name' => 'wordlimitenabled'
),
'value',
MUST_EXIST,
);
// If the wordlimit is enabled get the word limit and pass it to the javascript module.
if ( '1' === $wordlimitenabled->value ) {
$wordlimit = $DB->get_record(
'assign_plugin_config',
array(
'assignment' => $assignmentid,
'name' => 'wordlimit'
),
'value',
MUST_EXIST,
);
return $wordlimit->value;
}
return null;
}

/**
* Get the wordlimits for an essay of a certain page inside a quiz.
*
* @param int $attempdid the attempd-id of the quiz
* @param string $page the number of the page as in the database, offset +1 in the frontend.
* @return array $wordlimits
*/
protected static function get_wordlimits_for_essay_in_quiz($attempdid, $page) {
global $DB;
// Make a database query to see if a maxwordlimit is set on this question.
// We need to also select slot, because the slot is unique here: there might be multiple
// editors with the same wordlimit on the same page, and then only the first would be returned.
$sql = "SELECT {question_attempts}.slot, {qtype_essay_options}.maxwordlimit
FROM {qtype_essay_options}
JOIN {question_attempts} ON {question_attempts}.questionid = {qtype_essay_options}.questionid
JOIN {quiz_attempts} ON {quiz_attempts}.uniqueid = {question_attempts}.questionusageid
JOIN {quiz_slots} ON {quiz_slots}.quizid = {quiz_attempts}.quiz AND {quiz_slots}.slot = {question_attempts}.slot
WHERE {quiz_attempts}.id = ? AND {quiz_slots}.page = ?
ORDER BY slot;";
$wordlimits = $DB->get_records_sql( $sql, array( $attempdid, $page ) );
$wordlimits = array_column( $wordlimits, 'maxwordlimit' );
return $wordlimits;
}

/**
* Get the wordlimit depending on the type of page which is beein edited.
*
* @return array $wordlimits
*/
public static function get_wordlimits() {

global $PAGE;

// Define the parameter array which is served to the javascript of the plugin.
$wordlimits = array( null );

$path = $PAGE->url->get_path();

// Check if we are on a page where the users submits/edits an onlinetext for an assignment.
$action = optional_param('action', null, PARAM_ALPHANUMEXT);
if ( '/mod/assign/view.php' === $path && 'editsubmission' === $action ) {
$id = $PAGE->cm->instance;
$wordlimit = self::get_wordlimit_for_onlinesubmission($id);
// We have to pass wordlimits as an array.
$wordlimits = array( 0 => $wordlimit);
// We can return now and don't need to check for a quiz page.
return $wordlimits;
}

if ( '/mod/quiz/attempt.php' === $path && "mod-quiz-attempt" === $PAGE->pagetype ) {
// The attempt id is a required parameter for the quiz/attemp.php page.
$attemptid = required_param('attempt', PARAM_INT);
// See on which page of the quiz we are.
$page = optional_param('page', 0, PARAM_INT);
// The page in the URL Params is starting with zero, in the database they start with 1. So there is an offset.
$page = $page + 1;
$wordlimits = self::get_wordlimits_for_essay_in_quiz( $attemptid, $page );
}

return $wordlimits;
}

}
15 changes: 14 additions & 1 deletion lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
*
* @package atto_wordcount
* @copyright Avi Levy <[email protected]>
* 2022 André Menrath <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

defined('MOODLE_INTERNAL') || die();

/**
* Initialise the js strings required for this module.
Expand All @@ -32,3 +32,16 @@ function atto_wordcount_strings_for_js() {

$PAGE->requires->strings_for_js(['words', 'wordscount'], 'atto_wordcount');
}


/**
* Pass the wordlimits to the js part of the plugin.
*
* @return array $params.
*/
function atto_wordcount_params_for_js() {
$wordlimits = atto_wordcount\wordlimit::get_wordlimits();
// Wrapp the wordlimits into an array whith wordlimits as the key.
$params = array ( 'wordlimits' => $wordlimits );
return $params;
}
42 changes: 32 additions & 10 deletions scss/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,41 @@ body.path-question-type {
}

.editor_atto_wrap {
.editor_atto_content_wrap {
.editor_atto_content.form-control {
border-radius: 0;
}
}
.editor_atto_toolbar {
&.editor_atto_toolbar_bottom {
font-size: 0.7rem;
font-size: 0.8rem;
min-height: unset;
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
justify-content: right;
background: inherit;
border: none;
.danger {
background-color: var(--danger);
color: #fff;
font-weight: bolder;
padding: 0 4px;
border-radius: 4px;
}
.warning {
background-color: var(--warning);
font-weight: normal;
padding: 0 4px;
border-radius: 4px;
}
.warning-icon {
align-items: center;
justify-content: center;
height: 100%;
display: none;
}
> div {
padding: 2px 5px;
> *:first-child {
margin: 0 0.2rem;
}
> * {
margin: 0 0.05rem;
}
}
}
}
}
51 changes: 42 additions & 9 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,48 @@ body.path-question-type .form-group .sr-only:not(legend):not([for="id_category"]
overflow: hidden;
}

.editor_atto_wrap .editor_atto_content_wrap .editor_atto_content.form-control {
border-radius: 0;
}

.editor_atto_wrap .editor_atto_toolbar.editor_atto_toolbar_bottom {
font-size: 0.7rem;
font-size: 0.8rem;
min-height: unset;
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
justify-content: right;
background: inherit;
border: none;
}

.editor_atto_wrap .editor_atto_toolbar.editor_atto_toolbar_bottom .danger {
background-color: var(--danger);
color: #fff;
font-weight: bolder;
padding: 0 4px;
border-radius: 4px;
}

.editor_atto_wrap .editor_atto_toolbar.editor_atto_toolbar_bottom .warning {
background-color: var(--warning);
font-weight: normal;
padding: 0 4px;
border-radius: 4px;
}

.editor_atto_wrap .editor_atto_toolbar.editor_atto_toolbar_bottom .warning-icon {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
height: 100%;
display: none;
}

.editor_atto_wrap .editor_atto_toolbar.editor_atto_toolbar_bottom > div {
padding: 2px 5px;
}

.editor_atto_wrap .editor_atto_toolbar.editor_atto_toolbar_bottom > div > *:first-child {
margin: 0 0.2rem;
}

.editor_atto_wrap .editor_atto_toolbar.editor_atto_toolbar_bottom > div > * {
margin: 0 0.05rem;
}
Loading