Skip to content

Extending modules

Universal Discovery Widget (UDW)

Universal Discovery module allows you to browse the content structure and search for content using an interactive interface: browse, search, create, and bookmarks view .

UDW tutorial

For a detailed example on how to add a new UDW tab, see step 5 of the Extending Admin UI tutorial.

How to use UDW?

With vanilla JS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const container = document.querySelector('#react-udw');

ReactDOM.render(React.createElement(eZ.modules.UniversalDiscovery, {
    restInfo: {
        token: {String},
        siteaccess: {String}
    }
    onConfirm: {Function},
    onCancel: {Function},
}), container);

With JSX:

1
2
3
4
5
6
const props = {
    onConfirm: {Function},
    onCancel: {Function}
};

<UniversalDiscoveryModule {...props} />

Adding new tabs to the UDW

The Universal Discovery module is highly customizable. It allows you to add new tabs to the module.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const props = {
    onConfirm: {Function},
    onCancel: {Function},
    extraTabs: [{
        id: {String},
        title: {String},
        panel: {Element}, // React component that represents content of a tab
        attrs: {Object}
    }]
};

<UniversalDiscoveryModule {...props} />

Each tab definition is an object containing properties:

  • id {String} - unique tab identifier (it cannot be: browse or search)
  • title {String} - tab button title/label
  • panel {Element} - any kind of React component. A panel component will receive the following props:
    • isVisible {Boolean} - visible flag
    • onItemSelect {Function} - a callback to be invoked when content is selected
    • maxHeight {Number} - the maximum height of the panel container
    • id {String} - panel identifier
    • startingLocationId {Number} - location ID
    • findLocationsByParentLocationId {Function} - finds locations related to the parent location
    • findContentBySearchQuery {Function} - finds content matching a given text query
    • contentTypesMap {Object} - content types map with content type ids as keys
    • multiple {Boolean} - can select multiple content items flag
    • labels {Object} - a hash containing text messages to be placed across many places in a component
  • attrs {Object} - any optional list of props that should applied to the panel component. It can override the panel props listed above.

Property list

The <UniversalDiscoveryModule /> module can handle additional properties. There are 2 types of properties: required and optional.

Required properties

Without all the following properties the Universal Discovery module will not work.

onConfirm {Function} - a callback to be invoked when a user clicks on the confirm button in a Universal Discovery popup. The function takes one param: content which is an array of content items structs.

onCancel {Function} - a callback to be invoked when a user clicks on the cancel button in a Universal Discovery popup. It takes no extra params.

restInfo {Function} - a config hash containing: token ({String}) and siteaccess ({String}).

Optional props

Optionally, Universal Discovery module can take a following list of props:

  • loadContentInfo {Function} - loads content info. It takes 3 params: restInfo, contentId and callback
  • loadContentTypes {Function} - loads content types data. It takes 2 params: restInfo, callback,
  • canSelectContent {Function} - checks whether a content item can be selected. It takes one param: a data object containing an item property as the content struct and itemsCount as a number of selected items in UDW,
  • findContentBySearchQuery {Function} - finds a content using a search query. It takes 3 params: restInfo, query and callback,
  • findLocationsByParentLocationId {Function} - finds sub items of a given location. It takes 3 params: restInfo, parentLocationId and callback,
  • title {String} - the title of Universal Discovery popup. Default value: Find content,
  • multiple {Boolean} - can select multiple content items flag. Default value: true,
  • activeTab {String} - active tab identifier. Default value: browse,
  • visibleTabs {Array} - which UDW tabs are available (e.g. Browse, Search, Create),
  • startingLocationId {Number} - location ID. Default value: 1,
  • maxHeight {Number} - maximum height of panel container. Default value: 500,
  • searchResultsPerPage {Number} - max amount of items visible per page in the search results. Default value: 10,
  • extraTabs {Array} - optional, extra tabs. Each tab definition is an object containing the following properties (all of them are required):
    • id {String} - unique tab identifier (it cannot be: browse or search),
    • title {String} - tab button title/label,
    • panel {Element} - any kind of React component,
    • attrs {Object} - any optional list of props that should applied to the panel component. })),
  • labels {Object} - a hash containing text messages to be placed across many places in a component. It contains text labels for child components, see universal.discovery.module.js for details,
  • selectedItemsLimit {Number} - the limit of items that can be selected. Should be combined with the multiple attribute set to true. Default value is 0, which means no limit,
  • allowContainersOnly {Boolean} - when true, only containers can be selected. Default value: false,
  • cotfPreselectedLanguage {String} - language that is preselected in Content on the Fly,
  • cotfAllowedLanguages {Array} - languages that are available in Content on the Fly,
  • cotfPreselectedContentType {String} - Content Type that is preselected in Content on the Fly,
  • cotfAllowedContentTypes {Array} - Content Types that are available in Content on the Fly,
  • allowedContentTypes {Array} - Content Types that are available in other UDW tabs,
  • cotfPreselectedLocation {Number} - Location that is preselected in Content on the Fly,
  • cotfAllowedLocations {Array} - Locations that are available in Content on the Fly

