Topics on this page

BriteCore UI plugins overview

Note: This refers to software in development and is subject to change.

UI plugins allow you to add your own functionality to BriteCore without having to introduce any changes into BriteCore’s codebase. To do so, you need to:

  1. Know of a plugin slot that supports your functionality.
  2. Write a plugin using the BriteCore provided JavaScript library.
  3. Host your plugin in a publicly accessible location.
  4. Register the plugin (support is in development).

Plugin slots

Plugin slots are predefined sections of BriteCore’s UI where third parties can connect their plugins.

For example, BriteCore provides a plugin slot called britequote:risk-edit::bottom-row:button-row, which lets users add custom action buttons into the quoting form.

Each plugin slot type may have instances spread in multiple locations in the UI; the standard format for naming is {product}:{page}:{location}:{slot-type}. For example, the button-row slot could be available in different places across the system:

  • britequote:risk-edit:bottom-row:button-row

Each plugin slot can be placed in multiple locations on a given page. The plugin slot name property controls in which part of the page a plugin slot should be available. For instance, the britequote:risk-edit:bottom-row:button-row plugin slot is placed in the sidebar location of the quoting form.

Plugin slots reference

BriteCore UI offers slots in its UI where developers can extend the functionality of the UI.

button-row

The button-row slot allows you to plug in action buttons on various pages. The slot is going to render the buttons that the plugin requested during its initialization and will call the plugin callbacks upon clicking the button.

Details
  • Slot type: button-row.
  • Slot instances in the UI: britequote:risk-edit:bottom-row:button-row and britequote:risk-edit:sidebar:button-row
  • Interface: requires an object upon initialization

Example initialization object:

View code
{  buttons: [{    
       text: 'Capitalize',    
       callback: capitalizeFields  
}]
}

The callback function must be defined in your plugin file and it will be called whenever the button is clicked.

The button-row slot type allows developers to write plugins to read data from a page, process this data and send the results back to the page.

Such buttons can get the input data in a context object and do any computations, third party services lookups, validations, etc. As a result, they can emit events back to BriteCore UI with new data. Then, the latter can apply the changes on the data used by the page.

This button-row slot type is currently available in two locations:

  1. britequote:risk-edit:sidebar:button-row
  2. britequote:risk-edit:bottom-row:button-row

Plugins connected to this slot will receive the following parameters in their context input object:

  • riskType
  • riskTypes
  • riskTypeState
  • riskState
  • config
  • pluginConfig
  • quote
  • rootRiskQuote

Plugins connected to this slot are expected to emit the following events up to BriteCore-UI:

  • update-risk
  • create-and-update-risk
  • attachFileToQuote
  • displayErrors
  • displayMessage
  • showLodaingIndicator
  • create-and-update-risk

Write a plugin

JavaScript Library

BriteCore provides a beta JavaScript library you can use to build your plugins.

Add the script tag to your plugin HTML file:

View code

<script src="https://d1zol2vqugn1g2.cloudfront.net/britecore-ui-plugins.js">
</script>

Then, you can use the BriteCorePlugin helper so your plugin can communicate with BriteCore:

View code
let plugin = new BriteCorePlugin('Plugin Name')
  plugin.initialize({
    'slot-name': slotInput
  })

The slotInput object will vary upon the plugin slot you want to connect to.

Example: the button-row slot with a single button:

View code
let plugin = new BriteCorePlugin('Plugin Name')
  plugin.initialize({
    'button-row': {
      buttons: [{
        text: 'Lookup',
        callback: lookupDetails,
        visible: true,
        enabled: false,
      }]
    }
  })

Hosting

Each plugin is a HTML document rendered in a hidden iframe. BriteCore’s UI queries the plugins available and renders any plugin on the specified pages.

Since BriteCore’s UI runs in a browser, the request for the plugin must occur without credentials to a publicly available location, or BriteCore must host the plugin placing the HTML file behind our authentication.

Plugins often query other restricted resources. If the plugin is served from a domain that also has access to the credentials, it’s possible to use those.

Example:

ABC Insurance Company allows logged in agents to quote. Upon logging in, ABC Insurance stores an access token in the local storage of the browser. A plugin served from https://www.ABCInsurance.com can access the local storage for that domain and use the access token to make further requests.

Integrating

A central plugin registry provides the following data to BriteCore’s UI:

View code
{
    "name": "vendor",
    "base_url": "https://www.example.com",
    "plugin_slots": [
        {
            "slot_name": "britequote:risk-edit:sidebar:button-row",
            "plugin_file_path": "/my/plugin",
            "execution_trigger": None,
            "fields_to_watch": [],
        }
    ],
}

The registry is currently within the source code, with plans to provide an API to manage the registry.

Example: Write a new BriteCore plugin to capitalize fields in the quoting form

Writing a new plugin will depend on which type of plugin you want to create. There must be an existent plugin slot that:

  1. Is in the UI location where you want load your plugin.
  2. Allows for the behavior you want your plugin to have.

Use case: the Capitalizer plugin

BriteCore UI provides a slot that allows a third party plugin to render an action button to execute actions on a quoting form: the button-row slot.

Create the plugin HTML file

The contract that a plugin has to implement to connect to the button-row slot requires you to provide a label for the button and a callback function capable of reading the form fields from a context object and sending a JSON Patch object with the changes you want to make to the form data.

Once you load the JavaScript library in your plugin HTML file, you can able to use the BriteCorePlugin helper class to connect your plugin to BriteCore via the initialize method.

This is how the Capitalizer plugin would look like:

