Broadleaf Microservices
  • v1.0.0-latest-prod

TrackingContextProvider

Overview

This provider component is used to provide and manage the tracking context and state for other components in the Admin application, and is particularly concerned with maintaining/updating the state and cache for tenant/application level catalog and sandbox data.

State and Cache Management for Catalog and Sandbox

Before we discuss how the TrackingContextProvider goes about managing the state and cache for catalog and sandbox data, it should be noted that the concept of sandboxing and tracking changes across domains is central to the idea of why catalog and sandbox data is grouped under the tracking provider, or why it is considered "trackable". You can read more about sandboxing and persistence behaviors of trackable entities here.

In essence, the selection of a sandbox is important to the function of the Admin application as it dictates where changes are saved in a temporary space before being deployed into production, and selection of a catalog dictates how entities are grouped and distributed according to the catalog type. By default, changes done in a catalog are done in a sandbox as well.

Note

Here are the current types of Catalogs:

Each type is used in the initialization of the provider state to ensure that all types have hydrated data both in the CatalogContext, as well as the cached catalog data.

Aside from persisting these changes via API calls to keep track of what catalog and/or sandbox is currently being manipulated, the provider also makes use of the browser cache in order to save catalog and sandbox state data like currently selected IDs, the entities themselves, and possible options for selection.

Tip
The browser cache can be accessed and manipulated via the web storage objects available via Javascript, particularly the localStorage and sessionStorage global variables.

Upon initialization and/or mounting of the TrackingContextProvider, three effectful functions are called that do the bulk of the work of initializing and updating state & cached data:

  • hydrateUserSandboxes

    • resolves sandboxes using passed name via API call to GET /sandbox/sandboxes, and sets sandboxes and sandbox id in cache and in state.

    • also has conditional checking in place to ensure hydration cannot occur concurrently. this effect has no dependencies that will cause it to be called again upon dependency change.

  • hydrateAssignedCatalogs

    • resolves catalogs using the passed catalog type & optionally a catalog name via API call to GET /tenant/catalogs, and sets catalogs and catalog id in cache and in state.

    • also has conditional checking in place to ensure hydration of the same type cannot occur concurrently. this effect has no dependencies that will cause it to be called again upon dependency change.

  • useLayoutEffect function that updates the cached catalog and/or sandbox id when location is changed after first render, and rehydrates catalogs & sandboxes if the application changed as well.

    • the dependencies of this effect are the:

      • applicationId passed into the provider

      • location state via React Router

      • provider state assigned catalogs by type value

      • provider state user sandboxes value

How Components Access Tracking Context and State Data

Other components in the Admin application have numerous ways of accessing the tracking context and state data that is set and updated by the TrackingContextProvider:

  • directly accessing the catalog and sandbox contexts by calling the useContext(CatalogContext) or useContext(SandboxContext) hooks

  • calling the useTracking hook to access tracking state data

  • mapping the trackng state to the components' props by using the connectTracking function

useTracking
const SampleTrackable: FC<SampleTrackableProps> = props => {
  const {
    metadata
  } = props;

  // uses metadata to determine what special trackable data exists such as catalog/profile or sandbox
  const tracking = useTracking(metadata);
  // effects and other operations

  return (
    // some component
  );
};
connectTracking
interface SampleTrackableProps {
  application?: any;
  applicationId?: string;
  catalog?: any;
  sandbox?: any;
  tenant?: object;
  tenantId?: string;
}

const SampleTrackable: FC<SampleTrackableProps> = props => {
  const {
    application,
    applicationId,
    catalog,
    sandbox,
    tenant,
    tenantId
  } = props;

  // effects and other operations

  return (
    // some component
  );
};

const mapTrackingToProps = state => {
  return {
    application: state.application,
    applicationId: state.applicationId,
    catalog: state.catalog,
    sandbox: state.sandbox,
    tenant: state.tenant,
    tenantId: state.tenantId
  };
};

export default connectTracking(mapTrackingToProps)(SampleTrackable);

All three methods are essentially accessing the same source of data — both the useTracking hook and connectTracking function access the catalog and sandbox contexts, but they differ slightly in that: (1) the useTracking hook returns an object that combines tenant, application, catalog and sandbox data into one object that can be easily attached as part of the context request for API calls, while the connectTracking function simply maps the same group of data as part of the props of the wrapped component; and (2) the useTracking hook checks the metadata of the component to see if it is catalog/profile/sandbox discriminated and maps certain data accordingly for easier access, while the connectTracking function does not.

The sandbox state initialized by the TrackingContextProvider as well as effectful functions such as hydrateUserSandboxes, resolveUserSandboxes (fetches sandboxes via API request), and setCurrentSandboxById (updates location state with previous and current sandbox ids) are all passed into the SandboxContext. These are accessed/called by components that deal with selecting and displaying sandboxable data such as SandboxSelector and SandboxRibbon.

The catalog state initialized by the TrackingContextProvider as well as effectful functions such as hydrateAssignedCatalogs, resolveAssignedCatalogs (fetches catalogs via API request), and setCurrentCatalogById (updates location state with previous and current catalog ids) are all passed into the CatalogContext. These are accessed/called by components that deal with selecting and displaying catalogs such as CatalogSelector, CatalogSelectorIfNecessary, and CatalogRibbon.