1. Appendix B: Publication of the client library jars to Maven Central

This is a summary of the steps that were necessary to initially set up the publication of jars to Maven Central. The process to actually publish the jars for each release is detailed in the release process documentation.

Publication process overview
  1. Building and signing the jars

  2. Publishing them to a staging repository where there are validations (e.g. check that the POM contains the required information, validating the signature against the public key)

  3. If the validations pass, release the jar to Maven Central

1.1. Claiming the org.opfab namespace on Maven Central

This is done by logging an issue on the Sonatype JIRA (create an account first). The namespace needs to match a domain that you own (and this will be verified), which is why we had to rename our packages to org.opfab.XXX.

You can then request other users to be granted rights on the namespace as well.

1.2. Creating a GPG key pair

The key pair is generated with GPG2, keeping the default options and using the opfabtech technical account email as contact. The key is further secured with a passphrase.

gpg2 --full-generate-key

gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 3072
Requested keysize is 3072 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 18m
Key expires at Tue 11 Oct 2022 12:38:13 CEST
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: opfabtech
E-mail address: opfabtech@gmail.com
Comment: technical account for the OperatorFabric project
You selected this USER-ID:
    "opfabtech (technical account for the OperatorFabric project) <opfabtech@gmail.com>"

Change (N)ame, (C)omment, (E)-mail or (O)kay/(Q)uit? o
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilise the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key 469E7252B8D25328 marked as ultimately trusted
gpg: directory '/home/guironnetale/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/guironnetale/.gnupg/openpgp-revocs.d/FE0D7AFF9C129CFBBDC18A0B469E7252B8D25328.rev'
public and secret key created and signed.

pub   rsa3072 2021-04-19 [SC] [expires: 2022-10-11]
      FE0D7AFF9C129CFBBDC18A0B469E7252B8D25328
uid                      opfabtech (technical account for the OperatorFabric project) <opfabtech@gmail.com>
sub   rsa3072 2021-04-19 [E] [expires: 2022-10-11]
A standard practice is to have the key expire in 18 months, so I set up a calendar reminder for us to renew it.

1.3. Sharing the signing key

For other developers to be able to sign jars, you need to share both the key pair and the passphrase.

  • Export the key pair to a file

gpg2 --export-secret-keys OPFAB_KEY_ID > key_pair.key

1.4. Publishing the public key

The public key needs to be published to (preferably several) key directories so people wanting to use the signed jars can check the signature against the public key. It is also checked as part of the validations performed on the staging repository.

Our public key was initially published to pool.sks-keyservers.net, which became deprecated (causing the publication to fail), so it was then published to the two servers that the sonatype validations seem to rely on.

For OpenPGP you need to export the public key (and not the key pair) to a file and upload it to their web interface.

gpg2 --export OPFAB_KEY_ID > my_key.pub

For Ubuntu you need to export the public key as ascii-armored ascii and paste the result to their web interface

gpg2 --export --armor OPFAB_KEY_ID
The key can be retrieved from both these servers by searching either for opfabtech@gmail.com or for the key ID.

1.5. Setting up the signing and publication in Gradle

You can’t publish a jar with version "SNAPSHOT" to the Maven staging repositories (you would get a 403 BAD REQUEST), that’s why the Gradle publication task is configured so that if the version ends with "SNAPSHOT", the jars should be published to a local directory (repos/snapshots) rather than to the Maven Central staging repository.

2. Migration Guide from release 3.0.0 to release 3.1.0

2.1. Kafka date format

The signature for sending card dates via Kafka have been changed to better reflect the REST API. Instead of sending the date in seconds since epoch, you can now use the Java Instant object. The following methods are affected:

  • startDate

  • endDate

  • lttd

  • publishDate

  • TimeSpan.setStart

  • TimeSpan.setEnd

For example the following code:

Card card = Card.newBuilder().setStartDate(12345L).build();

becomes:

Card card = Card.newBuilder().setStartDate(Instant.now()).build();

3. Migration Guide from release 3.1.0 to release 3.2.0

3.1. Cache configuration for i18n files

Add the following lines in your nginx.conf to avoid keeping in cache old translation files when migrating opfab

  location /ui/assets/i18n/ {
    add_header Cache-Control "no-cache";
    alias /usr/share/nginx/html/assets/i18n/;
  }

see the reference nginx configuration file : github.com/opfab/operatorfabric-core/blob//config/docker/nginx.conf

3.2. Tag feed filter removal

The feature to filter tags in the feed has been removed. In consequence, you can remove the following parameters in your web-ui.json configuration file:

  • settings.tags.hide

  • settings.infos.hide.tags

4. Migration Guide from release 3.4.0 to release 3.5.0

4.1. Timezone management removal

The feature to manage timeline inside opfab has been removed. In consequence, you can remove the following parameters in your web-ui.json configuration file:

  • i10n.supported.time-zones

  • settings.infos.hide.timezone

4.2. Kafka card format changes

The Kafka message schema has been changed. The single card used to send messages to and receive from Operator Fabric has been split into two cards; one for sending to OpFab and one for receiving messages from OpFab. The CardCommand structure now contains a card (to OpFab) and a responseCard (from OpFab). You will need to change the Kafka listener to get the response card.