View code
<html>
  <head>
    <script src='https://d1zol2vqugn1g2.cloudfront.net/britecore-ui-plugins.js'></script>

    <script>
      const PLUGIN_NAME = 'Capitalizer'
      function capitalize(thing) {
        return thing.replace(/^\w/, c => c.toUpperCase())
      }
      
      function capitalizeFields (context) {
        let fa = context.field_answers
        const jsonPatch = [
          {op: 'replace', path: '/field_answers/make', value: capitalize(fa.make)},
          {op: 'replace', path: '/field_answers/model', value: capitalize(fa.model)},
        ]
        this.emit(PLUGIN_NAME + '-update-risk', jsonPatch) // this namespaces the event and is important
      }

      let plugin = new BriteCorePlugin(PLUGIN_NAME)
      plugin.initialize({
        'button-row': {
          buttons: [{
            text: 'Capitalize',
            callback: capitalizeFields,
            visible: true,
            enabled: true,
          }]
        }
      })
    </script>
  </head>
</html>

We are initializing the plugin with an object where the keys are the slots that our plugin needs to interact with and the values are the objects expected during the slot initialization.

We are providing an array of objects containing a label, a callback function to handle the form data  and send the JSON Patch object back, and two booleans for visibility and an enabled state.

Upon load, the BriteCorePlugin object will start the connection to the plugin slot and, once that is done, it will emit an initialization event to the slot, sending along the object with the buttons it wants to be rendered. The slot will be waiting for such an event and will render the buttons wherever it is placed.

Object Reference

riskTypes keys and description include:

  • id: Unique risk type ID
  • label: Risk type label
  • name: Risk type name
  • parentRiskTypeId: Risk type ID of parent risk type
  • __typename: Type of entity i.e. RiskType

Example:

View code

[
   {
       "id": "246fcbdc-42e9-4cdc-9783-0efa82cef984",
       "label": "Accident/Violation (5 Year History)",
       "name": "violations",
       "parentRiskTypeId": "e1711652-8450-4492-b965-ed3a016152c3",
       "__typename": "RiskType"
   },
   {
       "id": "e1711652-8450-4492-b965-ed3a016152c3",
       "label": "Driver",
       "name": "drivers",
       "parentRiskTypeId": "6bf23139-95ff-45ed-856e-b079573d851a",
       "__typename": "RiskType"
   },
   {
       "id": "6bf23139-95ff-45ed-856e-b079573d851a",
       "label": "Policy",
       "name": "policy",
       "parentRiskTypeId": null,
       "__typename": "RiskType"
   },
   {
       "id": "3cbccfb0-68e6-4b21-ac18-176c1ea70496",
       "label": "Private Passenger Auto",
       "name": "privatePassengerAutos",
       "parentRiskTypeId": "6bf23139-95ff-45ed-856e-b079573d851a",
       "__typename": "RiskType"
   }
]

riskState keys and descriptions include:

  • id: Unique risk ID.
  • meta: Meta data information e.g. static_id.
  • name: Risk name as calculated via risk_name_template.
  • type: Risk type information e.g. Risk Type name, label and ID.
  • number: Risk number is calculated based on type. It can be used in calculations to know how many risks of a particular type have been added.
  • total_premium: Sum of all enabled items coverages premium.
  • pro_rata: Sum of all enabled Items coverages pro rata.
  • items: Enabled and soft deleted items on risk. If an item contains deleted_at key, this means that the item is soft deleted. This key will only be present for soft deleted items in Endorsement transactions.
  • field_answers: Fields answers for enabled items.
  • detached_answers: Field answers for items which are disabled/unchecked by user. Used later to repopulate associated fields of an item when it gets re-enabled.
  • detached_items: Contains name of items having presence Default or Optional which are removed from risk.
  • field_overrides: Contains replacement properties for fields defined in risk type state depending on the current risk state.
  • item_overrides: Contains replacement properties for items defined in risk type state depending on the current risk state.
  • calculations: Contains resolved shared calculations.
  • rate_tables: Contains resolved rate tables.
  • deleted_at: Contains a datetime string if the risk was soft deleted. This key will only be present for soft deleted risks in Endorsement transactions.
  • children: Array containing child risks, if any.

Example:

View code

{
  "schema_version": "1.3",
  "id": "c26fffcd-7897-4384-98c4-95de6b0902e8",
  "meta": {
    "static_id": "012f3c80-23d5-4b32-bda4-7961b2356002"
  },
  "name": "Vehicle 1",
  "type": {
    "label": "Vehicle",
    "id": "3aa43696-8c18-49d6-8c6d-dc03b5081e98",
    "name": "vehicles"
  },
  "number": 1,
  "total_premium": 54.0,
  "pro_rata": {
    "value": 0.0
  },
  "items": {
    "additionalEquipment": {
      "premium": 45.0,
      "pro_rata": {
        "value": null
      },
      "limits": {
        "perRiskLimit": 100.0,
        "policyAggregateLimit": 500.0
      },
      "deductible": 20.0
    },
    "medicalExpense": {
      "premium": 0.0,
      "pro_rata": {
        "value": 0
      },
      "deleted_at": "2020-07-28T00:00:00+00:00"
    }
  },
  "field_answers": {
    "additionalEquipmentCoverageLimit": "501-1000",
    "vin": "5YJSA1E28HF190648",
    "make": "Tesla",
    "model": "Model S",
    "chosenDriver": ""
  },
  "detached_answers": {
    "towingLimit": "75"
  },
  "detached_items": ["towing"],
  "field_overrides": {
    "chosenDriver": {
      "options": [
        {
          "value": "ef763124-8b7f-4016-ac54-7d07e4adfe70",
          "label": "John Doe"
        }
      ]
    }
  },
  "item_overrides": {
    "towing": {
      "visible": false
    }
  },
  "calculations": {
    "driverFactor": 1.0
  },
  "rate_tables": {
    "towingRateTable": 0
  },
  "deleted_at": null,
  "children": []
}