My course overview improvements

Jump to: navigation, search

This page will detail the technical specification for the improvements to the My course overview block.

Improvements to my course overview block.
Project state Starting
Tracker issue MDL-55611
Discussion https://tracker.moodle.org/browse/UX-8
Assignee HQ Projects Team


Summary

The new design for the UI for the course overview block requires the ability for Moodle to efficiently query plugins for a list of "date based" tasks for the current user.

The existing "mod print_overview" callbacks do not have sufficient functionality (no separation of fields, inefficient, incomplete, no relation to completion API, inconsistently implemented across modules) so we will have to build a new API (and deprecate mod_xx_print_overview).

Requirements

https://docs.google.com/document/d/13ukTgOBdDzkKmPhfyMH81inWkbfJL5CPsyQmLBDWq5k/edit

Technical Details

Course Overview Block

The course overview block will communicate exclusively with the Todo API and will present the Todo's as described in UX-8. We need to remove the old code used to render the course overview block and have it use the new APIs.

  • Mustache templates:
    • General template for the block (wrapping template)
      • Timeline view
        • Sort by dates (wrapping template)
          • Template for displaying single todo (rendered in list)
        • Sort by courses (wrapping template)
          • Single course section, includes list of todos similar to "sort by dates" (can maybe re-use the template for a single todo here)
    • Courses view
      • Single template can probably be re-used for "in progress", "upcoming" and "completed" views, just rendered with different data
      • As above, single template for a course
  • Javascript
    • Module for the course overview block that handles the high level interaction (changing between timeline and courses views etc)
    • Module for timeline view (maybe even have separate modules for "sort by dates" and "sort by courses"?). Handles requesting the data and rendering the templates etc.
      • Module needs to handle paginated results (view more button being clicked)
    • Module for courses view that handles requesting the data and rendering the templates
      • Module needs to handle paginated results (view more button being clicked)
    • Use the new pie chart we add
    • User the todo api javascript module to interact with the server external API
  • CSS: Style each of the templates (try to re-use the Bootstrap classes to keep this minimal)
    • Style Boost theme
    • Style bootstrap base theme (e.g. clean)
    • Add responsive styling (need to ask the UX team for some mock ups of smaller resolutions)
  • Accessibility: Add the appropriate aria attributes to each of the templates above to make the block accessible by a screen reader (more work than it seems)
  • Update blocks/course_overview/block_course_overview.php "get_content" to render a template via the renderer (need to add a new function)
  • Remove the existing functions being used to render the course overview (including functions in the renderer and lib.php)
  • Add behat tests for the interface that covers each permutation of the view (timeline, sort by dates, courses, courseview etc)

Action Event API

This will be a new API in core to represent the concept of "action events" in Moodle, i.e. the list of items displayed in the course overview block. A action event is made up of a calendar event and an associated action for the user.

The appropriate action will need to be calculated on a per user basis, per event, and per module because of complex permission problems. E.g. a user may have an event for an assignment that they no longer have permission to view or they may have an event for an assignment that can't be started until after another module has been completed etc.

Given the intensity of some of these calculations we'll need to look into aggressively caching results and maybe even avoid doing the calculations per request.

Since we're leveraging the existing calendar events for the static data we may not need to actually persist the todos anywhere other than caching.

  • Add a todo class (pretty please can we have an actual class rather than just stdClass)
    • Some properties of the class:
      • unique id (context id, component, area and item id?)
      • name - the name of the thing the todo relates to (e.g. activity name)
      • url - the url of the thing the todo relates to (e.g. view.php of the module)
      • user id - the id of the user this todo belong to
      • course id - the course that the todo relates to
      • icon url - the icon for the todo (default to the module icon)
      • start date (optional) - when the todo starts
      • end date (optional) - when the todo must be actioned by
      • item count - how many associated items there are (e.g. 4 unread posts)
      • action name - display name of the todo (e.g. "submit assignment")
      • action url - url of the todo action (e.g. link to the assignment submission page)
      • action start date - a date after which the todo can be actioned (only display the action url after this date)
      • action state - Has this been actioned? Eg, The assignment was submitted.
  • Add an API class to provide access to todos (get todos for a user, get todos for a user grouped by course etc).
    • Retrieval of todos needs to suppose pagination (and pagination with filters, e.g. first 10 todos in the next 7 days, second 10 todos in the next 7 days).
  • Add a data access layer that abstracts away all of the SQL so that we don't have that logic everywhere (ideally).
    • The API class would benefit from this.
    • It can also hide the fact that we're piggy backing on the calendar events, just in case we want to change that in the future.
    • It can also handle all of the caching
    • Support pagination as above
  • Add a standard interface for plugins to implement which will perform the required calculations and permission checks to generate the correct action based on the given user and event(s).
    • The core action event API can't (and shouldn't) know every place that will want to create a action event, so we need to provide a standard way for each plugin to register itself as something that will create an action event and an interface for them to do the data manipulation required.
  • Add an external API class.
    • This class shouldn't contain any business logic (that all lives in the API class).
    • All it needs to do is call into the API class to get the appropriate todos and then create the correct renderables from the action event.
    • All functions should be accessible via ajax. This is the class that the course overview block (and mobile app) will use.
  • Add some renderables for the action event
    • The action events should probably just be renderable / template-able themselves
    • These will be used by the external API class.
  • Improve performance using caching (this will be trial and error with the performance testing)
  • Write unit tests for all new API functions and external API functions
  • Add a javascript module to interact with the action event API (no bespoke ajax requests everywhere please)

