Added: zeppelin/site/docs/0.8.1/development/helium/writing_visualization_basic.html URL: http://svn.apache.org/viewvc/zeppelin/site/docs/0.8.1/development/helium/writing_visualization_basic.html?rev=1851877&view=auto ============================================================================== --- zeppelin/site/docs/0.8.1/development/helium/writing_visualization_basic.html (added) +++ zeppelin/site/docs/0.8.1/development/helium/writing_visualization_basic.html Wed Jan 23 04:28:00 2019 @@ -0,0 +1,447 @@ + + + + + + Apache Zeppelin 0.8.0 Documentation: Writing a new Helium Visualization: basic + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + +

Writing a new Visualization

+ +
+ +

What is Apache Zeppelin Visualization

+ +

Apache Zeppelin Visualization is a pluggable package that can be loaded/unloaded on runtime through Helium framework in Zeppelin. A Visualization is a javascript npm package and user can use them just like any other built-in visualization in notebook.

+ +

How it works

+ +

1. Load Helium package files from registry

+ +

Zeppelin needs to know what Visualization packages are available. Zeppelin will read information of packages from both online and local registry. +Registries are configurable through ZEPPELIN_HELIUM_LOCALREGISTRY_DEFAULT env variable or zeppelin.helium.localregistry.default property.

+ +

2. Enable packages

+ +

Once Zeppelin loads Helium package files from registries, available packages are displayed in Helium menu.

+ +

Click 'enable' button.

+ +

+ +

3. Create and load visualization bundle on the fly

+ +

Once a Visualization package is enabled, HeliumBundleFactory creates a js bundle. The js bundle is served by helium/bundle/load rest api endpoint.

+ +

4. Run visualization

+ +

Zeppelin shows additional button for loaded Visualizations. +User can use just like any other built-in visualizations.

+ +

+ +

Write new Visualization

+ +

1. Create a npm package

+ +

Create a package.json in your new Visualization directory. You can add any dependencies in package.json, but you must include two dependencies: zeppelin-vis and zeppelin-tabledata.

+ +

Here's an example

+
{
+  "name": "zeppelin_horizontalbar",
+  "description" : "Horizontal Bar chart",
+  "version": "1.0.0",
+  "main": "horizontalbar",
+  "author": "",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "zeppelin-tabledata": "*",
+    "zeppelin-vis": "*"
+  }
+}
+
+

2. Create your own visualization

+ +

To create your own visualization, you need to create a js file and import Visualization class from zeppelin-vis package and extend the class. zeppelin-tabledata package provides some useful transformations, like pivot, you can use in your visualization. (you can create your own transformation, too).

+ +

Visualization class, there're several methods that you need to override and implement. Here's simple visualization that just prints Hello world.

+
import Visualization from 'zeppelin-vis'
+import PassthroughTransformation from 'zeppelin-tabledata/passthrough'
+
+export default class helloworld extends Visualization {
+  constructor(targetEl, config) {
+    super(targetEl, config)
+    this.passthrough = new PassthroughTransformation(config);
+  }
+
+  render(tableData) {
+    this.targetEl.html('Hello world!')
+  }
+
+  getTransformation() {
+    return this.passthrough
+  }
+}
+
+

To learn more about Visualization class, check visualization.js.

+ +

You can check complete visualization package example here.

+ +

Zeppelin's built-in visualization uses the same API, so you can check built-in visualizations as additional examples.

+ +

3. Create Helium package file and locally deploy

+ +

Helium Package file is a json file that provides information about the application. +Json file contains the following information

+
{
+  "type" : "VISUALIZATION",
+  "name" : "zeppelin_horizontalbar",
+  "description" : "Horizontal Bar chart (example)",
+  "license" : "Apache-2.0",
+  "artifact" : "./zeppelin-examples/zeppelin-example-horizontalbar",
+  "icon" : "<i class='fa fa-bar-chart rotate90flipX'></i>"
+}
+
+

Place this file in your local registry directory (default ./helium).

+ +
type
+ +

When you're creating a visualization, 'type' should be 'VISUALIZATION'. Check these types as well.

+ + + +
name
+ +

Name of visualization. Should be unique. Allows [A-Za-z90-9_].

+ +
description
+ +

A short description about visualization.

+ +
artifact
+ +

Location of the visualization npm package. Support npm package with version or local filesystem path.

+ +

e.g.

+ +

When artifact exists in npm repository

+
"artifact": "my-visualiztion@1.0.0"
+
+

When artifact exists in local file system

+
"artifact": "/path/to/my/visualization"
+
+
license
+ +

License information.

+ +

e.g.

+
"license": "Apache-2.0"
+
+
icon
+ +

Icon to be used in visualization select button. String in this field will be rendered as a HTML tag.

+ +

e.g.

+
"icon": "<i class='fa fa-coffee'></i>"
+
+

4. Run in dev mode

