Xblocks and beyond

Felipe Montoya

https://edunext.co

About me

In the community since 2013.

One of the earliest open source contributors.

CTO of eduNEXT

EPFL CEDE

First and largest SaaS provider

xblock-flow-control

html-email

ELK for real time analytics

Microsites

Insights

About the talk

  • What kind of info can I access in an xblock

  • What can I do when the info I want is not in the list

  • How to best cross the line in the xblock vs app dichotomy to access more data

  • Requirements and consequences of crossing the line

  • How to keep my codebase modular and extend the platform beyond the course content into the course pages

  • How to keep complicated extensions to the LMS through xblocks sane and easy to port to newer named releases

Answers the questions

Xblocks: bird's eye

What is an Xblock

edX’s component architecture for courseware

Quick reminder:

Xblocks create a hierarchy of pieces

One of the primary extension points for course content

Why are they nice

OLX

Xblocks

Studio

def author_view(self, context=None):
    pass

def studio_view(self, context=None):
    pass

def author_view(self, context=None):   
    pass

Wrapper of external services

Stable interface (pre alpha)

Independent repository

<video youtube="1.00:dQw4w9WgXcQ" url_name="ff000e7ca278461e86a87a39248c5e76" display_name="Lesson" download_track="true" download_video="true" edx_video_id="aefd2be1-18c8-44e7-8815-2f890c971271" html5_sources="[]" only_on_web="true" sub="dQw4w9WgXcQ" youtube_id_1_0="dQw4w9WgXcQ">
  <video_asset client_video_id="someVideo.6.mov" duration="716.12">
    <encoded_video bitrate="0" file_size="0" profile="youtube" url="dQw4w9WgXcQ"/>
    <encoded_video bitrate="211" file_size="18910223" profile="mobile_high" url="https://123.cloudfront.net/dQw4w9WgXcQ/someVideo.mp4"/>
    <encoded_video bitrate="166" file_size="14896810" profile="mobile_low" url="https://123.cloudfront.net/dQw4w9WgXcQ/someVideo.mp4"/>
    <encoded_video bitrate="284" file_size="25424960" profile="desktop_mp4" url="https://123.cloudfront.net/dQw4w9WgXcQ/someVideo.mp4"/>
  </video_asset>
</video>

Tools of the trade

Xblocks

What's out there?

Xblocks


Poll & Survey
LTI consumer
Staff graded assesment
Word Cloud
Vector Drawing

Scorm

Problem builder
Recommender tool

Schoolyourself

Randomized content blocks
Annotations
Drag and Drop V2
Oppia explorations
Office Mix

Google drive
Flow control
Peer instruction tool
Done
Image Explorer

What's not an Xblock?

Xblocks

Djangoapps

Proctoring

Submissions

Teams

Notes

Auxiliary Services

Course pages

Features

Xblocks: up close

How to Xblock

Detail

https://github.com/open-craft/quote-of-the-day-xblock

General guideline

  • Download SDK
  • Use cookie cutter
  • Developer fun!
  • Require services
  • Use Xblock API

How far can you go?

Extend

What is inside the box

Services in the lms Xblock runtime

Detail

# lms/djangoapps/lms_xblock/runtime.py

'fs',               # xblock.reference.plugins.FSService()
'field-data',       # lms.djangoapps.lms_xblock.field_data.LmsFieldData
'i18n',             # xmodule.modulestore.django.ModuleI18nService
'user',             # xblock_django.user_service.DjangoXBlockUserService
'settings',         # xmodule.services.SettingsService
'partitions',       # lms.djangoapps.lms_xblock.runtime.LmsPartitionService()
'bookmarks',        # openedx.core.djangoapps.bookmarks.services.BookmarksService
'proctoring',       # edx_proctoring.services.ProctoringService
'verification',     # lms.djangoapps.verify_student.services.VerificationService
'reverification',   # lms.djangoapps.verify_student.services.ReverificationService
'badging',          # badges.service.BadgingService
'milestones',       # milestones.services.MilestonesService
'user_tags',        # lms.djangoapps.lms_xblock.runtime.UserTagsService()
'credit',           # openedx.core.djangoapps.credit.services.CreditService
'library_tools',    # xmodule.library_tools.LibraryToolsService

