Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Moodle Mobile 2 (Ionic 1) Developing a plugin tutorial part 2: Difference between revisions

From MoodleDocs
No edit summary
No edit summary
 
(7 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{Moodle Mobile}}
{{Template:WillNotMigrate}}
{{Work in progress}}
{{Moodle Mobile 2 (Ionic 1)}}
 
IMPORTANT: This documentation will be obsolete in May 2018, please [https://moodle.org/mod/forum/discuss.php?d=360412 read this announcement].


== Introduction ==
== Introduction ==
Line 41: Line 43:


'''www/addons/notes/main.js'''
'''www/addons/notes/main.js'''
<code javascript>
<syntaxhighlight lang="javascript">
angular.module('mm.addons.notes', [])
angular.module('mm.addons.notes', [])


Line 90: Line 92:
     });
     });
});
});
</code>
</syntaxhighlight>


Here we declare the plugin, and register the Plugin (this means that the plugin will be displayed in the course main menu.
Here we declare the plugin, and register the Plugin (this means that the plugin will be displayed in the course main menu.
Line 108: Line 110:
This is the controller that inject data in the types.html view, the code is pretty simple:
This is the controller that inject data in the types.html view, the code is pretty simple:


<code javascript>
<syntaxhighlight lang="javascript">
angular.module('mm.addons.notes')
angular.module('mm.addons.notes')
.controller('mmaNotesTypesCtrl', function($scope, $stateParams) {
.controller('mmaNotesTypesCtrl', function($scope, $stateParams) {
Line 117: Line 119:


});
});
</code>
</syntaxhighlight>


It just make available in the $scope the courseid, that is required because is passed as a state parameter for the list view.
It just make available in the $scope the courseid, that is required because is passed as a state parameter for the list view.
Line 125: Line 127:
This controller is the one that will render in the list view the notes:
This controller is the one that will render in the list view the notes:


<code javascript>
<syntaxhighlight lang="javascript">
.controller('mmaNotesListCtrl', function($scope, $stateParams, $mmUtil, $mmaNotes, $mmSite, $translate) {
.controller('mmaNotesListCtrl', function($scope, $stateParams, $mmUtil, $mmaNotes, $mmSite, $translate) {


     var courseid = $stateParams.courseid,
     var courseid = $stateParams.courseid,
         type = $stateParams.type;
         type = $stateParams.type;
</code>
</syntaxhighlight>
Here we retrieved the state parameters (the course id and the type of notes) that were declared in the types.html view.
Here we retrieved the state parameters (the course id and the type of notes) that were declared in the types.html view.


<code javascript>
<syntaxhighlight lang="javascript">
     function fetchNotes(refresh) {
     function fetchNotes(refresh) {
         return $mmaNotes.getNotes(courseid, refresh).then(function(notes) {
         return $mmaNotes.getNotes(courseid, refresh).then(function(notes) {
Line 146: Line 148:
         });
         });
     }
     }
</code>
</syntaxhighlight>
The fetchNotes function is responsible of using the Notes service getNotes to retrieve the data, note that we use an additional function getNotesUserData to retrieve the full user profile information (since via getNotes we only get the userid)
The fetchNotes function is responsible of using the Notes service getNotes to retrieve the data, note that we use an additional function getNotesUserData to retrieve the full user profile information (since via getNotes we only get the userid)


<code javascript>
<syntaxhighlight lang="javascript">
fetchNotes().then(function() {
fetchNotes().then(function() {
         // Add log in Moodle.
         // Add log in Moodle.
Line 157: Line 159:
         });
         });
     })
     })
</code>
</syntaxhighlight>
After retrieving the notes, we do logging in Moodle (so the actions are registered in the web interface)
After retrieving the notes, we do logging in Moodle (so the actions are registered in the web interface)


<code javascript>
<syntaxhighlight lang="javascript">
     $scope.refreshNotes = function() {
     $scope.refreshNotes = function() {
         fetchNotes(true).finally(function() {
         fetchNotes(true).finally(function() {
Line 166: Line 168:
         });
         });
     };
     };
</code>
</syntaxhighlight>
This function is triggered by the "Pull down to refresh" action in order to refresh the view (empty the cache), note that the true parameter in the fetchNotes function means to not use cache.
This function is triggered by the "Pull down to refresh" action in order to refresh the view (empty the cache), note that the true parameter in the fetchNotes function means to not use cache.


Line 174: Line 176:
The notes services holds all the main plugin logic, it's responsible of checking if the plugin is available, retrieve information for the server and format the information so it can be rendered in the view by the controller.
The notes services holds all the main plugin logic, it's responsible of checking if the plugin is available, retrieve information for the server and format the information so it can be rendered in the view by the controller.


<code javascript>
<syntaxhighlight lang="javascript">
     self.isPluginViewNotesEnabled = function() {
     self.isPluginViewNotesEnabled = function() {
         var infos;
         var infos;
Line 188: Line 190:
         return true;
         return true;
     };
     };
</code>
</syntaxhighlight>
Here we checked if the plugin is enabled, the user must logged in, enablenotes should be enabled in the Moodle global settings and the core_notes_get_course_notes function should be available.
Here we checked if the plugin is enabled, the user must logged in, enablenotes should be enabled in the Moodle global settings and the core_notes_get_course_notes function should be available.


<code javascript>
<syntaxhighlight lang="javascript">
     self.getNotes = function(courseid, refresh) {
     self.getNotes = function(courseid, refresh) {


Line 206: Line 208:
         return $mmSite.read('core_notes_get_course_notes', data, presets);
         return $mmSite.read('core_notes_get_course_notes', data, presets);
     };
     };
</code>
</syntaxhighlight>
Here we retrieve the notes information from Moodle via Web Services, note that the refresh function is used for invalidating the cache (for example, when the user performs a pull down to refresh).
Here we retrieve the notes information from Moodle via Web Services, note that the refresh function is used for invalidating the cache (for example, when the user performs a pull down to refresh).


<code javascript>
<syntaxhighlight lang="javascript">
     self.getNotesUserData = function(notes, courseid) {
     self.getNotesUserData = function(notes, courseid) {
         var promises = [];
         var promises = [];
Line 230: Line 232:
         });
         });
     };
     };