The following props are deprecated:

  • cotfForcedLanguage {String} - language code. When set, Content on the Fly is locked on this language.
  • languages and contentTypes are lists of languages and Content Types in the system, read from the application config.
  • onlyContentOnTheFly {Boolean} - when true, only Content on the Fly is shown in the Universal Discovery Widget (UDW). Default value: false.

Configuration

You can configure Universal Discovery module in universal_discovery_widget.yml file. There you can set e.g. visible tabs, allowed Content Types, search limits etc.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
system:
    <siteaccess|siteaccess_group>:
        universal_discovery_widget_module:
            configuration:
                default:
                    visible_tabs: [browse, search, bookmarks]
                    allowed_content_types: []
                    search:
                        results_per_page: 10
                        limit: 50

UDW configuration is SiteAccess-aware. For each defined SiteAccess, you need to be able to use the same configuration tree in order to define SiteAccess-specific config. These settings need to be mapped to SiteAccess-aware internal parameters that you can retrieve via the ConfigResolver. For more information on ConfigResolver, see eZ Platform dynamic configuration basics.

Adding new configuration

UDW configuration can change dynamically depending on occurring events. It can be used e.g. for defining which content should be exposed to a user after logging in.

By default only one element from configuration file is applied to Universal Discovery module. You can modify it dynamically by passing context to generate configuration based on a specific event. This context event is caught by event listener ConfigResolveEvent::NAME before the original configuration is used. Depending on what additional parameters are provided, original or event-specific configuration is applied.

In the example below my_custom_udw is used as a base configuration element for the following steps:

1
2
3
4
5
6
7
ezpublish:
    system:
        <siteaccess|siteaccess_group>:
            universal_discovery_widget_module:
                configuration:
                    my_custom_udw:
                        multiple: false
Adding new configuration to a button

In the ez_udw_config Twig helper define a specific part of YAML configuration that will be used to render the Content Browser. You can find Twig helper in your button template. In the example below, a key is pointing to my_custom_udw configuration and has additional parameter johndoe.

1
2
3
4
5
6
7
<button class="btn btn-primary open-my-custom-udw" data-udw-config="{{
    ez_udw_config('my_custom_udw', {
        'some_contextual_parameter': 'johndoe'
    }
) }}">
    Open My UDW
</button>
Additional parameters

If an event listener catches additional parameters passed with context, it will use a configuration specified for it in the event subscriber.

In the example below the johndoe parameter enables the user to choose multiple items from a Browser window by changing multiple: false from my_custom_udw configuration to multiple: true.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class JohnDoeCanSelectMore implements EventSubscriberInterface
{
    private const CONFIGURATION_NAME = 'my_custom_udw';

    /**
     * Returns an array of event names this subscriber wants to listen to.
     *
     * @return array The event names to listen to
     */
    public static function getSubscribedEvents()
    {
        return [
            ConfigResolveEvent::NAME => 'onUdwConfigResolve',
        ];
    }

    /**
     * @param \EzSystems\EzPlatformAdminUi\UniversalDiscovery\Event\ConfigResolveEvent $event
     */
    public function onUdwConfigResolve(ConfigResolveEvent $event)
    {
        if ($event->getConfigName !== self::CONFIGURATION_NAME) {
            return;
        }

        $config = $event->getConfig();
        $context = $event->getContext();

        if (isset($context['some_contextual_parameter'])) {
            if ($context['some_contextual_parameter'] === 'johndoe') {
                $config['multiple'] = true;
            }
        }

        $event->setConfig($config);
    }
}

