Skip to content

Latest commit

 

History

History
105 lines (96 loc) · 3.04 KB

STATE.md

File metadata and controls

105 lines (96 loc) · 3.04 KB

State

The State of an app describes the difference of the current applications state and the modules it has loaded. For instance, the currently active layers (or inactive layers, which would be active on startup), a style defined on an active layer, the current viewpoint are all stored within the state.

On loading the app, the state is set once for each module for which the state was defined. Once all modules for which the state was defined have been loaded once, reloading them will no longer set the state.

Furthermore, each plugin may provide its own state via the getState(forUrl: boolean):* API. During initialization of the plugin, the state is passed into the plugin (if the plugin is loaded in a module for which the state applies). Plugins may define any number of state parameters, for instance the current window position of their windows, include form values, drawn geometries, selected features etc. Since the state can also be used to create a link to the current application, including a subset of the state, the API uses a boolean flag to indicate this. It is crucial that plugins only provide a minimal set of state parameters when setting the state for an URL and do not provide sensitive information within the state.

The following outlines how a plugin might implement the getState API:

import { createToggleAction, ButtonLocation } from '@vcmap/ui';

/**
 * @typedef {Object} PluginConfig
 * @property {string} title
 */

/**
 * @typedef {Object} PluginState
 * @property {WindowPositionOptions} [windowPosition]
 * @property {boolean} active
 */

/**
 * @param {PluginConfig} config
 * @returns {VcsPlugin<PluginConfig, PluginState>}
 */
export default function (config) {
  const name = 'state-test';
  return {
    title: config.title ?? name,
    name,
    /**
     * @param {VcsUiApp} app
     * @param {PluginState} state
     */
    initialize(app, state) {
      const { action, destroy } = createToggleAction(
        { name: this.title },
        { id: 'pluginState', component: { template: '<div>HELLO</div>' } },
        app.windowManager,
        name,
      );
      app.navbarManager.add(
        {
          id: 'pluginState',
          action,
        },
        name,
        ButtonLocation.TOOL,
      );

      if (state?.active) {
        action.callback();
      }
      if (state?.position) {
        app.windowManager.get('pluginState').position = state.position;
      }
      this._destroyAction = destroy;
      this._app = app;
    },
    /**
     * @param {boolean} forUrl
     * @returns {PluginState}
     */
    getState(forUrl) {
      const state = {
        active: this._app.windowManager.has('pluginState'),
      };
      if (!forUrl) {
        state.position = this._app.windowManager.get('pluginState').position;
      }
      return state;
    },
    /**
     * @returns {PluginConfig}
     */
    toJSON() {
      return {
        title: this.title,
      };
    },
    destroy() {
      if (this._destroyAction) {
        this._destroyAction();
        this._destroyAction = null;
      }
    },
  };
}