Content Type Plugins
Clone this wiki locally
Content in Concerto 2 is designed around a plugin model where additional types of content, supplementing the initial Graphics, Ticker Text, etc, can be added to the system via plugins. These plugins can define custom upload forms, views, and player display code to control the end-to-end flow working with a new type of content in Concerto 2.
Official Concerto plugins
For a plugin to be included as part of Concerto by default, it should meet some basic criteria:
- Have a code review performed by a dev team member
- Be licensed under a license compatible with Concerto's own (Apache v2), with a license text inside the repository
- Be inside the concerto Github organization with access granted to dev team members
- Be accessible for at least a few key dev team members to upload to on Rubygems
The content upload form in Concerto 2 is controller with a series of partials, letting you override specific components of the form or the entire form if necessary. The default form is broken down into three partials: top, middle, and bottom. Each of these partials is passed the FormBuilder as
form, allowing you to use
form.text_field :name and alike. You can mix and match what pieces you want to override in a plugin. As an example, the Graphic content type only defines a custom top which adds a file upload field, the rest of the form uses the default middle and bottom sections. You can also replace the entire form with your own custom form if this 3 blocks don't provide suitable flexibility for your plugin.
The top form partial (
_form_top.html.erb) is traditionally used to capture the most important part of the content, like the file being uploaded, ticker text entry, path to an RSS feed, etc. The default form_top just captures a string for the data field.
The middle form partial (
By default, the bottom form partial (
_form_bottom.html.erb) provides a simple submit button, nothing too fancy here. If you create your own bottom, please be sure to add a submit button somewhere on the page for folks to upload their content.
If you would not like to use the 3 form block approach that the default content types use, you're welcome to define your own full form creating a
_form_full.html.erb partial. If a content type has a full_form it will render this file instead of the 3 blocks. Note, a full form is responsible for displaying error messages if the content cannot be saved.
If you'd like to specify an icon for the tab then add a partial called
_tab_icon.html.erb. An example would be the simple-rss tab icon, which is simply
This icon is also used in the submission tiles under browse content, and has opacity applied to it.
Content Display Views
In addition to the form used to upload the content, a content type plugin must also define partials to control how the content is displayed throughout the admin UI. We use a series of render_ partials to do this, where types are the different places in the UI content is shown. Currently the only types this author is aware of is
grid, used for the grid-style content listing, and
default, used everywhere else. If a type-specific render partial is missing, like render_grid, the system will fall back to a default rendering partial for that type. In the grid instance, this partial renders a generic content icon.
These partials are called with a local
content variable with the content to render.
To render content that requires a file, we can call use a url returned from
display_content_path to access the file returned from a model's
render method as described below.
As an example, for Graphic content we use render_grid (_render_grid.html.erb) to generate an image tag that renders a small thumbnail of the content and the default (_render_default.html.erb) returns the full sized graphic.
Each content type should define it's own model for the new content, inheriting from Content or DynamicContent as appropriate. To customize the behavior of this content you probably want to define several methods / variables:
The name of this content type as it should be displayed must be defined in a
DISPLAY_NAME variable, containing a string like "Video" or "Ticker Text". This string is only used for display purposes throughout the admin ui.
Each content needs to be associated with a Kind in Concerto 2. A Kind represents the type of block on a screen that the content should be rendered in. Currently, Concerto 2 has
Text kinds which roughly map to ticker fields, large graphics areas, and sidebar text. We recommend using an
after_initialize hook to set the set the Kind of the content, this can be as simple as
self.kind = Kind.where(:name => 'Graphics').first (from Graphic.rb).
If the content can't be displayed as plain text or HTML, you'll need to implement a
render method which should return the File is to be displayed. We use this in the Graphic class to resize and return an image to users. The render method will get called with all the params passed in the URL to display the content. The controller displaying the result expects a File-like object that responds to
pre_render method is called on each piece of content before it's information is passed along to the frontend to be rendered in a screen. The method is called with two parameters: the screen the content is going to be displayed on, and the field that content will be in. You can use this information to perform any specific transforms necessary to render the content in a specific field. This method doesn't need to return anything, but should cache that information until
render_details is called.
When content information is returned to a screen, we call
render_details with no arguments to figure out what should be passed along to the screen. In the default case (including Ticker Text), we return a hash with the content's data field stored in the data attribute. For Graphics, we use this method to build a URL to the image to be rendered, using the cached values from pre_render.
Form Attributes / Strong Parameters
We use Strong Parameters in Concerto 2 to help secure forms and prevent data from getting changed that we would rather not have changed. This also means that unless a field is whitelisted, forms won't be able to write to them. We define a class method
self.form_attributes which should return an array of attributes to be allowed in the content upload form for this content type. If you are using the default fields from the middle form you probably want to make a call to
super() to get those default fields from Content and concat your own onto the array. The Graphic class has a good example, adding a nested
media field to support the file upload.