Content Picker

Oracle Content and Experience supports two mechanisms for integration so users can browse and select content and assets to bring into Oracle Content and Experience.

The content picker for a content connector can be either the common content picker or a custom one:

  • The common content picker is provided by Oracle Content and Experience.

    With the generic common picker, Oracle Content and Experience provides a basic framework and capabilities to build content browsing and selection. This works seamlessly in conjunction with the Connector Framework SDK and the APIs defined.

  • The custom picker needs to be built by the content connector and can be built using any JS technology.

    The custom picker is typically used in cases where the content connector builds its own experience for accessing content in the remote store. Some stores have their own native pickers, which the content connector could reuse for integrating with the asset repository; for example, Google Drive, Microsoft OneDrive, and Dropbox. Additionally, the content connector can develop its own picker UI following the predefined interfaces and callback mechanisms prescribed by Oracle Content and Experience.

If the content connector uses the common picker, then the connector needs to define pickerType in the server implementation:

intradoc.connectorcommon.server.ServerResource implementation

serverInfo.pickerType = PickerType.COMMON;

The content connector also needs to implement the intradoc.connectorcommon.server.FilesystemResource interface. The implementation needs to adhere to following guidelines in its filesystem REST implementation:

  1. The content connector must append "fFolderGUID:" in uri, parentUri for each folder in the response of fileSystem.

  2. A few fields are mandatory for every folder and file to be set in FileSystemResource for the common UI to work without any issues: uri, parentUri, and name. If parentUri is not applicable, then it can be set to fFolderGUID:null.

  3. You must know the size of the result set being returned up front; that is, totalItemsCount needs to be set.

Use the Common UI

If the content connector uses the common picker, then it needs to define pickerType in the eserver implementation:

intradoc.connectorcommon.server.ServerResource implementation

serverInfo.pickerType = PickerType.COMMON;

The content connector also needs to implement the intradoc.connectorcommon.server.FilesystemResource interface. The implementation needs to adhere to following guidelines in its filesystem REST implementation:

  1. The content connector must append "fFolderGUID:" in uri, parentUri for each folder in the response of fileSystem.

  2. A few fields are mandatory for every folder and file to be set in FileSystemResource for the common UI to work without any issues: uri, parentUri, and name. If parentUri is not applicable, then it can be set to fFolderGUID:null.

  3. You must know the size of the result set being returned up front; that is, totalItemsCount needs to be set.

The common UI supports customizations, which can be defined in the connector configuration. The following table describes the additional settings that can be passed in a connector's ServerResource implementation.

Property Values Description
hide_breadcrumbs

true

false (default)

To show or hide breadcrumbs
nextPrevPaginationEnabled

true

false (default)

To show page with next and prev buttons for pagination

For numbered pagination, don't set this property to true.

CommonPickerShowVideoView

true

false (default)

Card layout will be displayed, with each card having the following items:
  • Iframe with video link
  • Description of video
  • Channel name
CommonPickerShowImageView

true

false (default)

Card layout will be displayed, with each card having the following items:
  • Image thumbnail with link to open full image in next tab
  • Photographer URL
  • Name of image
  • mimeType
show_termsOfUse

true

false (default)

To show the terms and condition link
termsOfUse_link String

If the show_termsOfUse property is true, then the link for terms and conditions is specified using this property.

show_privacyPolicy

true

false (default)

To show the privacy policy link
privacyPolicy_link String

If the show_privacyPolicy property is true, then the link for the privacy policy is specified using this property.

show_view_action

true

false (default)

To show the view action on select of item
page_size

String

50 (default)

The size of one page. If results are more than the given page size, then the results will be paginated.

The settings are in the form of a map that needs to be set on ServerInfo. An example follows:

    //Add UI Settings for the connector that will be read by the common 
picker 
    Map<String,Object> additionalSettingsMap = new HashMap<String,Object>(); 
    Map<String,String> uiSettingsMap = new HashMap<String,String>(); 
    uiSettingsMap.put("CommonPickerShowImageView", "true"); 
    uiSettingsMap.put("hide_breadcrumbs", "true"); 
    uiSettingsMap.put("show_termsOfUse","true"); 
    uiSettingsMap.put("show_privacyPolicy","true"); 
    uiSettingsMap.put("termsOfUse_link","https://unsplash.com/terms"); 
    uiSettingsMap.put("privacyPolicy_link","https://unsplash.com/privacy"); 
    uiSettingsMap.put("show_view_action","true"); 
    additionalSettingsMap.put("UISettings", uiSettingsMap); 
    serverInfo.addtionalSettings = additionalSettingsMap; 

The resulting JSON structure follows:


    "addtionalSettings": { 
        "UISettings": { 
            "hide_breadcrumbs": "true", 
            "show_view_action": "true", 
            "CommonPickerShowImageView": "true", 
            "termsOfUse_link": "https://unsplash.com/terms", 
            "privacyPolicy_link": "https://unsplash.com/privacy", 
            "show_privacyPolicy": "true", 
            "show_termsOfUse": "true", 
            "page_size": "30" 
        } 
    } 

Use a Custom UI

