Overview

The configuration service evaluates a series of conditional configuration blocks and determines which blocks to keep in composing a final configuration document for the user interface. The configuration document consists of blocks that define JSON structures that are to be merged into a final JSON configuration that powers the user interface.

The configuration service executes two phases - evaluate and merge. It essentially looks like this:

[block1]   -->            --> [config1]  -->
[block2]   -->          
[block3]   -->  evaluate                      merge  --> [final configuration]
[block4]   -->            --> [config4]  -->
[block5]   -->            --> [config5]  -->

In the evaluate phase, the conditional blocks are evaluated to determine whether they should be kept. An evaluator is used and the current runtime state is matched against the given condition. If true, the block portion is carried forward.

In the merge phase, the carried forward blocks are merged into a final configuration document.

Each conditional block takes on a structure like this:

{
    "evaluator": "{evaluatorId}",
    "condition": {condition},
    "config": {
        ...
    }
}

The config section consists of any arbitrary JSON. Upon merge, the config section is merged together with any other config sections. The merge logic is pretty simple.

  • Objects are composed together key by key. Keys that already exist are overwritten by later config entries. null entries result in key removal.
  • Arrays are additive and append on merge
  • All other types are overwrite in nature. The last config entry with the key wins. null removes the key.

One the merge completes, a final configuration JSON document is assembled. This document is for all intents and purposes normalized. The user interface looks to this document to tell it how to render and what to do. It defines things like:

  • What actions to include on the Document Actions page
  • What buttons to include in the Selection... dropdown when navigating documents
  • What menu options to show on the left-hand side when viewing a project
  • What dashlets to show on the platform dashlets page

All of these decisions take into account the context of what is being looked at (i.e. what URI is being looked at and what observables are populated), who is looking at it (i.e. who is logged in) and what their authorities and permissions are. Evaluators play an important role here. Each evaluator is essentially a small bit of very fast executing JavaScript that is responsible for making very quick decisions regarding the above.

The Config Service is built to be fast. It can consider a very large set of blocks and deduce a normalized configuration in a matter of milliseconds.

Additional Settings

In addition to the base properties of evaluator, condition and config, you can also specify the following:

  • replace indicates whether to replace instead of merge (true or false)

Example

To get a sense, imagine we have three config blocks like this:

Block #1

{
    "evaluator": "document-is-file",
    "config": {
        "document-actions": [{
            "id": "custom-preview-in-website"
        }]
    }
}

Block #2

{
    "evaluator": "document-has-type",
    "condition": "my:article",
    "config": {
        "document-actions": [{
            "id": "custom-copy-text-to-clipboard"
        }]
    }
}

Block #3

{
    "evaluator": "and",
    "condition": [{
        "evaluator": "document-is-file"
    }, {
        "evaluator": "document-has-attachment",
        "condition": "scan"
    }]
    "config": {
        "document-actions": [{
            "id": "custom-download-scan"
        }]
    }
}

Each of these blocks provides conditions by which the document-actions array will be constructed. If all three were to evaluate to true, the resulting config document would look like this:

{
    "config": {
        "document-actions": [{
            "id": "custom-preview-in-website"
        }, {
            "id": "custom-copy-text-to-clipboard"
        }, {
            "id": "custom-download-scan"
        }]
    }
}

However, all three conditions will evaluate separately and will only be true depending on where the user is, who they are and what they're working with.

  • If the user were looking at a file, block #1 would be included since it has a document-is-file evaluator. Block #2 might be included if the document is of type my:article. And block #3 would only be included if the document were both a file and also had a scan attachment.

  • If the user were looking at a folder, only block #2 has a chance of being shown. And it would only show if the folder had the my:article node type. Which is possible, depending on how you model your content.

This is a contrived example but one which demonstrates how configuration blocks assemble based on runtime information about what is being viewed. In this case, the document-actions configuration changes. This configuration drives what menu options appear in the Cloud CMS user interface under the Actions dropdown for a file or a folder.