Skip to content

Instantly share code, notes, and snippets.

@jabrah
Created April 2, 2020 19:06
Show Gist options
  • Save jabrah/690560c3edbc8f01fb7ef5f3008964db to your computer and use it in GitHub Desktop.
Save jabrah/690560c3edbc8f01fb7ef5f3008964db to your computer and use it in GitHub Desktop.

Mirador Plugins

I did start with the M3 Creating a Mirador Plugin wiki page and used nwb when creating a new project. Beyond that, some of the plugins listed in the Mirador wiki served as good examples of some different approaches https://github.com/ProjectMirador/mirador/wiki/M3---Mirador-3-plugins

Plugin Definition

{
  name: 'JHAnnotationFetchPlugin',
  target: "WindowCanvasNavigationControls",
  mode: 'wrap',
  component: JHAnnotationFetcher,
  mapStateToProps,
  mapDispatchToProps
}

It is required to have a Mirador-style plugin definition. In the example above, you can see some important properties to include:

  • name: (Required) unique name for your plugin. I'm not sure how much this is used in Mirador, but at a minimum it is logged if the plugin does not pass validation
  • target: (Required) this is the name of the Mirador component your plugin targets
  • mode: (Required) (wrap|add) a plugin can be defined either as a wrap plugin or an add plugin
  • component: (Required) your plugin class
  • mapStateToProps: JSON object that lets you bring in Mirador state into your plugin props
  • mapDispatchToProps: JSON object that lets you bring Mirador actions into your plugin props

name

Pretty self explanitory, the name you want to give your plugin that Mirador may use for things.

target

The class name of the Mirador component your plugin targets. Not all Mirador components can be the target of a plugin, only those that are deliberatly designed to provide a plugin context (?? not really sure how to explain this). If you look for a component's container (components will generally have a container in src/containers/), components that support plugins will enhanced with the withPlugins function. An example container that supports plugins may look like:

const enhance = compose(
  withTranslation(),
  withStyles(styles),
  connect(mapStateToProps, null),
  withPlugins('WindowSideBarAnnotationPanel'),
  // further HOC
);

If you are interested in using a plugin to replace a certain component in Mirador, first check that components container to see if withPlugins appears. If so, it seems you are free to target that component. Otherwise, if you target a component that does not have withPlugins in its container, then Mirador will simply do nothing with your plugin.

As a side note, this code snippet can tell you some more about what may be available to the component through its React props. styles is defined in the same file and can interact with Mirador's theme. It is used by MaterialUI to programmatically add styles to the component.

mode

This can take only two valid values: add or wrap

add: This kind of plugin will add the plugin component to the target component. For example, you can add a button to WindowTopBarPluginMenu component. Only a limited number of Mirador components will accept add plugins:

  • Window
  • BackgroundPluginArea
  • WindowTopBarPluginMenu
  • WorkspaceControlPanelButtons
  • WorkspaceMenu
  • WorkspaceOptionsMenu

wrap: This kind of plugin will replace the target component. In your plugin's context, you'll have access to the target component's context. You will be able to access props.targetProps to get your target component's props that Mirador would have passed to the original component.

component

Your React component

mapStateToProps

This property is optional. If you wish, you could define a function that has access to Mirador's application state and the plugin's props. You can bring in parts of Mirador's state into your plugin.

function(state, props) { ... }

This function should return a simple JSON object, which will be added to your plugin's props.

function mapStateToProps(state, props) => {
  const selectedCanvases = getVisibleCanvases(state, { windowId: props.targetProps.windowId });
  const presentAnnotations = getAnnotationsForVisibleCanvases(state, selectedCanvases);

  return ({
    annotationCount: getAnnotationResourcesByMotivation(state, { motivations: ['oa:commenting', 'sc:painting', 'commenting'], windowId: props.targetProps.windowId }).length,
    selectedCanvases,
    presentAnnotations
  })
};

In this example, a few external dependencies are imported to help deal with Mirador's state.

  • getVisibleCanvases and getAnnotationResourcesByMotivation are two selectors imported from Mirador.
  • getAnnotationsForVisibleCanvases is a custom selector defined by my plugin.

mapDispatchToProps

@jabrah
Copy link
Author

jabrah commented Apr 2, 2020

(Hopefully) Temporary home for this documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment