From 29c220583fb048c7978adaee68413ffeb5a2a7f5 Mon Sep 17 00:00:00 2001 From: Ilya Tregubov Date: Mon, 28 Nov 2022 10:04:42 +0300 Subject: [PATCH] MDL-76146 gradereport_grader: Move action icons to action menu. --- grade/lib.php | 143 +++++++++++++ grade/report/grader/index.php | 2 +- .../grader/lang/en/gradereport_grader.php | 1 + grade/report/grader/lib.php | 202 ++++++++++++++---- grade/report/grader/styles.css | 46 +++- grade/report/grader/templates/cell.mustache | 48 +++++ .../grader/templates/grademenu.mustache | 38 ++++ grade/templates/grades/grader/input.mustache | 34 +++ grade/templates/grades/grader/scale.mustache | 28 +++ grade/templates/grades/grader/text.mustache | 30 +++ grade/tests/behat/behat_grade.php | 2 +- lang/en/grades.php | 1 + .../output/icon_system_fontawesome.php | 2 + theme/boost/scss/moodle/grade.scss | 11 + theme/boost/style/moodle.css | 7 + theme/classic/style/moodle.css | 7 + 16 files changed, 547 insertions(+), 55 deletions(-) create mode 100644 grade/report/grader/templates/cell.mustache create mode 100644 grade/report/grader/templates/grademenu.mustache create mode 100644 grade/templates/grades/grader/input.mustache create mode 100644 grade/templates/grades/grader/scale.mustache create mode 100644 grade/templates/grades/grader/text.mustache diff --git a/grade/lib.php b/grade/lib.php index 2d337b7ecea23..7c2f8d5f14faf 100644 --- a/grade/lib.php +++ b/grade/lib.php @@ -1710,6 +1710,23 @@ public function get_grade_analysis_icon(grade_grade $grade) { ['title' => $title, 'aria-label' => $title]); } + /** + * Returns a link leading to the grade analysis page + * + * @param grade_grade $grade + * @param string $gradeanalysisstring Language string + * @return string|null + */ + public function get_grade_analysis_link(grade_grade $grade, string $gradeanalysisstring): ?string { + $url = $this->get_grade_analysis_url($grade); + if (is_null($url)) { + return null; + } + + return html_writer::link($url, $gradeanalysisstring, + ['class' => 'dropdown-item', 'aria-label' => $gradeanalysisstring, 'role' => 'menuitem']); + } + /** * Returns an action menu for the grade. * @@ -1915,6 +1932,40 @@ public function get_edit_icon($element, $gpr, $returnactionmenulink = false) { } } + /** + * Returns a link leading to the edit grade/grade item/category page + * + * @param array $element An array representing an element in the grade_tree + * @param object $gpr A grade_plugin_return object + * @param array $langstrings Language strings + * @return string|null + */ + public function get_edit_link(array $element, object $gpr, array $langstrings): ?string { + $url = null; + $title = ''; + if (!has_capability('moodle/grade:manage', $this->context)) { + if (!($element['type'] == 'grade') || !has_capability('moodle/grade:edit', $this->context)) { + return null; + } + } + + $object = $element['object']; + + if ($element['type'] == 'grade') { + if (empty($object->id)) { + $url = new moodle_url('/grade/edit/tree/grade.php', + ['courseid' => $this->courseid, 'itemid' => $object->itemid, 'userid' => $object->userid]); + } else { + $url = new moodle_url('/grade/edit/tree/grade.php', + ['courseid' => $this->courseid, 'id' => $object->id]); + } + $title = $langstrings[0]; + } + $gpr->add_url_params($url); + return html_writer::link($url, $title, + ['class' => 'dropdown-item', 'aria-label' => $title, 'role' => 'menuitem']); + } + /** * Return hiding icon for give element * @@ -1973,6 +2024,50 @@ public function get_hiding_icon($element, $gpr, $returnactionmenulink = false) { return $hideicon; } + /** + * Returns a link with url to hide/unhide grade/grade item/grade category + * + * @param array $element An array representing an element in the grade_tree + * @param object $gpr A grade_plugin_return object + * @param array $langstrings Language strings + * @return string|null + */ + public function get_hiding_link(array $element, object $gpr, array $langstrings): ?string { + if (!$element['object']->can_control_visibility() || + (!has_capability('moodle/grade:manage', $this->context) && + !has_capability('moodle/grade:hide', $this->context))) { + return null; + } + + $url = new moodle_url('/grade/edit/tree/action.php', + ['id' => $this->courseid, 'sesskey' => sesskey(), 'eid' => $element['eid']]); + $url = $gpr->add_url_params($url); + + if ($element['object']->is_hidden()) { + $url->param('action', 'show'); + $title = $langstrings[0]; + } else { + $url->param('action', 'hide'); + $title = $langstrings[1]; + } + + $url = html_writer::link($url, $title, + ['class' => 'dropdown-item', 'aria-label' => $title, 'role' => 'menuitem']); + + if ($element['type'] == 'grade') { + $item = $element['object']->grade_item; + if ($item->hidden) { + $strparamobj = new stdClass(); + $strparamobj->itemname = $item->get_name(true, true); + $strnonunhideable = get_string('nonunhideableverbose', 'grades', $strparamobj); + $url = html_writer::span($title, 'text-muted dropdown-item', + ['title' => $strnonunhideable, 'aria-label' => $title, 'role' => 'menuitem']); + } + } + + return $url; + } + /** * Return locking icon for given element * @@ -2030,6 +2125,54 @@ public function get_locking_icon($element, $gpr) { return $action; } + /** + * Returns link to lock/unlock grade/grade item/grade category + * + * @param array $element An array representing an element in the grade_tree + * @param object $gpr A grade_plugin_return object + * @param array $langstrings Language strings + * + * @return string|null + */ + public function get_locking_link(array $element, object $gpr, array $langstrings): ?string { + + $title = ''; + $url = new moodle_url('/grade/edit/tree/action.php', + ['id' => $this->courseid, 'sesskey' => sesskey(), 'eid' => $element['eid']]); + $url = $gpr->add_url_params($url); + + if (($element['type'] == 'grade') && ($element['object']->grade_item->is_locked())) { + // Don't allow an unlocking action for a grade whose grade item is locked: just print a state icon. + $strparamobj = new stdClass(); + $strparamobj->itemname = $element['object']->grade_item->get_name(true, true); + $strnonunlockable = get_string('nonunlockableverbose', 'grades', $strparamobj); + $title = $langstrings[0]; + return html_writer::span($title, 'text-muted dropdown-item', ['title' => $strnonunlockable, + 'aria-label' => $title, 'role' => 'menuitem']); + } else if ($element['object']->is_locked()) { + $title = $langstrings[0]; + if (!has_capability('moodle/grade:manage', $this->context) && + !has_capability('moodle/grade:unlock', $this->context)) { + return html_writer::span($title, 'text-muted dropdown-item', + ['aria-label' => $title, 'role' => 'menuitem']); + } else { + $url->param('action', 'unlock'); + } + } else { + $title = $langstrings[1]; + if (!has_capability('moodle/grade:manage', $this->context) && + !has_capability('moodle/grade:lock', $this->context)) { + return html_writer::span($title, 'text-muted dropdown-item', + ['aria-label' => $title, 'role' => 'menuitem']); + } else { + $url->param('action', 'lock'); + } + } + + return html_writer::link($url, $title, + ['class' => 'dropdown-item', 'aria-label' => $title, 'role' => 'menuitem']); + } + /** * Return calculation icon for given element * diff --git a/grade/report/grader/index.php b/grade/report/grader/index.php index 4e10cf0553ad9..2d9058d8d4f6d 100644 --- a/grade/report/grader/index.php +++ b/grade/report/grader/index.php @@ -119,7 +119,7 @@ $actionbar = new \gradereport_grader\output\action_bar($context, $report, $numusers); print_grade_page_head($COURSE->id, 'report', 'grader', $reportname, false, $buttons, true, - null, null, null, $actionbar); + null, null, null, $actionbar, false); // make sure separate group does not prevent view if ($report->currentgroup == -2) { diff --git a/grade/report/grader/lang/en/gradereport_grader.php b/grade/report/grader/lang/en/gradereport_grader.php index 84d4e467f8fc2..b331885947ffe 100644 --- a/grade/report/grader/lang/en/gradereport_grader.php +++ b/grade/report/grader/lang/en/gradereport_grader.php @@ -51,6 +51,7 @@ $string['summarygrader'] = 'A table with the names of students in the first column, with assessable activities grouped by course and category across the top.'; $string['useractivitygrade'] = '{$a} grade'; $string['overriddengrade'] = 'Overridden grade'; +$string['cellactions'] = 'Cell actions'; // Deprecated since Moodle 4.2. $string['privacy:metadata:preference:grade_report_showquickfeedback'] = 'Whether to display a feedback text input box with a dotted border for each grade, allowing the feedback for many grades to be edited at the same time'; diff --git a/grade/report/grader/lib.php b/grade/report/grader/lib.php index 634e3725482df..4b84fa038ac30 100644 --- a/grade/report/grader/lib.php +++ b/grade/report/grader/lib.php @@ -199,7 +199,7 @@ public function process_data($data) { $needsupdate = false; - // skip, not a grade + // Skip, not a grade. if (strpos($varname, 'grade') === 0) { $datatype = 'grade'; } else { @@ -773,12 +773,13 @@ public function get_right_rows(bool $displayaverages) : array { // Get preferences once. $showactivityicons = $this->get_pref('showactivityicons'); $quickgrading = $this->get_pref('quickgrading'); - $showanalysisicon = $this->get_pref('showanalysisicon'); // Get strings which are re-used inside the loop. $strftimedatetimeshort = get_string('strftimedatetimeshort'); - $strexcludedgrades = get_string('excluded', 'grades'); $strerror = get_string('error'); + $stroverridengrade = get_string('overridden', 'grades'); + $strfail = get_string('fail', 'grades'); + $strpass = get_string('pass', 'grades'); $viewfullnames = has_capability('moodle/site:viewfullnames', $this->context); foreach ($this->gtree->get_levels() as $row) { @@ -945,6 +946,7 @@ public function get_right_rows(bool $displayaverages) : array { $itemcell->id = 'u' . $userid . 'i' . $itemid; $itemcell->attributes['data-itemid'] = $itemid; + $itemcell->attributes['class'] = 'gradecell'; // Get the decimal points preference for this item. $decimalpoints = $item->get_decimals(); @@ -957,6 +959,8 @@ public function get_right_rows(bool $displayaverages) : array { $gradeval = $grade->finalgrade; } + $context = new stdClass(); + // MDL-11274: Hide grades in the grader report if the current grader // doesn't have 'moodle/grade:viewhidden'. if (!$this->canviewhidden && $grade->is_hidden()) { @@ -964,11 +968,12 @@ public function get_right_rows(bool $displayaverages) : array { && !$item->is_category_item() && !$item->is_course_item()) { // The problem here is that we do not have the time when grade value was modified, // 'timemodified' is general modification date for grade_grades records. - $itemcell->text = "" . - userdate($grade->get_datesubmitted(), $strftimedatetimeshort) . ""; + $context->text = userdate($grade->get_datesubmitted(), $strftimedatetimeshort); + $context->extraclasses = 'datesubmitted'; } else { - $itemcell->text = '-'; + $context->text = '-'; } + $itemcell->text = $OUTPUT->render_from_template('gradereport_grader/cell', $context); $itemrow->cells[] = $itemcell; continue; } @@ -989,39 +994,27 @@ public function get_right_rows(bool $displayaverages) : array { $itemcell->attributes['aria-label'] = $stroverridengrade; } - if ($grade->is_excluded()) { - // Adding white spaces before and after to prevent a screenreader from - // thinking that the words are attached to the next/previous or text. - $itemcell->text .= " " . $strexcludedgrades . " "; - } - - // Do not show any icons if no grade (no record in DB to match) - if (!$item->needsupdate and !empty($USER->editing)) { - $itemcell->text .= $this->get_icons($element); - } - $hidden = ''; if ($grade->is_hidden()) { $hidden = ' dimmed_text '; } - $gradepass = ' gradefail '; - $gradepassicon = $OUTPUT->pix_icon('i/invalid', $strfail); + $context->gradepassicon = $OUTPUT->pix_icon('i/invalid', $strfail); if ($grade->is_passed($item)) { $gradepass = ' gradepass '; - $gradepassicon = $OUTPUT->pix_icon('i/valid', $strpass); + $context->gradepassicon = $OUTPUT->pix_icon('i/valid', $strpass); } else if (is_null($grade->is_passed($item))) { $gradepass = ''; - $gradepassicon = ''; + $context->gradepassicon = ''; } + $context->statusicons = $this->set_grade_status_icons($grade); // If in editing mode, we need to print either a text box or a drop down (for scales) // grades in item of type grade category or course are not directly editable. if ($item->needsupdate) { - $itemcell->text .= "" . $strerror . ""; - + $context->text = $strerror; + $context->extraclasses = 'gradingerror'; } else if (!empty($USER->editing)) { - if ($item->scaleid && !empty($scalesarray[$item->scaleid])) { $itemcell->attributes['class'] .= ' grade_type_scale'; } else if ($item->gradetype == GRADE_TYPE_VALUE) { @@ -1030,7 +1023,13 @@ public function get_right_rows(bool $displayaverages) : array { $itemcell->attributes['class'] .= ' grade_type_text'; } + if ($grade->is_locked()) { + $itemcell->attributes['class'] .= ' locked'; + } + if ($item->scaleid && !empty($scalesarray[$item->scaleid])) { + $context->scale = true; + $scale = $scalesarray[$item->scaleid]; $gradeval = (int)$gradeval; // Scales use only integers. $scales = explode(",", $scale->scale); @@ -1046,6 +1045,7 @@ public function get_right_rows(bool $displayaverages) : array { } if ($quickgrading && $grade->is_editable()) { + $context->iseditable = true; if (empty($item->outcomeid)) { $nogradestr = $this->get_lang_string('nograde'); } else { @@ -1056,38 +1056,50 @@ public function get_right_rows(bool $displayaverages) : array { 'id' => 'grade_' . $userid . '_' . $item->id ]; $gradelabel = $fullname . ' ' . $item->get_name(true); - $itemcell->text .= html_writer::label( - get_string('useractivitygrade', 'gradereport_grader', $gradelabel), $attributes['id'], false, - ['class' => 'accesshide']); - $itemcell->text .= html_writer::select($scaleopt, 'grade['.$userid.']['.$item->id.']', $gradeval, [-1=>$nogradestr], $attributes); + + if ($context->statusicons) { + $attributes['class'] = 'statusicons'; + } + + $context->label = html_writer::label( + get_string('useractivitygrade', 'gradereport_grader', $gradelabel), + $attributes['id'], false, ['class' => 'accesshide']); + $context->select = html_writer::select($scaleopt, 'grade['.$userid.']['.$item->id.']', + $gradeval, [-1 => $nogradestr], $attributes); } else if (!empty($scale)) { $scales = explode(",", $scale->scale); - // invalid grade if gradeval < 1 + $context->extraclasses = 'gradevalue' . $hidden . $gradepass; + // Invalid grade if gradeval < 1. if ($gradeval < 1) { - $itemcell->text .= $gradepassicon . - "-"; + $context->text = '-'; } else { // Just in case somebody changes scale. $gradeval = $grade->grade_item->bounded_grade($gradeval); - $itemcell->text .= $gradepassicon . - "{$scales[$gradeval - 1]}"; + $context->text = $scales[$gradeval - 1]; } } } else if ($item->gradetype != GRADE_TYPE_TEXT) { // Value type. if ($quickgrading and $grade->is_editable()) { + $context->iseditable = true; $value = format_float($gradeval, $decimalpoints); $gradelabel = $fullname . ' ' . $item->get_name(true); - $itemcell->text .= ''; - $itemcell->text .= ''; + + $context->id = 'grade_' . $userid . '_' . $item->id; + $context->name = 'grade[' . $userid . '][' . $item->id .']'; + $context->value = $value; + $context->label = get_string('useractivitygrade', 'gradereport_grader', $gradelabel); + $context->title = $strgrade; + $context->tabindex = $tabindices[$item->id]['grade']; + $context->extraclasses = 'form-control'; + if ($context->statusicons) { + $context->extraclasses .= ' statusicons'; + } } else { - $itemcell->text .= $gradepassicon . "" . - format_float($gradeval, $decimalpoints) . ""; + $context->extraclasses = 'gradevalue' . $hidden . $gradepass; + $context->text = format_float($gradeval, $decimalpoints); } } @@ -1104,7 +1116,8 @@ public function get_right_rows(bool $displayaverages) : array { } if ($item->needsupdate) { - $itemcell->text .= $gradepassicon . "" . $error . ""; + $context->text = $strerror; + $context->extraclasses = 'gradingerror' . $hidden . $gradepass; } else { // The max and min for an aggregation may be different to the grade_item. if (!is_null($gradeval)) { @@ -1112,14 +1125,18 @@ public function get_right_rows(bool $displayaverages) : array { $item->grademin = $grade->get_grade_min(); } - $itemcell->text .= $gradepassicon . "" . - grade_format_gradevalue($gradeval, $item, true, $gradedisplaytype, null) . ""; - if ($showanalysisicon) { - $itemcell->text .= $this->gtree->get_grade_analysis_icon($grade); - } + $context->extraclasses = 'gradevalue ' . $hidden . $gradepass; + $context->text = grade_format_gradevalue($gradeval, $item, true, + $gradedisplaytype, null); } } + if (!$item->needsupdate) { + $context->actionmenu = $this->get_grade_action_menu($element); + } + + $itemcell->text = $OUTPUT->render_from_template('gradereport_grader/cell', $context); + if (!empty($this->gradeserror[$item->id][$userid])) { $itemcell->text .= $this->gradeserror[$item->id][$userid]; } @@ -1143,6 +1160,45 @@ public function get_right_rows(bool $displayaverages) : array { return $rows; } + /** + * Sets status icons for the grade. + * @param grade_grade $grade Grade + * + * @return string status icons container HTML + */ + public function set_grade_status_icons(grade_grade $grade) : string { + global $OUTPUT; + + $attributes = ['class' => 'text-muted']; + + $statusicons = ''; + + if ($grade->is_hidden()) { + $statusicons .= $OUTPUT->pix_icon('i/show', $this->get_lang_string('hidden', 'grades'), + 'moodle', $attributes); + } + + if ($grade->is_locked()) { + $statusicons .= $OUTPUT->pix_icon('i/lock', $this->get_lang_string('locked', 'grades'), + 'moodle', $attributes); + } + + if ($grade->is_overridden()) { + $statusicons .= $OUTPUT->pix_icon('i/overriden_grade', + $this->get_lang_string('overridden', 'grades'), 'moodle', $attributes); + } + + if ($grade->is_excluded()) { + $statusicons .= $OUTPUT->pix_icon('i/excluded', $this->get_lang_string('excluded', 'grades'), + 'moodle', $attributes); + } + + if ($statusicons) { + $statusicons = $OUTPUT->container($statusicons, 'grade_icons'); + } + return $statusicons; + } + /** * Depending on the style of report (fixedstudents vs traditional one-table), * arranges the rows of data in one or two tables, and returns the output of @@ -1619,6 +1675,60 @@ protected function get_icons($element) { return $OUTPUT->container($editicon.$editcalculationicon.$showhideicon.$lockunlockicon.$gradeanalysisicon, 'grade_icons'); } + /** + * Returns an action menu for the grade. + * + * @param array $element Array with cell info. + * @return string + */ + public function get_grade_action_menu(array $element) : string { + global $OUTPUT, $USER; + + $editable = true; + + $context = new stdClass(); + + $editstrings = []; + $editstrings[] = $this->get_lang_string('editgrade', 'grades'); + + $hidestrings = []; + $hidestrings[] = $this->get_lang_string('show'); + $hidestrings[] = $this->get_lang_string('hide'); + + $lockstrings = []; + $lockstrings[] = $this->get_lang_string('unlock', 'grades'); + $lockstrings[] = $this->get_lang_string('lock', 'grades'); + + $gradeanalysisstring = $this->get_lang_string('gradeanalysis', 'grades'); + + if ($element['type'] == 'grade') { + $context->isgrade = true; + $item = $element['object']->grade_item; + if ($item->is_course_item() || $item->is_category_item()) { + $editable = $this->overridecat; + } + + if (!empty($USER->editing)) { + if ($editable) { + $context->editurl = $this->gtree->get_edit_link($element, $this->gpr, $editstrings); + } + + if (has_capability('moodle/grade:manage', $this->context)) { + $context->hideurl = $this->gtree->get_hiding_link($element, $this->gpr, $hidestrings); + $context->lockurl = $this->gtree->get_locking_link($element, $this->gpr, $lockstrings); + } + } + + $context->gradeanalysisurl = $this->gtree->get_grade_analysis_link($element['object'], $gradeanalysisstring); + } + + if (!empty($USER->editing) || isset($context->gradeanalysisurl)) { + return $OUTPUT->render_from_template('gradereport_grader/grademenu', $context); + } + return ''; + } + + /** * Given a category element returns collapsing +/- icon if available * diff --git a/grade/report/grader/styles.css b/grade/report/grader/styles.css index 48699bfde270d..dfb8217afe1c0 100644 --- a/grade/report/grader/styles.css +++ b/grade/report/grader/styles.css @@ -42,10 +42,29 @@ border-left-width: 0; padding: 4px 5px; vertical-align: middle; - text-align: right; + text-align: center; white-space: nowrap; } +.path-grade-report-grader .action-menu { + display: inline-block; +} + +.path-grade-report-grader .overriddengrade { + color: #495057; + border: none; + -moz-appearance: none; + -webkit-appearance: none; +} + +.path-grade-report-grader .gradepass { + color: #357a32; +} + +.path-grade-report-grader .gradefail { + color: #ca3120; +} + /** * All the floating divs. */ @@ -76,6 +95,16 @@ width: 200px; white-space: normal; vertical-align: top; + height: 100px; +} + +.path-grade-report-grader .gradeparent .gradecell { + vertical-align: top; + padding-top: 20px; +} + +.path-grade-report-grader .gradeparent .locked { + padding-top: 27px; } .path-grade-report-grader .gradeparent .user.cell .userpicture { @@ -140,11 +169,6 @@ display: inline-block; } -.path-grade-report-grader .gradeparent tr:nth-child(n) td.overridden:nth-child(n) { - /* Made very specific to override the default stripped style of the table. */ - background-color: #efd9a4; -} - .path-grade-report-grader .gradeparent tr:nth-child(n) td.ajaxoverridden:nth-child(n) { /* Made very specific to override the default stripped style of the table. */ background-color: #ffe3a0; @@ -163,11 +187,11 @@ /** * Editing fields. + * MDL-74286 - width 100% pushes action menu out of cell. */ .path-grade-report-grader .gradeparent select { text-overflow: ellipsis; min-width: 8rem; - width: 100%; } .path-grade-report-grader .gradeparent .text { @@ -178,6 +202,14 @@ text-align: center; } +.path-grade-report-grader .action-menu { + padding-left: 10px; +} + +.path-grade-report-grader .dropdown-menu { + width: max-content; +} + .path-grade-report-grader .yui3-overlay { border: 0; background: none; diff --git a/grade/report/grader/templates/cell.mustache b/grade/report/grader/templates/cell.mustache new file mode 100644 index 0000000000000..38a53bd117253 --- /dev/null +++ b/grade/report/grader/templates/cell.mustache @@ -0,0 +1,48 @@ +{{! + 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 . +}} +{{! + @template gradereport_grader/cell + + Cell template. + + Example context (json): + { + "iseditable": "true", + "statusicons": "
", + "actionmenu": "
", + "id": "grade_313_624", + "label": "grade_313_624", + "title": "Grade", + "extraclasses": "statusicons", + "value": "Text information", + "tabindex": "1", + "name": "grade[313][624]" + } +}} +{{#iseditable}} + {{#scale}} + {{>core_grades/grades/grader/scale}} + {{/scale}} + {{^scale}} + {{>core_grades/grades/grader/input}} + {{/scale}} +{{/iseditable}} +{{^iseditable}} + {{>core_grades/grades/grader/text}} +{{/iseditable}} +{{{actionmenu}}} +{{{statusicons}}} diff --git a/grade/report/grader/templates/grademenu.mustache b/grade/report/grader/templates/grademenu.mustache new file mode 100644 index 0000000000000..11c997dd7d5cf --- /dev/null +++ b/grade/report/grader/templates/grademenu.mustache @@ -0,0 +1,38 @@ +{{! + 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 . +}} +{{! + @template block_timeline/nav-day-filter + This template renders the day range selector for the timeline view. + Example context (json): + { + "editurl": "Edit grade", + "hideurl": "Hide" + } +}} +
+ +
diff --git a/grade/templates/grades/grader/input.mustache b/grade/templates/grades/grader/input.mustache new file mode 100644 index 0000000000000..7316678e9c2f2 --- /dev/null +++ b/grade/templates/grades/grader/input.mustache @@ -0,0 +1,34 @@ +{{! + 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 . +}} +{{! + @template gradereport_grader/input + + Input template for grader report cell. + + Example context (json): + { + "id": "grade_313_624", + "label": "grade_313_624", + "title": "Grade", + "extraclasses": "statusicons", + "value": "Text information", + "tabindex": "1", + "name": "grade[313][624]" + } +}} + + diff --git a/grade/templates/grades/grader/scale.mustache b/grade/templates/grades/grader/scale.mustache new file mode 100644 index 0000000000000..d0c26a762928e --- /dev/null +++ b/grade/templates/grades/grader/scale.mustache @@ -0,0 +1,28 @@ +{{! + 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 . +}} +{{! + @template gradereport_grader/scale + + Scale template for grader report cell. + + Example context (json): + { + "label": "Text label", + "select": "" + } +}} +{{{label}}}{{{select}}} diff --git a/grade/templates/grades/grader/text.mustache b/grade/templates/grades/grader/text.mustache new file mode 100644 index 0000000000000..9f1b2a84f8c6c --- /dev/null +++ b/grade/templates/grades/grader/text.mustache @@ -0,0 +1,30 @@ +{{! + 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 . +}} +{{! + @template gradereport_grader/text + + Text template for grader report cell. + + Example context (json): + { + "gradepassicon": "", + "extraclasses": " dimmed_text", + "text": "Mostly separate knowing" + } +}} +{{{gradepassicon}}} +{{{text}}} diff --git a/grade/tests/behat/behat_grade.php b/grade/tests/behat/behat_grade.php index 0c803a6e926d0..7c27d36d10654 100644 --- a/grade/tests/behat/behat_grade.php +++ b/grade/tests/behat/behat_grade.php @@ -60,7 +60,7 @@ public function i_set_the_following_settings_for_grade_item($gradeitem, TableNod $gradeitem = behat_context_helper::escape($gradeitem); if ($this->running_javascript()) { - $xpath = "//tr[contains(.,$gradeitem)]//*[contains(@class,'moodle-actionmenu')]"; + $xpath = "//tr[contains(.,$gradeitem)]//*[contains(@class,'moodle-actionmenu')][not(contains(@class,'grader'))]"; if ($this->getSession()->getPage()->findAll('xpath', $xpath)) { $this->execute("behat_action_menu::i_open_the_action_menu_in", array("//tr[contains(.,$gradeitem)]", diff --git a/lang/en/grades.php b/lang/en/grades.php index 1b015fd62ec7b..992006559d2e7 100644 --- a/lang/en/grades.php +++ b/lang/en/grades.php @@ -570,6 +570,7 @@ $string['nomode'] = 'NA'; $string['nonnumericweight'] = 'Received non-numeric value for'; $string['nonunlockableverbose'] = 'This grade cannot be unlocked until {$a->itemname} is unlocked.'; +$string['nonunhideableverbose'] = 'This grade cannot be unhidden until {$a->itemname} is hidden.'; $string['nonweightedpct'] = 'non-weighted %'; $string['nooutcome'] = 'No outcome'; $string['nooutcomes'] = 'Outcome items must be linked to a course outcome, but there are no outcomes for this course. Would you like to add one?'; diff --git a/lib/classes/output/icon_system_fontawesome.php b/lib/classes/output/icon_system_fontawesome.php index 6e8ef7cd72f25..f44a463341c20 100644 --- a/lib/classes/output/icon_system_fontawesome.php +++ b/lib/classes/output/icon_system_fontawesome.php @@ -236,6 +236,7 @@ public function get_core_icon_map() { 'core:i/empty' => 'fa-fw', 'core:i/enrolmentsuspended' => 'fa-pause', 'core:i/enrolusers' => 'fa-user-plus', + 'core:i/excluded' => 'fa-minus-circle', 'core:i/expired' => 'fa-exclamation text-warning', 'core:i/export' => 'fa-download', 'core:i/link' => 'fa-link', @@ -294,6 +295,7 @@ public function get_core_icon_map() { 'core:i/open' => 'fa-folder-open', 'core:i/otherevent' => 'fa-calendar', 'core:i/outcomes' => 'fa-tasks', + 'core:i/overriden_grade' => 'fa-edit', 'core:i/payment' => 'fa-money', 'core:i/permissionlock' => 'fa-lock', 'core:i/permissions' => 'fa-pencil-square-o', diff --git a/theme/boost/scss/moodle/grade.scss b/theme/boost/scss/moodle/grade.scss index 65caaf4ad6f2a..487a9a9ce6fdf 100644 --- a/theme/boost/scss/moodle/grade.scss +++ b/theme/boost/scss/moodle/grade.scss @@ -530,6 +530,17 @@ } } +.gradereport-grader-table { + input[name^="grade"] { + width: 80px; + display: inline-block; + } + .dropdown-toggle::after { + display: none; + } +} + + .search-widget { .dropdown-menu { padding: 0.8rem 1.2rem; diff --git a/theme/boost/style/moodle.css b/theme/boost/style/moodle.css index 8e86c40194be3..5ccac87f573a5 100644 --- a/theme/boost/style/moodle.css +++ b/theme/boost/style/moodle.css @@ -19855,6 +19855,13 @@ p.arrow_button { .path-grade-report-singleview .reporttable .dropdown-toggle::after { display: none; } +.gradereport-grader-table input[name^="grade"] { + width: 80px; + display: inline-block; } + +.gradereport-grader-table .dropdown-toggle::after { + display: none; } + .search-widget .dropdown-menu { padding: 0.8rem 1.2rem; } .search-widget .dropdown-menu.wide { diff --git a/theme/classic/style/moodle.css b/theme/classic/style/moodle.css index ba3f8f23f5ae5..16efdb4532005 100644 --- a/theme/classic/style/moodle.css +++ b/theme/classic/style/moodle.css @@ -19855,6 +19855,13 @@ p.arrow_button { .path-grade-report-singleview .reporttable .dropdown-toggle::after { display: none; } +.gradereport-grader-table input[name^="grade"] { + width: 80px; + display: inline-block; } + +.gradereport-grader-table .dropdown-toggle::after { + display: none; } + .search-widget .dropdown-menu { padding: 0.8rem 1.2rem; } .search-widget .dropdown-menu.wide {