Feature Requests

Please do NOT use this section of the forum to request help if Joomdle does not work for you in some particular way. Your post will be deleted.

Joomdle Course Reports

  • Simon Ball
  • Topic Author
  • Offline
  • New Member
  • New Member
More
11 years 7 months ago #1 by Simon Ball
Joomdle Course Reports was created by Simon Ball
Hi there,

This is a repost of www.joomdle.com/en/forum/tips-tricks/111...e-reports/edit/15842 because I accidentally posted to wrong forum apologies. For this request, I am happy to implement it properly if you can provide some guidance on the best way to develop for Joomdle. Right now, I have it as a hack.

Proposal
Provide a component view which allows a user to see the Activity/Course completion report for a course group from within Joomdle.

Current Approach
I have a course which has been set to run as "seperate groups". For each of these groups one (or more) users are designated "Team Manager". Team Manager is a user who has access to view reports.

From within Moodle you might end up with the following URL to see a report on a given group:
Code:
www.moodle-example.com/report/completion/?course=46&group=3#completion-progress
What I currently do is rather inefficient, consider the following pseudocode for a situation where the user is the Team Manager
  • Use API "joomdle_get_course_groups
  • For Each Group
  • Use API "joomdle_get_group_members"
  • If User in group
  • Fetch DOM Element "completion-progress" from report URL
The above is rather simple and for what I've got, would really love to integrate it in to Joomdle itself or at least as a component which relies on Joomdle, what do you reckon?

Please Log in or Create an account to join the conversation.

More
11 years 7 months ago #2 by Antonio Durán
Replied by Antonio Durán on topic Joomdle Course Reports
Hi.

At first, I guess you want to do something like dis in pseudo-code:
- New API call: user_belongs_to_group or similar, to remove your 2 API calls
- New API call to return all the info needed in the completion-progress via webservice
- Build new view, calling functions above

I also have other concerns: how do you present links in Joomdle? I mean, how do you decide if the Joomla user must see the Completion link? As only those allowed in Moodle can see it, I guess you would need to know that somehow in Joomla too.
This could be done polling moodle, as you do, although you will not be able to use "normal" links. ie: you cannot put the link in a menu.
You could have a module/view with links, and those links could be built according to Moodle permissions.

Please let me know if you think I can help with any specific questions you may have.

Please Log in or Create an account to join the conversation.

  • Simon Ball
  • Topic Author
  • Offline
  • New Member
  • New Member
More
11 years 7 months ago #3 by Simon Ball
Replied by Simon Ball on topic Joomdle Course Reports
Hi there Antonio,

Thanks for getting back so soon and with some useful feedback. I also share your concerns with regard to "where" it would be displayed. At present, this addition I propose would initially:
  • Require the group setup to be performed within Moodle
  • Show a button next to course listings IF the user is logged in as a "Team Manager". Team manager is a non-standard Moodle group that only has permissions to view reports
  • Show/Hide the button based on simple toggles as already shown from the "Views" configuration tab
  • Have the "processing" performed in a helper function so that it can be used across both modules and component views
As you can see, the whole thing really only depends on:
  • Setting up groups from Moodle
  • Having Joomdle aware of the Group ID representing "Team Manager"
  • Having a Joomdle view which uses "Course ID" and "Group ID" to go fetch the report HTML from Moodle
With regard to assistance, there is little help that I would actually need to make the modifications but I would like to work out a few of the specifics with you. I am approaching this feature with quite a biased mind but want to make it as useful for others as possible.

Please Log in or Create an account to join the conversation.

  • Simon Ball
  • Topic Author
  • Offline
  • New Member
  • New Member
More
11 years 7 months ago #4 by Simon Ball
Replied by Simon Ball on topic Joomdle Course Reports
Hi Antonio,