+ +

Place your Helium package file in local registry (ZEPPELIN_HOME/helium). +Run Zeppelin. And then run zeppelin-web in visualization dev mode.

+
cd zeppelin-web
+yarn run dev:helium
+
+

You can browse localhost:9000. Everytime refresh your browser, Zeppelin will rebuild your visualization and reload changes.

+ +

5. Publish your visualization

+ +

Once it's done, publish your visualization package using npm publish. +That's it. With in an hour, your visualization will be available in Zeppelin's helium menu.

+ +

See More

+ +

Check Helium Visualization: Transformation for more complex examples.

+ +
+
+ + +
+ +
+ + + + + + + + + + + Added: zeppelin/site/docs/0.8.1/development/helium/writing_visualization_transformation.html URL: http://svn.apache.org/viewvc/zeppelin/site/docs/0.8.1/development/helium/writing_visualization_transformation.html?rev=1851877&view=auto ============================================================================== --- zeppelin/site/docs/0.8.1/development/helium/writing_visualization_transformation.html (added) +++ zeppelin/site/docs/0.8.1/development/helium/writing_visualization_transformation.html Wed Jan 23 04:28:00 2019 @@ -0,0 +1,654 @@ + + + + + + Apache Zeppelin 0.8.0 Documentation: Transformations in Zeppelin Visualization + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + +

Transformations for Zeppelin Visualization

+ +
+ +

Overview

+ +

Transformations

+ +
    +
  • renders setting which allows users to set columns and
  • +
  • transforms table rows according to the configured columns.
  • +
+ +

Zeppelin provides 4 types of transformations.

+ +

1. PassthroughTransformation

+ +

PassthroughTransformation is the simple transformation which does not convert original tabledata at all.

+ +

See passthrough.js

+ +

2. ColumnselectorTransformation

+ +

ColumnselectorTransformation is uses when you need N axes but do not need aggregation.

+ +

See columnselector.js

+ +

3. PivotTransformation

+ +

PivotTransformation provides group by and aggregation. Every chart using PivotTransformation has 3 axes. Keys, Groups and Values.

+ +

See pivot.js

+ +

4. AdvancedTransformation

+ +

AdvancedTransformation has more detailed options while providing existing features of PivotTransformation and ColumnselectorTransformation

+ +
    +
  • multiple sub charts
  • +
  • configurable chart axes
  • +
  • parameter widgets: input, checkbox, option, textarea
  • +
  • parsing parameters automatically based on their types
  • +
  • expand / fold axis and parameter panels
  • +
  • multiple transformation methods while supporting lazy converting
  • +
  • re-initialize the whole configuration based on spec hash.
  • +
+ +

Spec

+ +

AdvancedTransformation requires spec which includes axis and parameter details for charts.

+ +

Let's create 2 sub-charts called line and no-group. Each sub chart can have different axis and parameter depending on their requirements.

+ +


