How to deal with code specific to a customer

In the API

In the API, all codes specific to a customer are grouped into chsdi/customers. This folder is organized like this:

  • to create the module.

  • models/ to put models specific to a customer. They should only be used in chsdi/customers/views/.

  • utils/ for utilities. By default, it contains a file in which all search keywords are stored. See the section about keywords in the API page to learn more how search keywords are handled.

  • views/ for customer specific views. Create a file per view. When you add a view, update the register_customer_view function from in order for the view to be registered by Pyramid. This should look like:

    def register_customer_view(config):
        config.add_route('<route_name>', '/{portal}/<route_name>')

In the frontend

Plugin System

Plugins are a way to have code specific to a customer without changing the rest of the code.

To create a plugin, create a javascript file in geo-front3/plugins/. The file must be named like this: <plugin_name>.js. In this file, put the code you need in your plugin (probably a function). For instance:

function test() {
    console.log('I am a plugin');

While writing the code of your plugin, keep in mind that it will be included in an object in the template below.

  This is a generated file which will contain the code for all activated plugins.
// We use gaGlobalOptions but we don't explicitely require
// goog.require('ga'); because closure-compiler will crash due to circular
// dependencies.

(function() {
  angular.module('gf3').factory('gf3Plugins', function($http, gaGlobalOptions) {
      var plugins  = {};
{% for plugin_name in activated_plugins %}
  {# We can be building for a branch without the plugins. In this case, we avoid syntax error by not including the code #}
  {% if available_plugins[plugin_name] %}
  plugins['${plugin_name}'] = ${available_plugins[plugin_name]}
  {% endif %}
{% endfor %}

  return plugins;

See the section about plugins in the user manual to know how to active them.

They can the be used with the gf3Plugins service. For instance, to use a plugin named test plugin, use gf3Plugins.test(). The arguments and behavior of the plugin depends on its definition.

To test if a plugin is enabled, test gf3Plugins.plugin_name !== undefined.


In geo-front3/src/components/features/FeaturesTemplatesService.js, we defined how each features will be rendered. Templates available for all customers must be in the defaultTemplates object from the devel branch. You can set customer specific templates in the customerTemplates object on their branch. Each of these object must follow this rule:

  • The key will be how the name of the column must end
  • The content must be the HTML used to render the cell within a string (so it is valid javascript).

For instance to render a cell whose name ends in _url as a clickable link, we need this HTML:

    <a target="_blank" href="{{cellValue}}" ng-if="cellValue">
        {{ cellValue | translate  }}

We will use this code:

defaultTemplates['url'] = '<div>' +
        '<a target="_blank" href="{{cellValue}}" ng-if="cellValue">' +
        '{{cellValue | translate  }}</a></div>';

The template will then be used in geo-front3/src/components/features/FeaturesService.js as the template to render the cell in Ultimate Data Table.

See the relevant section of the user documentation to see what is handled by default.