I've been putting in a bit of time to acquaint myself with both Joomdle and Moodle development a bit better and believe I have the majority of bases covered. Unfortunately, I can't test out the code for a day or two but was wondering whether you could please take a quick look at the Moodle part (I've only done some basic hacking on it till this point).

services.php
Code:
'joomdle_is_team_manager' => array( 'classname' => 'joomdle_helpers_external', 'methodname' => 'is_team_manager', 'classpath' => 'auth/joomdle/helpers/externallib.php', 'description' => 'Check whether the user has the "Team Manager" role', 'type' => 'read', ), 'joomdle_get_course_groups_with_user' => array( 'classname' => 'joomdle_helpers_external', 'methodname' => 'get_course_groups_with_user', 'classpath' => 'auth/joomdle/helpers/externallib.php', 'description' => 'For a given course, return course groups that the user is present in', 'type' => 'read', )

externallib.php
At this point in development, I've just kept the code in the library file, I'll push it to object once working.
Code:
/* is_team_manager */ public static function is_team_manager_parameters() { return new external_function_parameters( array( 'username' => new external_value(PARAM_TEXT, 'username'), 'teammanagerroleid' => new external_value(PARAM_INT, 'teammanagerroleid') ) ); } public static function is_team_manager_returns() { return new external_single_structure( array( 'ismanager' => new external_value( PARAM_BOOL, 'User is a team manager or not', 0 ) ) ); } public static function is_team_manager( $username, $teammanagerroleid ) { $params = self::validate_parameters( self::is_team_manager_parameters(), array( 'username' => $username, 'teammanagerroleid' => $teammanagerroleid ) ); $username = utf8_decode ($username); $username = strtolower ($username); $user = get_complete_user_data('username', $username); $aryReturn = array ( 'ismanager' => 0 ); if (!$user) { return $aryReturn; } if (user_has_role_assignment($user->id, $teammanagerroleid)) { $aryReturn['ismanager'] = 1; } return $aryReturn; } /* get_course_groups_with_user */ public static function get_course_groups_with_user_parameters() { return new external_function_parameters( array( 'username' => new external_value(PARAM_TEXT, 'username'), 'courseid' => new external_value(PARAM_INT, 'courseid') ) ); } public static function get_course_groups_with_user_returns() { return new external_multiple_structure( new external_single_structure( array( 'id' => new external_value( PARAM_INT, 'Group ID' ), 'name' => new external_value( PARAM_TEXT, 'Group Name' ), 'description' => new external_value( PARAM_TEXT, 'Group Description' ) ) ) ); } public static function get_course_groups_with_user( $strUserName, $intCourseID ) { $params = self::validate_parameters( self::get_course_groups_with_user_parameters(), array( 'username' => $strUserName, 'courseid' => $intCourseID ) ); $strUserName = strtolower( utf8_decode($strUserName) ); $objCurrentUser = get_complete_user_data('username', $username); if (!$objCurrentUser) { return; } $objAuth = new auth_plugin_joomdle (); $aryReturn = array(); /* If there are groups associated with the course */ if($objCourseGroups = $objAuth->get_course_groups($intCourseID)) { /* cycle through the groups */ foreach($objCourseGroups as $objGroup) { /* If there are group members */ if($objGroupMembers = $objAuth->get_group_members($objGroup->id)) { foreach($objGroupMembers as $objUser) { /* If this user is in the group */ if($objUser->id == $objCurrentUser->id) { $aryReturn[] = $objGroup; } } } } } return $aryReturn; }

Please Log in or Create an account to join the conversation.

More
11 years 7 months ago #5 by Antonio Durán
Replied by Antonio Durán on topic Joomdle Course Reports
Hi.
Sorry for the slow reply, I am away until the end of this week.

At first sight, your code seems ok. I would change only one thing: method is_team_manager could be changed to user_has_role or similar. That is a more general name, and this method could be used to check other roles, so I think it is better to have a more general name,

Please let me know if you think I can help when you start testing the code.

Please Log in or Create an account to join the conversation.

  • Simon Ball
  • Topic Author
  • Offline
  • New Member
  • New Member
More
11 years 7 months ago #6 by Simon Ball
Replied by Simon Ball on topic Joomdle Course Reports
Hi there Antonio,

I've almost completed the extension and just sorting out the actual links now. It looks like things should work quite well. I will make that change you recommended about user roles, it does make much more sense.

Moodle
services.php - done
externallib.php - done
land.php - done

Joomdle
Configuration parameters - done
Helper functions - done
Templating - 60% (Link building)

At this point, the only thing really left to think about is how the links will actually be displayed. Attached is a screenshot of a module i have made (based on my courses) and for the courses where completion reports are available was thinking of having the bars on the left hand side as you can see below:

To be truly useful, we'd need a theme independant method. Maybe i'm overthinking this entirely and will just have a proper table view with actions off to the right alongside "study" and "view my grades", what do you think?

After a few small changes, I'll create a zip for you to try out.

Please Log in or Create an account to join the conversation.

  • Simon Ball
  • Topic Author
  • Offline
  • New Member
  • New Member
More
11 years 7 months ago - 11 years 7 months ago #7 by Simon Ball
Replied by Simon Ball on topic Joomdle Course Reports
Hi Antonio,

Seems to be having a little spot of bother with one of the functions, last hurdle type stuff. The only issue now is that the auth_plugin_joomdle->get_group_members method doesn't ever seem to be returning anything. In the code snippet below, I can get the code to pass up to the point where I'm returning the invalid response.

Here's a debug run through using some stuffed data:
Table Data: __groups
Code:
'2', '17', 'grouptestfac', 'Test Facilitation Group', '', '1', '', '0', '0', '1409538937', '1410334542'
Table Data: __groups_members
Below uses the above group and has ALL users in the system part of that group
Code:
'12', '2', '244', '1410334536', '', '0' '13', '2', '239', '1410334542', '', '0' '14', '2', '2', '1410334542', '', '0' '15', '2', '17', '1410334542', '', '0' '16', '2', '59', '1410334542', '', '0' '17', '2', '228', '1410334542', '', '0' '18', '2', '41', '1410334542', '', '0' '19', '2', '19', '1410334542', '', '0' '20', '2', '39', '1410334542', '', '0'

get_course_groups_with_user takes a username and course ID so if I put a manual stops at various places IF the course ID matches the group above:

externallib.php function that is called
Code:
/* If there are groups associated with the course */ /* intCourseID = '17' */ if($objCourseGroups = $objAuth->get_course_groups($intCourseID)) { /* cycle through the groups */ foreach($objCourseGroups as $intKey => $aryGroup) { /* If there are group members */ /* $aryGroup['id'] = '2'; */ /* $objCurrentUser->id = '244' */ if($aryGroupMembers = $objAuth->get_group_members($aryGroup['id'], $objCurrentUser->id)) { return 'found'; /* <-- This will never return the invalid response message I want */ } } }

I'm going to look further in to the get_group_members function but just wanted ask you first as it is part of the existing Joomdle distribution and to keep you up to date. any ideas?
Last edit: 11 years 7 months ago by Simon Ball.

Please Log in or Create an account to join the conversation.

  • Simon Ball
  • Topic Author
  • Offline
  • New Member
  • New Member
More
11 years 7 months ago - 11 years 7 months ago #8 by Simon Ball
Replied by Simon Ball on topic Joomdle Course Reports
Hi Antonio,

I think I have found a (or the) bug, maybe you could explain the code if this is not the case:
auth.php - get_group_members ~line 3584
Code:
function get_group_members ($group_id, $search = '') { $users = groups_get_members ($group_id); $rdo = array (); foreach ($users as $u) { if ($search) { if ( (stripos ($u->username, $search) === false) && (stripos ($u->firstname, $search) === false) && (stripos ($u->lastname, $search) === false) && (stripos ($u->idnumber, $search) === false) ) continue; } $member['id'] = $u->id; $member['firstname'] = $u->firstname; $member['lastname'] = $u->lastname; $member['username'] = $u->username; $rdo[] = $member; } return $rdo; }

In the above, if performing a search shouldn't we switch the ampersands for pipes and check for positives? It seems kind of odd that through API use a person would need to search all four user fields at the same time. Is there a particular reason to have it this way?
Last edit: 11 years 7 months ago by Simon Ball.

Please Log in or Create an account to join the conversation.

More
11 years 7 months ago #9 by Antonio Durán
Replied by Antonio Durán on topic Joomdle Course Reports
Hi Simon.

Moodle function groups_get_members returns all users in group.
If we use search, we need to check username, name and email ( i don't remember about why we have idnumber in there, but it should not matter)

So, after gettign all users in group, we cycle through them. If search is used, we discard any non-matching user (that is why we use &&, as it needs to fail all checks to be discarded)

What I see in your code in previous post is this:
if($aryGroupMembers = $objAuth->get_group_members($aryGroup, $objCurrentUser->id))

"id" is not used in search, so you should not pass that, but instead use the username of the user, right?


I will try to test the function later today to confirm it is working as expected.

Please Log in or Create an account to join the conversation.

  • Simon Ball
  • Topic Author
  • Offline
  • New Member
  • New Member
More
11 years 7 months ago #10 by Simon Ball
Replied by Simon Ball on topic Joomdle Course Reports
Hi antonio,

That did it, everything is working now. Just some neatening up of the code/presentation along with a few language definitions and good to go. Developer site screenie below.

Please Log in or Create an account to join the conversation.