For more information follow Symfony Doctrine Event Listeners and Subscribers tutorial.

Sub-items List

The Sub-items List module is meant to be used as a part of the editorial interface of eZ Platform. It provides an interface for listing the Sub-items of any Location.

Caution

If you want to load the Sub-items module, you need to load the JS code for it in your view, as it is not available by default.

How to use it?

With vanilla JS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const containerNode = document.querySelector('#sub-items-container');

    ReactDOM.render(
        React.createElement(eZ.modules.SubItems, {
            parentLocationId: { Number },
            restInfo: {
                token: { String },
                siteaccess: { String }
            }
        }),
        containerNode
    );

With JSX:

1
2
3
4
5
6
7
8
9
const attrs = {
    parentLocationId: {Number},
    restInfo: {
        token: {String},
        siteaccess: {String}
    }
};

<SubItemsModule {...attrs}/>

Properties list

The <SubItemsModule /> module can handle additional properties. There are 2 types of properties: required and optional. All of them are listed below.

Required props

Without all the following properties the Sub-items module will not work.

  • parentLocationId {Number} - parent location ID.
  • restInfo {Object} - backend config object:
    • token {String} - CSRF token,
    • siteaccess {String} - SiteAccess identifier.
  • handleEditItem {Function} - callback to handle edit content action.
  • generateLink {Function} - callback to handle view content action.

Optional properties

Optionally, Sub-items module can take a following list of props:

  • loadContentInfo {Function} - loads content items info. Takes 2 params:
    • contentIds {Array} - list of content IDs
    • callback {Function} - a callback invoked when content info is loaded
  • loadContentTypes {Function} - loads content types. Takes one param:
    • callback {Function} - callback invoked when content types are loaded
  • loadLocation {Function} - loads location. Takes 4 params:
    • restInfo {Object} - REST info params:
      • token {String} - the user token
      • siteaccess {String} - the current SiteAccess
    • queryConfig {Object} - query config:
      • locationId {Number} - location ID
      • limit {Number} - content item limit
      • offset {Number} - items offset
      • sortClauses {Object} - the sort clauses, e.g. {LocationPriority: 'ascending'}
    • callback {Function} - callback invoked when location is loaded
  • updateLocationPriority - updates item location priority. Takes 2 params:
    • params {Object} - parameters hash containing:
      • priority {Number} - priority value
      • location {String} - REST location id
      • token {String} - CSRF token
      • siteaccess {String} - SiteAccess identifier
    • callback {Function} - callback invoked when content location priority is updated
  • activeView {String} - active list view identifier
  • extraActions {Array} - list of extra actions. Each action is an object containing:
    • component {Element} - React component class
    • attrs {Object} - additional component properties
  • items {Array} - list of location sub items
  • limit {Number} - items limit count
  • offset {Number} - items limit offset
  • labels {Object} - list of module labels, see sub.items.module.js for details. Contains definitions for sub components:
    • subItems {Object} - list of sub items module labels
    • tableView {Object} - list of table view component labels
    • tableViewItem {Object} - list of table item view component labels
    • loadMore {Object} - list of load more component labels
    • gridViewItem {Object} - list of grid item view component labels

Multi-file Upload

The Multi-file Upload module is meant to be used as a part of editorial interface of eZ Platform. It provides an interface to publish content based on dropped files while uploading them in the interface.

Caution

If you want to load the Multi-file Upload module, you need to load the JS code for it in your view, as it is not available by default.

How to use it?

With vanilla JS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
React.createElement(eZ.modules.MultiFileUpload, {
    onAfterUpload: {Function},
    adminUiConfig: {
        multiFileUpload: {
            defaultMappings: [{
                contentTypeIdentifier: {String},
                contentFieldIdentifier: {String},
                contentNameIdentifier: {String},
                mimeTypes: [{String}, {String}, ...]
            }],
            fallbackContentType: {
                contentTypeIdentifier: {String},
                contentFieldIdentifier: {String},
                contentNameIdentifier: {String}
            },
            locationMappings: [{Object}],
            maxFileSize: {Number}
        },
        token: {String},
        siteaccess: {String}
    },
    parentInfo: {
        contentTypeIdentifier: {String},
        contentTypeId: {Number},
        locationPath: {String},
        language: {String}
    }
});