A content connector can implement a custom UI for its picker. This can be built using any JS technology. However, it needs to invoke some predefined methods in Oracle Content and Experience to obtain connector configuration and to pass back selections. The custom picker can be built to expose its own OK and Cancel buttons, in which case it needs to invoke the appropriate handlers. If the picker doesn't expose its own OK and Cancel buttons, Oracle Content and Experience will provide this.

The pickerType needs to be defined as CUSTOM in the server implementation:

intradoc.connectorcommon.server.ServerResource implementation

serverInfo.pickerType = PickerType.CUSTOM;

The custom implementation needs to include the following JS file in its library:

oracle-oce-custompicker.js

/*global window:true*/
(function() {
  'use strict';
 
  var name = window.name; // name set on iframe element to uniquely identify the instance
  var receiver = window.opener || window.parent;
  var origin = "*";
  function _postMessage(msg) {
    msg.name = name;
    receiver.postMessage(msg, origin);
  }
 
  var namespace = "OCE"; //todo: allow passing in data attribute
  if (!window[namespace]) {
    window[namespace] = {};
  }
  var OCE = window[namespace];
 
  if (!OCE.CustomPicker) {
 
    OCE.CustomPicker = {
 
      selection: [],
 
      addItem: function(id, name, type, size) {
        var item = {id: id, name: name, type: type, size: size};
        this.selection.push(item);
        this.onChange();
      },
 
      removeItem: function(id) {
        this.selection = this.selection.filter(function(item) {
          return item.id !== id;
        });
        this.onChange();
      },
 
      onInit: function(cbInit) {
        var msg = {
          message: 'init',
          needAuthToken: true
        };
        _postMessage(msg);
        this.messageListener = this.onPostMessage.bind(this);
        window.addEventListener('message', this.messageListener, false);
        this.cbInit = cbInit;
      },
 
      onClose: function() {
        window.removeEventListener('message', this.messageListener, false);
      },
 
      onPostMessage: function(event) {
        if (event.data && event.data.message === "init") {
          if (this.cbInit) {
            this.cbInit(event.data);
          }
        }
      },
 
      onChange: function() {
        var msg = {
          message: 'change',
          selection: this.selection
        };
        _postMessage(msg);
      },
 
      onOk: function(selection) {
        selection = selection || this.selection;
        var msg = {
          message: 'ok',
          selection: this.selection
        };
        _postMessage(msg);
      },
 
      onCancel: function() {
        var msg = {
          message: 'cancel'
        };
        _postMessage(msg);
      }
    };
  }
 
})();

This JS file needs to be packaged in a content connector.

This library follows the JS postMessaging paradigm to pass information. The following methods are of interest.

onInit

The custom picker needs to invoke this method during its initialization. This is where the custom picker can get connector configuration information, like client ID and access token. The attributes defined in the connector configuration (/rest/api/v1/server) are passed via this method.

OCE.CustomPicker.onInit(function(data) {
    {
        if (data != null) {
            self.clientId = data.ClientID;
 
            //If connector uses OAuth
            self.AccessToken = data.AccessToken;
             
            //If connector uses BASIC auth
            self.user = data.UserName;
            self.password = Base64.decode(data.UserPwd);
    }
 
        //Use client id and access token to fetch data from back end.
    }
})

onOk

If the custom picker exposes its own OK button, then it needs to invoke this method to pass back the event to Oracle Content and Experience.

function pickerCallback(data) {
  if (data[google.picker.Response.ACTION] === google.picker.Action.PICKED) {
    data[google.picker.Response.DOCUMENTS].forEach(function(doc) {
      OCE.CustomPicker.addItem(doc.id, doc.name, "file", doc.sizeBytes);
    });
    OCE.CustomPicker.onOk();
  }
  else if (data[google.picker.Response.ACTION] === google.picker.Action.CANCEL) {
    OCE.CustomPicker.onCancel();
  }
}

onCancel

If the custom picker exposes its own Cancel button, then it needs to invoke this method to pass back the event to Oracle Content and Experience, like the onOk method does for the OK button in the preceding snippet.

addItem

This method needs to be invoked to pass back selections from the custom picker to Oracle Content and Experience so that it displays the list of selected items in the Add to repository dialog. The IDs passed here are then used to fetch content with /rest/api/v1/content while adding an item to the asset repository.

addImage(selectedImages: Image[]) {
    selectedImages.forEach(o => {
        var name = "PexelsImages_" + o.uri;
        OCE.CustomPicker.addItem(o.uri, name, o.thumbnail, o.size);
    });
}

removeItem

This method needs to be invoked when an item is unselected from a custom picker so that the list maintained by Oracle Content and Experience is up to date. The final list is shown in the Add to repository dialog. The ID passed here is the same as the ID passed in the addItem call.
removeImage(image: Image) {
    OCE.CustomPicker.removeItem(image);
}

Package the custom picker in the connector. While registering the content connector, specify the following values:

  1. Custom Picker URL: Such as http://host:port/pexels-picker/web (This is the custom picker packaged in the content connector.)

  2. Custom Picker uses its own OK/Cancel buttons: Leave it unchecked. (This indicates that you want Oracle Content and Experience to embed your picker in their dialog.)

    If the custom picker implements its own OK and Cancel buttons, then check this.