+
class AwesomeVisualization extends Visualization {
+  constructor(targetEl, config) {
+    super(targetEl, config)
+
+    const spec = {
+      charts: {
+        'line': {
+          transform: { method: 'object', },
+          sharedAxis: false, /** set if you want to share axes between sub charts, default is `false` */
+          axis: {
+            'xAxis': { dimension: 'multiple', axisType: 'key', description: 'serial', },
+            'yAxis': { dimension: 'multiple', axisType: 'aggregator', description: 'serial', },
+            'category': { dimension: 'multiple', axisType: 'group', description: 'categorical', },
+          },
+          parameter: {
+            'xAxisUnit': { valueType: 'string', defaultValue: '', description: 'unit of xAxis', },
+            'yAxisUnit': { valueType: 'string', defaultValue: '', description: 'unit of yAxis', },
+            'lineWidth': { valueType: 'int', defaultValue: 0, description: 'width of line', },
+          },
+        },
+
+        'no-group': {
+          transform: { method: 'object', },
+          sharedAxis: false,
+          axis: {
+            'xAxis': { dimension: 'single', axisType: 'key', },
+            'yAxis': { dimension: 'multiple', axisType: 'value', },
+          },
+          parameter: {
+            'xAxisUnit': { valueType: 'string', defaultValue: '', description: 'unit of xAxis', },
+            'yAxisUnit': { valueType: 'string', defaultValue: '', description: 'unit of yAxis', },
+        },
+      },
+    }
+
+    this.transformation = new AdvancedTransformation(config, spec)
+  }
+
+  ...
+
+  // `render` will be called whenever `axis` or `parameter` is changed 
+  render(data) {
+    const { chart, parameter, column, transformer, } = data
+
+    if (chart === 'line') {
+      const transformed = transformer()
+      // draw line chart 
+    } else if (chart === 'no-group') {
+      const transformed = transformer()
+      // draw no-group chart 
+    }
+  }
+}
+
+


+ +

Spec: axis

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameAvailable Values (type)Description
dimensionsingleAxis can contains only 1 column
dimensionmultipleAxis can contains multiple columns
axisTypekeyColumn(s) in this axis will be used as key like in PivotTransformation. These columns will be served in column.key
axisTypeaggregatorColumn(s) in this axis will be used as value like in PivotTransformation. These columns will be served in column.aggregator
axisTypegroupColumn(s) in this axis will be used as group like in PivotTransformation. These columns will be served in column.group
axisType(string)Any string value can be used here. These columns will be served in column.custom
maxAxisCount (optional)(int)The max number of columns that this axis can contain. (unlimited if undefined)
minAxisCount (optional)(int)The min number of columns that this axis should contain to draw chart. (1 in case of single dimension)
description (optional)(string)Description for the axis.
+ +


+ +

Here is an example.

+
axis: {
+  'xAxis': { dimension: 'multiple', axisType: 'key',  },
+  'yAxis': { dimension: 'multiple', axisType: 'aggregator'},
+  'category': { dimension: 'multiple', axisType: 'group', maxAxisCount: 2, valueType: 'string', },
+},
+
+


+ +

Spec: sharedAxis

+ +

If you set sharedAxis: false for sub charts, then their axes are persisted in global space (shared). It's useful for when you creating multiple sub charts sharing their axes but have different parameters. For example,

+ +
    +
  • basic-column, stacked-column, percent-column
  • +
  • pie and donut
  • +
+ +


+ +

Here is an example.

+
    const spec = {
+      charts: {
+        'column': {
+          transform: { method: 'array', },
+          sharedAxis: true,
+          axis: { ... },
+          parameter: { ... },
+        },
+
+        'stacked': {
+          transform: { method: 'array', },
+          sharedAxis: true,
+          axis: { ... }
+          parameter: { ... },
+        },
+
+


+ +

Spec: parameter

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameAvailable Values (type)Description
valueTypestringParameter which has string value
valueTypeintParameter which has int value
valueTypefloatParameter which has float value
valueTypebooleanParameter which has boolean value used with checkbox widget usually
valueTypeJSONParameter which has JSON value used with textarea widget usually. defaultValue should be "" (empty string). This
description(string)Description of this parameter. This value will be parsed as HTML for pretty output
widgetinputUse input widget. This is the default widget (if widget is undefined)
widgetcheckboxUse checkbox widget.
widgettextareaUse textarea widget.
widgetoptionUse select + option widget. This parameter should have optionValues field as well.
optionValues(Array)Available option values used with the option widget
+ +


+ +

Here is an example.

+
parameter: {
+  // string type, input widget
+  'xAxisUnit': { valueType: 'string', defaultValue: '', description: 'unit of xAxis', },
+
+  // boolean type, checkbox widget
+  'inverted': { widget: 'checkbox', valueType: 'boolean', defaultValue: false, description: 'invert x and y axes', },
+
+  // string type, option widget with `optionValues`
+  'graphType': { widget: 'option', valueType: 'string', defaultValue: 'line', description: 'graph type', optionValues: [ 'line', 'smoothedLine', 'step', ], },
+
+  // HTML in `description`
+  'dateFormat': { valueType: 'string', defaultValue: '', description: 'format of date (<a href="https://docs.amcharts.com/3/javascriptcharts/AmGraph#dateFormat">doc</a>) (e.g YYYY-MM-DD)', },
+
+  // JSON type, textarea widget
+  'yAxisGuides': { widget: 'textarea', valueType: 'JSON', defaultValue: '', description: 'guides of yAxis ', },
+
+


+ +

Spec: transform

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameAvailable Values (type)Description
methodobjectdesigned for rows requiring object manipulation
methodarraydesigned for rows requiring array manipulation
methodarray:2-keydesigned for xyz charts (e.g bubble chart)
methoddrill-downdesigned for drill-down charts
methodrawwill return the original tableData.rows
+ +


+ +

Whatever you specified as transform.method, the transformer value will be always function for lazy computation.

+
// advanced-transformation.util#getTransformer
+
+if (transformSpec.method === 'raw') {
+  transformer = () => { return rows; }
+} else if (transformSpec.method === 'array') {
+  transformer = () => {
+    ...
+    return { ... }
+  }
+}
+
+

Here is actual usage.

+
class AwesomeVisualization extends Visualization {
+  constructor(...) { /** setup your spec */ }
+
+  ... 
+
+  // `render` will be called whenever `axis` or `parameter` are changed
+  render(data) {
+    const { chart, parameter, column, transformer, } = data
+
+    if (chart === 'line') {
+      const transformed = transformer()
+      // draw line chart 
+    } else if (chart === 'no-group') {
+      const transformed = transformer()
+      // draw no-group chart 
+    }
+  }
+
+  ...
+}
+
+
+
+ + +
+ +
+ + + + + + + + + + +