Implemented custom user-tops and did somestyling in the courses list
This commit is contained in:
parent
29c8dd9aa4
commit
737da8c051
2
amd/build/studyplan-editor-components.min.js
vendored
2
amd/build/studyplan-editor-components.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
|
@ -3821,14 +3821,15 @@ export default {
|
||||||
template: `
|
template: `
|
||||||
<li class="t-coursecat-list-item">
|
<li class="t-coursecat-list-item">
|
||||||
<span v-if="hasDetails" v-b-toggle="'coursecat-'+value.id">
|
<span v-if="hasDetails" v-b-toggle="'coursecat-'+value.id">
|
||||||
<i class="when-closed fa fa-caret-right"></i>
|
<i class="when-closed fa fa-caret-right t-caret"></i>
|
||||||
<i class="when-open fa fa-caret-down"></i>
|
<i class="when-open fa fa-caret-down t-caret"></i>
|
||||||
<span class="t-coursecat-heading">
|
<span class="t-coursecat-heading">
|
||||||
<i class="t-coursecat-list-item fa fa-tasks"></i>
|
<i class="t-coursecat-list-item fa fa-tasks"></i>
|
||||||
{{ value.category.name }}
|
{{ value.category.name }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
|
<i class="when-closed fa t-caret" style="visibility: hidden"></i>
|
||||||
<span class="t-coursecat-heading">
|
<span class="t-coursecat-heading">
|
||||||
<i class="t-coursecat-list-item fa fa-tasks"></i>
|
<i class="t-coursecat-list-item fa fa-tasks"></i>
|
||||||
{{ value.category.name }}
|
{{ value.category.name }}
|
||||||
|
|
|
@ -48,6 +48,87 @@ class courseservice extends \external_api {
|
||||||
const CAP_VIEW = "local/treestudyplan:viewuserreports";
|
const CAP_VIEW = "local/treestudyplan:viewuserreports";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the topmost categories for the specicied user.
|
||||||
|
* Most of the work is offloaded to an SQL query in the interest of speed, but moodle functions are used to double check access permissions.
|
||||||
|
* @param int $userid Id of the user
|
||||||
|
* @return array of core_course_category
|
||||||
|
*/
|
||||||
|
public static function user_tops($userid) {
|
||||||
|
global $DB;
|
||||||
|
$tops = [];
|
||||||
|
|
||||||
|
/*
|
||||||
|
SELECT UNIQUE ctx.* FROM mdl_context AS ctx
|
||||||
|
INNER JOIN mdl_role_assignments AS ra ON ra.contextid = ctx.id
|
||||||
|
INNER JOIN mdl_role_capabilities AS rc ON ra.roleid = rc.roleid
|
||||||
|
LEFT JOIN mdl_course_categories AS cat ON ctx.instanceid = cat.id
|
||||||
|
WHERE ( ctx.contextlevel = 40 OR ctx.contextlevel = 10 )
|
||||||
|
AND ra.userid = 58 AND rc.capability = 'moodle/category:viewcourselist'
|
||||||
|
ORDER BY ctx.depth ASC, cat.sortorder ASC;
|
||||||
|
*/
|
||||||
|
$capability = 'moodle/category:viewcourselist';
|
||||||
|
|
||||||
|
$sql = "SELECT UNIQUE ctx.* FROM {context} AS ctx
|
||||||
|
INNER JOIN {role_assignments} AS ra ON ra.contextid = ctx.id
|
||||||
|
INNER JOIN {role_capabilities} AS rc ON ra.roleid = rc.roleid
|
||||||
|
LEFT JOIN {course_categories} AS cat ON ctx.instanceid = cat.id
|
||||||
|
WHERE ( ctx.contextlevel = :ctxl_coursecat OR ctx.contextlevel = :ctxl_system )
|
||||||
|
AND ra.userid = :userid AND rc.capability = :capability
|
||||||
|
ORDER BY ctx.depth ASC, cat.sortorder ASC";
|
||||||
|
|
||||||
|
// Use recordset to handle the eventuality of a really big and complex moodle setup.
|
||||||
|
$recordset = $DB->get_recordset_sql($sql, ["userid" => $userid, "capability" => $capability,
|
||||||
|
"ctxl_coursecat" => \CONTEXT_COURSECAT, "ctxl_system" => \CONTEXT_SYSTEM,]);
|
||||||
|
|
||||||
|
$contextids = [];
|
||||||
|
foreach ($recordset as $r) {
|
||||||
|
// Get the paths as an array.
|
||||||
|
$parents = explode("/",$r->path);
|
||||||
|
// Strip the first item, since it is an empty one.
|
||||||
|
array_shift($parents);
|
||||||
|
// Strip the last item, since it refers to self.
|
||||||
|
array_pop($parents);
|
||||||
|
// Figure out if any of the remaining parent contexts are already contexts with permission.
|
||||||
|
$intersect = array_intersect($contextids,$parents);
|
||||||
|
if (count($intersect) == 0) {
|
||||||
|
// Double check permissions according to the moodle capability system.
|
||||||
|
$ctx = \context::instance_by_id($r->id);
|
||||||
|
if (has_capability($capability,$ctx,$userid)) {
|
||||||
|
// Get the actual category object.
|
||||||
|
if ($r->contextlevel == \CONTEXT_SYSTEM) {
|
||||||
|
// The user can view all (non-hidden) categories, so add all categories of depth = 1;
|
||||||
|
$tops = []; // Reset the array, just in case.
|
||||||
|
$rs = $DB->get_recordset("course_categories",["depth" => 1],'sortorder');
|
||||||
|
foreach( $rs as $rcat) {
|
||||||
|
// Get the category, and double check if the category is visible to the current user.
|
||||||
|
// Just in case it is a hidden category and the user does not have the viewhidden permission.
|
||||||
|
$cat = \core_course_category::get($rcat->id, \IGNORE_MISSING, false, $userid);
|
||||||
|
if ($cat !== null) {
|
||||||
|
// Register the category.
|
||||||
|
array_push($tops,$cat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$rs->close();
|
||||||
|
break; // Stop the loop immediately so the list of visible depth 2 categories is returned.
|
||||||
|
} else { // Can only be \CONTEXT_COURSECAT according to the SQL query.
|
||||||
|
// Get the category, and double check if the category is visible to the current user.
|
||||||
|
// Just in case it is a hidden category and the user does not have the viewhidden permission.
|
||||||
|
$cat = \core_course_category::get($r->instanceid, \IGNORE_MISSING, false, $userid);
|
||||||
|
if ($cat !== null) {
|
||||||
|
// Register the context id in the list now, since we know the category is really visible.
|
||||||
|
array_push($contextids,$r->id);
|
||||||
|
// Register the category.
|
||||||
|
array_push($tops,$cat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$recordset->close();
|
||||||
|
return $tops;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return value description for map_categories function
|
* Return value description for map_categories function
|
||||||
*/
|
*/
|
||||||
|
@ -93,7 +174,7 @@ class courseservice extends \external_api {
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function map_categories($rootid = 0) {
|
public static function map_categories($rootid = 0) {
|
||||||
global $CFG, $DB;
|
global $USER;
|
||||||
|
|
||||||
$root = \core_course_category::get($rootid,\MUST_EXIST,true);
|
$root = \core_course_category::get($rootid,\MUST_EXIST,true);
|
||||||
|
|
||||||
|
@ -101,15 +182,12 @@ class courseservice extends \external_api {
|
||||||
|
|
||||||
if ($root->id == 0) {
|
if ($root->id == 0) {
|
||||||
// On the system level, determine the user's topmost allowed catecories.
|
// On the system level, determine the user's topmost allowed catecories.
|
||||||
$usertop = \core_course_category::user_top();
|
// This uses a custom function, since moodle's "core_course_category::user_top()" is somewhat deficient.
|
||||||
if ($usertop->id == 0) {
|
$children = self::user_tops($USER->id);
|
||||||
// Top category..
|
|
||||||
$children = $root->get_children(); // Returns a list of çore_course_category, let it overwrite $children.
|
|
||||||
} else {
|
|
||||||
$children = [$usertop];
|
|
||||||
}
|
|
||||||
} else if ($root->is_uservisible()) {
|
} else if ($root->is_uservisible()) {
|
||||||
$children = [$root];
|
$children = [$root];
|
||||||
|
} else {
|
||||||
|
return []; // Category not user visible.
|
||||||
}
|
}
|
||||||
|
|
||||||
$list = [];
|
$list = [];
|
||||||
|
|
|
@ -121,7 +121,6 @@ class studyplanservice extends \external_api {
|
||||||
$studyplan = studyplan::find_by_id($id);
|
$studyplan = studyplan::find_by_id($id);
|
||||||
webservicehelper::require_capabilities([self::CAP_EDIT, self::CAP_VIEW], $studyplan->context());
|
webservicehelper::require_capabilities([self::CAP_EDIT, self::CAP_VIEW], $studyplan->context());
|
||||||
$model = $studyplan->editor_model();
|
$model = $studyplan->editor_model();
|
||||||
debug::dump($model);
|
|
||||||
return $model;
|
return $model;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -264,6 +264,22 @@
|
||||||
stroke-opacity: 0.5;
|
stroke-opacity: 0.5;
|
||||||
stroke-dasharray: 4 4;
|
stroke-dasharray: 4 4;
|
||||||
}
|
}
|
||||||
|
.path-local-treestudyplan ul.t-coursecat-list,
|
||||||
|
.path-local-treestudyplan ul.t-course-list,
|
||||||
|
.features-treestudyplan ul.t-coursecat-list,
|
||||||
|
.features-treestudyplan ul.t-course-list {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan ul.t-coursecat-list ul.t-coursecat-list,
|
||||||
|
.path-local-treestudyplan ul.t-coursecat-list ul.t-course-list,
|
||||||
|
.path-local-treestudyplan ul.t-course-list ul.t-coursecat-list,
|
||||||
|
.path-local-treestudyplan ul.t-course-list ul.t-course-list,
|
||||||
|
.features-treestudyplan ul.t-coursecat-list ul.t-coursecat-list,
|
||||||
|
.features-treestudyplan ul.t-coursecat-list ul.t-course-list,
|
||||||
|
.features-treestudyplan ul.t-course-list ul.t-coursecat-list,
|
||||||
|
.features-treestudyplan ul.t-course-list ul.t-course-list {
|
||||||
|
padding-left: 1.5em;
|
||||||
|
}
|
||||||
.path-local-treestudyplan ul.t-item-module-children,
|
.path-local-treestudyplan ul.t-item-module-children,
|
||||||
.path-local-treestudyplan ul.t-coursecat-list li,
|
.path-local-treestudyplan ul.t-coursecat-list li,
|
||||||
.path-local-treestudyplan ul.t-course-list li,
|
.path-local-treestudyplan ul.t-course-list li,
|
||||||
|
@ -293,6 +309,26 @@
|
||||||
max-width: 24px;
|
max-width: 24px;
|
||||||
max-height: 24px;
|
max-height: 24px;
|
||||||
}
|
}
|
||||||
|
.path-local-treestudyplan li.t-coursecat-list-item i.t-caret,
|
||||||
|
.features-treestudyplan li.t-coursecat-list-item i.t-caret {
|
||||||
|
width: 9px;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan li.t-coursecat-list-item,
|
||||||
|
.path-local-treestudyplan li.t-course-list-item .draggable-course,
|
||||||
|
.features-treestudyplan li.t-coursecat-list-item,
|
||||||
|
.features-treestudyplan li.t-course-list-item .draggable-course {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan li.t-coursecat-list-item:hover,
|
||||||
|
.path-local-treestudyplan li.t-course-list-item .draggable-course:hover,
|
||||||
|
.features-treestudyplan li.t-coursecat-list-item:hover,
|
||||||
|
.features-treestudyplan li.t-course-list-item .draggable-course:hover {
|
||||||
|
text-overflow: clip;
|
||||||
|
white-space: normal;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
.path-local-treestudyplan i.t-coursecat-list-item,
|
.path-local-treestudyplan i.t-coursecat-list-item,
|
||||||
.features-treestudyplan i.t-coursecat-list-item {
|
.features-treestudyplan i.t-coursecat-list-item {
|
||||||
color: var(--coursecat-list);
|
color: var(--coursecat-list);
|
||||||
|
|
|
@ -169,6 +169,16 @@
|
||||||
stroke-dasharray: 4 4;
|
stroke-dasharray: 4 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul.t-coursecat-list,
|
||||||
|
ul.t-course-list {
|
||||||
|
padding-left: 1em;
|
||||||
|
|
||||||
|
ul.t-coursecat-list,
|
||||||
|
ul.t-course-list {
|
||||||
|
padding-left: 1.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ul.t-item-module-children,
|
ul.t-item-module-children,
|
||||||
ul.t-coursecat-list li,
|
ul.t-coursecat-list li,
|
||||||
ul.t-course-list li {
|
ul.t-course-list li {
|
||||||
|
@ -195,6 +205,26 @@
|
||||||
max-height: 24px;
|
max-height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li.t-coursecat-list-item {
|
||||||
|
i.t-caret {
|
||||||
|
width: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
li.t-coursecat-list-item, li.t-course-list-item .draggable-course {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-overflow: clip;
|
||||||
|
white-space: normal;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
i.t-coursecat-list-item {
|
i.t-coursecat-list-item {
|
||||||
color: var(--coursecat-list);
|
color: var(--coursecat-list);
|
||||||
}
|
}
|
||||||
|
|
36
styles.css
36
styles.css
|
@ -264,6 +264,22 @@
|
||||||
stroke-opacity: 0.5;
|
stroke-opacity: 0.5;
|
||||||
stroke-dasharray: 4 4;
|
stroke-dasharray: 4 4;
|
||||||
}
|
}
|
||||||
|
.path-local-treestudyplan ul.t-coursecat-list,
|
||||||
|
.path-local-treestudyplan ul.t-course-list,
|
||||||
|
.features-treestudyplan ul.t-coursecat-list,
|
||||||
|
.features-treestudyplan ul.t-course-list {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan ul.t-coursecat-list ul.t-coursecat-list,
|
||||||
|
.path-local-treestudyplan ul.t-coursecat-list ul.t-course-list,
|
||||||
|
.path-local-treestudyplan ul.t-course-list ul.t-coursecat-list,
|
||||||
|
.path-local-treestudyplan ul.t-course-list ul.t-course-list,
|
||||||
|
.features-treestudyplan ul.t-coursecat-list ul.t-coursecat-list,
|
||||||
|
.features-treestudyplan ul.t-coursecat-list ul.t-course-list,
|
||||||
|
.features-treestudyplan ul.t-course-list ul.t-coursecat-list,
|
||||||
|
.features-treestudyplan ul.t-course-list ul.t-course-list {
|
||||||
|
padding-left: 1.5em;
|
||||||
|
}
|
||||||
.path-local-treestudyplan ul.t-item-module-children,
|
.path-local-treestudyplan ul.t-item-module-children,
|
||||||
.path-local-treestudyplan ul.t-coursecat-list li,
|
.path-local-treestudyplan ul.t-coursecat-list li,
|
||||||
.path-local-treestudyplan ul.t-course-list li,
|
.path-local-treestudyplan ul.t-course-list li,
|
||||||
|
@ -293,6 +309,26 @@
|
||||||
max-width: 24px;
|
max-width: 24px;
|
||||||
max-height: 24px;
|
max-height: 24px;
|
||||||
}
|
}
|
||||||
|
.path-local-treestudyplan li.t-coursecat-list-item i.t-caret,
|
||||||
|
.features-treestudyplan li.t-coursecat-list-item i.t-caret {
|
||||||
|
width: 9px;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan li.t-coursecat-list-item,
|
||||||
|
.path-local-treestudyplan li.t-course-list-item .draggable-course,
|
||||||
|
.features-treestudyplan li.t-coursecat-list-item,
|
||||||
|
.features-treestudyplan li.t-course-list-item .draggable-course {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan li.t-coursecat-list-item:hover,
|
||||||
|
.path-local-treestudyplan li.t-course-list-item .draggable-course:hover,
|
||||||
|
.features-treestudyplan li.t-coursecat-list-item:hover,
|
||||||
|
.features-treestudyplan li.t-course-list-item .draggable-course:hover {
|
||||||
|
text-overflow: clip;
|
||||||
|
white-space: normal;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
.path-local-treestudyplan i.t-coursecat-list-item,
|
.path-local-treestudyplan i.t-coursecat-list-item,
|
||||||
.features-treestudyplan i.t-coursecat-list-item {
|
.features-treestudyplan i.t-coursecat-list-item {
|
||||||
color: var(--coursecat-list);
|
color: var(--coursecat-list);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user