MDL-76147 gradereport_grader: Move grade items and categories icons to action menu.

This commit is contained in:
Ilya Tregubov
2023-03-24 09:26:45 +08:00
parent 1c9d0e57b1
commit 7656f5b6b0
17 changed files with 554 additions and 221 deletions
+194 -46
View File
@@ -1539,11 +1539,13 @@ class grade_structure {
* @param bool $withdescription Show description if defined by this item.
* @param bool $fulltotal If the item is a category total, returns $categoryname."total"
* instead of "Category total" or "Course total"
* @param moodle_url|null $sortlink Link to sort column.
*
* @return string header
*/
public function get_element_header(&$element, $withlink = false, $icon = true, $spacerifnone = false,
$withdescription = false, $fulltotal = false) {
public function get_element_header(array &$element, bool $withlink = false, bool $icon = true,
bool $spacerifnone = false, bool $withdescription = false, bool $fulltotal = false,
?moodle_url $sortlink = null) {
$header = '';
if ($icon) {
@@ -1559,15 +1561,22 @@ class grade_structure {
return $header;
}
if ($withlink && $url = $this->get_activity_link($element)) {
$a = new stdClass();
$a->name = get_string('modulename', $element['object']->itemmodule);
$a->title = $titleunescaped;
$title = get_string('linktoactivity', 'grades', $a);
if ($sortlink) {
$url = $sortlink;
$header = html_writer::link($url, $header,
['title' => $titleunescaped, 'class' => 'gradeitemheader']);
}
$header = html_writer::link($url, $header, array('title' => $title, 'class' => 'gradeitemheader'));
} else {
$header = html_writer::span($header, 'gradeitemheader', array('title' => $titleunescaped, 'tabindex' => '0'));
if (!$sortlink) {
if ($withlink && $url = $this->get_activity_link($element)) {
$a = new stdClass();
$a->name = get_string('modulename', $element['object']->itemmodule);
$a->title = $titleunescaped;
$title = get_string('linktoactivity', 'grades', $a);
$header = html_writer::link($url, $header, ['title' => $title, 'class' => 'gradeitemheader']);
} else {
$header = html_writer::span($header, 'gradeitemheader', ['title' => $titleunescaped, 'tabindex' => '0']);
}
}
if ($withdescription) {
@@ -1942,10 +1951,9 @@ class grade_structure {
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)) {
if ((!has_capability('moodle/grade:manage', $this->context) &&
(!($element['type'] == 'grade') || !has_capability('moodle/grade:edit', $this->context)))) {
return null;
}
}
$object = $element['object'];
@@ -1960,11 +1968,84 @@ class grade_structure {
}
$url = $gpr->add_url_params($url);
$title = $langstrings[0];
} else if (($element['type'] == 'item') || ($element['type'] == 'categoryitem') ||
($element['type'] == 'courseitem')) {
if (empty($object->outcomeid) || empty($CFG->enableoutcomes)) {
$url = new moodle_url('/grade/edit/tree/item.php',
['courseid' => $this->courseid, 'id' => $object->id]);
} else {
$url = new moodle_url('/grade/edit/tree/outcomeitem.php',
['courseid' => $this->courseid, 'id' => $object->id]);
}
$url = $gpr->add_url_params($url);
$title = $langstrings[1];
} else if ($element['type'] == 'category') {
$url = new moodle_url('/grade/edit/tree/category.php',
['courseid' => $this->courseid, 'id' => $object->id]);
$url = $gpr->add_url_params($url);
$title = $langstrings[2];
}
return html_writer::link($url, $title,
['class' => 'dropdown-item', 'aria-label' => $title, 'role' => 'menuitem']);
}
/**
* Returns link to the advanced grading page
*
* @param array $element An array representing an element in the grade_tree
* @param object $gpr A grade_plugin_return object
* @return string|null
*/
public function get_advanced_grading_link(array $element, object $gpr): ?string {
global $CFG;
/** @var array static cache of the grade.php file existence flags */
static $hasgradephp = [];
$itemtype = $element['object']->itemtype;
$itemmodule = $element['object']->itemmodule;
$iteminstance = $element['object']->iteminstance;
$itemnumber = $element['object']->itemnumber;
// Links only for module items that have valid instance, module and are
// called from grade_tree with valid modinfo.
if ($itemtype == 'mod' && $iteminstance && $itemmodule && $this->modinfo) {
// Get $cm efficiently and with visibility information using modinfo.
$instances = $this->modinfo->get_instances();
if (!empty($instances[$itemmodule][$iteminstance])) {
$cm = $instances[$itemmodule][$iteminstance];
// Do not add link if activity is not visible to the current user.
if ($cm->uservisible) {
if (!array_key_exists($itemmodule, $hasgradephp)) {
if (file_exists($CFG->dirroot . '/mod/' . $itemmodule . '/grade.php')) {
$hasgradephp[$itemmodule] = true;
} else {
$hasgradephp[$itemmodule] = false;
}
}
// If module has grade.php, add link to that.
if ($hasgradephp[$itemmodule]) {
$args = array('id' => $cm->id, 'itemnumber' => $itemnumber);
if (isset($element['userid'])) {
$args['userid'] = $element['userid'];
}
$url = new moodle_url('/mod/' . $itemmodule . '/grade.php', $args);
$title = get_string('advancedgrading', 'gradereport_grader', $itemmodule);
$gpr->add_url_params($url);
return html_writer::link($url, $title,
['class' => 'dropdown-item', 'aria-label' => $title, 'role' => 'menuitem']);
}
}
}
}
return null;
}
/**
* Return hiding icon for give element
*
@@ -2032,9 +2113,8 @@ class grade_structure {
* @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))) {
if (!$element['object']->can_control_visibility() || !has_capability('moodle/grade:manage', $this->context) ||
!has_capability('moodle/grade:hide', $this->context)) {
return null;
}
@@ -2135,41 +2215,41 @@ class grade_structure {
*/
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 (has_capability('moodle/grade:manage', $this->context)) {
$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']);
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()) {
if (has_capability('moodle/grade:unlock', $this->context)) {
$title = $langstrings[0];
$url->param('action', 'unlock');
} else {
return null;
}
} else {
$url->param('action', 'unlock');
if (has_capability('moodle/grade:lock', $this->context)) {
$title = $langstrings[1];
$url->param('action', 'lock');
} else {
return null;
}
}
return html_writer::link($url, $title,
['class' => 'dropdown-item', 'aria-label' => $title, 'role' => 'menuitem']);
} 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 null;
}
return html_writer::link($url, $title,
['class' => 'dropdown-item', 'aria-label' => $title, 'role' => 'menuitem']);
}
/**
@@ -2218,6 +2298,53 @@ class grade_structure {
return $returnactionmenulink ? null : '';
}
/**
* Returns link to edit calculation for a grade item.
*
* @param array $element An array representing an element in the grade_tree
* @param object $gpr A grade_plugin_return object
* @param string $editcalculationstrings Language string
*
* @return string|null
*/
public function get_edit_calculation_link(array $element, object $gpr,
string $editcalculationstrings): ?string {
if (has_capability('moodle/grade:manage', $this->context)) {
$object = $element['object'];
$isscale = $object->gradetype == GRADE_TYPE_SCALE;
$isvalue = $object->gradetype == GRADE_TYPE_VALUE;
// Show calculation icon only when calculation possible.
if (!$object->is_external_item() && ($isscale || $isvalue)) {
$url = new moodle_url('/grade/edit/tree/calculation.php',
['courseid' => $this->courseid, 'id' => $object->id]);
$url = $gpr->add_url_params($url);
return html_writer::link($url, $editcalculationstrings,
['class' => 'dropdown-item', 'aria-label' => $editcalculationstrings, 'role' => 'menuitem']);
}
}
return null;
}
/**
* Returns link to change category view mode.
*
* @param moodle_url $url Url to grader report page
* @param string $title Menu item title
* @param string $action View mode to change to
* @param bool $active Whether link is active in dropdown
*
* @return string|null
*/
public function get_category_view_mode_link(moodle_url $url, string $title, string $action, bool $active = false): ?string {
$urlnew = $url;
$urlnew->param('action', $action);
$active = $active ? 'true' : 'false';
return html_writer::link($urlnew, $title,
['class' => 'dropdown-item', 'aria-label' => $title, 'aria-current' => $active, 'role' => 'menuitem']);
}
}
/**
@@ -3051,6 +3178,27 @@ abstract class grade_helper {
*/
protected static $aggregationstrings = null;
/**
* Cached grade tree plugin strings
* @var array
*/
protected static $langstrings = [];
/**
* First checks the cached language strings, then returns match if found, or uses get_string()
* to get it from the DB, caches it then returns it.
*
* @param string $strcode
* @param string|null $section Optional language section
* @return string
*/
public static function get_lang_string(string $strcode, ?string $section = null): string {
if (empty(self::$langstrings[$strcode])) {
self::$langstrings[$strcode] = get_string($strcode, $section);
}
return self::$langstrings[$strcode];
}
/**
* Gets strings commonly used by the describe plugins
*
@@ -48,6 +48,7 @@ $string['privacy:request:preference:grade_report_grader_collapsed_categories'] =
$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['advancedgrading'] = 'View {$a} results';
$string['cellactions'] = 'Cell actions';
// Deprecated since Moodle 4.2.
+164 -150
View File
@@ -596,24 +596,13 @@ class grade_report_grader extends grade_report {
$rows = [];
$showuserimage = $this->get_pref('showuserimage');
// FIXME: MDL-52678 This get_capability_info is hacky and we should have an API for inserting grade row links instead.
$canseeuserreport = false;
$canseesingleview = false;
if (get_capability_info('gradereport/' . $CFG->grade_profilereport.':view')) {
$canseeuserreport = has_capability('gradereport/' . $CFG->grade_profilereport.':view', $this->context);
}
if (get_capability_info('gradereport/singleview:view')) {
$canseesingleview = has_all_capabilities(['gradereport/singleview:view',
'moodle/grade:viewall', 'moodle/grade:edit'], $this->context);
}
$hasuserreportcell = $canseeuserreport || $canseesingleview;
$viewfullnames = has_capability('moodle/site:viewfullnames', $this->context);
$extrafields = \core_user\fields::get_identity_fields($this->context);
$arrows = $this->get_sort_arrows($extrafields);
$colspan = 1 + $hasuserreportcell + count($extrafields);
$colspan = 1 + count($extrafields);
$levels = count($this->gtree->levels) - 1;
@@ -646,25 +635,17 @@ class grade_report_grader extends grade_report {
$studentheader->text = $arrows['studentname'];
$headerrow->cells[] = $studentheader;
if ($hasuserreportcell) {
$emptyheader = new html_table_cell();
$headerrow->cells[] = $emptyheader;
}
foreach ($extrafields as $field) {
$fieldheader = new html_table_cell();
$fieldheader->attributes['class'] = 'userfield user' . $field;
$fieldheader->scope = 'col';
$fieldheader->header = true;
$fieldheader->text = $arrows[$field];
$headerrow->cells[] = $fieldheader;
}
$rows[] = $headerrow;
$rows = $this->get_left_icons_row($rows, $colspan);
$suspendedstring = null;
$usercount = 0;
@@ -705,35 +686,10 @@ class grade_report_grader extends grade_report {
// when horizontally scrolling through the table contents (most noticeable when in RTL mode).
// Therefore, add slight padding on the left or right when using RTL mode.
$usercell->attributes['class'] .= ' pl-3';
$usercell->text .= $this->get_cell_action_menu(['userid' => $userid], 'user');
$userrow->cells[] = $usercell;
$userreportcell = new html_table_cell();
$userreportcell->attributes['class'] = 'userreport';
$userreportcell->header = false;
if ($canseeuserreport) {
$a = new stdClass();
$a->user = $fullname;
$strgradesforuser = get_string('gradesforuser', 'grades', $a);
$url = new moodle_url('/grade/report/'.$CFG->grade_profilereport.'/index.php',
['userid' => $user->id, 'id' => $this->course->id]);
$userreportcell->text .= $OUTPUT->action_icon($url, new pix_icon('t/grades', ''), null,
['title' => $strgradesforuser, 'aria-label' => $strgradesforuser]);
}
if ($canseesingleview) {
$strsingleview = get_string('singleview', 'grades', $fullname);
$url = new moodle_url('/grade/report/singleview/index.php',
['id' => $this->course->id, 'itemid' => $user->id, 'item' => 'user']);
$singleview = $OUTPUT->action_icon($url, new pix_icon('t/editstring', ''), null,
['title' => $strsingleview, 'aria-label' => $strsingleview]);
$userreportcell->text .= $singleview;
}
if ($userreportcell->text) {
$userrow->cells[] = $userreportcell;
}
foreach ($extrafields as $field) {
$fieldcell = new html_table_cell();
$fieldcell->attributes['class'] = 'userfield user' . $field;
@@ -827,62 +783,42 @@ class grade_report_grader extends grade_report {
$categorycell->header = true;
$categorycell->scope = 'col';
// Print icons.
if (!empty($USER->editing)) {
$categorycell->text .= $this->get_icons($element);
$statusicons = $this->set_grade_status_icons($element);
if ($statusicons) {
$categorycell->text .= $statusicons;
$categorycell->attributes['class'] .= ' statusicons';
}
$headingrow->cells[] = $categorycell;
}
} else {
// Element is a grade_item.
$arrow = '';
if ($element['object']->id == $this->sortitemid) {
if ($this->sortorder == 'ASC') {
$arrow = $this->get_sort_arrow('up', $sortlink);
} else {
$arrow = $this->get_sort_arrow('down', $sortlink);
}
} else {
$arrow = $this->get_sort_arrow('move', $sortlink);
}
$headerlink = $this->gtree->get_element_header($element, true,
$showactivityicons, false, false, true);
true, false, false, true, $sortlink);
$itemcell = new html_table_cell();
$itemcell->attributes['class'] = $type . ' ' . $catlevel .
' highlightable'. ' i'. $element['object']->id;
$itemcell->attributes['data-itemid'] = $element['object']->id;
if ($element['object']->is_hidden()) {
$itemcell->attributes['class'] .= ' dimmed_text';
}
$singleview = '';
// FIXME: MDL-52678 This is extremely hacky we should have an API for inserting grade column links.
if (get_capability_info('gradereport/singleview:view')) {
if (has_all_capabilities(['gradereport/singleview:view', 'moodle/grade:viewall',
'moodle/grade:edit'], $this->context)) {
$strsingleview = get_string('singleview', 'grades',
$element['object']->get_name());
$url = new moodle_url('/grade/report/singleview/index.php', [
'id' => $this->course->id,
'item' => 'grade',
'itemid' => $element['object']->id
]);
$singleview = $OUTPUT->action_icon(
$url,
new pix_icon('t/editstring', ''),
null,
['title' => $strsingleview, 'aria-label' => $strsingleview]
);
}
$singleview = $this->get_cell_action_menu($element, 'gradeitem');
$statusicons = $this->set_grade_status_icons($element);
if ($statusicons) {
$itemcell->attributes['class'] .= ' statusicons';
}
$itemcell->colspan = $colspan;
$itemcell->text = $headerlink . $arrow . $singleview;
$itemcell->text = $headerlink . $arrow . $singleview . $statusicons;
$itemcell->header = true;
$itemcell->scope = 'col';
@@ -892,8 +828,6 @@ class grade_report_grader extends grade_report {
$rows[] = $headingrow;
}
$rows = $this->get_right_icons_row($rows);
// Preload scale objects for items with a scaleid and initialize tab indices.
$scaleslist = [];
$tabindices = [];
@@ -1007,7 +941,7 @@ class grade_report_grader extends grade_report {
$gradepass = '';
$context->gradepassicon = '';
}
$context->statusicons = $this->set_grade_status_icons($grade);
$context->statusicons = $this->set_grade_status_icons($element);
// 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.
@@ -1132,7 +1066,7 @@ class grade_report_grader extends grade_report {
}
if (!$item->needsupdate) {
$context->actionmenu = $this->get_grade_action_menu($element);
$context->actionmenu = $this->get_cell_action_menu($element, 'gradeitem');
}
$itemcell->text = $OUTPUT->render_from_template('gradereport_grader/cell', $context);
@@ -1162,39 +1096,45 @@ class grade_report_grader extends grade_report {
/**
* Sets status icons for the grade.
* @param grade_grade $grade Grade
* @param array $element array with grade item info
*
* @return string status icons container HTML
*/
public function set_grade_status_icons(grade_grade $grade) : string {
public function set_grade_status_icons(array $element) : string {
global $OUTPUT;
$attributes = ['class' => 'text-muted'];
$statusicons = '';
if ($grade->is_hidden()) {
if ($element['object']->is_hidden()) {
$statusicons .= $OUTPUT->pix_icon('i/show', $this->get_lang_string('hidden', 'grades'),
'moodle', $attributes);
}
if ($grade->is_locked()) {
if ($element['object']->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 ($element['object'] instanceof grade_grade) {
$grade = $element['object'];
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 ($grade->is_excluded()) {
$statusicons .= $OUTPUT->pix_icon('i/excluded', $this->get_lang_string('excluded', 'grades'),
'moodle', $attributes);
$class = 'grade_icons';
if ($element['type'] == 'category') {
$class = 'category_grade_icons';
}
if ($statusicons) {
$statusicons = $OUTPUT->container($statusicons, 'grade_icons');
$statusicons = $OUTPUT->container($statusicons, $class);
}
return $statusicons;
}
@@ -1236,10 +1176,15 @@ class grade_report_grader extends grade_report {
* @param array $rows The Array of rows for the left part of the report
* @param int $colspan The number of columns this cell has to span
* @return array Array of rows for the left part of the report
* @deprecated since Moodle 4.2 - The row is not shown anymore - we have actions menu.
* @todo MDL-77307 This will be deleted in Moodle 4.6.
*/
public function get_left_icons_row($rows=array(), $colspan=1) {
global $USER;
debugging('The function get_left_icons_row() is deprecated, please do not use it anymore.',
DEBUG_DEVELOPER);
if (!empty($USER->editing)) {
$controlsrow = new html_table_row();
$controlsrow->attributes['class'] = 'controls';
@@ -1335,9 +1280,14 @@ class grade_report_grader extends grade_report {
* Builds and return the row of icons when editing is on, for the right part of the grader report.
* @param array $rows The Array of rows for the right part of the report
* @return array Array of rows for the right part of the report
* @deprecated since Moodle 4.2 - The row is not shown anymore - we have actions menu.
* @todo MDL-77307 This will be deleted in Moodle 4.6.
*/
public function get_right_icons_row($rows=array()) {
global $USER;
debugging('The function get_right_icons_row() is deprecated, please do not use it anymore.',
DEBUG_DEVELOPER);
if (!empty($USER->editing)) {
$iconsrow = new html_table_row();
$iconsrow->attributes['class'] = 'controls';
@@ -1571,34 +1521,14 @@ class grade_report_grader extends grade_report {
* @return string HTML
*/
protected function get_course_header($element) {
global $OUTPUT;
$actionmenu = $this->get_cell_action_menu($element, 'gradeitem');
$icon = '';
// If object is a category, display expand/contract icon.
if ($element['type'] == 'category') {
// Load language strings.
$strswitchminus = $this->get_lang_string('aggregatesonly', 'grades');
$strswitchplus = $this->get_lang_string('gradesonly', 'grades');
$strswitchwhole = $this->get_lang_string('fullmode', 'grades');
$url = new moodle_url($this->gpr->get_return_url(null, array('target' => $element['eid'], 'sesskey' => sesskey())));
if (in_array($element['object']->id, $this->collapsed['aggregatesonly'])) {
$url->param('action', 'switch_plus');
$icon = $OUTPUT->action_icon($url, new pix_icon('t/switch_plus', ''), null,
['title' => $strswitchplus, 'aria-label' => $strswitchplus]);
$showing = get_string('showingaggregatesonly', 'grades');
} else if (in_array($element['object']->id, $this->collapsed['gradesonly'])) {
$url->param('action', 'switch_whole');
$icon = $OUTPUT->action_icon($url, new pix_icon('t/switch_whole', ''), null,
['title' => $strswitchwhole, 'aria-label' => $strswitchwhole]);
$showing = get_string('showinggradesonly', 'grades');
} else {
$url->param('action', 'switch_minus');
$icon = $OUTPUT->action_icon($url, new pix_icon('t/switch_minus', ''), null,
['title' => $strswitchminus, 'aria-label' => $strswitchminus]);
$showing = get_string('showingfullmode', 'grades');
}
if (in_array($element['object']->id, $this->collapsed['aggregatesonly'])) {
$showing = get_string('showingaggregatesonly', 'grades');
} else if (in_array($element['object']->id, $this->collapsed['gradesonly'])) {
$showing = get_string('showinggradesonly', 'grades');
} else {
$showing = get_string('showingfullmode', 'grades');
}
$name = $element['object']->get_name();
@@ -1612,7 +1542,7 @@ class grade_report_grader extends grade_report {
$courseheader .= html_writer::div($showing, 'sr-only', [
'id' => $describedbyid
]);
$courseheader .= $icon;
$courseheader .= $actionmenu;
return $courseheader;
}
@@ -1624,9 +1554,13 @@ class grade_report_grader extends grade_report {
*
* @param array $element
* @return string HTML
* @deprecated since Moodle 4.2 - The row is not shown anymore - we have actions menu.
* @todo MDL-77307 This will be deleted in Moodle 4.6.
*/
protected function get_icons($element) {
global $CFG, $USER, $OUTPUT;
debugging('The function get_icons() is deprecated, please do not use it anymore.',
DEBUG_DEVELOPER);
if (empty($USER->editing)) {
return '<div class="grade_icons" />';
@@ -1674,56 +1608,131 @@ class grade_report_grader extends grade_report {
* Returns an action menu for the grade.
*
* @param array $element Array with cell info.
* @param string $mode Mode - gradeitem or user
* @return string
*/
public function get_grade_action_menu(array $element) : string {
global $OUTPUT, $USER;
$editable = true;
public function get_cell_action_menu(array $element, string $mode): string {
global $OUTPUT, $USER, $CFG;
$context = new stdClass();
$editstrings = [];
$editstrings[] = $this->get_lang_string('editgrade', 'grades');
if ($mode == 'gradeitem') {
$editable = true;
$editstrings = [];
$editstrings[] = $this->get_lang_string('editgrade', 'grades');
$editstrings[] = $this->get_lang_string('itemsedit', 'grades');
$editstrings[] = $this->get_lang_string('categoryedit', 'grades');
$hidestrings = [];
$hidestrings[] = $this->get_lang_string('show');
$hidestrings[] = $this->get_lang_string('hide');
$editcalculationstrings = $this->get_lang_string('editcalculation', 'grades');
$lockstrings = [];
$lockstrings[] = $this->get_lang_string('unlock', 'grades');
$lockstrings[] = $this->get_lang_string('lock', 'grades');
$hidestrings = [];
$hidestrings[] = $this->get_lang_string('show');
$hidestrings[] = $this->get_lang_string('hide');
$gradeanalysisstring = $this->get_lang_string('gradeanalysis', 'grades');
$lockstrings = [];
$lockstrings[] = $this->get_lang_string('unlock', 'grades');
$lockstrings[] = $this->get_lang_string('lock', '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;
}
$gradeanalysisstring = $this->get_lang_string('gradeanalysis', 'grades');
if (!empty($USER->editing)) {
if ($editable) {
$context->editurl = $this->gtree->get_edit_link($element, $this->gpr, $editstrings);
if ($element['type'] == 'grade') {
$item = $element['object']->grade_item;
if ($item->is_course_item() || $item->is_category_item()) {
$editable = $this->overridecat;
}
if (has_capability('moodle/grade:manage', $this->context)) {
if (!empty($USER->editing)) {
if ($editable) {
$context->editurl = $this->gtree->get_edit_link($element, $this->gpr, $editstrings);
}
$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);
} else if (($element['type'] == 'item') ||
($element['type'] == 'categoryitem') ||
($element['type'] == 'courseitem')) {
if ($element['type'] == 'item') {
foreach ($this->get_report_links($this->context, $this->courseid, $element, $this->gpr, $mode)
as $count => $reportlink) {
$temp = 'reporturl' . $count;
$context->$temp = $reportlink;
}
$context->advancedgradingurl = $this->gtree->get_advanced_grading_link($element, $this->gpr);
}
if (!empty($USER->editing)) {
$context->divider = true;
if ($element['type'] == 'item') {
$context->editurl = $this->gtree->get_edit_link($element, $this->gpr, $editstrings);
}
$context->editcalculationurl =
$this->gtree->get_edit_calculation_link($element, $this->gpr, $editcalculationstrings);
$object = $element['object'];
if ($object->itemmodule !== 'quiz') {
$context->hideurl = $this->gtree->get_hiding_link($element, $this->gpr, $hidestrings);
}
$context->lockurl = $this->gtree->get_locking_link($element, $this->gpr, $lockstrings);
}
} else if ($element['type'] == 'category') {
$categoryid = $element['object']->id;
// Load language strings.
$strswitchminus = $this->get_lang_string('aggregatesonly', 'grades');
$strswitchplus = $this->get_lang_string('gradesonly', 'grades');
$strswitchwhole = $this->get_lang_string('fullmode', 'grades');
$url = new moodle_url($this->gpr->get_return_url(null,
['target' => $element['eid'], 'sesskey' => sesskey()]));
$gradesonly = false;
$aggregatesonly = false;
$fullmode = false;
if (in_array($categoryid, $this->collapsed['gradesonly'])) {
$gradesonly = true;
} else if (in_array($categoryid, $this->collapsed['aggregatesonly'])) {
$aggregatesonly = true;
} else {
$fullmode = true;
}
$context->gradesonlyurl =
$this->gtree->get_category_view_mode_link($url, $strswitchplus, 'switch_plus', $gradesonly);
$context->aggregatesonlyurl =
$this->gtree->get_category_view_mode_link($url, $strswitchminus, 'switch_minus', $aggregatesonly);
$context->fullmodeurl =
$this->gtree->get_category_view_mode_link($url, $strswitchwhole, 'switch_whole', $fullmode);
if (!empty($USER->editing)) {
$context->divider = true;
$context->editurl = $this->gtree->get_edit_link($element, $this->gpr, $editstrings);
$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);
$context->dataid = $element['object']->id;
} else if ($mode == 'user') {
foreach ($this->get_report_links($this->context, $this->courseid, $element, $this->gpr, $mode)
as $count => $reportlink) {
$temp = 'reporturl' . $count;
$context->$temp = $reportlink;
}
$context->dataid = $element['userid'];
}
if (!empty($USER->editing) || isset($context->gradeanalysisurl)) {
return $OUTPUT->render_from_template('gradereport_grader/grademenu', $context);
if (!empty($USER->editing) || isset($context->gradeanalysisurl) || isset($context->gradesonlyurl)
|| isset($context->aggregatesonlyurl) || isset($context->fullmodeurl) || isset($context->reporturl0)) {
return $OUTPUT->render_from_template('gradereport_grader/cellmenu', $context);
}
return '';
}
/**
* Given a category element returns collapsing +/- icon if available
*
@@ -1910,6 +1919,11 @@ class grade_report_grader extends grade_report {
static::set_collapsed_preferences($courseid, $collapsed);
}
$key = array_search($targetid, $collapsed['aggregatesonly']);
if ($key !== false) {
unset($collapsed['aggregatesonly'][$key]);
static::set_collapsed_preferences($courseid, $collapsed);
}
break;
default:
break;
+16 -4
View File
@@ -65,6 +65,10 @@
color: #ca3120;
}
.path-grade-report-grader .grade_icons {
text-align: center;
}
/**
* All the floating divs.
*/
@@ -91,13 +95,21 @@
* The user cells.
*/
.path-grade-report-grader .gradeparent .user.cell {
min-width: 200px;
width: 200px;
min-width: 250px;
width: 250px;
white-space: normal;
vertical-align: top;
vertical-align: middle;
height: 100px;
}
.path-grade-report-grader .gradeparent .highlightable.cell {
height: 80px;
text-align: center;
vertical-align: top;
padding-top: 20px;
min-width: 150px;
}
.path-grade-report-grader .gradeparent .gradecell {
vertical-align: top;
padding-top: 20px;
@@ -117,7 +129,7 @@
overflow: hidden;
text-overflow: ellipsis;
max-width: 200px;
vertical-align: bottom;
vertical-align: middle;
}
/**
@@ -1,29 +1,35 @@
{{!
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/>.
}}
{{!
@template block_timeline/nav-day-filter
This template renders the day range selector for the timeline view.
@template gradereport_grader/cellmenu
This template renders action menu for a given cell.
Example context (json):
{
"editurl": "<a class='dropdown-item' aria-label='Edit grade' role='menuitem' href='grade/edit/tree/grade.php?courseid=13&itemid=608&userid=85&gpr_type=report&gpr_plugin=grader&gpr_courseid=13'>Edit grade</a>",
"hideurl": "<a class='dropdown-item' aria-label='Single view for this item' role='menuitem' href='grade/edit/tree/action.php?id=13&sesskey=sMAOMLAAN5&eid=n608u85&gpr_type=report&gpr_plugin=grader&gpr_courseid=13&action=hide'>Hide</a>"
"hideurl": "<a class='dropdown-item' aria-label='Hide' role='menuitem' href='grade/edit/tree/action.php?id=13&sesskey=sMAOMLAAN5&eid=n608u85&gpr_type=report&gpr_plugin=grader&gpr_courseid=13&action=hide'>Hide</a>",
"reporturl0": "<a class='dropdown-item' aria-label='Single view for this user' role='menuitem' href='grade/report/singleview/index.php?id=13&amp;itemid=39&amp;item=user&amp;gpr_type=report&amp;gpr_plugin=grader&amp;gpr_courseid=13'>Single view for this user</a>",
"reporturl1": "<a class='dropdown-item' aria-label='User report' role='menuitem' href='grade/report/user/index.php?userid=39&amp;id=13&amp;gpr_type=report&amp;gpr_plugin=grader&amp;gpr_courseid=13'>User report</a>"
}
}}
<div class="action-menu mb-1 moodle-actionmenu grader">
<div class="dropdown">
<button class="btn btn-link btn-icon icon-size-3 grademenubtn"
type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<button class="btn btn-link btn-icon icon-size-3 cellmenubtn"
type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-id={{dataid}}>
<i class="icon fa fa-ellipsis-h fa-fw m-0" title="{{#str}} cellactions, gradereport_grader {{/str}}" aria-hidden="true"></i>
<span class="sr-only">{{#str}} cellactions, gradereport_grader {{/str}}</span>
</button>
@@ -31,6 +37,15 @@
<div role="menu" class="dropdown-menu">
{{#editurl}}{{{editurl}}}{{/editurl}}
{{#gradeanalysisurl}}{{{gradeanalysisurl}}}{{/gradeanalysisurl}}
{{#editcalculationurl}}{{{editcalculationurl}}}{{/editcalculationurl}}
{{#reporturl0}}{{{reporturl0}}}{{/reporturl0}}
{{#reporturl1}}{{{reporturl1}}}{{/reporturl1}}
{{#gradesonlyurl}}{{{gradesonlyurl}}}{{/gradesonlyurl}}
{{#aggregatesonlyurl}}{{{aggregatesonlyurl}}}{{/aggregatesonlyurl}}
{{#fullmodeurl}}{{{fullmodeurl}}}{{/fullmodeurl}}
{{#divider}}
<div class="dropdown-divider" role="separator"></div>
{{/divider}}
{{#hideurl}}{{{hideurl}}}{{/hideurl}}
{{#lockurl}}{{{lockurl}}}{{/lockurl}}
</div>
+29 -5
View File
@@ -270,6 +270,30 @@ abstract class grade_report {
*/
abstract public function process_action($target, $action);
/**
* Returns an array of links to appropriate report pages for the current element
* @param context_course $context Course context
* @param int $courseid Course ID
* @param array $element An array representing an element in the grade_tree
* @param grade_plugin_return $gpr A grade_plugin_return object
* @param string $mode Mode - gradeitem or user
* @return array Link to appropriate report
*/
public function get_report_links(context_course $context, int $courseid, array $element,
grade_plugin_return $gpr, string $mode): array {
$reports = [];
foreach (core_component::get_plugin_list('gradereport') as $plugin => $plugindir) {
$params = [$context, $courseid, $element, $gpr, $mode];
$component = 'gradereport_' . $plugin;
if ($reportlink = component_callback($component, 'get_report_link', $params)) {
$reports[] = $reportlink;
}
}
return $reports;
}
/**
* First checks the cached language strings, then returns match if found, or uses get_string()
* to get it from the DB, caches it then returns it.
@@ -412,13 +436,13 @@ abstract class grade_report {
/**
* Returns an arrow icon inside an <a> tag, for the purpose of sorting a column.
* @param string $direction
* @param moodle_url $sortlink
* @param moodle_url|null $sortlink
*/
protected function get_sort_arrow($direction='move', $sortlink=null) {
protected function get_sort_arrow(string $direction = 'down', ?moodle_url $sortlink = null) {
global $OUTPUT;
$pix = array('up' => 't/sort_desc', 'down' => 't/sort_asc', 'move' => 't/sort');
$matrix = array('up' => 'desc', 'down' => 'asc', 'move' => 'asc');
$strsort = $this->get_lang_string('sort' . $matrix[$direction]);
$pix = ['up' => 't/sort_desc', 'down' => 't/sort_asc'];
$matrix = ['up' => 'desc', 'down' => 'asc'];
$strsort = $this->get_lang_string($matrix[$direction], 'moodle');
$arrow = $OUTPUT->pix_icon($pix[$direction], '', '', ['class' => 'sorticon']);
return html_writer::link($sortlink, $arrow, ['title' => $strsort, 'aria-label' => $strsort]);
@@ -17,7 +17,9 @@
namespace gradereport_singleview\report;
use context_course;
use grade_helper;
use grade_report;
use html_writer;
use moodle_url;
use renderer_base;
use stdClass;
@@ -196,5 +198,4 @@ class singleview extends grade_report {
return $output->render($menu);
}
}
@@ -67,6 +67,8 @@ $string['savegrades'] = 'Saving grades';
$string['save'] = 'Save';
$string['savegradessuccess'] = 'Grades were set for {$a} items';
$string['singleview:view'] = 'View single view';
$string['singleviewreport_user'] = 'Single view for this user';
$string['singleviewreport_gradeitem'] = 'Single view for this item';
$string['summarygrade'] = 'A table of users, with columns for range, grade, feedback, and whether to override or exclude a particular grade.';
$string['summaryuser'] = 'A table of grade items, with columns for grade category, range, grade, feedback, and whether to override or exclude a particular grade.';
$string['unsavedataalert'] = 'If you have unsaved changes on the page, you will lose them if you proceed with bulk insert grades.';
+74
View File
@@ -0,0 +1,74 @@
<?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/>.
/**
* Singleview report generic functions
*
* @package gradereport_singleview
* @copyright 2023 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Returns link to singleview report for the current element
*
* @param context_course $context Course context
* @param int $courseid Course ID
* @param array $element An array representing an element in the grade_tree
* @param grade_plugin_return $gpr A grade_plugin_return object
* @param string $mode Mode - gradeitem or user
* @return string|null
*/
function gradereport_singleview_get_report_link(context_course $context, int $courseid,
array $element, grade_plugin_return $gpr, string $mode): ?string {
$reportstring = grade_helper::get_lang_string('singleviewreport_' . $mode, 'gradereport_singleview');
if ($mode == 'gradeitem') {
// View all grades items.
// FIXME: MDL-52678 This is extremely hacky we should have an API for inserting grade column links.
if (get_capability_info('gradereport/singleview:view')) {
if (has_all_capabilities(['gradereport/singleview:view', 'moodle/grade:viewall',
'moodle/grade:edit'], $context)) {
$url = new moodle_url('/grade/report/singleview/index.php', [
'id' => $courseid,
'item' => 'grade',
'itemid' => $element['object']->id
]);
$gpr->add_url_params($url);
return html_writer::link($url, $reportstring,
['class' => 'dropdown-item', 'aria-label' => $reportstring, 'role' => 'menuitem']);
}
}
} else if ($mode == 'user') {
// FIXME: MDL-52678 This get_capability_info is hacky and we should have an API for inserting grade row links instead.
$canseesingleview = false;
if (get_capability_info('gradereport/singleview:view')) {
$canseesingleview = has_all_capabilities(['gradereport/singleview:view',
'moodle/grade:viewall', 'moodle/grade:edit'], $context);
}
if ($canseesingleview) {
$url = new moodle_url('/grade/report/singleview/index.php',
['id' => $courseid, 'itemid' => $element['userid'], 'item' => 'user']);
$gpr->add_url_params($url);
return html_writer::link($url, $reportstring,
['class' => 'dropdown-item', 'aria-label' => $reportstring, 'role' => 'menuitem']);
}
}
return null;
}
+5
View File
@@ -2,11 +2,16 @@ This files describes API changes in /grade/report/*,
information provided here is intended especially for developers.
=== 4.2 ===
* The grade_report_grader:get_icons(), grade_report_grader:get_left_icons_row()
and grade_report_grader:get_right_icons_row() functions have been deprecated and are not used anymore.
* 'Show grade analysis icon' setting has been removed from grader report (link is moved to grade action menu)
* 'Show locks' setting has been removed from grader report (link is moved to grade action menu)
* 'Show show/hide icons' setting has been removed from grader report (link is moved to grade action menu)
* 'Enable AJAX' interface has been deprecated for grader report
* 'Quick feedback' interface has been deprecated for grader report
* A new method grade_report::get_report_links() is created to obtain links to other grade plugins report pages.
It loops through all installed grade report plugins and checks if callback function gradereport_*_get_report_link
is implemented in for given grade report plugin in the corresponding lib.php
=== 3.6 ===
* External function gradereport_user_external::get_grade_items now return the following information (only for course managers).
@@ -19,8 +19,11 @@ namespace gradereport_user\report;
use context_course;
use course_modinfo;
use grade_grade;
use grade_helper;
use grade_report;
use grade_tree;
use html_writer;
use moodle_url;
defined('MOODLE_INTERNAL') || die;
@@ -34,3 +34,4 @@ $string['userreportdesc'] = 'User reports include a users grades, feedback an
$string['userreports'] = 'Select a user above to view their report';
$string['privacy:metadata:preference:gradereport_user_view_user'] = 'Whether to view report as current user or another user in the gradebook reports';
$string['tablesummary'] = 'The table is arranged as a list of graded items including categories of graded items. When items are in a category they will be indicated as such.';
$string['userreport_user'] = 'User report';
+34
View File
@@ -238,3 +238,37 @@ function gradereport_user_myprofile_navigation(tree $tree, stdClass $user, bool
}
}
}
/**
* Returns link to user report for the current element
*
* @param context_course $context Course context
* @param int $courseid Course ID
* @param array $element An array representing an element in the grade_tree
* @param grade_plugin_return $gpr A grade_plugin_return object
* @param string $mode Mode - gradeitem or user
* @return string|null
*/
function gradereport_user_get_report_link(context_course $context, int $courseid, array $element,
grade_plugin_return $gpr, string $mode): ?string {
global $CFG;
if ($mode == 'user') {
$reportstring = grade_helper::get_lang_string('userreport_' . $mode, 'gradereport_user');
// FIXME: MDL-52678 This get_capability_info is hacky and we should have an API for inserting grade row links instead.
$canseeuserreport = false;
if (get_capability_info('gradereport/' . $CFG->grade_profilereport . ':view')) {
$canseeuserreport = has_capability('gradereport/' . $CFG->grade_profilereport . ':view', $context);
}
if ($canseeuserreport) {
$url = new moodle_url('/grade/report/' . $CFG->grade_profilereport . '/index.php',
['userid' => $element['userid'], 'id' => $courseid]);
$gpr->add_url_params($url);
return html_writer::link($url, $reportstring,
['class' => 'dropdown-item', 'aria-label' => $reportstring, 'role' => 'menuitem']);
}
}
return null;
}
+6 -7
View File
@@ -48,7 +48,7 @@ $string['aggregateonlygraded_help'] = 'An empty grade is a grade which is missin
This setting determines whether empty grades are not included in the aggregation or are counted as minimal grades, for example 0 for an assignment graded between 0 and 100.';
$string['aggregateoutcomes'] = 'Include outcomes in aggregation';
$string['aggregateoutcomes_help'] = 'If enabled, outcomes are included in the aggregation. This may result in an unexpected category total.';
$string['aggregatesonly'] = 'Change to aggregates only';
$string['aggregatesonly'] = 'Show totals only';
$string['aggregatesum'] = 'Natural';
$string['aggregateweightedmean'] = 'Weighted mean of grades';
$string['aggregateweightedmean2'] = 'Simple weighted mean of grades';
@@ -125,7 +125,6 @@ $string['compact'] = 'Compact';
$string['componentcontrolsvisibility'] = 'Whether this grade item is hidden is controlled by the activity settings.';
$string['contract'] = 'Contract category';
$string['contributiontocoursetotal'] = 'Contribution to course total';
$string['controls'] = 'Controls';
$string['courseavg'] = 'Course average';
$string['coursegradecategory'] = 'Course grade category';
$string['coursegradedisplaytype'] = 'Course grade display type';
@@ -251,7 +250,7 @@ $string['forceon'] = 'Force: On';
$string['forelementtypes'] = 'for the selected {$a}';
$string['forstudents'] = 'For students';
$string['full'] = 'Full';
$string['fullmode'] = 'Change to full view';
$string['fullmode'] = 'Show grades and totals';
$string['generalsettings'] = 'General settings';
$string['grade'] = 'Grade';
$string['grade_help'] = 'The grade to award the student for their work.';
@@ -348,8 +347,7 @@ $string['gradereport'] = 'Grade report';
$string['graderreport'] = 'Grader report';
$string['grades'] = 'Grades';
$string['gradesforuser'] = 'Grades for {$a->user}';
$string['singleview'] = 'Single view for {$a}';
$string['gradesonly'] = 'Change to grades only';
$string['gradesonly'] = 'Show grades only';
$string['gradesmoduledeletionpendingwarning'] = 'Warning: Activity deletion in progress! Some grades are about to be removed.';
$string['gradesmoduledeletionprefix'] = '[Deletion in progress]';
$string['gradessettings'] = 'Grade settings';
@@ -761,8 +759,8 @@ $string['showfeedback'] = 'Show feedback';
$string['showfeedback_help'] = 'Whether to show a column for feedback.';
$string['showgrade'] = 'Show grades';
$string['showgrade_help'] = 'Whether to show a column for grades.';
$string['showingaggregatesonly'] = 'Showing aggregates only';
$string['showingfullmode'] = 'Showing full view';
$string['showingaggregatesonly'] = 'Showing totals only';
$string['showingfullmode'] = 'Showing grades and totals';
$string['showinggradesonly'] = 'Showing grades only';
$string['showlettergrade'] = 'Show letter grades';
$string['showlettergrade_help'] = 'Whether to show a column for letter grades.';
@@ -915,3 +913,4 @@ $string['showquickfeedback_help'] = 'If enabled, when editing is turned on, a fe
Note that when feedback is edited in the grader report, an overridden flag is set, meaning that the feedback can no longer be changed from within the related activity.';
$string['enableajax'] = 'Enable AJAX';
$string['enableajax_help'] = 'Adds a layer of AJAX functionality to the grader report, simplifying and speeding up common operations. Depends on Javascript being switched on at the user\'s browser level.';
$string['controls'] = 'Controls';
+1 -1
View File
@@ -487,7 +487,6 @@
tr.lastrow {
position: sticky;
bottom: 0;
z-index: 1;
td,
th {
@@ -498,6 +497,7 @@
th.header {
position: sticky;
left: -3rem;
z-index: 1;
}
td.noborder {
+1 -1
View File
@@ -34945,7 +34945,6 @@ p.arrow_button {
.path-grade-report-grader .gradeparent tr.lastrow {
position: sticky;
bottom: 0;
z-index: 1;
}
.path-grade-report-grader .gradeparent tr.lastrow td,
.path-grade-report-grader .gradeparent tr.lastrow th {
@@ -34954,6 +34953,7 @@ p.arrow_button {
.path-grade-report-grader .gradeparent th.header {
position: sticky;
left: -3rem;
z-index: 1;
}
.path-grade-report-grader .gradeparent td.noborder {
border-right: transparent;
+1 -1
View File
@@ -34945,7 +34945,6 @@ p.arrow_button {
.path-grade-report-grader .gradeparent tr.lastrow {
position: sticky;
bottom: 0;
z-index: 1;
}
.path-grade-report-grader .gradeparent tr.lastrow td,
.path-grade-report-grader .gradeparent tr.lastrow th {
@@ -34954,6 +34953,7 @@ p.arrow_button {
.path-grade-report-grader .gradeparent th.header {
position: sticky;
left: -3rem;
z-index: 1;
}
.path-grade-report-grader .gradeparent td.noborder {
border-right: transparent;