Chart.js

  • Add a new chart type (pie chart) to Moodle's chart API for use in the templates above

Calendar Event API

We'll be using the existing calendar events as the basis for the "action events". The current calendar event data structure contains most of the data that we'll need so we'll leverage that rather than create duplicate data. The API will need to be extended in order to support the more complex data requests we'll need.

  • Add a display/order by date field to the calendar event table to allow us to do the date sorting (e.g. get me all events in the next 7 days) without having to do the start date + duration calculation
  • Add indexes to the event table if they are missing
    • display/order by date
    • course id
    • user id
  • Add functions to the calendar event API to retrieve groups of events for a given user(s)
    • currently it seems the API only loads one at a time so you need to do direct SQL in the calling code
    • API should probably handle grouping of results, e.g. events for a user would be the distinct set of any course level events + group event override + user event override, where each has higher precedence than the last in the result set
    • API needs to support order by new date field
    • API needs to support limit and offset
  • Add unit tests for new API functions

Calendar Block

  • Make sure all of the action events are showing up in the calendar for the user
    • Note: we *should* get this for free since we are simply creating calendar events
  • Make sure we are only displaying appropriate events (ie. if there is a user override then show that for the user, not multiple).

Course Completion Tracking

  • Develop a way to track completion on for all courses
    • This needs to take into account all activities within the course, even ones that don't have any completion tracking enabled
  • Add an API to query the completion status of a course that implements the agreed approach
  • Do we need to persist the course progress somewhere or can it be calculated at run time?
    • Assess performance of both options
  • If we need to persist the completion then we need to add hooks into all places that can alter the completion value and update the persistence so that the data is always accurate

Notes

There are different ways of calculating the completion percentage for a course and some will be more informative than others, depending on the type of usage of the course.

Some possible options are:

  • The number of completed+visible activities / The number of visible activities
  • The number of completed activities / The number of activities
  • The current week / the number of weeks
  • The (current date - course start date) / (course end date - course start date) * Requires a course end date
  • The current course grade / the required course grade (don’t expose hidden grades)
  • The enrolment duration / the required enrolment duration

Because each course completion criteria requires a different calculation, one possible method is:

If course completion is enabled

for each course completion criteria - get the current and total possible values for completion

if all are required:

normalise and sum/average the values

if any is required

calculate the highest percentage completion

If only activity completion is enabled (and not course completion)

calculate the completion percentage purely on the number of activities complete / the total number of activities. (Ignoring activities with no completion - should we ignore activities the current user cannot see via access restrictions?)

If course completion is not enabled

Try and calculation the completion based purely on the course start / end date

To calculate the current and total values for each completion criteria:

  • Activity completion - number of activities complete / number of activities required to be completed
  • Completion of other courses - number of courses complete / number of courses required to be completed
  • Enrolment Date - the current date - course start date / the enrolled until date - course start date. If there is no course start date use the enrolment start date. Max of 1.
  • Enroled duration - the number of days enrolled / the number of days required to be enrolled. Max of 1.
  • Unenrollment. 0 if enrolled, 1 if unenrolled.
  • Course grade - current course grade / required course grade. Max of 1.
  • Manual self completion. 0 if not complete, 1 if complete
  • Manual completion by others. 0 if not complete, 1 if complete

General Moodle stuff

  • Remove all uses of the "print_overview" callback thingo we're using through Moodle for modules to add stuff to the course overview block
  • Find all of the places in Moodle that need to generate create a todo and have them create appropriate calendar events
  • Find all of the places that may affect the status of a calendar event and update the event to make sure it is accurate (eg. editing a module, submitting an assignment, changing course dates etc)
  • Add an implementation of the callback interface thingo to each module that will be creating a todo
    • This implementation will take a calendar event and the user and do all of the appropriate checks to see if the user should see the todo, etc
    • It will then create the appropriate todo from the calendar event and add all of the action stuff.

General Testing

  • We need to do some performance testing on the overview with a site that has thousands of events and hundreds of courses to ensure that everything renders in a timely manner.