mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 20:42:22 +02:00
Merge branch 'MDL-77902' of https://github.com/Chocolate-lightning/moodle
This commit is contained in:
commit
df2e6c1cd4
2
grade/report/grader/amd/build/search.min.js
vendored
2
grade/report/grader/amd/build/search.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -31,6 +31,7 @@ import {renderForPromise, replaceNodeContents} from 'core/templates';
|
||||
const selectors = {
|
||||
component: '.user-search',
|
||||
courseid: '[data-region="courseid"]',
|
||||
resetPageButton: '[data-action="resetpage"]',
|
||||
};
|
||||
const component = document.querySelector(selectors.component);
|
||||
const courseID = component.querySelector(selectors.courseid).dataset.courseid;
|
||||
@ -81,10 +82,10 @@ export default class UserSearch extends GradebookSearchClass {
|
||||
*/
|
||||
async renderDropdown() {
|
||||
const {html, js} = await renderForPromise('gradereport_grader/search/resultset', {
|
||||
users: this.getMatchedResults(),
|
||||
users: this.getMatchedResults().slice(0, 5),
|
||||
hasusers: this.getMatchedResults().length > 0,
|
||||
total: this.getDatasetSize(),
|
||||
found: this.getMatchedResults().length,
|
||||
matches: this.getMatchedResults().length,
|
||||
showing: this.getMatchedResults().slice(0, 5).length,
|
||||
searchterm: this.getSearchTerm(),
|
||||
selectall: this.selectAllResultsLink(),
|
||||
});
|
||||
@ -135,6 +136,7 @@ export default class UserSearch extends GradebookSearchClass {
|
||||
this.getPreppedSearchTerm(),
|
||||
`<span class="font-weight-bold">${this.getSearchTerm()}</span>`
|
||||
);
|
||||
user.matchingField = `${user.matchingField} (${user.email})`;
|
||||
user.link = this.selectOneLink(user.id);
|
||||
break;
|
||||
}
|
||||
@ -153,6 +155,9 @@ export default class UserSearch extends GradebookSearchClass {
|
||||
if (e.target === this.getHTMLElements().currentViewAll && e.button === 0) {
|
||||
window.location = this.selectAllResultsLink();
|
||||
}
|
||||
if (e.target.closest(selectors.resetPageButton)) {
|
||||
window.location = e.target.closest(selectors.resetPageButton).href;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,11 +185,18 @@ export default class UserSearch extends GradebookSearchClass {
|
||||
}
|
||||
}
|
||||
if (document.activeElement === this.getHTMLElements().clearSearchButton) {
|
||||
this.closeSearch();
|
||||
this.closeSearch(true);
|
||||
break;
|
||||
}
|
||||
if (e.target.closest(selectors.resetPageButton)) {
|
||||
window.location = e.target.closest(selectors.resetPageButton).href;
|
||||
break;
|
||||
}
|
||||
if (e.target.closest('.dropdown-item')) {
|
||||
e.preventDefault();
|
||||
window.location = e.target.closest('.dropdown-item').href;
|
||||
break;
|
||||
}
|
||||
e.preventDefault();
|
||||
window.location = e.target.closest('.dropdown-item').href;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -222,14 +222,18 @@ export default class {
|
||||
|
||||
/**
|
||||
* When called, close the dropdown and reset the input field attributes.
|
||||
*
|
||||
* @param {Boolean} clear Conditionality clear the input box.
|
||||
*/
|
||||
closeSearch() {
|
||||
closeSearch(clear = false) {
|
||||
this.toggleDropdown();
|
||||
// Hide the "clear" search button search bar.
|
||||
this.clearSearchButton.classList.add('d-none');
|
||||
// Clear the entered search query in the search bar and hide the search results container.
|
||||
this.setSearchTerms('');
|
||||
this.searchInput.value = "";
|
||||
if (clear) {
|
||||
// Clear the entered search query in the search bar and hide the search results container.
|
||||
this.setSearchTerms('');
|
||||
this.searchInput.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -379,7 +383,7 @@ export default class {
|
||||
}
|
||||
// The "clear search" button is triggered.
|
||||
if (e.target.closest(this.selectors.clearSearch) && e.button === 0) {
|
||||
this.closeSearch();
|
||||
this.closeSearch(true);
|
||||
this.searchInput.focus({preventScroll: true});
|
||||
}
|
||||
// User may have accidentally clicked off the dropdown and wants to reopen it.
|
||||
@ -418,7 +422,7 @@ export default class {
|
||||
case 'Tab':
|
||||
// If the current focus is on clear search, then check if viewall exists then around tab to it.
|
||||
if (e.target.closest(this.selectors.clearSearch)) {
|
||||
if (this.currentViewAll) {
|
||||
if (this.currentViewAll && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
this.currentViewAll.focus({preventScroll: true});
|
||||
} else {
|
||||
|
@ -101,7 +101,7 @@ class get_users_in_report extends external_api {
|
||||
$userpicture->size = 0; // Size f2.
|
||||
$user->profileimageurlsmall = $userpicture->get_url($PAGE)->out(false);
|
||||
return $user;
|
||||
}, $report->load_users());
|
||||
}, $report->load_users(true));
|
||||
sort($users);
|
||||
|
||||
return [
|
||||
|
@ -92,9 +92,11 @@ class action_bar extends \core_grades\output\action_bar {
|
||||
$data['initialselector'] = $initialselector->export_for_template($output);
|
||||
$data['groupselector'] = $gradesrenderer->group_selector($course);
|
||||
|
||||
$resetlink = new moodle_url('/grade/report/grader/index.php', ['id' => $courseid]);
|
||||
$searchinput = $OUTPUT->render_from_template('gradereport_grader/search/searchinput', [
|
||||
'currentvalue' => $this->usersearch,
|
||||
'courseid' => $courseid,
|
||||
'resetlink' => $resetlink->out(false),
|
||||
]);
|
||||
$searchdropdown = new gradebook_dropdown(
|
||||
true,
|
||||
|
@ -23,6 +23,7 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['clearsearch'] = 'Clear searched users';
|
||||
$string['collapsedcolumns'] = 'Collapsed columns <span class="badge badge-pill badge-primary ml-1" data-collapse="count">{$a}</span>';
|
||||
$string['eventgradereportviewed'] = 'Grader report viewed';
|
||||
$string['grader:manage'] = 'Manage the grader report';
|
||||
@ -46,12 +47,11 @@ $string['privacy:metadata:preference:grade_report_studentsperpage'] = 'The numbe
|
||||
$string['privacy:request:preference:grade_report_grader_collapsed_categories'] = 'You have some gradebook categories collapsed in the "{$a->name}" course';
|
||||
$string['reopencolumn'] = 'Reopen {$a} column';
|
||||
$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['showingxofy'] = 'Showing {$a->found} of {$a->total}';
|
||||
$string['useractivitygrade'] = '{$a} grade';
|
||||
$string['overriddengrade'] = 'Overridden grade';
|
||||
$string['advancedgrading'] = 'View {$a} results';
|
||||
$string['cellactions'] = 'Cell actions';
|
||||
$string['viewallresults'] = 'View all results for "{$a}"';
|
||||
$string['viewallresults'] = 'View all results ({$a})';
|
||||
$string['viewresultsuser'] = 'View results for {$a}';
|
||||
|
||||
// Deprecated since Moodle 4.2.
|
||||
|
@ -389,8 +389,10 @@ class grade_report_grader extends grade_report {
|
||||
|
||||
/**
|
||||
* pulls out the userids of the users to be display, and sorts them
|
||||
*
|
||||
* @param bool $allusers If we are getting the users within the report, we want them all irrespective of paging.
|
||||
*/
|
||||
public function load_users() {
|
||||
public function load_users(bool $allusers = false) {
|
||||
global $CFG, $DB;
|
||||
|
||||
if (!empty($this->users)) {
|
||||
@ -465,7 +467,8 @@ class grade_report_grader extends grade_report {
|
||||
$this->groupwheresql
|
||||
ORDER BY $sort";
|
||||
// We never work with unlimited result. Limit the number of records by MAX_STUDENTS_PER_PAGE if no other limit is specified.
|
||||
$studentsperpage = $this->get_students_per_page() ?: static::MAX_STUDENTS_PER_PAGE;
|
||||
$studentsperpage = ($this->get_students_per_page() && !$allusers) ?
|
||||
$this->get_students_per_page() : static::MAX_STUDENTS_PER_PAGE;
|
||||
$this->users = $DB->get_records_sql($sql, $params, $studentsperpage * $this->page, $studentsperpage);
|
||||
|
||||
if (empty($this->users)) {
|
||||
|
@ -234,7 +234,8 @@
|
||||
pointer-events: initial;
|
||||
z-index: 1;
|
||||
}
|
||||
.path-grade-report-grader .usersearchwidget button {
|
||||
.path-grade-report-grader .usersearchwidget button,
|
||||
.path-grade-report-grader .usersearchwidget a {
|
||||
pointer-events: initial;
|
||||
}
|
||||
.path-grade-report-grader .usersearchdropdown {
|
||||
|
@ -45,10 +45,10 @@
|
||||
{{/profileimageurl}}
|
||||
</div>
|
||||
<div class="d-block pr-3 w-75">
|
||||
<span class="d-flex w-100 p-0 font-weight-bold">
|
||||
<span class="d-block w-100 p-0 text-truncate font-weight-bold">
|
||||
{{fullname}}
|
||||
</span>
|
||||
<span class="d-flex w-100 pull-left text-truncate small" aria-hidden="true">
|
||||
<span class="d-block w-100 pull-left text-truncate small" aria-hidden="true">
|
||||
{{{matchingField}}}
|
||||
</span>
|
||||
<span class="sr-only" aria-label="{{#str}}usermatchedon, core_grades{{/str}}">{{matchingFieldName}}</span>
|
||||
|
@ -44,8 +44,7 @@
|
||||
"link": "http://foo.bar/grade/report/grader/index.php?id=42&userid=3"
|
||||
}
|
||||
],
|
||||
"found": 2,
|
||||
"total": 20,
|
||||
"matches": 20,
|
||||
"selectall": "https://foo.bar/grade/report/grader/index.php?id=2&searchvalue=abe",
|
||||
"searchterm": "Foo",
|
||||
"hasusers": true
|
||||
@ -53,17 +52,16 @@
|
||||
}}
|
||||
<div class="d-flex flex-column mh-100 h-100">
|
||||
{{#hasusers}}
|
||||
<span class="small d-block px-4 my-2">{{#str}}showingxofy, gradereport_grader, {"found": "{{found}}", "total": "{{total}}"}{{/str}}</span>
|
||||
<ul class="searchresultitemscontainer d-flex flex-column mw-100 position-relative py-2 list-group h-100 mh-100 mx-0" role="listbox" data-region="search-result-items-container" tabindex="-1">
|
||||
{{#users}}
|
||||
{{>gradereport_grader/search/resultitem}}
|
||||
{{/users}}
|
||||
<li class="w-100 result-row p-1 border-top bottom-0 position-sticky" role="none" id="result-row-{{id}}">
|
||||
<a role="option" class="dropdown-item d-flex small p-3" id="select-all" href="{{{selectall}}}" tabindex="-1">
|
||||
{{#str}}viewallresults, gradereport_grader, {{matches}}{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="unsearchablecontentcontainer p-1">
|
||||
<a role="button" id="select-all" href="{{{selectall}}}" class="small d-block p-4" tabindex="-1">
|
||||
{{#str}}viewallresults, gradereport_grader, {{searchterm}}{{/str}}
|
||||
</a>
|
||||
</div>
|
||||
{{/hasusers}}
|
||||
{{^hasusers}}
|
||||
<span class="small d-block px-4 my-4">{{#str}} noresultsfor, core_grades, {{searchterm}}{{/str}}</span>
|
||||
|
@ -23,7 +23,8 @@
|
||||
Example context (json):
|
||||
{
|
||||
"currentvalue": "bar",
|
||||
"courseid": 2
|
||||
"courseid": 2,
|
||||
"resetlink": "grade/report/grader/index.php?id=2"
|
||||
}
|
||||
}}
|
||||
<span class="d-none" data-region="courseid" data-courseid="{{courseid}}" aria-hidden="true"></span>
|
||||
@ -34,6 +35,9 @@
|
||||
{{/str}}{{/label}}
|
||||
{{$value}}{{{currentvalue}}}{{/value}}
|
||||
{{/ core/search_input_auto }}
|
||||
<a class="ml-2 btn btn-link border-0" href="{{resetlink}}" data-action="resetpage" role="link" aria-label="{{#str}}clearsearch, gradereport_grader{{/str}}">
|
||||
{{#str}}clear{{/str}}
|
||||
</a>
|
||||
{{/currentvalue}}
|
||||
{{^currentvalue}}
|
||||
{{< core/search_input_auto }}
|
||||
|
@ -49,7 +49,7 @@ Feature: Within the grader report, test that we can search for users
|
||||
| -1- |
|
||||
| Teacher 1 |
|
||||
When I set the field "Search users" to "Turtle"
|
||||
And I wait until "View all results for \"Turtle\"" "button" exists
|
||||
And I wait until "View all results (1)" "option_role" exists
|
||||
And "Turtle Manatee" "list_item" should exist in the ".user-search" "css_element"
|
||||
And "User Example" "list_item" should not exist in the ".user-search" "css_element"
|
||||
And I click on "Turtle Manatee" "list_item"
|
||||
@ -66,14 +66,14 @@ Feature: Within the grader report, test that we can search for users
|
||||
| User Test |
|
||||
| Dummy User |
|
||||
And I set the field "Search users" to "Turt"
|
||||
And I wait until "View all results for \"Turt\"" "button" exists
|
||||
And I wait until "View all results (1)" "option_role" exists
|
||||
And I click on "Clear search input" "button" in the ".user-search" "css_element"
|
||||
And "View all results for \"Turt\"" "button" should not be visible
|
||||
And "View all results (1)" "option_role" should not be visible
|
||||
|
||||
Scenario: A teacher can search the grader report to find specified users
|
||||
# Case: Standard search.
|
||||
Given I set the field "Search users" to "Dummy"
|
||||
And I wait until "View all results for \"Dummy\"" "button" exists
|
||||
And I wait until "View all results (1)" "option_role" exists
|
||||
And I click on "Dummy User" "option_role"
|
||||
And I wait until the page is ready
|
||||
And the following should exist in the "user-grades" table:
|
||||
@ -104,11 +104,15 @@ Feature: Within the grader report, test that we can search for users
|
||||
|
||||
# Case: Multiple users found and select only one result.
|
||||
Then I set the field "Search users" to "User"
|
||||
And I wait until "View all results for \"User\"" "button" exists
|
||||
And I wait until "View all results (3)" "option_role" exists
|
||||
And "Dummy User" "list_item" should exist in the ".user-search" "css_element"
|
||||
And "User Example" "list_item" should exist in the ".user-search" "css_element"
|
||||
And "User Test" "list_item" should exist in the ".user-search" "css_element"
|
||||
And "Turtle Manatee" "list_item" should not exist in the ".user-search" "css_element"
|
||||
# Check if the matched field names (by lines) includes some identifiable info to help differentiate similar users.
|
||||
And "User (student2@example.com)" "list_item" should exist in the ".user-search" "css_element"
|
||||
And "User (student3@example.com)" "list_item" should exist in the ".user-search" "css_element"
|
||||
And "User (student4@example.com)" "list_item" should exist in the ".user-search" "css_element"
|
||||
And I click on "Dummy User" "list_item"
|
||||
And I wait until the page is ready
|
||||
And the following should exist in the "user-grades" table:
|
||||
@ -125,12 +129,11 @@ Feature: Within the grader report, test that we can search for users
|
||||
# Business case: When searching with multiple partial matches, show the matches in the dropdown + a "View all results for (Bob)"
|
||||
# Business case cont. When pressing enter with multiple partial matches, behave like when you select the "View all results for (Bob)"
|
||||
# Case: Multiple users found and select all partial matches.
|
||||
# TODO: Need to look at maybe adding the users email or something in the case multiple matches exist?
|
||||
And I set the field "Search users" to "User"
|
||||
And I wait until "View all results for \"User\"" "button" exists
|
||||
And I wait until "View all results (3)" "option_role" exists
|
||||
# Dont need to check if all users are in the dropdown, we checked that earlier in this test.
|
||||
And "View all results for \"User\"" "button" should exist
|
||||
And I click on "View all results for \"User\"" "button"
|
||||
And "View all results (3)" "option_role" should exist
|
||||
And I click on "View all results (3)" "option_role"
|
||||
And I wait until the page is ready
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- |
|
||||
@ -142,15 +145,24 @@ Feature: Within the grader report, test that we can search for users
|
||||
| Teacher 1 |
|
||||
| Student 1 |
|
||||
| Turtle Manatee |
|
||||
And I click on "Clear" "link" in the ".user-search" "css_element"
|
||||
And I wait until the page is ready
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- |
|
||||
| Turtle Manatee |
|
||||
| Student 1 |
|
||||
| User Example |
|
||||
| User Test |
|
||||
| Dummy User |
|
||||
|
||||
Scenario: A teacher can quickly tell that a search is active on the current table
|
||||
Given I set the field "Search users" to "Turtle"
|
||||
And I wait until "View all results for \"Turtle\"" "button" exists
|
||||
And I wait until "View all results (1)" "option_role" exists
|
||||
And I click on "Turtle Manatee" "list_item"
|
||||
And I wait until the page is ready
|
||||
# The search input remains in the field on reload this is in keeping with other search implementations.
|
||||
When the field "Search users" matches value "Turtle"
|
||||
And "View all results for \"Turtle\"" "link" should not exist
|
||||
And "View all results (1)" "link" should not exist
|
||||
# Test if we can then further retain the turtle result set and further filter from there.
|
||||
Then I set the field "Search users" to "Turtle plagiarism"
|
||||
And "Turtle Manatee" "list_item" should not exist
|
||||
@ -158,10 +170,10 @@ Feature: Within the grader report, test that we can search for users
|
||||
|
||||
Scenario: A teacher can search for values besides the users' name
|
||||
Given I set the field "Search users" to "student5@example.com"
|
||||
And I wait until "View all results for \"student5@example.com\"" "button" exists
|
||||
And I wait until "View all results (1)" "option_role" exists
|
||||
And "Turtle Manatee" "list_item" should exist
|
||||
And I set the field "Search users" to "@example.com"
|
||||
And I wait until "View all results for \"@example.com\"" "button" exists
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
# Note: All learners match this email & showing emails is current default.
|
||||
And "Dummy User" "list_item" should exist in the ".user-search" "css_element"
|
||||
And "User Example" "list_item" should exist in the ".user-search" "css_element"
|
||||
@ -238,11 +250,11 @@ Feature: Within the grader report, test that we can search for users
|
||||
And I press the down key
|
||||
And the focused element is "Student 1" "option_role"
|
||||
And I press the end key
|
||||
And the focused element is "Turtle Manatee" "option_role"
|
||||
And the focused element is "View all results (5)" "option_role"
|
||||
And I press the home key
|
||||
And the focused element is "Student 1" "option_role"
|
||||
And I press the up key
|
||||
And the focused element is "Turtle Manatee" "option_role"
|
||||
And the focused element is "View all results (5)" "option_role"
|
||||
And I press the down key
|
||||
And the focused element is "Student 1" "option_role"
|
||||
And I press the escape key
|
||||
@ -250,14 +262,20 @@ Feature: Within the grader report, test that we can search for users
|
||||
Then I set the field "Search users" to "Goodmeme"
|
||||
And I press the down key
|
||||
And the focused element is "Search users" "field"
|
||||
|
||||
And I navigate to "View > Grader report" in the course gradebook
|
||||
And I set the field "Search users" to "ABC"
|
||||
And I wait until "Turtle Manatee" "option_role" exists
|
||||
And I press the down key
|
||||
And the focused element is "Student 1" "option_role"
|
||||
|
||||
# Lets check the tabbing order.
|
||||
And I set the field "Search users" to "ABC"
|
||||
And I wait "3" seconds
|
||||
And I wait until "View all results for \"ABC\"" "button" exists
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And I press the tab key
|
||||
And the focused element is "Clear search input" "button"
|
||||
And I press the tab key
|
||||
And the focused element is "View all results for \"ABC\"" "button"
|
||||
And the focused element is "View all results (5)" "option_role"
|
||||
And I press the tab key
|
||||
And the focused element is ".search-widget[data-searchtype='group'] [data-toggle='dropdown']" "css_element"
|
||||
# Ensure we can interact with the input & clear search options with the keyboard.
|
||||
@ -307,3 +325,20 @@ Feature: Within the grader report, test that we can search for users
|
||||
# Begin the search checking if we are adhering the filters.
|
||||
When I set the field "Search users" to "Turtle"
|
||||
Then "Turtle Manatee" "list_item" should not exist in the ".user-search" "css_element"
|
||||
|
||||
Scenario: As a teacher I can dynamically find users whilst ignoring pagination
|
||||
Given "42" "users" exist with the following data:
|
||||
| username | students[count] |
|
||||
| firstname | Student |
|
||||
| lastname | s[count] |
|
||||
| email | students[count]@example.com |
|
||||
And "42" "course enrolments" exist with the following data:
|
||||
| user | students[count] |
|
||||
| course | C1 |
|
||||
| role |student |
|
||||
And I reload the page
|
||||
And the field "perpage" matches value "20"
|
||||
When I set the field "Search users" to "42"
|
||||
# One of the users' phone numbers also matches.
|
||||
And I wait until "View all results (2)" "link" exists
|
||||
Then "Student s42" "list_item" should exist in the ".user-search" "css_element"
|
||||
|
Loading…
x
Reference in New Issue
Block a user