Skip to content

Getting Started

First, install the ui-attributes-graphs library:

npm i @leverege/ui-attributes-graphs

Next, define UI Attributes for the data that you are hoping to graph. For instance, the below example defines three attributes for a fictitious 'test.history' data type. If you are using Molten, you may already have a number of UI Attributes defined for you based on your Imagine project's blueprints:

Plugins.add( 'Attribute', {
  name : 'name',
  displayName : 'Name',
  valueType : 'string',
  objectType : 'test.history',
  placement : {
    group : [ ]
  },
  get : ( obj ) => {
    return obj?.name
  }
} )
Plugins.add( 'Attribute', {
  name : 'test.history.time',
  displayName : 'Time',
  valueType : 'timestamp',
  objectType : 'test.history',
  placement : {
    group : [ ]
  },
  get : ( obj ) => {
    const time = obj && obj.time

    return time == null ? null : new Date( time )
  }
} )

Plugins.add( 'Attribute', {
  name : 'test.history.temperature',
  displayName : 'Temperature',
  valueType : 'temperature',
  objectType : 'test.history',
  baseUnit : 'degC',
  placement : {
    group : [ ]
  },
  get : ( obj ) => {
    const temp = obj?.data?.temperature

    return temp == null ? null : {
      type : 'temperature',
      value : temp,
      unit : 'degC'
    }
  }
} )

In this case, time and temperature will be the two data points that we will be graphing against one another. Name is (in this case) a unique identifier for the objects that these data represent and will be used to key the data into series to facilitate graphing.

Using the useSeriesData hook or the withSeriesData HOC exported by this library, prepare your data for graphing. The hook/HOC expect to be passed an array of data that you want to be graphed, an attribute name that will be used to chunk that data, and an options object with possible properties of obejctType and sortAttribute. The hook/HOC will transform and memoize this data into an object keyed on the values of the chunk attribute that you have passed. If you pass an objectType in the options, it will be used to help disambiguate the chunk and sort attributes rather than using the first attribute registered with that particular name. If you pass a sortAttribute in the options, it will be used to sort the data in your series.

Example

const dataArray = [
  {
    "type": "test.history",
    "id": "1",
    "data": {
      "time": 1642444110759,
      "name": "Device 1",
      "data": {
        "temperature": 45.7891
      }
    }
  },
  {
    "type": "test.history",
    "id": "2",
    "data": {
      "time": 1642461033498,
      "name": "Device 1",
      "data": {
        "temperature": 40.7705
      }
    }
  },
  {
    "type": "test.history",
    "id": "3",
    "data": {
      "time": 1642411955689,
      "name": "Device 1",
      "data": {
        "temperature": 48.7092
      }
    }
  },
  {
    "type": "test.history",
    "id": "7",
    "data": {
      "time": 1642474048199,
      "name": "Device 2",
      "data": {
        "temperature": 12.299
      }
    }
  },
  {
    "type": "test.history",
    "id": "8",
    "data": {
      "time": 1642407220379,
      "name": "Device 2",
      "data": {
        "temperature": 5.4862
      }
    }
  },
  {
    "type": "test.history",
    "id": "9",
    "data": {
      "time": 1642478679300,
      "name": "Device 2",
      "data": {
        "temperature": 4.5652
      }
    }
  }
]

const seriesData = useSeriesData( dataArray, 'name', { sortAttribute : 'test.time' } )

/*
  seriesData => {
  "Device 2": [
    {
      "type": "test.history",
      "id": "8",
      "data": {
        "time": 1642407220379,
        "name": "Device 2",
        "data": {
          "temperature": 5.4862
        }
      }
    },
    {
      "type": "test.history",
      "id": "7",
      "data": {
        "time": 1642474048199,
        "name": "Device 2",
        "data": {
          "temperature": 12.299
        }
      }
    },
    {
      "type": "test.history",
      "id": "9",
      "data": {
        "time": 1642478679300,
        "name": "Device 2",
        "data": {
          "temperature": 4.5652
        }
      }
    }
  ],
  "Device 1": [
    {
      "type": "test.history",
      "id": "3",
      "data": {
        "time": 1642411955689,
        "name": "Device 1",
        "data": {
          "temperature": 48.7092
        }
      }
    },
    {
      "type": "test.history",
      "id": "1",
      "data": {
        "time": 1642444110759,
        "name": "Device 1",
        "data": {
          "temperature": 45.7891
        }
      }
    },
    {
      "type": "test.history",
      "id": "2",
      "data": {
        "time": 1642461033498,
        "name": "Device 1",
        "data": {
          "temperature": 40.7705
        }
      }
    }
  ]
}
 */
This hook/HOC will format your data into series in a manner that can be used by the ui-attributes-graphs library and will memoize the data to prevent unnecessary re-renders. If you can't use the hook/HOC because of the complexity of your data or formatting needs, a normal object keyed on some unique property will work fine, just remember to memoize the data yourself. Now simply pass this data, a Model for your chart and the objectType for your data (in the above example, this would be 'test.history') to a chart renderer and watch as your data is graphed in stunning color.
import { XYChartModel, XYChartRenderer, useSeriesData } from '@leverege/ui-attributes-graphs'

const [ model, setModel ] = useState( XYChartModel.create() )
const seriesData = useSeriesData( myUnformattedData, 'name', { sortAttribute : 'test.time' } )

return (
  <XYChartRenderer
    data={seriesData}
    objectType="test.history"
    model={model} />
)