MavenWorks

High Level Architectural Overview

Dashboard

The Dashboard class represents a complete dashboard. The Dashboard manages the dashboard model, owns the various services required by a dashboard, and exposes methods for setting the model and signalling model dirtiness.

Dashboard uses the following classes:

Dashboard works with the following classes:

Layout Engine

The Layout engine is one of the most important components of a Dashboard, along with the PartManager. The Engine is built using Phosphor, and thus uses Phosphor constructs extensively.

It uses a top-down approach, where constraints are evaluated at the root and then passed down to solve the whole tree. This approach works well for dashboards, as it greatly simplifies the framework and enables analytical, linear-time algorithms for otherwise-complex layout schemes.

The engine also includes a drag-n’-drop docking framework. This framework is largely bolt-on, and exposes ways for regions to customize docking behavior. Note that while PhosphorJS includes a DockPanel, the DockPanel is insufficient for dashboards. DockPanels lack the flexibility demanded of comprehensive, production-ready dashboards and are designed instead for an IDE dock layout.

LayoutManager

The LayoutManager handles the visual layout of the dashboard. Parts are organized into a tree of containers, such as a Stack Panel or a Tab Panel. The LayoutManager exposes some basic facilities for working with these regions, while LayoutActions exposes tree manipulation helpers.

The LayoutManager also tracks the UX state of the layout. For instane, it will track which region most recently had focus, and report that as the focused region.

The LayoutManager can be used independently of a dashboard, it just needs a part provider and some factory for creating new parts.

One caveat is that the LayoutManager must always have a root region. This must be a RegionWithChildren,

LayoutManager uses the following classes:

LayoutManager works with the following classes:

DashboardLayoutRegion

The DashboardLayoutRegion is the base class for all layout regions used by the LayoutManager. A layout region implementation must subclass this class, and may override the following methods:

By convention, layout properties are described with two brackets in the documentation (eg, [[showOverlays]]).

RegionWithChildren

RegionWithChildren is a subclass of DashboardLayoutRegion that implements methods for working with children.

In addition to the methods exposed by DashboardLayoutRegion, RegionWithChildren subclassers may override the following methods:

Some layout properties are per-child, but do not make sense globally. Subclassers can define “Attached Properties” for these cases, to define a per-part property that is only respected by a particular RegionWithChildren subclass. Eg, [[StackPanelLayoutRegion.FixedSize]]. Declare the existence of these properties in GetMetadata(), using metadata#addAttachedMetdata().

Regions may also have Chroming; These are widgets added by the parent layout to children, and are cleared whenever the widget is moved in the tree. Use these for things like resizer-grips.

Parts

Parts are the bread-and-butter of Maven dashboards, and comprise an execution framework and a view. Views communicate using a set of “Options”, which are managed by the PartManager and can be bound together using bindings.

PartManager

The PartManager controls the instantiation and execution of Part instances.

PartManager works with the following classes: - PartFactory - Used to instantiate new parts - GlobalsService - Used to enable 2-way bindings via globals - BindingsProvider - Used to evaluate all other types of bindings

The flow of execution is as follows:

PartFactory

A PartFactory is where part constructors are registered. Parts are associated with a string name that is used in serialization. Consumers of PartFactory can retrieve all the registered parts, and use that information to do things like populating lists in UI designers.

Part factories are hierarchal- there is a global PartFactory that all built-in parts are registered to. Each Dashboard’s part factory derives from a given PartFactory, which is used for Local Parts (UDPs that are saved alongside the dashboard). Implementations may define whatever levels of hierarchy between the global factory and the one provided to the Dashboard. (Eg, The JupyterLab plugin leverages this to scope KernelParts to a given kernel)

Part

A Part represents an individual view in a Dashboard. Parts do not interact with the rest of the dashboard, and are isolated from one another. They instead use Options, which the framework will manage. When these options change, the part will be re-rendered.

Part options are declared by overwriting the static method GetMetadata(), in a similar fashion to layout regions. Options named “Input Table” are special- cased in the UI, and recieve additional integrations (such as a binding editor and a “Copy/Paste Table Binding” command).

Parts primarily consist of two methods:

It’s good practice to front-load as much work onto initialize as possible- the more lightweight you can make render, the snappier the view will be.

Part may be subclassed directly, which will work for most implementations. For views using React, you may find the ReactPart subclass helpful.

The Part base class manages some lifecycle methods, and handles the stateful part overlay that appears over the part when the part is calculating options, rendering, initalizing, or awaiting a command from the user to refresh.

Bindings

Bindings define how part options interact with each other. They glue a dashboard together into a cohesive, maintainable unit.

Dashboards normally have the following types of bindings:

BindingsProvider

The BindingsProvider manages the binding evaluators, and owns the shared thread pool that the MQL and JS binding evaluators use. It offers a layer of indirection to the binding types, so that in the future we can make this more dynamic and pluggable.

BindingsProvider uses the following class: - MqlWorkerPool (1:1) - Hard-coded 8 threads, with a cancel timeout of 15 seconds.

BindingsProvider works with the following classes: - GlobalsService - The globals service is provided to all binding evaluators, so that they can retrieve the globals referenced in a binding just prior to evaluation. - IExpressionEvaluator - Optional. - If provided, an EvalBindingsEvaluator will be added to the evaluators list and made available to consumers.

GlobalsService

The GlobalsService tracks changes in dashboard-level global variables, and includes methods for manipulating and retrieving the globals. It also exposes an Observable for global deltas, so that consumers can react to new globals, updated globals, renamed globals, and deleted globals.

Globals are typed using the serializer’s annotation system. It does not check type validity, it merely exposes the types for consumers to check against. A future update may add type validity checking to GlobalsService#set.