Jump to >

Review UI Integration

Review UIs are used in reviewing file attachments of particular mimetypes. For example, an Image Review UI is used to render image files and allow comments to be attached to specific areas of an image. Similarly, a Markdown Review UI renders the raw text from a .md file into a corresponding HTML.

Extensions can integrate custom Review UIs into Review Board by defining a hook that subclasses ReviewUIHook. Each extension may define and register zero or more Review UIs. When the extension is enabled through the admin page, the hook registers its list of Review UIs. Likewise, the hook unregisters these Review UIs when the extension is disabled.

We use a simple XMLReviewUI that performs syntax highlighting as an example to demonstrate the key anatomical points for integrating ReviewUIs through extensions.

Subclassing ReviewUIHook

extension.py must use a Review UI Hook to register its list of Review UIs. This can be using reviewboard.extensions.hooks.ReviewUIHook directly, using a subclass of it. ReviewUIHook expects a list of Review UIs as argument in addition to the extension instance.

Since you will be writing custom JavaScript and, likely, custom CSS, you will also need to define some static media bundles to load.

Example: XMLReviewUIExtension:

from reviewboard.extensions.base import Extension
from reviewboard.extensions.hooks import ReviewUIHook


class XMLReviewUIExtension(Extension):
    css_bundles = {
        'xmlreviewable': {
            'source_filenames': ['css/xmlreviewable.less'],
        },
    }

    js_bundles = {
        'xmlreviewable': {
            'source_filenames': [
                'js/XMLReviewableModel.js',
                'js/XMLReviewableView.js',
            ],
        },
    }

    def initialize(self):
        ReviewUIHook(self, [XMLReviewUI])

ReviewUI Class

Each Review UI must be defined by its own ReviewUI class that subclasses reviewboard.reviews.ui.base.FileAttachmentReviewUI. It must also define the following class variables:

  • name: The name for the review UI.
  • supported_mimetypes: a list of mimetypes of the files that this Review UI will be responsible for rendering.
  • js_model_class: The JavaScript model name that will store information for the view.
  • js_model_view: The JavaScript view name that will provide the review experience for the file.
  • css_bundle_names: A list of CSS bundles defined by your extension that the page will include.
  • js_bundle_names: A list of JavaScript bundles defined by your extension that the page will include.

Example: XMLReviewUI:

import logging

from django.utils.encoding import force_unicode
import pygments

from reviewboard.reviews.ui.base import FileAttachmentReviewUI


class XMLReviewUI(FileAttachmentReviewUI):
    """ReviewUI for XML mimetypes"""
    name = 'XML'
    supported_mimetypes = ['application/xml', 'text/xml']

    css_bundles = ['xmlreviewable']
    js_bundles = ['xmlreviewable']

    js_model_class = 'MyVendor.XMLReviewable'
    js_view_class = 'MyVendor.XMLReviewableView'

Generally, you will also want to provide data for the model, such as the contents of the file. You will do this in get_js_model_data(). For example:

def get_js_model_data(self):
    data = super(XMLReviewUI, self).get_js_model_data()

    data_string = ""

    with self.obj.file as f:
       try:
           f.open()
           data_string = f.read()
       except (ValueError, IOError) as e:
           logging.error('Failed to read from file %s: %s', self.obj.pk, e)

    data['xmlContent'] = pygments.highlight(
        force_unicode(data_string),
        pygments.lexers.XmlLexer(),
        pygments.formatters.HtmlFormatter())

    return data

You may also provide get_js_view_data() to pass options to the view.

There are a number of functions you may want to override, all documented in reviewboard.reviews.ui.base.ReviewUI.

ReviewUI JavaScript

Here are the corresponding JavaScript used in the above extension.

xml_review_ui_extension/static/js/XMLReviewableModel.js:

/*
 * Provides review capabilities for XML files.
 */
MyVendor.XMLReviewable = RB.FileAttachmentReviewable.extend({
    defaults: _.defaults({
        xmlContent: ''
    }, RB.FileAttachmentReviewable.prototype.defaults)
});

xml_review_ui_extension/static/js/XMLReviewableView.js:

/*
 * Displays a review UI for XML files.
 */
MyVendor.XMLReviewableView = RB.FileAttachmentReviewableView.extend({
    className: 'xml-review-ui',

    /*
     * Renders the view.
     */
    renderContent: function() {
        this.$el.html(this.model.get('xmlContent'));

        return this;
    }
});

File Attachment Thumbnails

Most extensions that add Review UIs will also want to render custom thumbnails for the attachments on the review request page. See FileAttachmentThumbnailHook for information on how to implement custom thumbnailers.