Beyond Xblocks

Xblock on steroids

Extend

Hybrid Xblock - App

Import core modules

Let's do this

Extend

One of two ways:

# common.py

OPTIONAL_APPS = (
    'mentoring',
    'problem_builder',
    'edx_sga',
    'submissions',
    'openassessment',

    # ...
    # Your Xblock here
    'custom_xblock_app',
    # ...
)
# Your preferred way of
# adding fines to lms.env.json

EDXAPP_ENV_EXTRA:
  # ...
  # Your Xblock here
  ADDL_INSTALLED_APPS:
    - "custom_xblock_app"

And then what?

Extend

Access to all the core modules

Management commands

Models

Translations (the django way)

Is this even legal?

Extend

  • openassessment.xblock
  • edx_sga
  • problem_builder
  • mentoring

Many examples in the wild

But at which cost?

Extend

+ Still plays nice with OLX and Studio
+ All the platform data to interact
+ Django

- More surface area (security)
- Changes to the platform will break it

How to keep you sanity

Independent services

Keep you sanity

# Service with @XBlock.needs decorator

grades_service = self.runtime.service(self, 'grades')


# Custom Service

from xblock.reference.plugins import Service

class GradeService(Service):
    """Custom Service Class"""
    pass

grades_service = GradeService()

Use Json Handler

With or without fragments

Initialize them, or not

Keep your sanity

Course scoped API

Each handler an endpoint

Simple Pattern

Keep your sanity

@XBlock.json_handler

edx-platform

custom services

Pattern: Xblock

Keep your sanity

@XBlock.json_handler
def api_endpoint_example(self, data, suffix=''):
    """  Returns the actual condition state  """

    return {
        'success': True,
        'status': self.any_xblock_method(),
        'grades': self.cutting_edge_method(),
    }

Pattern: Studio

Keep your sanity

Pages

Works on units or student_view

<!--
    Studio Page
    Parameters: 
    data-location="block-v1:SV_test+SV_test+SV_test+type@grade-podium+block@unique_id" 
    data-course-id="course-v1:SV_test+SV_test+SV_test"
    data-extra="You can pass more variables here"
-->
<div id="app-anchor-js"
    data-location="block-v1:SV+CV+2016co+type@grade-podium+block@unique_id" 
    data-course-id="course-v1:SV+CV+2016co"
    data-background-img="https://s19.postimg.org/q8y5al5nn/Wallpaper_01.jpg">
></div>
<script type="text/javascript" src="https://static.edunext.co/static/podium/js/podium.app.require.js"></script>

Pattern: Javascript

Keep your sanity

define = define || RequireJS.define;

(function (require, define) {
  'use strict';

  require.config({
    baseUrl: "../",
    paths: {
      /* Load jquery from google cdn */
      'jquery': ['//ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min'],
      /* Load from cdn */
      'backbone': ['https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min'],
      'underscore': ['https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min'],
      'text': ['https://cdnjs.cloudflare.com/ajax/libs/require-text/2.0.12/text.min']
    },
    shim: {
      /* Set bootstrap dependencies (just jQuery) */
      'backbone' : ['underscore']
    }
  });

  require([
    'jquery',
    'underscore',
    'backbone',
    'text!/static/template/main.html',
    ], function ($, _, Backbone, template) {
  
    // All your code here
    var extras = $('#page-app').data('extras');

  });

}).call(this, require || RequireJS.require, define || RequireJS.define);

Test. Not negotiable

Keep custom services separate

https://stackoverflow.com/a/6794451/2072496

Keep your sanity

Use Continuous integration tools

Travis-CI, CircleCI, Jenkins

Our experience

Keep your sanity

In contrast

Keep your sanity

Questions?

Lets talk

felipe.montoya@edunext.co

github.com/felipemontoya

Xblocks and beyond

By Felipe Montoya

Xblocks and beyond

  • 1,126