- Created by Dominika Kurek, last modified on Jan 25, 2017
Backoffice interface
The backend interface is produced by the PlatformUI Bundle which provides a JavaScript Single Page Application based on the YUI App Framework. This application is accessible in your browser at http://[uri_of_platform]/ez.
Technical architecture
The PlatformUI application code is divided into different types of components:
- Application: this is the top level component, the PlatformUI application is an instance of it. It is responsible for authenticating the user and for handling the routing.
- Models: models are the main objects handled by the application, they represent our main domain objects (Content, Location, Content Type, etc.)
- View services: view services act between the Application and the Views. They are configured on the routes and the main responsibility of a view service is to provide the model (or other data) to the views and to perform the operations requested by the user (removing a Content item, copying, etc.)
- Views: views generate the user interface and handle the user interaction (clicking, form submitting, etc.). A view can have several sub-views which can have further sub-views themselves.
- Plugins: plugins can enhance the application, the view services or the views for instance to provide additional features or to tweak the behavior of the plugged component.
The following chart depicts the interaction between those components:
Views: main view, sub-view, side view
The views represent a large part of the application and each of them can be used in three different contexts:
- As the main view
- As a sub-view of another (sub-)view
- As a side view
Main view
A view used as a main view is configured at the route level to be displayed when the user navigates to that route.
For instance, when reaching /ez
, the user is redirected to the loginForm
route (/ez#/login
) and this route is configured in the following way in the application component:
Among others things, this means the view loginFormView
will be used as the main view when this route is matched. loginFormView
is actually the identifier of the view metadata registered in the view
property of the Application.
Sub-view
To avoid having huge main views doing too many things in the application, the views are divided into smaller parts called sub-views.
For instance, the view used to display a Location is divided into several views at several levels, it contains:
- An action bar view for the right toolbar, which contains:
- a view for the Minimize button
- a view for the Create button which contains:
- a view to list and select a Content Type
- a view for the Edit button
- ...
- A Location View tab view which contains:
- the Raw Content View to display the fields which contains:
- A view for each fields
- ...
- the Raw Content View to display the fields which contains:
- A Location Details tab view
- ...
- A sub-item list view
Side view
A view can also be used as a side view. As its name suggests a side view can represent anything that is not part of the main view.
For instance, when displaying a Location, the top menu (the Navigation hub) or the left toolbar (the Discovery Bar) are side views.
The side views are also used for various widgets providing a service used several times in the application, such as the Universal Discovery Widget.
View services
The view services act between the Application and the Views for both the main views and the side views. They are responsible for providing the required data needed by a main view or a side view to be rendered. A view service will also receive the events triggered by the view to react or provide the additional data. For that, the view services receive an instance of the JavaScript REST Client.
How are pages generated?
Depending on the part of the PlatformUI Application you are using, the page may be generated in two different ways. From an end-user perspective, this is almost transparent but as a developer it is important to understand how the page is generated to be able to extend it.
Browser side rendering
The pages in the content part (as opposed to admin related pages) are fully rendered in the browser. For instance, when displaying a Location in PlatformUI, the corresponding view service loads the Location model and the related models (Content, Content Type, etc.) with the eZ Platform REST API (through the JavaScript REST Client) and gives them the LocationView to be displayed directly by this view and/or by its sub-views. If you open the browser developer tools in the network panel, you can see the REST requests needed to build the page and they only contain a JSON structure.
Server side rendering
The pages in the admin are build in a more traditional way as they are partly rendered server side. For those pages, the view service fetches one (or several) HTML fragment(s) from the server. This HTML fragment follows a very simple structure and can be generated by any means on the server and of course, in PlatformUI this is done in a quite standard Symfony controller. By opening the browser developer tools in the network panel you can see the requests needed to build the section list page.
UI Components
Navigation hub
The Navigation Hub is a side view displaying the top menu.
It displays 4 Navigation zones:
- Content
- Page
- Performance
- Admin Panel
A zone can contain an arbitrary number of Navigation zone items. By default, the Content zone has 2 navigation items: Content structure and Media library.
Bar views: Discovery Bar View, Action Bar View, Edit Action Bar View
Bar views provide a set of potential actions for the user.
When navigating in the Content zone, the Discovery Bar View allows you to discover content while the Action Bar View on the right allows you to act on the Content item being viewed (edit, move, copy, etc.).
When editing a Content item, the Edit Action Bar View on the right allows you to act on the Content item being edited.
Universal Discovery Widget
The Universal Discovery Widget is a side view triggered when the user needs to pick a Content item (or a Location). It can provide several Discovery Methods. By default, Browse and Search are available.
Extending the Dashboard
V1.4
eZ Platform contains a Dashboard which shows the user the most relevant Content items divided into blocks for a quick overview.
Aside from the built-in blocks you can extend the Dashboard with new ones and remove existing ones.
It can be done in four steps:
- Create a block view
- Create a template
Create a plugin for the view
Add modules to configuration
Create a block view
The first step is creating a view that will be added to the Dashboard. You can do it based on the Dashboard Block Asynchronous View. Thanks to this you only need to provide the data to display in the table.
Using the Dashboard Block Asynchronous View you need to set an identifier
of the block. The asynchronous view fires the _fireLoadDataEvent
method to get the data. The data must find itself in an array with the items
attribute.
In the example below an images
block is defined which looks up all content under the /images/
folder in the tree:
In the _getTemplateItem
method you can specify the structure of the item which will be provided to the template. In the example above each item will be an object with four properties.
Create a template
Now you have to create a template for the view, for example:
loadingError
, because the asynchronous view provides it if there are problems with loading data. If no error occurs, a table with basic info about your images will be displayed.Create a plugin for the view
The next step is adding the view and the template to the Dashboard. To do this, you need to create a plugin for the Dashboard view.
In the initializer you can use the public addBlock
method from the Dashboard view. In this method you only have to provide the instance of your view. Here you also set some properties for your new view: bubbleTargets
to make sure that the events will bubble up to the other views, and priority
where you can set the order of blocks in the Dashboard (higher number goes first).
If for whatever reason you want to remove a block, use another public method, removeBlock
, and provide it with just the block identifier.
Add modules to configuration
The last thing you have to do is add new modules to the yml configuration:
In this example the plugin is added as a dependency of the Dashboard block view, requiring the new images block view. The Dashboard images view in turn requires the asynchronous view.
After this configuration is complete the Dashboard should display the new block.
Further extensibility
Content Type icons
V1.4
A Content item can be treated as an instance of a Content Type. The type of a Content item is very important information to provide to the user. The Content Type to which a Content item belongs is represented graphically using an icon near the Content item name. Essentially, the Content Types are project-specific so the icons can be easily configured and extended by integrators.
Font icons + CSS
Icons in the PlatformUI interface are provided by an icon font. For Content Types, the idea is to expand that concept so that while generating the interface, we end up with a code similar to:
With such classes, the h1
is specified to display a Content Type icon. The class ez-contenttype-icon
makes sure the element is styled for that and gets the default Content Type icon. The second class is specific to the Content Type based on its identifier and if it's defined in one of the CSS files, the element will get the custom Content Type icon defined there.
Adding new Content Type icons
The extensibility of Content Type icons is tackled differently depending on the use case, but it relies on the ability to embed a custom CSS file in PlatformUI with css.yml
.
To prevent the need to configure/extend the system, we provide several pre-configured icons for very common Content Types such as:
product
author
category
gallery
/portfolio
blog_post
/blogpost
/post
blog
/weblog
news
pdf
document
photo
comment
wiki
wiki_page
/wikipage
There are three ways of choosing Content Type icons:
Pick an icon for a custom Content Type from existing icons
In such a case you need to pick the icon code. For that, the icomoon application can be used until the UI guidelines are up-to-date and reference the available icons. To ease that process and the readability of the code, we'll use ligatures in the font icon so that the CSS code for a custom Content Type could look like:
Add custom icons
If the icons we provide do not fit a custom Content Type, then a new custom icon font has to be added. To generate the icon, the Icomoon App can be used (or any other tool). Then, using a custom CSS stylesheet, this font can be included and the ez-contenttype-icon-<content type identifier>
can be configured to use that font.
Example:
Completely override the icon set
The solution for this use case is very close to the previous one. A custom icon font will have to be produced, loaded with a custom CSS file, and then the ez-contenttype-icon
style has to be changed to use that new font.
Example:
Custom Javascript
Custom Javascript can be added to PlatformUI using the following configuration block:
Extending the Form Builder
V1.7
EZ ENTERPRISE
Form Builder Bundle currently comes with three basic types of fields: Single Line Text, Paragraph Text and Email.
It was designed to be easy to extend by adding new types of fields.
Field definitions
Default field definitions are available in Resources\config\default_fields.yml
.
Field definition structure
Field definitions are contained under the fields
key. Each definition has its own key, e.g. single_line_text
. Each definition must contain two sections:
identifier
- name of the definition used on the front enddisplayName
- name displayed in the Page mode editor in thefields
tab
The definition can also contain the following optional sections:
validators
- defines validators that the field will use. This must contain the validator's identifier and the values that will be checked during validation, for example:
attributes
- contains the field's attributes. You can place here custom attributes for new fields, like in https://github.com/ezsystems/ezstudio-form-builder/blob/master/bundle/Resources/config/default_fields.yml#L33. There are also four default attributes that are used for every field:LABEL_NAME
,LABEL_HELP_TEXT
,LABEL_ADMIN_LABEL
andLABEL_PLACEHOLDER_TEXT
. If you wish, you can override them in your configuration.
views
- provides a list of views that will be used to display the field. At least one view must be defined, with the keysname
,thumbnail
andtemplate
, for example:
Adding a new field definition
This procedure assumes you are creating a separate Bundle to house your new type of form field.
1. Create a YAML file with field definition
Create a YAML configuration file, e.g. Resources\config\extended_fields.yml
, with the following code:
When creating a new template for the field definition, remember to add mandatory ezform-field
class and field.id
as shown below:
2. Modify the DependencyInjection\TestExtension.php
class
The class must implement the PrependExtensionInterface
interface:
In the prepend
method in TestExtension.php
add the following lines at the end:
Validators
Creating your own validators
You can create your own validators by reproducing the following configuration:
Validator configuration
A validator implements the EzSystems\FormBuilder\SPI\ValidatorInterface.php
interface and extends the abstract class EzSystems\FormBuilder\Core\Validator\Validator.php
.
The interface requires the implementation of the following methods:
validate
getLabel
getErrorMessage
setLimitation
getValueType
The validate
method is the one that contains the logic for the validation. It returns true
when validation is successful, or false
when the data does not validate:
The getLabel
method returns a string with the name of the validator that will be used in the editor:
The getErrorMessage
method returns error message(s) to appear when the validate
method returns false
:
The setLimitation
method allows the configuration of limitations. Its default implementation is contained in the Validator
abstract class:
The getValueType
method returns the name of the checked value type:
Currently the abstract class Validator
has three value types (defined in Core\Validator\Validator.php
):
The validator must be tagged as form_builder.field_validator
. Due to this the Resources\config\validator_services.yml
file contains two entries, one in the parameters
section:
and one in the services
section:
Signal slots
Whenever a form is submitted and stored in a database, lib\Core\SignalSlot\Signal\FormSubmit
emits signal in a submitForm
service. You can create your own listeners, called Signal slots, to capture the FormSubmit signal.
Below you can find an example of a custom Signal slot. It saves submission to a text file.
It has to be registered as a tagged Symfony service, like this:
Other Form Builder fields
V1.8
Form Builder fields introduced in v1.8 require additional configuration.
Date field
To make use of the Date field you need to add the necessary assets. The assets should be added in page head with the following code:
Adding new date format
If you wish to add a new date format, the alias
in the date field config must follow this pattern:
d
or D
- day of the month (1-2 digits)
dd
or DD
- day of the month (2 digits)
m
or M
- month of the year (1-2 digits)
mm
or MM
- month (2 digits)
yy
or YY
- year (2 digits)
yyyy
or YYYY
- year (4 digits)
for example:
d-m-yyyy
- 16-1-2017
mm/dd/yy
- 01/16/17