For example change

 @KafkaListener
    public void receivedResponseCard(@Payload ConsumerRecord<String, CardCommand> consumerRecord) {
        CardCommand cardCommand = consumerRecord.value();
        Card = cardCommand.getCard();

to

 @KafkaListener
    public void receivedResponseCard(@Payload ConsumerRecord<String, CardCommand> consumerRecord) {
        CardCommand cardCommand = consumerRecord.value();
        ResponseCard = cardCommand.getResponseCard();

4.2.1. Redirect to business application from a card

The templateGateway.redirectToBusinessMenu function to redirect to business application from a card has changed. The third argument of the function is now a url extension that can contain sub paths and/or parameters instead of only parameters.

You will need to change the call adding a '?' character at the beginning of the third argument.

For example change:

templateGateway.redirectToBusinessMenu('myMenu','myEntry','param1=aParam&param2=anotherParam')

to

templateGateway.redirectToBusinessMenu('myMenu','myEntry','?param1=aParam&param2=anotherParam')

5. Migration Guide from release 3.5.0 to release 3.6.0

5.1. Template rendering

Bootstrap library has been migrate to v5.

If you use bootstrap css classes in your templates, it’s strongly recommended checking your template rendering after migration.

Charts library has been upgraded from version 3.2.1 to 3.7.1

If you use charts in your templates, it’s strongly recommended checking your template rendering after migration.

5.2. Mongo data migration steps

This section outlines the necessary steps to migrate existing data.

If you use response card feature, you need to perform these steps before starting up the OperatorFabric instance to avoid displaying wrong data in archives page.
  1. Backup your existing Mongo data.

  2. Run the following scripts in the mongo shell to update the value of the new field deletionDate for archived cards:

    db.archivedCards.updateMany(
    {"deletionDate": {"$exists": false}},
    {"$set": {"deletionDate": new ISODate("1970-01-01T00:00:00Z")}}
    )

5.3. About screen

You do not need anymore to precise opfab version in web-ui.json to see it on about screen. So you need to remove the corresponding line. For example :

      "operatorfabric": {
        "name": "OperatorFabric",
        "rank": 0,
        "version": "2.5.0.RELEASE"
      }

5.4. Deprecated feature

5.4.1. Method templateGateway.getSpecificCardInformation()

Implementation of method templateGateway.getSpecificCardInformation() in usercard templates is now deprecated, replace it by usercardTemplateGateway.getSpecificCardInformation(). It is just a naming change, the behavior is the same.

5.4.2. Restrict recipient dropdown list for user

Using "recipientList" in state definition (in config.json) is now deprecated

If you use "recipientList" to restrict the list of recipients shown to user, replace it with code in template as in the following example :

    usercardTemplateGateway.setDropdownEntityRecipientList([
            {"id": "ENTITY_FR", "levels": [0,1]},
            {"id": "IT_SUPERVISOR_ENTITY"}
        ]);

5.4.3. Set the list of recipients

Using "recipientList" in state definition (in config.json) is now deprecated

If you use "recipientList" to set the list of recipients, provide now the list of recipients when returning the card object in usercardTemplateGateway.getSpecificCardInformation() in the field entityRecipients.

Example:

    usercardTemplateGateway.getSpecificCardInformation = function () {
        const message = document.getElementById('message').value;
        const card = {
          summary : {key : "message.summary"},
          title : {key : "message.title"},
          entityRecipients: ["ENTITY_FR","IT_SUPERVISOR_ENTITY"],
          data : {message: message}
        };
        if (message.length<1) return { valid:false , errorMsg:'You must provide a message'}
        return {
            valid: true,
            card: card
        };

6. Migration Guide from release 3.6.0 to release 3.7.0

6.1. Docker images names changed

From version 3.7.0 the docker names of the former "business services" are changed. Here are there old names and the new ones.

Old docker name New docker name

lfeoperatorfabric/of-cards-consultation-business-service:3.6.0.RELEASE

lfeoperatorfabric/of-cards-consultation-service:3.7.0.RELEASE

lfeoperatorfabric/of-cards-publication-business-service:3.6.0.RELEASE

lfeoperatorfabric/of-cards-publication-service:3.7.0.RELEASE

lfeoperatorfabric/of-users-business-service:3.6.0.RELEASE

lfeoperatorfabric/of-users-service:3.7.0.RELEASE

lfeoperatorfabric/of-businessconfig-business-service:3.6.0.RELEASE

lfeoperatorfabric/of-businessconfig-service:3.7.0.RELEASE

You must change your docker-compose files accordingly.

6.2. Third parties configuration

The configuration of the third parties applications as external recipents has changed. It is now possible to configure wether the user token shall be propagated to the third party or not by setting the "propagateUserToken" boolean property.

If you have third parties configured in your 'cards-publication.yml' you should change the configuration as follows:

From:

externalRecipients-url: "{\
           third-party1: \"http://thirdparty1/test1\", \
           third-party2: \"http://thirdparty2:8090/test2\", \
           }"

To

external-recipients:
  recipients:
    - id: "third-party1"
      url: "http://thirdparty1/test1"
      propagateUserToken: true
    - id: "third-party2"
      url: "http://thirdparty2:8090/test2"
      propagateUserToken: true

6.3. Rename attribute externalDeviceId

It is now possible to have several external device systems, therefore the attribute externalDeviceId is now renamed into externalDeviceIds and is now a list.

6.3.1. In the configuration file

In the configuration file, replace

userConfigurations:
        - userLogin: operator1_fr
          externalDeviceId: CDS_1
        - userLogin: operator2_fr
          externalDeviceId: CDS_2
        - userLogin: operator3_fr
          externalDeviceId: CDS_3
        - userLogin: operator4_fr
          externalDeviceId: CDS_1

by

userConfigurations:
        - userLogin: operator1_fr
          externalDeviceIds: ["CDS_1"]
        - userLogin: operator2_fr
          externalDeviceIds: ["CDS_2"]
        - userLogin: operator3_fr
          externalDeviceIds: ["CDS_3"]
        - userLogin: operator4_fr
          externalDeviceIds: ["CDS_1"]

6.3.2. Changes in the Mongo data base

6.3.2.1. Before the migration

Before the migration to 3.7.0, one should save its current database, then add the attribute "externalDeviceIds" based on the value of the existing attribute "externalDeviceId". To add this attribute, simply launch the commands :

var collection = db.getCollection("userConfigurations")
collection.find().forEach(function(user) {collection.updateOne({_id: user._id}, {$set: {externalDeviceIds: [user.externalDeviceId]}})})
6.3.2.2. Once the migration is done

Once the migration to 3.7.0 is done, the attribute "externalDeviceId" is not used anymore. You can remove it by launching :

var collection = db.getCollection("userConfigurations")
collection.find().forEach(function(user) {collection.updateOne({_id: user._id}, {$unset: {"externalDeviceId": 1}})})

6.4. Deprecated feature

6.4.1. Field recurrence

Using "recurrence" field returned by getSpecificCardInformation() method definition is now deprecated.

If you are using the "viewCardInAgenda" and "recurrence" field, use the "timeSpans" field instead when returning the card object in usercardTemplateGateway.getSpecificCardInformation() to configure the visibility of the card in timeline and agenda.

Example:

    usercardTemplateGateway.getSpecificCardInformation = function () {
        const message = document.getElementById('message').value;
        const card = {
          summary : {key : "message.summary"},
          title : {key : "message.title"},
          entityRecipients: ["ENTITY_FR","IT_SUPERVISOR_ENTITY"],
          data : {message: message}
        };

        const recurrence = {
            daysOfWeek : [1,2,3],
            hoursAndMinutes : {hours:10,minutes:44},
            durationInMinutes: 15
        }

        const mystartDate = new Date();
        const timeSpans = [{
            startDate: mystartDate.getTime(),
            endDate: mystartDate.getTime() + 7 * 24 * 3600000,
            recurrence: recurrence
        }]

        return {
            valid: true,
            card: card,
            timeSpans: timeSpans
        };

7. Migration Guide from release 3.7.0 to release 3.8.0

7.1. Kafka card format changes

The Kafka message schema has been changed. Two new, optional fields are added:

  • wktGeometry

  • wktProjection

Make sure your Kafka consumers and producers are updated and use the latest card and responseCard definitions.

8. Migration Guide from release 3.8.x to release 3.9.0

8.1. web-ui.json config file

To declare settings parameters, you now need to group all fields under settings: { } and you must not use a statement like this one : settings.replayInterval: 10

For example:

Replace the following invalid settings config

  "settings.replayInterval": 10,
  "settings.replayEnabled": true,
  "settings": {
    "about": {
      "keycloak": {
        "name": "Keycloak",
        "rank": 2,
        "version": "6.0.1"
      },
    }
    "locale": "en",
    "dateTimeFormat": "HH:mm DD/MM/YYYY",
    "dateFormat": "DD/MM/YYYY",
    "styleWhenNightDayModeDesactivated": "NIGHT"
  },

By this valid one :

  "settings": {
    "replayInterval": 10,
    "replayEnabled": true,
    "about": {
      "keycloak": {
        "name": "Keycloak",
        "rank": 2,
        "version": "6.0.1"
      },
    }
    "locale": "en",
    "dateTimeFormat": "HH:mm DD/MM/YYYY",
    "dateFormat": "DD/MM/YYYY",
    "styleWhenNightDayModeDesactivated": "NIGHT"
  },

9. Migration Guide from release 3.9.x to release 3.10.0

9.1. Card publication with not existent process or state

OperatorFabric will refuse the publication of cards referring a not existent process or state. To allow the publication of cards with not existent process or state you should set the authorizeToSendCardWithInvalidProcessState property to true in cards-publication.yml configuration file.

9.2. web-ui.json config file

9.2.1. settings.about section

The section to configure about screen has been moved from settings section to the root level. You need to change the configuration file accordingly.

For example:

Replace the following invalid config

  "settings": {
    "about": {
      "keycloak": {
        "name": "Keycloak",
        "rank": 2,
        "version": "6.0.1"
      },
    },
    "replayInterval": 10,
    "replayEnabled": true,
    "locale": "en",
    "dateTimeFormat": "HH:mm DD/MM/YYYY",
    "dateFormat": "DD/MM/YYYY",
    "styleWhenNightDayModeDesactivated": "NIGHT"
  },

By this valid one :

  "settings": {
    "replayInterval": 10,
    "replayEnabled": true,
    "locale": "en",
    "dateTimeFormat": "HH:mm DD/MM/YYYY",
    "dateFormat": "DD/MM/YYYY",
    "styleWhenNightDayModeDesactivated": "NIGHT"
  },
  "about": {
    "keycloak": {
      "name": "Keycloak",
      "rank": 2,
      "version": "6.0.1"
    }
  }

9.2.2. settings.infos.hide section

The section to configure hidden fields for the settings screen has been moved from settings.infos.hide section to settingsScreen.hiddenSettings. This new field is an array of string and possible values are : "description", "language", "remoteLoggingEnabled" and "sounds". So, you need to change the configuration file accordingly.

For example:

Replace the following invalid config

  "settings": {
    "infos": {
      "hide": {
        "description": true
      }
    }
  }

By this valid one :

  "settingsScreen": {
    "hiddenSettings":  ["description"]
  }

9.2.3. Feed filtering and sorting

In feed configuration the following parameters to hide filtering and sorting options have been removed: feed.card.hideAckFilter, feed.card.hideReadSort, feed.card.hideSeveritySort

Instead, it is possible to configure the default behaviour for sorting and acknowledgment filtering by setting the following parameters in web-ui.json:

  • feed.defaultSorting : possible values are : "unread", "date", "severity", "startDate", "endDate"

  • feed.defaultAcknowledgmentFilter : possible values are : "notack", "ack", "all"

10. Migration Guide from release 3.10.x to release 3.11.0

10.1. Card publication

OperatorFabric will now check user perimeter when publishing cards via endpoint /cards (it does not concern user cards which are always controlled). To disable perimeter validation it is possible to set the configuration parameter checkPerimeterForCardSending to false in cards-publication service configuration file.

10.2. templateGateway onStyleChange() method

A new onStyleChange() method has been added to templateGateway. OpFab will call this method when switching day/night mode. It may have to be implemented by a template to refresh styles and reload embedded charts when user change day/night mode, please check your existing templates.

10.3. Nginx configuration

Nginx configuration file has to be modified to allow the forwarding of query parameters to the new 'userActionLogs' API. You have to modify nginx.conf file as follows:

Replace

  location ~ "^/users/(.*)" {
    proxy_set_header Host $http_host;
    proxy_pass http://users:8080/$1;
    proxy_set_header X-Forwarded-For $remote_addr;
  }

With

  location ~ "^/users/(.*)" {
    proxy_set_header Host $http_host;
    proxy_pass http://users:8080/$1$is_args$args;
    proxy_set_header X-Forwarded-For $remote_addr;
  }

11. Migration Guide from release 3.11.x to release 3.12.0

11.1. Java 17

OperatorFabric now runs on java 17, which means that the client library is now compiled with java 17. If you are using the client library, you may need to upgrade your application to java 17 or use client 3.11.2 which is compatible with version 3.12.0 and compiled with java 11.

11.2. Expiration date

A new 'expirationDate' field has been added to the card. Cards with an expiration date will be automatically deleted from the card feed after the expiration date is passed.

The expiration date is by default visible in the usercard screen. You can hide the expiration date in the usercard screen by adding the new 'expirationDateVisible' value to your usercard configuration in the config.json of your bundle.

  • Hide expiration date → "expirationDateVisible" : false

    "processState": {
      "name": "Process example ",
      "description": "Process state",
      "color": "#0070C0",
      "userCard" : {
        "template" : "usercard_process",
        "lttdVisible" : false,
        "expirationDateVisible" : false,
        "recipientList" : [{"id": "ENTITY_FR", "levels": [0,1]}, {"id": "IT_SUPERVISOR_ENTITY"}]
      },
  • Show expiration date → "expirationDateVisible" : false

    "processState": {
      "name": "Process example ",
      "description": "Process state",
      "color": "#0070C0",
      "userCard" : {
        "template" : "usercard_process",
        "lttdVisible" : false,
        "expirationDateVisible" : true,
        "recipientList" : [{"id": "ENTITY_FR", "levels": [0,1]}, {"id": "IT_SUPERVISOR_ENTITY"}]
      },

11.3. Remove deprecated method templateGateway.getSpecificCardInformation()

The deprecated method 'templateGateway.getSpecificCardInformation()' in usercard templates has been removed, use 'usercardTemplateGateway.getSpecificCardInformation()' method instead.

11.4. Nginx configuration

You need to modify your existing opfab nginx configuration (nginx.conf file), replace line :

proxy_pass http://users:8080/$1;

by

proxy_pass http://users:8080/$1$is_args$args;

12. Migration Guide from release 3.12.0 to release 3.13.0

12.1. Trailing slash

When calling an opfab API you cannot use anymore trailing slash on url.

If, for example, one makes a request like opfab/businessconfig/processes/, it must be replace by opfab/businessconfig/processes

12.2. viewCardInAgenda Parameter renamed

The viewCardInAgenda parameter (specified in the usercard template through getSpecificCardInformation) has been renamed viewCardInCalendar to be consistent with other parts of the software. So you may have to update your usercard templates.

12.3. Default value set to false for lttdVisible and expirationDateVisible

In usercard state definition, the default value for fields lttdVisible and expirationDateVisible is now set to false.

13. Migration Guide from release 3.13.0 to release 3.14.0

13.1. Bundles folder

Bundles are not stored directly into the business config storage path defined in configuration anymore (operatorfabric.businessconfig.storage.path) but in a subdirectory named bundles. So in order to migrate, it is needed to move your bundles directories to a subdirectory named bundles.

To help you migrate your production environment you can use the following script : github.com/opfab/operatorfabric-core/blob//src/tooling/migration-opfab3.13/moveBundles.sh

14. Migration Guide from release 3.14.0 to release 3.15.0

14.1. CrossOrigin for GeoJSON

The option feed.geomap.layer.geojson.crossOrigin, used to set a cross-origin option when downloading GeoJSON, has been removed.

14.2. Remove deprecated field from state definition

The deprecated field recipientList has been removed from card state definition. To restrict the recipient list options use the method usercardTemplateGateway.setDropdownEntityRecipientList in template.

14.3. Remove use of groups column in realtime screen

The field groups has been removed from the object entitiesGroups of the configuration file realtimescreens.json. To conform to this new structure, you have to remove this field from your configuration file.

15. Migration Guide from release 3.15.0 to release 4.0.0

15.1. Management of core menus and custom menus

The structure of the ui-menu.json file has changed. Fields coreMenusConfiguration and menus do not exist anymore.

Now ui-menu.json file contains 4 fields :

  • navigationBar : contains the navigation bar mixing core menus and custom menus

  • topRightIconMenus : contains only the two menu icons agenda and usercard on the top right of the screen

  • topRightMenus : contains the core menus you want to see when you click the user, on the top right of the screen

  • locales : contains the translations for the custom menus

With the new structure of the file, it is now possible to mix core menus and custom menus in the navigation bar.

You can find more information and a full example in the documentation : opfab.github.io/documentation/current/reference_doc/#menu_entries

15.2. UI Configuration

Some fields of the web-ui.json file have changed and renamed:

  • alertMessageBusinessAutoClose has been moved to the alerts section and is now called messageBusinessAutoClose

  • alertMessageOnBottomOfTheScreen has been moved to the alerts section and is now called messageOnBottomOfTheScreen

15.3. OpfabAPI

Use of methods or attributes starting with templateGateway are now deprecated , the following table give you the new methods to use

Deprecated method or attribute New method

templateGateway.getEntityName(entityId)

opfab.users.entities.getEntityName(entityId)

templateGateway.getEntity(entityId)

opfab.users.entities.getEntity(entityId)

templateGateway.getAllEntities()

opfab.users.entities.getAllEntities()

templateGateway.redirectToBusinessMenu(menuId, menuItemId, urlExtension)

opfab.navigate.redirectToBusinessMenu(menuId, menuItemId, urlExtension)

templateGateway.isUserAllowedToRespond()

opfab.currentCard.isUserAllowedToRespond()

templateGateway.isUserMemberOfAnEntityRequiredToRespond()

opfab.currentCard.isUserMemberOfAnEntityRequiredToRespond()

templateGateway.getEntitiesAllowedToRespond()

opfab.currentCard.getEntitiesAllowedToRespond()

templateGateway.getEntityUsedForUserResponse()

opfab.currentCard.getEntityUsedForUserResponse()

templateGateway.getDisplayContext()

opfab.currentCard.getDisplayContext()

templateGateway.displayLoadingSpinner()

opfab.currentCard.displayLoadingSpinner()

templateGateway.hideLoadingSpinner()

opfab.currentCard.hideLoadingSpinner()

templateGateway.childCards

opfab.currentCard.getChildCards()

templateGateway.isLocked

opfab.currentCard.isResponseLocked()

templateGateway.lockAnswer = function () {//do some stuff}

opfab.currentCard.listenToResponseLock( () ⇒ {//do some stuff} )

templateGateway.unlockAnswer = function () {//do some stuff}

opfab.currentCard.listenToResponseUnlock( () ⇒ {//do some stuff} )

templateGateway.setLttdExpired = function () {//do some stuff}

opfab.currentCard.listenToLttdExpired( () ⇒ {//do some stuff} )

templateGateway.onStyleChange = function () {//do some stuff}

opfab.currentCard.listenToStyleChange( () ⇒ {//do some stuff} )

templateGateway.setScreenSize = function () {//do some stuff}

opfab.currentCard.listenToScreenSize( () ⇒ {//do some stuff} )

templateGateway.onTemplateRenderingComplete = function () {//do some stuff}

opfab.currentCard.listenToTemplateRenderingComplete( () ⇒ {//do some stuff} )

templateGateway.getUserResponse = function () {//do some stuff}

opfab.currentCard.registerFunctionToGetUserResponse( () ⇒ {//do some stuff} )

templateGateway.applyChildCards = function () {//do some stuff}

opfab.currentCard.listenToChildCards( () ⇒ {//do some stuff} )

usercardTemplateGateway.getCurrentProcess()

opfab.currentUserCard.getProcessId()

usercardTemplateGateway.getEditionMode()

opfab.currentUserCard.getEditionMode()

usercardTemplateGateway.getEndDate()

opfab.currentUserCard.getEndDate()

usercardTemplateGateway.getExpirationDate()

opfab.currentUserCard.getExpirationDate()

usercardTemplateGateway.getLttd()

opfab.currentUserCard.getLttd()

usercardTemplateGateway.getSelectedEntityRecipients()

opfab.currentUserCard.getSelectedEntityRecipients()

usercardTemplateGateway.getSelectedEntityForInformationRecipients()

opfab.currentUserCard.getSelectedEntityForInformationRecipients()

usercardTemplateGateway.getStartDate()

opfab.currentUserCard.getStartDate()

usercardTemplateGateway.getCurrentState()

opfab.currentUserCard.getState()

usercardTemplateGateway.getUserEntityChildCardFromCurrentCard()

opfab.currentUserCard.getUserEntityChildCard()

usercardTemplateGateway.getSpecificCardInformation = function () {//do some stuff}

opfab.currentUserCard.registerFunctionToGetSpecificCardInformation( () ⇒ {//do some stuff} )

usercardTemplateGateway.setDropdownEntityRecipientList(recipients)

opfab.currentUserCard.setDropdownEntityRecipientList(recipients)

usercardTemplateGateway.setDropdownEntityRecipientForInformationList(recipients)

opfab.currentUserCard.setDropdownEntityRecipientForInformationList(recipients)

userCardTemplateGateway.setEntityUsedForSendingCard = function (entityID) {//do some stuff}

opfab.currentUserCard.listenToEntityUsedForSendingCard( (entityID) ⇒ {//do some stuff} )

usercardTemplateGateway.setInitialEndDate(endDate)

opfab.currentUserCard.setInitialEndDate(endDate)

usercardTemplateGateway.setInitialExpirationDate(expirationDate)

opfab.currentUserCard.setInitialExpirationDate(expirationDate)

usercardTemplateGateway.setInitialLttd(lttd)

opfab.currentUserCard.setInitialLttd(lttd)

usercardTemplateGateway.setInitialSelectedRecipients(recipients)

opfab.currentUserCard.setInitialSelectedRecipients(recipients)

usercardTemplateGateway.setInitialSelectedRecipientsForInformation(recipients)

opfab.currentUserCard.setInitialSelectedRecipientsForInformation(recipients)

usercardTemplateGateway.setInitialSeverity(initialSeverity)

opfab.currentUserCard.setInitialSeverity(initialSeverity)

usercardTemplateGateway.setInitialStartDate(startDate)

opfab.currentUserCard.setInitialStartDate(startDate)

15.4. Write right for user (RightsEnum.Write)

The Write right has been removed. Considering Receive and ReceiveAndWrite rights, Write was useless and confusing for the code.

Before upgrading to 4.0, you must replace all "Write" rights by "ReceiveAndWrite" rights. If you want to automate it, you can do it directly in the database via the following request :

db.perimeter.updateMany({"stateRights.right": "Write"}, {"$set": {"stateRights.$.right": "ReceiveAndWrite"}});

15.5. Cards reminder

Cards reminder logic has been moved from front-end to back-end. The reminder logic is handled by the new "cards-reminder" service.

After upgrading to 4.0, you must call the /reset endpoint to populate the reminders database by processing all current cards with reminder set. For example using cURL:

curl http://localhost:2107/reset -H "Authorization:Bearer $token"

15.6. Internal technical account

The new back service for reminder and the new service regarding mail diffusion and supervision introduce the need of an internal account to communicate between opfab back services. Therefore, if you intend to utilize any of these services, it is necessary to create an Opfab technical account with ADMIN permissions and configure it within your shared YAML configuration file, for example :

operatorfabric:
  internalAccount:
    login: opfab
    password: the_password

The services require knowledge of the URL to retrieve the account’s token, and this URL should be configured within operatorfabric.servicesUrls.authToken. A default value, based on OperatorFabric default installation, is set to: "http://web-ui/auth/token".

15.7. Port mapping

In release 4.0, the listening port is not any more 8080 for services in docker, it is now identical to the default port mapping outside the docker.

So you need to modify your port mapping to migrate replacing the 8080 legacy port by the new port :

2100

businessconfig

2102

cards-publication

2103

users

2104

cards-consultation

2105

external-devices

Depending on your production configuration, you may need as well to change the ports in your nginx conf file.

If you want to keep the old port 8080, you can change it via the server.port parameter in the yml config files of the services.

15.8. RabbitMQ

In previous versions, it was necessary to start a RabbitMQ container referencing "rabbitmq:3-management." We now highly recommend that you update your configuration to utilize "lfeoperatorfabric/of-rabbitmq:4.0.0.RELEASE" instead. This adjustment ensures that you have a qualified version that is fully compatible with OpFab.

When migrating your production environment you may be unable to start rabbitMQ with the following error in log :

2023-09-14 13:57:00.803114+00:00 [error] <0.230.0> Feature flags: `maintenance_mode_status`: required feature flag not enabled! It must be enabled before upgrading RabbitMQ.
2023-09-14 13:57:00.955976+00:00 [error] <0.230.0> Failed to initialize feature flags registry:{disabled_required_feature_flag,
2023-09-14 13:57:00.955976+00:00 [error] <0.230.0>                                               maintenance_mode_status}

BOOT
FAILED
===========
Error during startup: {error,failed_to_initialize_feature_flags_registry}

2023-09-14 13:57:01.022987+00:00 [error] <0.230.0>
2023-09-14 13:57:01.022987+00:00 [error] <0.230.0> BOOT FAILED
2023-09-14 13:57:01.022987+00:00 [error] <0.230.0> ===========
2023-09-14 13:57:01.022987+00:00 [error] <0.230.0> Error during startup: {error,failed_to_initialize_feature_flags_registry}

This issue arises because the persisted data (RabbitMQ queues) generated by the previous version of RabbitMQ is incompatible with the current RabbitMQ version. To address this problem, it is necessary to remove the persisted data before launching OpFab, which can be found at the path mapping /var/lib/rabbitmq/mnesia/ within the Docker container.

If you have configured RabbitMQ persistence, we recommend implementing this as a preventive measure to avoid service unavailability in production.

15.9. Configuration

The configuration has been simplified, you have now default parameters you do not need to set anymore in the back configuration:

  • in all yml file you do not need to set anymore spring.application.name

  • a default kafka configuration is provided, you only have to add "kafka.consumer.group-id : opfab-command" to enable kafka

  • a default rabbit configuration is provided

  • default value are provided for "operatorfabric.servicesUrls.users" and "operatorfabric.servicesUrls.businessconfig"

  • "spring.data.mongodb.database" is not to be set anymore

  • you still need to set "management.endpoints.web.exposure.include: '*'" if you want to monitor opfab via prometheus

  • operatorfabric.businessconfig.storage.path is set by default to "/businessconfig-storage"

The nginx configuration has been simplified as well, the best is to redefine your actual nginx based on the example /config/docker/nginx.conf. The main modification is the removal of the following endpoints declaration :

  • /archives

  • /ui

  • /ui/assets/i18n

  • /config/web-ui.json

  • /config/menu-ui.json

We have also implemented data compression for the information supplied by the "businessconfig" service within the "nginx.conf" reference file. This is done by adding in the location /businessconfig :

    gzip on;
    gzip_types application/json;

The nginx conf is not loaded anymore in /usr/share/nginx/html/opfab in the docker but in /usr/share/nginx/html/config. You need to modify your volume configuration . For example in docker compose :

    volumes:
      - "./ui-config:/usr/share/nginx/html/opfab"

becomes :

    volumes:
      - "./ui-config:/usr/share/nginx/html/config"

In the web-ui.json file, you do not need anymore to set : - security.jwt.expire-claim - security.oauth2.flow.provider - security.oauth2.provider-realm - security.oauth2.provider-url

15.10. Normalization of some configuration parameters

Some configuration parameters have been renamed, so you have to check your config files and adapt them. Here are the concerned parameters (old name → new name):

  • daysBeforeLogExpiration → operatorfabric.users.daysBeforeLogExpiration

  • checkAuthenticationForCardSending → operatorfabric.cards-publication.checkAuthenticationForCardSending

  • authorizeToSendCardWithInvalidProcessState → operatorfabric.cards-publication.authorizeToSendCardWithInvalidProcessState

  • checkPerimeterForCardSending → operatorfabric.cards-publication.checkPerimeterForCardSending

  • external-recipients.* → operatorfabric.cards-publication.external-recipients.*

  • opfab.kafka.topics.card.topicname → operatorfabric.cards-publication.kafka.topics.card.topicname

  • opfab.kafka.topics.response-card.topicname → operatorfabric.cards-publication.kafka.topics.response-card.topicname

  • opfab.kafka.schema.registry.url → operatorfabric.cards-publication.kafka.schema.registry.url

  • delayForDeleteExpiredCardsScheduling → operatorfabric.cards-publication.delayForDeleteExpiredCardsScheduling

  • checkIfUserIsAlreadyConnected → operatorfabric.checkIfUserIsAlreadyConnected

  • spring.data.mongodb.uri -→ operatorfabric.mongodb.uri

  • spring.rabbitmq.* -→ operatorfabric.rabbitmq.*

  • spring.security.oauth2.resourceserver.jwt.jwk-set-uri -→ operatorfabric.security.oauth2.resourceserver.jwt.jwk-set-uri

15.11. Mongodb uri

The option "authMode=scram-sha1" has to be removed from mongodb uri as SCRAM authentication is enabled by default and "authMode" option is not supported by node.js mongodb driver. For example you should change :

 mongodb:
    uri: mongodb://root:password@mongodb:27017/operator-fabric?authSource=admin&authMode=scram-sha1

to

 mongodb:
    uri: mongodb://root:password@mongodb:27017/operator-fabric?authSource=admin

15.12. Rate limiter for card sendings

External publishers are now monitored by a new module which limits how many cards they can send cardSendingLimitCardCount in a period of time cardSendingLimitPeriod . This is to avoid potential overloading due to external apps stuck in a card sending loop.

Default value is set to 1000 cards per hour. It can be disabled / enabled with activateCardSendingLimiter

16. Migration Guide from release 4.0.0 to release 4.1.0

16.1. Optimizing Nginx Configuration for Latency Reduction

An optimization has been introduced in the Nginx configuration to reduce latency. To implement this optimization in your nginx.conf you need to add in location /cards/ the directive proxy_buffering off

For example :

  location /cards/ {
    proxy_buffering off;
    proxy_set_header Host $http_host;
    proxy_pass http://cards-consultation:2104/;
    proxy_set_header X-Forwarded-For $remote_addr;
  }

16.2. Updating the file size limit

The limit of maximum file size has been updated to 100 MB. To implement this limit in your nginx.conf you need to add in location /businessconfig/ the directive client_max_body_size 100M;

For example :

  location /businessconfig {
    proxy_set_header Host $http_host;
    proxy_pass http://${MY_DOCKER_HOST}:2100;
    proxy_set_header X-Forwarded-For $remote_addr;
    client_max_body_size 100M;
  }

16.3. Nginx Configuration for entity supervision administration

The new 'Supervised Entities' admin page requires interaction with the supervisor API via Nginx. To enable access to the supervisor API, please incorporate the following configuration into your nginx.conf file:

  location ~ "^/supervisor/(.*)" {
    set $supervisor http://supervisor:2108;
    proxy_set_header Host $http_host;
    proxy_pass $supervisor/$1;
    proxy_set_header X-Forwarded-For $remote_addr;
  }

16.4. Supervisor configuration change

The configuration of 'supervisor.defaultConfig.entitiesToSupervise' parameter has changed. The supervised entity field id has been renamed to entityId. You should modify your configuration accordingly.

For example:

  supervisor:
    defaultConfig:
      entitiesToSupervise:
      - id: ENTITY1_FR
        supervisors:
        - ENTITY2_FR
      - id: ENTITY2_FR
        supervisors:
        - ENTITY1_FR

should be changed to:

  supervisor:
    defaultConfig:
      entitiesToSupervise:
      - entityId: ENTITY1_FR
        supervisors:
        - ENTITY2_FR
      - entityId: ENTITY2_FR
        supervisors:
        - ENTITY1_FR

16.5. Log directories in docker

For the services cards-reminder, supervisor, cards-external-diffusion the log directory in the docker is not anymore /usr/app/logs but /var/log/opfab. So if you map the log directory in your configuration , you need to change it.

16.6. OpfabAPI

The following method is deprecated and it is recommended you use the new method:

Deprecated method or attribute New method

opfab.currentCard.getEntityUsedForUserResponse()

opfab.currentCard.getEntitiesUsableForUserResponse()

17. Migration Guide from release 4.1.0 to release 4.2.0

17.1. Deletion of parameter displayConnectionCirclesInPreview

The parameter displayConnectionCirclesInPreview has been deleted. Now, in the usercard preview, users will see which recipients entities are connected or not via badges : a blue badge if connected and a gray one if not. This feature is provided for all users. So you have to remove this parameter from the configuration file web-ui.json.

17.2. Configuration files of the realtime users screen

Previously, to configure this screen, the json file had to fit the following structure :

{
  "realTimeScreens": [
    {
      "screenName": <Name of the screen>,
      "screenColumns": [
        {
          "entitiesGroups": [
            {
              "name": <Name of a group of entities>,
              "entities": [
                <entity1 id>,
                <entity2 id>
              ]
            },
            {
              "name": <Name of another group of entities>,
              "entities": [
                <entity3 id>,
                <entity4 id>
              ]
            }
          ]
        }
      ]
    }
  ]
}

Now entities shouldn’t be grouped in the configuration file anymore. Instead entities are grouped by a shared parent entity. The configuration file needs to be changed to the following structure:

{
  "realTimeScreens": [
    {
      "screenName": <Name of the screen>,
      "screenColumns": [
        {
          "entitiesGroups": ["<parent entity 1 id>","<parent entity 2 id>"]
        }
      ]
    }
  ]
}

With this parent entity 1 and parent entity 2 need to be declared and the name of the parent entities will be the name of the groups.

17.3. Updating the entity roles in the database

In this release the "roles" attribute has been added to the entity object. It defines the utility of an entity. It absorbs and broaden the logic of the attribute "entityAllowedToSendCard" which becomes deprecated. To update the entities in your mongo database, you can execute the following script located in OF_HOME/src/tooling/migration-entity-roles :

./launchMigration.sh <IP or DNSNameMongoDB> <portMongoDB> <loginMongoDB> <passwordMongoDB>

This script will assign the roles "ACTIVITY_AREA", "CARD_RECEIVER" and "CARD_SENDER" to all the entities that have "entityAllowedToSendCard = true" and the role "CARD_RECEIVER" to the others. Please refer to the documentation to see the other possible roles and their effect.

After successful execution of the previous script you should execute the following script to cleanup the database removing the deprecated attribute "entityAllowedToSendCard":

./cleanMongoAfterMigration.sh <IP or DNSNameMongoDB> <portMongoDB> <loginMongoDB> <passwordMongoDB>

17.4. Deletion of deprecated functions in templateGateway/usercardTemplateGateway

Functions in templateGateway/usercardTemplateGateway do not exist anymore, you can refer to the migration documentation to opfab 4.0 to know which functions you have to use.

17.5. Card keepChildCards

The card field keepChildCards is now deprecated, use the new actions field (string array) including "KEEP_CHILD_CARDS" action instead.

17.6. Feed process and state filter

New filters have been added to feed filters to allow filtering by card process and state. It is possible to hide the process filter by setting feed.card.hideProcessFilter to true in web-ui.json config file. When process filter is hidden than also state filter is hidden. It is possible to hide just the the state filter by setting feed.card.hideStateFilter to true in web-ui.json config file.

17.7. User settings

A new setting to send emails in plain text instead of HTML has been added in the settings screen of the user. This setting can be hidden in the configuration file of the web-ui by the field "settings.settingsScreen.hiddenSettings" by adding the value "emailToPlainText".

18. Migration Guide from release 4.2.0 to release 4.3.0

18.1. ADMIN group

Users belonging to 'ADMIN' group will not be automatically given admin rights anymore. The admin rights will be set only if user is member of a group with ADMIN permission.

Before initiating the migration process, ensure that all users with administrative privileges are members of a group that has been explicitly granted the 'ADMIN' permission. Failing to do so may result in loss of the ability to administrate operator fabric

18.2. Map multiple GeoJSON layers

It is now possible to add more than one GeoJSON layer to the map. To allow the configuration of multiple layers the feed.geomap.layer.geojson configuration parameter in web-ui.json is now an array. for each layer it is possible to specify the url and an optional style. The style object can have styling properties for stroke, fill, image, and text styles as defined in OpenLayer flat style (openlayers.org/en/latest/apidoc/module-ol_style_flat.html) You should change your configuration for geoJSON layer to configure it as an array, for example:

      "layer": {
        "geojson": {
          "url": "assets/layers/geojson-layer.json"
        }
      }

should be changed to:

      "layer": {
        "geojson": [
          {
            "url": "assets/layers/geojson-layer.json"
          }
        ]
      }

Or adding the style:

      "layer": {
        "geojson": [
          {
            "url": "assets/layers/geojson-layer.json",
            "style": {
              "stroke-color": "blue",
              "stroke-width": 1.5,
              "fill-color": "rgba(39, 245, 164, 0.4)"
            }
          }
        ]
      }

If no style is defined the layer will be rendered with default Opfab style.

19. Migration Guide from release 4.3.X to release 4.4.0

19.1. Use of client_id to obtain token

In the example script getToken.sh, a parameter client_id is set to opfab-client. This value was in fact not necessary and has been removed . The client_id is managed by the web-ui service and is not required in the authentication requests. You can remove the client_id from your scripts.

19.2. Endpoints configuration

To enhance consistency and avoid confusion, we made the following modifications to the endpoints:

  • When accessed via web-ui(nginx), the endpoint /cards has been replaced by /cards-consultation.

  • When accessed via web-ui(nginx), the endpoint /cardspub has been replaced by /cards-publication.

  • The base path for accessing the businessconfig service directly (without passing through web-ui) has been changed from /businessconfig to /.

  • Added endpoints /cards-reminder and /cards-external diffusion to access cards-reminder and cards-external diffusion services via nginx for opfab cli

Please note that the old endpoint /businessconfig is still available but will be removed in a future release.

We have simplified our nginx reference configuration. Instead of adjusting your configuration for the new release, you can rebuild your configuration using the new reference configuration (located at config/docker/nginx.conf) and adapt it to your specific needs.

If you prefer to adapt your existing file, the following changes should be made:

For example, consider this configuration:

  location /cards/ {
    proxy_buffering off;
    proxy_set_header Host $http_host;
    proxy_pass http://cards-consultation:2104/;
    proxy_set_header X-Forwarded-For $remote_addr;
  }

  location /cardspub/cards {
    proxy_set_header Host $http_host;
    proxy_pass http://cards-publication:2102/cards;
    proxy_set_header X-Forwarded-For $remote_addr;
  }

   location /businessconfig {
    gzip on;
    gzip_types application/json;
    proxy_set_header Host $http_host;
    proxy_pass http://businessconfig:2100;
    proxy_set_header X-Forwarded-For $remote_addr;
    client_max_body_size 100M;
  }

This should be changed to:

  location /cards-consultation/ {
    proxy_buffering off;
    proxy_set_header Host $http_host;
    proxy_pass http://cards-consultation:2104/;
    proxy_set_header X-Forwarded-For $remote_addr;
  }

  location /cards-publication/ {
    proxy_set_header Host $http_host;
    proxy_pass http://cards-publication:2102/;
    proxy_set_header X-Forwarded-For $remote_addr;
  }

  location /businessconfig/ {
    gzip on;
    gzip_types application/json;
    proxy_set_header Host $http_host;
    proxy_pass http://businessconfig:2100/;
    proxy_set_header X-Forwarded-For $remote_addr;
    client_max_body_size 100M;
  }

  location /cards-external-diffusion/ {
    proxy_set_header Host $http_host;
    proxy_pass http://cards-external-diffusion:2106/;
    proxy_set_header X-Forwarded-For $remote_addr;
  }

  location /cards-reminder/ {
    proxy_set_header Host $http_host;
    proxy_pass http://cards-reminder:2107/;
    proxy_set_header X-Forwarded-For $remote_addr;
  }

For a smooth, real-time migration, you can temporarily keep endpoints '/cards' and '/cardspub' in your Nginx configuration and remove the old one after a while.

If you are using the businessconfig service directly via some scripts, you need to update these scripts.

19.3. Tooltips

For templates and external applications, the tooltip styling now allows HTML inside of it and the implementation syntax changed from:

<span opfab-tooltip-text="Here is an example of tooltip" class="opfab-tooltip">Some tooltip text</span>

to :

<div class="opfab-tooltip">Some tooltip text
    <div class="opfab-tooltip-content">Here is an example of a tooltip</div>
</div>

For positioning, it is done in the element with class opfab-tooltip-content instead of the element with class opfab-tooltip. You need to change for example from:

  <span opfab-tooltip-text="Here is an example of tooltip" class="opfab-tooltip left">Some tooltip text</span>

to:

<div class="opfab-tooltip">Some tooltip text
    <div class="opfab-tooltip-content left">Here is an example of tooltip</div>
</div>

20. Migration Guide from release 4.4.X to release 4.5.0

20.1. Use of docker compose v2

OperatorFabric is now using docker compose v2, so you have to upgrade this tool to continue using opfab. You can find more information in the docker documentation : docs.docker.com/compose/migrate/

20.2. Use of date-fns instead of Moment.js library

OperatorFabric is now using date-fns library instead of Moment.js. The format used for defining a formatted date string is now different. So, if needed:

  • in the file web-ui.json, you have to modify your fields : settings.dateTimeformat and settings.dateFormat.

  • in your templates when using handlebars helper dateFormat, you have to modify the formatting string

You can find the available formats here : date-fns.org/v3.6.0/docs/format

Especially you have to replace YYYY by yyyy and DD by dd.

20.3. Deletion of the parameter secondsAfterPublicationToConsiderCardAsNotRead

OperatorFabric is now sending emails whether a card is read or not. So, the parameter secondsAfterPublicationToConsiderCardAsNotRead having become useless, it was deleted, and you can safely remove it from your configuration file.

20.4. UI Configuration

Some fields of the web-ui.json file have changed and renamed:

  • alerts.messageBusinessAutoClose has been renamed as alerts.alarmLevelAutoClose

  • alerts.hideBusinessMessages has been renamed as alerts.doNotAlertForHiddenCardReceived

20.5. Hallway mode setting

The settings.usersInHallwayMode configuration field has been removed from web-ui.json. The option to automatically open the most recent card (hallway mode) is now available as a user setting in UI settings view.

20.6. Process monitoring configuration

The configuration for process monitoring screen has been removed from web-ui.json and externalized in a dedicated JSON file. The process monitoring configuration file has to be loaded by sending an HTTP POST request to the /processmonitoring API of businessconfig service or using the CLI command opfab process-monitoring load <file>. The structure of the process monitoring configuration fields has to be modified as follows:

  • "fieldsForProcesses" is now an array of objects with "process" and "fields" fields.

  • The "size" attribute in now a number, not a string as before

  • "filters" is now an object with "pageSize" and "tags" fields

So for example the configuration should be changed from:

"fieldsForProcesses": {
      "conferenceAndITIncidentExample" : [
        { "field": "startDate", "type": "date", "colName": "Start Date", "size": "200"},
        { "field": "titleTranslated", "colName": "Title", "size": "250"},
        { "field": "entityRecipients", "type": "array", "colName": "Entity Recipients", "size": "400"}
      ],
      "messageOrQuestionExample" : [
        { "field": "startDate", "type": "date", "colName": "Start Date", "size": "200"},
        { "field": "endDate", "type": "date", "colName": "End Date", "size": "200"},
        { "field": "titleTranslated", "colName": "Title", "size": "250"},
        { "field": "entityRecipients", "type": "array", "colName": "Entity Recipients", "size": "400"}
      ]
    },
    "filters": {
      "tags": {
        "list": [
          {
            "label": "Label for tag 1",
            "value": "tag1"
          },
          {
            "label": "Label for tag 2",
            "value": "tag2"
          }
        ]
      },
      "page": {
        "size": 10
      }
    }

to

   "fieldsForProcesses": [
      {
        "process": "conferenceAndITIncidentExample",
        "fields" : [
        { "field": "startDate", "type": "date", "colName": "Start Date", "size": 200},
        { "field": "titleTranslated", "colName": "Title", "size": 250},
        { "field": "entityRecipients", "type": "array", "colName": "Entity Recipients", "size": 400}
      ]}, {
        "process" : "messageOrQuestionExample",
        "fields" : [
        { "field": "startDate", "type": "date", "colName": "Start Date", "size": 200},
        { "field": "endDate", "type": "date", "colName": "End Date", "size": 200},
        { "field": "titleTranslated", "colName": "Title", "size": 250},
        { "field": "entityRecipients", "type": "array", "colName": "Entity Recipients", "size": 400}
      ]}
    ],
    "filters": {
      "tags": [
          {
            "label": "Label for tag 1",
            "value": "tag1"
          },
          {
            "label": "Label for tag 2",
            "value": "tag2"
          }
        ],
        "pageSize": 10
      }

20.7. Deletion of VIEW_ALL_ARCHIVED_CARDS and VIEW_ALL_ARCHIVED_CARDS_FOR_USER_PERIMETERS permissions

In order to simplify the code and the administration of opfab, we have deleted the permissions VIEW_ALL_ARCHIVED_CARDS and VIEW_ALL_ARCHIVED_CARDS_FOR_USER_PERIMETERS. So, administrators of opfab have to update manually the permissions of the users via the UI, replacing VIEW_ALL_ARCHIVED_CARDS by VIEW_ALL_CARDS and VIEW_ALL_ARCHIVED_CARDS_FOR_USER_PERIMETERS by VIEW_ALL_CARDS_FOR_USER_PERIMETERS.

20.8. Deletion of the deprecated API method opfab.currentCard.getEntityUsedForUserResponse()

As mentioned in the migration guide to opfab 4.1, the API method opfab.currentCard.getEntityUsedForUserResponse() has been replaced by opfab.currentCard.getEntitiesUsableForUserResponse(). Now, this deprecated API method has been deleted, so you need to upgrade your code and use the method opfab.currentCard.getEntitiesUsableForUserResponse().

20.9. Removed deprecated keepChildCards field

The deprecated card field keepChildCards has been removed. Use the actions field (string array) including "KEEP_CHILD_CARDS" action instead.

20.10. Opfab CLI : renaming log commands

The log commands for opfab CLI have been renamed.

Now, instead of doing opfab service get-log-level <serviceName>, you have to do opfab log get-level <serviceName>. And instead of doing opfab service set-log-level <serviceName> <level>, you have to do opfab log set-level <serviceName> <level>.

20.11. RabbitMQ

The version of RabbitMQ is now 4.0.2. Before deploying it in production, if you are using a persistent queue, you need to clean the persistent file directory; otherwise, you will not be able to start the RabbitMQ docker container. (Inside the docker, the persistent folder is /var/lib/rabbitmq/mnesia/)

21. Migration Guide from release 4.5.X to release 4.6.0

21.1. Removed field toNotify

The card field toNotify has been removed. You must use the actions field including "STORE_ONLY_IN_ARCHIVES" action instead.

21.2. New line added between opfab fields and template in usercard form

A new line (<br/>) has been added in the usercard form, between the opfab fields (service/process/state or severity or dates fields (depending on which fields are visible or not)) and the display of the template. So you have to check that the display of your usercard form still suits you.

21.3. Timeline domain TR renamed RT

To be consistent, the timeline domain TR has been renamed RT (Real Time). So if necessary, you have to update your config file web-ui.json, replacing value TR with RT in the field feed.timeline.domains, for example :

 "timeline": {
   "domains": [
     "RT",
     "J",
     "7D",
     "W",
     "M",
     "Y"
   ]
 }

21.4. UI archives and logging number of lines per page

Since it is now possible to select the number of lines per page displayed in the archive and logging screens, the configuration parameters archive.filters.page.size and logging.filters.page.size are no longer needed and can be removed from the web-ui.json file.

21.5. Configuration for recap email

The feature to send weekly recapitulation email has been added and thus the configuration of operatorfabric.cardsExternalDiffusion has changed. Before, this was the default configuration for the daily email :

  dailyEmailTitle: 'Cards received during the day'
  hourToSendDailyEmail: 7
  minuteToSendDailyEmail: 30

Now the following fields have been added :

  • dailyEmailBodyPrefix

  • weeklyEmailBodyPrefix

  • weeklyEmailTitle

  • dayOfWeekToSendWeeklyRecapEmail

And the time fields have changed from :

  • hourToSendDailyEmail

  • minuteToSendDailyEmail

to :

  • hourToSendRecapEmail

  • minuteToSendRecapEmail

The new default configuration is as such :

  dailyEmailTitle: 'Cards received during the day'
  weeklyEmailTitle: 'Cards received during the week'
  dailyEmailBodyPrefix: 'You received the following cards during the past 24 hours : '
  weeklyEmailBodyPrefix: 'You received the following cards during the past 7 days : '
  dayOfWeekToSendWeeklyRecapEmail: 1
  hourToSendRecapEmail: 7
  minuteToSendRecapEmail: 30

21.6. Timezone

For the cards-external-diffusion service, the timezone configuration has been moved from the Dockerfile to the docker-compose.yml file. If nothing is set in the docker compose file, the default value will be the local timezone of your machine.

21.7. Email templates

To be homogeneous with UI templates, it is now necessary to prefix the handlebars variables with "card" in the email templates. For example, the following code

<div id="apogee-contingencies">
    {{#data.networkContingencies}}

is to be changed to

<div id="apogee-contingencies">
  {{#card.data.networkContingencies}}

21.8. Email templates custom parameters

It is now possible to configure custom parameters to be used in handlebars email templates. The custom parameter can be added in cards-external-diffusion configuration under the "defaultConfig.customConfig" section:

cardsExternalDiffusion:
    adminPort: 2106
    activeOnStartup: true
    defaultConfig:
      mailFrom: opfab@localhost.it
      subjectPrefix: 'Opfab card received '
      customConfig:
             myParam1: 'myValue1'
             myParam2: 'myValue2'

The custom parameters can then be referred in handlebars template prefixed with "config", for example:

{{#config.myParam1}}

This change has an impact on existing mail templates, as the existing handlebars variables will have to be prefixed with "card", for example on the existing example:

<div id="apogee-contingencies">
    {{#data.networkContingencies}}

is to be changed to

<div id="apogee-contingencies">
  {{#card.data.networkContingencies}}

21.9. Removed field timespans.recurrence

The field timespans.recurrence has been removed. So now, to create a recurrent card, you must use the field rRule. There is a script to migrate existing tasks using recurrence object. After the call to this script, you have to call the endpoint "reset". Example :

  • node migration-rrule-recurrence.js <databaseURL> <databasePort> <databaseLogin> <databasePassword> <oldProcessId> <newProcessId> <oldStateId> <newStateId> <newProcessVersion>

  • curl localhost:2107/reset -H "Authorization:Bearer $token"

22. Migration Guide from release 4.6.X to release 4.7.0

22.1. User settings

A new setting to activate or not the templating of emails has been added in the settings screen of the user. This setting can be hidden in the configuration file of the web-ui by the field "settings.settingsScreen.hiddenSettings" by adding the value "disableCardContentInEmails".

22.2. Response card

The object that should be returned by the method registered via opfab.currentCard.registerFunctionToGetUserResponse is to be changed.

Previously, the object was structured as follows:

{
    valid: true/false,
    errorMsg: string,
    responseCardData: {},
    responseState: string,
    publisher: string,
    actions: [string]
}

Now, all elements related to the response card are encapsulated within a responseCard object:

{
    valid: true/false,
    errorMsg: string,
    responseCard: {
        data: {},
        state: string,
        publisher: string,
        actions: [string]
    }
}

Note that the responseState field has been renamed to state.

The old structure will be supported as a fallback for a limited time, it is recommended to update your code to use the new structure. `

23. Migration Guide from release 4.8.X to release 4.9.0

23.1. Geomap configuration

As a new layer type (wmts) has been added, the geomap configuration has been updated for improved clarity in layer management. All layers are now stored in a single property.

You must update your configuration to match this new structure.

The layers and tiles of the map can now be configured using the feed.geomap.layers property. This property accepts an array of objects, each representing a layer with a type property and additional configuration options depending on the layer type. The following layer types are supported:

  • osm: OpenStreetMap tiles. No additional configuration required.

  • geojson: GeoJSON layers. Requires a url for the GeoJSON file and optionally a style object for feature styling. The style object supports stroke, fill, image, and text styles as defined in the OpenLayers flat style format (see: openlayers.org/en/latest/apidoc/module-ol_style_flat.html).

  • xyz: XYZ tiles. Requires a url endpoint with {x}, {y}, and {z} variables (e.g., "https://service.pdok.nl/brt/achtergrondkaart/wmts/v2_0/grijs/EPSG:3857/{z}/{x}/{y}.png"). You may also specify:

    • tileSize: Integer value (e.g., 256). Required for custom background layers.

    • crossOrigin: Optional. Default is null.

  • wmts: WMTS layers. Requires capabilitiesUrl, layer, and matrixSet.

Example configuration for the feed.geomap.layers property:

"layers": [
                {
                    "type":"osm"
                },
                {
                    "type":"wmts",
                    "capabilitiesUrl":"https://data.geopf.fr/annexes/ressources/wmts/essentiels.xml",
                    "layer":"CADASTRALPARCELS.PARCELLAIRE_EXPRESS",
                    "matrixSet":"PM_0_19"
                },
                {
                    "type": "geojson",
                    "url": "https://opendata.agenceore.fr/api/explore/v2.1/catalog/datasets/reseau-aerien-haute-tension-htb/exports/geojson?lang=fr&timezone=Europe%2FBerlin",
                    "style": {
                        "stroke-color": "red"
                    }
                },
                {
                    "type": "geojson",
                    "url": "assets/layers/geojson-layer2.json"
                }

            ]

23.2. Entities in Token

When retrieving entities from a token, the recommended approach is to use an array attribute containing entity IDs as strings. The previous method, which uses a single string with semicolon-separated IDs, remains available for backward compatibility. To enable the old mode, set the parameter operatorfabric.security.jwt.entitiesIdClaimSingleString to true in your YAML services configuration.

23.3. Deletion of monitoring screen

The monitoring screen is not needed anymore as a similar screen can be defined via custom screens. Here is a custom screen configuration that can replace the monitoring screen :

{
    const CustomScreenMonitoring = {
        id: 'monitoringId',
        name: 'monitoring',
        headerFilters: ['PROCESS', 'TYPE_OF_STATE', 'RESPONSE_FROM_MY_ENTITIES'],

        results: {
            columns: [
                {
                    field: 'severity',
                    cardField: 'severity',
                    fieldType: 'SEVERITY'
                },
                {
                    field: 'TIME',
                    headerName: 'TIME',
                    cardField: 'publishDate',
                    fieldType: 'DATE_AND_TIME',
                    minWidth: 150,
                    flex: 0.5
                },
                {
                    field: 'title',
                    headerName: 'TITLE',
                    cardField: 'titleTranslated',
                    fieldType: 'STRING',
                    flex: 1,
                    minWidth: 150
                },
                {
                    field: 'summary',
                    headerName: 'SUMMARY',
                    cardField: 'summaryTranslated',
                    fieldType: 'STRING',
                    flex: 2,
                    minWidth: 150,
                    showTooltips: true
                },
                {
                    fieldType: 'TYPE_OF_STATE',
                    headerName: 'PROCESS STATUS',
                    flex: 0.6,
                    minWidth: 150
                },
                {
                    field: 'publisher',
                    headerName: 'EMITTER',
                    cardField: 'publisher',
                    fieldType: 'PUBLISHER',
                    flex: 1,
                    minWidth: 150
                },
                {
                    headerName: 'ANSWERS',
                    fieldType: 'RESPONSES',
                    flex: 2,
                    minWidth: 400
                }
            ]
        }
    };
    opfab.businessconfig.registerCustomScreen(CustomScreenMonitoring);
}