Adding Review Request Fields¶
One of the most common uses for extensions is to add custom fields to review
requests. These fields act like any other field on a review request. They can
be edited, saved along with a draft, published, and their history can be shown
in the “Review request changed” boxes. Their data can be accessed through the
extra_data fields of Review Request Resource and
Review Request Draft Resource.
Creating new review request fields involves a few steps:
Creating a subclass of
BaseReviewRequestField. There are several different superclass types available which provide different types of fields.Using ReviewRequestFieldsHook and ReviewRequestFieldSetsHook to register the fields.
Built-in Field Types¶
Each field is first defined in Python using a subclass of
BaseReviewRequestField. There are
several built-in types which provide more specific behavior:
BaseEditableField- A simple single-line text field.BaseTextAreaField- A multi-line text field, with optional Markdown support.BaseCommaEditableField- A single-line text field which allows selecting multiple comma-separated values.BaseCheckboxField- A boolean-valued field which is displayed as a checkbox.BaseDropdownField- A field which allows selecting one of several predefined options. This additionally requires defining theoptionsattribute, which is a list of 2-tuples containing avalueandlabel.BaseDateField- A field which allows selecting a date.
At a minimum, your subclass will need to define two class attributes,
field_id and
label. Depending
on the type, there may be additional attributes which can be overridden to
manipulate the behavior.
Example¶
from reviewboard.extensions.base import Extension
from reviewboard.extensions.hooks import (
ReviewRequestFieldsHook,
ReviewRequestFieldSetsHook,
)
from reviewboard.reviews.fields import (
BaseCommaEditableField,
BaseCheckboxField,
BaseDateField,
BaseDropdownField,
BaseEditableField,
BaseTextAreaField,
)
class MilestoneField(BaseEditableField):
field_id = 'myvendor_milestone'
label = 'Milestone'
class NotesField(BaseTextAreaField):
field_id = 'myvendor_notes'
label = 'Notes'
class TagsField(BaseCommaEditableField):
field_id = 'myvendor_tags'
label = 'Tags'
class SecurityRelatedField(BaseCheckboxField):
field_id = 'myvendor_security_related'
label = 'Security Related'
class PriorityField(BaseDropdownField):
field_id = 'myvendor_priority'
label = 'Priority'
options = [
('low', 'Low'),
('medium', 'Medium'),
('high', 'High'),
]
class DueDateField(BaseDateField):
field_id = 'myvendor_due'
label = 'Due Date'
class SampleFieldSet(BaseReviewRequestFieldSet):
fieldset_id = 'sample_fields'
label = 'My Fields'
field_classes = [SecurityRelatedField, PriorityField]
class SampleExtension(Extension):
def initialize(self) -> None:
ReviewRequestFieldSetsHook(self, [SampleFieldSet])
ReviewRequestFieldsHook(self, 'info',
[MilestoneField, DueDateField])
ReviewRequestFieldsHook(self, 'main',
[NotesField, TagsField])
Creating a JavaScript FieldView Subclass¶
Each Python field type has an associated JavaScript view which handles user interaction and value serialization. If you subclass one of the builtin field types, you do not need to create an override for these, but doing so can allow you to implement more advanced UIs such as autocomplete or custom editor widgets.
You will need to define static media bundles for your JavaScript (and CSS, if necessary).
Example¶
Suppose we wanted a field which used Selectize as its editor. First, we’d define a JavaScript view that set up Selectize on the editor’s field:
window.MyExtension = {};
MyExtension.SelectizeFieldView =
RB.ReviewRequestFields.TextFieldView.extend({
/**
* Render the view.
*/
render() {
RB.ReviewRequestFields.TextFieldView.prototype.render.call(this);
this.inlineEditorView.$field.selectize();
},
});
We can then reference the new JavaScript view using the
reviewboard.reviews.fields.BaseReviewRequestField.js_view_class
attribute.
from reviewboard.reviews.fields import BaseEditableField
class MilestoneField(BaseEditableField):
field_id = 'myvendor_milestone'
label = 'Milestone'
js_view_class = 'MyExtension.SelectizeField'