sdi_appstate-api

This bundle provides base components that are used to create, update, delete and load app states from map.apps SDI. These components are used for example by the sdi_appstate-ui bundle.

Usage

App states are saved in the map.apps SDI database on the server, so it is required to install and configure the map.apps SDI savestate backend web application on the application server. You can find detailed installation instructions in the map.apps SDI product documentation.

How it works internally

The MainEncoderDecoder component of this bundle collects all components that implement the sdi_appstate-api.EncoderDecoder interface and creates a collective app state containing the data returned by the encode methods of each of these EncoderDecoders. For example, the sdi_appstate-map bundle has a component MapViewEncoderDecoder that provides the interface sdi_appstate-api.EncoderDecoder. Its encode method returns the specific data required to restore the state of the map.

To restore the state, the MainEncoderDecoder passes the saved data to the decode methods of the respective EncoderDecoders.

Implementing custom EncoderDecoders

Developers can provide custom EncoderDecoder components to enable more features of an app to be saved and restored. Saving and restoring the state of a map.apps SDI app is performed by components that implement the sdi_appstate-api.EncoderDecoder interface. So to create a custom EncoderDecoder, add a new component to the manifest.json file of your bundle that looks as such:

{
    "name": "CustomEncoderDecoder",
    "provides": "sdi_appstate-api.EncoderDecoder"
}

The class for this component must implement the EncoderDecoder interface. Here is an example:

import {JSONValue} from "sdi_appstate-api/api";

export default class CustomEncoderDecoder implements EncoderDecoder {
    readonly name: string;

    async encode(): Promise<JSONValue> {
        // Return the data saved to the database. Must be compatible with JSON.stringify
        return {
            mySavedProperty: this.myFeature.myProperty
        }
    }

    async decode(data: JSONValue): Promise<void> {
        // Apply the saved data to our component again 
        this.myFeature.myProperty = data.mySavedProperty;
    }
}

Overriding app state properties with URL parameters

When using map.apps SDI together with the map.apps parameter-url bundle, you can override certain properties if the name of the URL parameter is the same as a property in the app state.

Example

In this example, the c parameter in the URL will override the c property from the app state.

URL: sdi_appstate/index.html?c=7.13,52.4&bm=topo

App State:

{
    "mapView": {
        "c": "5.34,48.9"
    }
}

Backward compatibility

map.apps SDI 5.5 is backward compatible with app states created with map.apps SDI versions prior to 5.5. However, if you implemented custom ParameterResolvers, you'll have to convert these to the new EncoderDecoder interface. Additionally, add a mapping entry to the customDecoderMap property of the LegacyStateConversionConfig component. See the reference for details.

Configuration reference

The following sections describe the configurable components and properties for the app.json of this bundle's components.

LegacyStateConversionConfig

In older versions of map.apps SDI, app states were structured according to the following schema:

{
    "theme": "everlasting",
    "vm": "2D",
    "s": 9244648.868618,
    "r": 0,
    "c": "1137586.745771235,6501498.924616195",
    "myProperty": "a"
}

All properties were stored at the root level of the app state object.

In the new format, the properties are grouped by the names of the corresponding EncoderDecoders:

{
    "theme": {
        "theme": "everlasting"
    },
    "mapView": {
        "vm": "2D",
        "s": 9244648.868618,
        "r": 0,
        "c": "1137586.745771235,6501498.924616195"
    },
    "myFeature": {
        "myProperty": "a"
    },
    "_version": "5.5"
}

There is a new property _version as well to easily distinguish the new format from the old one.

When loading a legacy app state the MainEncoderDecoder needs to know the correct EncoderDecoder for each property. While in the new format it's easy to determine the corresponding EncoderDecoder for a certain property, we cannot figure this out in the old format. We need a map to get the correct EncoderDecoder name for a given property.

We can specify this map in the app.json file with the customDecoderMap property. In the following example, we add one entry to the map. It means "decode the property myProperty with the EncoderDecoder with the name myFeature".

{
    "sdi_appstate-api": {
        "LegacyStateConversionConfig": {
            "customDecoderMap": {
                "myProperty": "myFeature"
            }
        }
    }
}

You only have to include the properties for custom EncoderDecoders. The default EncoderDecoders coming with map.apps SDI are already included in the defaultDecoderMap.