With JSX:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const attrs = {
    onAfterUpload: {Function},
    adminUiConfig: {
        multiFileUpload: {
            defaultMappings: [{
                contentTypeIdentifier: {String},
                contentFieldIdentifier: {String},
                contentNameIdentifier: {String},
                mimeTypes: [{String}, {String}, ...]
            }],
            fallbackContentType: {
                contentTypeIdentifier: {String},
                contentFieldIdentifier: {String},
                contentNameIdentifier: {String}
            },
            locationMappings: [{Object}],
            maxFileSize: {Number}
        },
        token: {String},
        siteaccess: {String}
    },
    parentInfo: {
        contentTypeIdentifier: {String},
        contentTypeId: {Number},
        locationPath: {String},
        language: {String}
    }
};

<MultiFileUploadModule {...attrs}/>

Properties list

The <MultiFileUpload /> module can handle additional properties. There are 2 types of properties: required and optional. All of them are listed below.

Required properties

Without all the following properties the Multi-file Upload will not work.

  • onAfterUpload {Function} - a callback to be invoked just after a file has been uploaded
  • adminUiConfig {Object} - UI config object. It should keep the following structure:
    • multiFileUpload {Object} - multi file upload module config:
      • defaultMappings {Array} - a list of file type to content type mappings Sample mapping be an object and should follow the convention:
        • contentTypeIdentifier {String} - Content Type identifier
        • contentFieldIdentifier {String} - Content field identifier
        • nameFieldIdentifier {String} - name field identifier
        • mimeTypes {Array} - a list of file typers assigned to a specific content type
      • fallbackContentType {Object} - a fallback content type definition. Should contain the following info:
        • contentTypeIdentifier {String} - Content Type identifier
        • contentFieldIdentifier {String} - Content Field identifier
        • nameFieldIdentifier {String} - name Field identifier
      • locationMappings {Array} - list of file type to content type mappings based on a location identifier
      • maxFileSize {Number} - maximum file size allowed for uploading. It's a number of bytes
    • token {String} - CSRF token
    • siteaccess {String} - SiteAccess identifier
  • parentInfo {Object} - parent location meta information:
    • contentTypeIdentifier {String} - Content Type identifier
    • contentTypeId {Number} - Content Type id
    • locationPath {String} - location path string
    • language {String} - language code identifier

Optional properties

Optionally, the Multi-file Upload module can take a following list of props:

  • checkCanUpload {Function} - checks whether am uploaded file can be uploaded. The callback takes 4 params:
    • file {File} - file object,
    • parentInfo {Object} - parent location meta information,
    • config {Object} - Multi-file Upload module config,
    • callbacks {Object} - error callbacks list: fileTypeNotAllowedCallback and fileSizeNotAllowedCallback.
  • createFileStruct {Function} - a function that creates a ContentCreate struct. The function takes 2 params:
    • file {File} - file object,
    • params {Object} - params hash containing: parentInfo and adminUiConfig stored under the config key.
  • deleteFile {Function} - a function deleting Content created from a given file. It takes 3 params:
    • systemInfo {Object} - hash containing information about CSRF token and siteaccess: token and siteaccess,
    • struct {Object} - Content struct,
    • callback {Function} - content deleted callback.
  • onPopupClose {Function} - function invoked when closing a Multi-file Upload popup. It takes one param: itemsUploaded - the list of uploaded items.
  • publishFile {Function} - publishes an uploaded file-based content item. Takes 3 params:
    • data {Object} - an object containing information about:
      • struct {Object} - the ContentCreate struct (),
      • token {String} - CSRF token,
      • siteaccess {String} - SiteAccess identifier,
    • requestEventHandlers {Object} - a list of upload event handlers:
      • onloadstart {Function} - on load start callback,
      • upload {Object} - file upload events:
        • onabort {Function} - on abort callback,
        • onload {Function} - on load callback,
        • onprogress {Function} - on progress callback,
        • ontimeout {Function} - on timeout callback.
    • callback {Function} - a callback invoked when an uploaded file-based content has been published.