Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

As per the vocabulary, the Registry is designed as a storage place for apps outside of ui-dashboard to register resources. These will then become available to dashboard for the purposes of dynamic interactions between different frontend apps.

...

Code Block
static eventHandler(event, _s, data) {
  if (event === 'ui-dashboard-registry-loadLOAD_STRIPES_REGISTRY') {
    // Data should contain Registry singleton:
    setUpRegistry(data);
    return null;
  }
  return null;
}

Here the index.js file in ui-licenses consumes the event 'ui-dashboard-registry-loadLOAD_STRIPES_REGISTRY', and then triggers a function which sets up the license resource within the registry:

Code Block
const setUpRegistry = (registry) => {
  // License Resource
  const licenseReg = registry.registerResource('license');
  licenseReg.addViewAllsetViewResources('/licenses');
  licenseReg.addViewTemplatesetViewResource(license => `/licenses/${license.id}`);

  // Lookup plugin
  licenseReg.addLookupComponent(LicenseLookup);
};

...

Note

Information on how stripes eventing works can be found here: https://github.com/folio-org/stripes/blob/master/doc/dev-guide.md#handlers-and-events

Not mentioned in that document are the necessary additions to the package.json of an implementing module. The string "handler" will need to be added to the "actsAs" array, and "handlerName" will need to reflect the name of the event method in the module's index.js, most likely "eventHandler".

Code Block
"actsAs": [
  "app",
  "handler",
  "settings"
],
"handlerName": "eventHandler",


Registry API

The implementation details above cover some of the registry's API, namely how to register a resource and provide a lookupComponent. This section will cover more in depth how an implementing module can interact with the registry.

"The registry" is currently comprised of two objects and one exception:

  • Registry
  • RegistryResource
  • RegistryException

Registry, as mentioned above is a singleton, and so all additions/manipulations made by any module are reflected for all of its consumers. It does not have any publically available fields, and so all interactions must take place via its methods:

getRegistry()

Returns a Javascript Map with String keys of the resources available and values of type RegistryResource.

getRegistryCount()

Returns the number of entries in the Map above.

registerResource(resourceName)

Assigns a new RegistryResource to the Map above with the key "resourceName" and returns that RegistryResource.

getResource(resourceName)

Returns the RegistryResource with that key from the Map (or unassigned if the resource does not exist).

setRenderFunction(resourceName, fieldName, func)

This is a passthrough of the same method on a particular RegistryResource.

getRenderFunction(resourceName, fieldName)

This is a passthrough of the same method on a particular RegistryResource.


A RegistryResource is a class containing information about a particular resource of the registry. It has fields that are technically publically available, but they should only be accessed through the requisite getters and setters.

Once https://github.com/tc39/proposal-private-methods#private-methods-and-fields or equivalent become available and supported, these fields should be made private. This class contains the following methods with which to interact with it:
 

Warning

getLink/setLink are implemented, but their shape is not yet finalised in generality. It is HIGHLY recommended that these are not utilised, and any early implementors confine their use to get/set for ViewResource and ViewResources.


getLinkMap()

This function will return a Javascript Map with keys that are Strings referring to a kind of link, eg "viewResource", and values that are either Strings or functions.

setLink(linkName, link)

This function sets a string OR function entry on the above Map.

getLink(linkName)

This function returns the string OR function entry set on the above Map.

Note

Currently it is presumed that a string link implies a direct URL which can be followed, and a function link is to be passed one parameter, namely the resource in question. See the agreements implementation for an example.


setViewResources(link)

A function for the special case of setLink which should reflect a basic URL path for a "view all" page for the resource. In the case of agreements it would be "/erm/agreements/"

setViewResource(link)

A function for the special case of setLink which should reflect a basic URL path for a "view" page for a resource. In the case of agreements it would be "/erm/agreements/{id}".

getViewResources()

A function which fetches 'viewResources' from above.

getViewResource()

A function which fetches 'viewResource' from above.

setLookupComponent(component)

Takes in a react component and assigns it to the field "lookupComponent".

This component can make use of the following props:

  • disabled: a boolean reflecting whether the lookup component ought to be active or not
  • id: a string to ensure uniqueness within the React component heirachy. For example SimpleSearch uses the LookupComponent in its "filters" FieldArray and so passes the id

    Code Block
     "`simple-search-filter-field-card[${index}]`"


  • input: an object passed by Final Form fields. This is to enable the lookup component to be used within forms.


  • onResourceSelected: a function which handles what to do when the selected resource changes
  • resource: The currently selected resource as handled by the component calling the LookupComponent, can be used for display purposes. 


getLookupComponent()

Returns the lookupComponent above.

setRenderFunction(name, func)

Sets a new key in a Map field "renderFunctionMap", and assigns it a function "func" as a value. This can be used to calculate/display fields in a complicated manner. 
For example "agreements" might declare:

Code Block
agreementReg.setRenderFunction('currentPeriodStartDate', record => {
  const date = record.periods.find(p => p.periodStatus === 'current')?.startDate;
  return date ?
    <FormattedUTCDate value={date} /> :
    <NoValue />;
});

This function takes in an agreement record, and then finds a period from the array "periods" with a "periodStatus" of 'current'. It then returns that as a FormattedUTCDate.

In this way, ui-agreements can specify the method of returning a value for "currentPeriodStartDate", and other modules can consume that, cutting down on repeated code. Furthermore, it can be used in modules such as dashboard to allow for dynamic rendering of complicated object fields without ui-dashboard needing to be aware of anything about that object or its structure.

getRenderFunction(name)

This method returns the renderFunction for a given name as above.



Warning

The methods above for links and custom rendering are essentially just code injection, so it is vitally important that implementers consider that their code is just going to be run within ui-dashboard, and potentially elsewhere too. The risk here is minimal, with no user defined methods, but it's still worth noting and taking care when implementing a custom render function.



ui-stripes-registry