</code>
</syntaxhighlight>
Since getNotes returns only userids, we need to retrieve the complete user information in order to be able to display his full name and profile image. We use the $mmUser service getProfile function.
Since getNotes returns only userids, we need to retrieve the complete user information in order to be able to display his full name and profile image. We use the $mmUser service getProfile function.


[[Category: Mobile]]
[[Category: Mobile]]
[[Category: Tutorial]]
[[Category: Tutorial]]

Latest revision as of 07:14, 29 April 2022


Warning: This page is no longer in use. The information contained on the page should NOT be seen as relevant or reliable.



Warning: This page is no longer in use. The information contained on the page should NOT be seen as relevant or reliable.


IMPORTANT: This documentation will be obsolete in May 2018, please read this announcement.

Introduction

In this tutorial we are going to extend the notes add-on functionality

Add-on spec

We want to develop a plugin that will display a new option at course level (at the same line that contents, participants and grades).

This option will display all the course notes for all the participants in the course (it's suitable for teachers).

A couple of screenshots with the desired result:

Initial view
Note types view
Notes view

Steps

Set up your development environment

Please, read Setting up your development environment for Moodle Mobile 2

Set up your Moodle installation

Enable debugging, disable caches, etc... the typical settings for developing.

Enable the Mobile Service via Admin / Plugins / Web Services / Mobile

Develop the Moodle Web Services you are going to need

In this case we'll use an existing web service (core_notes_get_course_notes) that is already available in the Moodle Mobile app service, if you need custom functions you will need to develop a local plugin including there your new Web Services (see https://moodle.org/plugins/view/local_wstemplate) and create a custom service.

Develop the Moodle Mobile add-on

The full source code can be found here: https://github.com/moodlehq/moodlemobile2/tree/master/www/addons/notes

www/addons/notes/main.js

angular.module('mm.addons.notes', [])

.config(function($stateProvider) {

    $stateProvider

    .state('site.notes-types', {
        url: '/notes-types',
        views: {
            'site': {
                templateUrl: 'addons/notes/templates/types.html',
                controller: 'mmaNotesTypesCtrl'
            }
        },
        params: {
            course: null
        }
    })

    .state('site.notes-list', {
        url: '/notes-list',
        views: {
            'site': {
                templateUrl: 'addons/notes/templates/list.html',
                controller: 'mmaNotesListCtrl'
            }
        },
        params: {
            courseid: null,
            type: null
        }
    });
})

.run(function($mmUserDelegate, $mmaNotesHandlers, $mmCoursesDelegate, $mmaNotes) {

    // Register plugin on course list.
    $mmCoursesDelegate.registerPlugin('mmaNotes', function() {

        if ($mmaNotes.isPluginViewNotesEnabled()) {
            return {
                icon: 'ion-ios-list',
                state: 'site.notes-types',
                title: 'mma.notes.notes'
            };
        }
    });
});

Here we declare the plugin, and register the Plugin (this means that the plugin will be displayed in the course main menu.

Note also that we are declaring the states (views) the plugin will support, in this case there are two views:

  • notes-types: Is a list that display the different note types available (site, course, personal).
  • notes-lists: that will display a list of notes for the type selected in the previous view.

www/addons/notes/templates/types.html and www/addons/notes/templates/list.html

These files contains the templates used for the view, the first one is very simple since it only links to the different note types.

The second one is more complex since requires a controller that is going to do all the logic for retrieving the note and prepare them to be displayed.

www/addons/notes/controllers/types.js

This is the controller that inject data in the types.html view, the code is pretty simple:

angular.module('mm.addons.notes')
.controller('mmaNotesTypesCtrl', function($scope, $stateParams) {
    var course = $stateParams.course,
        courseid = course.id;

    $scope.courseid = courseid;

});

It just make available in the $scope the courseid, that is required because is passed as a state parameter for the list view.

www/addons/notes/controllers/list.js

This controller is the one that will render in the list view the notes:

.controller('mmaNotesListCtrl', function($scope, $stateParams, $mmUtil, $mmaNotes, $mmSite, $translate) {

    var courseid = $stateParams.courseid,
        type = $stateParams.type;

Here we retrieved the state parameters (the course id and the type of notes) that were declared in the types.html view.

    function fetchNotes(refresh) {
        return $mmaNotes.getNotes(courseid, refresh).then(function(notes) {
            notes = notes[type + 'notes'];

            return $mmaNotes.getNotesUserData(notes, courseid).then(function(notes) {
                $scope.notes = notes;
            });

        }, function(message) {
            $mmUtil.showErrorModal(message);
        });
    }

The fetchNotes function is responsible of using the Notes service getNotes to retrieve the data, note that we use an additional function getNotesUserData to retrieve the full user profile information (since via getNotes we only get the userid)

fetchNotes().then(function() {
        // Add log in Moodle.
        $mmSite.write('core_notes_view_notes', {
            courseid: courseid,
            userid: 0
        });
    })

After retrieving the notes, we do logging in Moodle (so the actions are registered in the web interface)

    $scope.refreshNotes = function() {
        fetchNotes(true).finally(function() {
            $scope.$broadcast('scroll.refreshComplete');
        });
    };

This function is triggered by the "Pull down to refresh" action in order to refresh the view (empty the cache), note that the true parameter in the fetchNotes function means to not use cache.


www/addons/notes/services/notes.js

The notes services holds all the main plugin logic, it's responsible of checking if the plugin is available, retrieve information for the server and format the information so it can be rendered in the view by the controller.

    self.isPluginViewNotesEnabled = function() {
        var infos;

        if (!$mmSite.isLoggedIn()) {
            return false;
        } else if (!$mmSite.canUseAdvancedFeature('enablenotes')) {
            return false;
        } else if (!$mmSite.wsAvailable('core_notes_get_course_notes')) {
            return false;
        }

        return true;
    };

Here we checked if the plugin is enabled, the user must logged in, enablenotes should be enabled in the Moodle global settings and the core_notes_get_course_notes function should be available.

    self.getNotes = function(courseid, refresh) {

        $log.debug('Get notes for course ' + courseid);

        var data = {
                courseid : courseid
            },
            presets = {};
        if (refresh) {
            presets.getFromCache = false;
        }

        return $mmSite.read('core_notes_get_course_notes', data, presets);
    };

Here we retrieve the notes information from Moodle via Web Services, note that the refresh function is used for invalidating the cache (for example, when the user performs a pull down to refresh).

    self.getNotesUserData = function(notes, courseid) {
        var promises = [];

        angular.forEach(notes, function(note) {
            var promise = $mmUser.getProfile(note.userid, courseid, true);
            promises.push(promise);
            promise.then(function(user) {
                note.userfullname = user.fullname;
                note.userprofileimageurl = user.profileimageurl;
            }, function() {
                // Error getting profile. Set default data.
                return $translate('mma.notes.userwithid', {id: note.userid}).then(function(str) {
                    note.userfullname = str;
                });
            });
        });
        return $q.all(promises).then(function() {
            return notes;
        });
    };

Since getNotes returns only userids, we need to retrieve the complete user information in order to be able to display his full name and profile image. We use the $mmUser service getProfile function.