superset-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ccwilli...@apache.org
Subject [incubator-superset] branch master updated: [SIP-6] Add reactify function and convert world map to new directory structure. (#5893)
Date Wed, 19 Sep 2018 06:35:42 GMT
This is an automated email from the ASF dual-hosted git repository.

ccwilliams pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 8fff0d9  [SIP-6] Add reactify function and convert world map to new directory structure.
(#5893)
8fff0d9 is described below

commit 8fff0d9e8f6374fa08ed815101d4eb93d4ae1c1e
Author: Krist Wongsuphasawat <krist.wongz@gmail.com>
AuthorDate: Tue Sep 18 23:35:36 2018 -0700

    [SIP-6] Add reactify function and convert world map to new directory structure. (#5893)
    
    * reactify world map
    
    * add createAdaptor
    
    * fix typo
    
    * add schema
    
    * move directory
    
    * remove unnecessary lines
    
    * make setRef a function
    
    * convert keys to camelcase
    
    * add unit test
    
    * update formatting
    
    * add check for displayName
    
    * pass width and height as separate inputs
---
 superset/assets/package.json                       |  1 +
 .../utils/convertKeysToCamelCase_spec.js           | 29 ++++++++++++
 .../assets/src/utils/convertKeysToCamelCase.js     | 11 +++++
 superset/assets/src/utils/createAdaptor.jsx        | 19 ++++++++
 superset/assets/src/utils/reactify.jsx             | 54 ++++++++++++++++++++++
 .../src/visualizations/WorldMap/ReactWorldMap.js   |  4 ++
 .../{world_map.css => WorldMap/WorldMap.css}       |  0
 .../{world_map.js => WorldMap/WorldMap.js}         | 20 +-------
 .../assets/src/visualizations/WorldMap/adaptor.jsx |  5 ++
 .../src/visualizations/WorldMap/transformProps.js  | 10 ++++
 superset/assets/src/visualizations/index.js        |  2 +-
 .../src/visualizations/models/BasicChartInput.js   | 10 ++++
 superset/assets/yarn.lock                          |  4 ++
 13 files changed, 150 insertions(+), 19 deletions(-)

diff --git a/superset/assets/package.json b/superset/assets/package.json
index f326ec6..6f2437c 100644
--- a/superset/assets/package.json
+++ b/superset/assets/package.json
@@ -79,6 +79,7 @@
     "jed": "^1.1.1",
     "jquery": "3.1.1",
     "json-bigint": "^0.3.0",
+    "lodash": "^4.17.11",
     "lodash.throttle": "^4.1.1",
     "mapbox-gl": "^0.45.0",
     "mathjs": "^3.20.2",
diff --git a/superset/assets/spec/javascripts/utils/convertKeysToCamelCase_spec.js b/superset/assets/spec/javascripts/utils/convertKeysToCamelCase_spec.js
new file mode 100644
index 0000000..6cae3c1
--- /dev/null
+++ b/superset/assets/spec/javascripts/utils/convertKeysToCamelCase_spec.js
@@ -0,0 +1,29 @@
+import { it, describe } from 'mocha';
+import { expect } from 'chai';
+import convertKeysToCamelCase from '../../../src/utils/convertKeysToCamelCase';
+
+describe.only('convertKeysToCamelCase(object)', () => {
+  it('returns undefined for undefined input', () => {
+    expect(convertKeysToCamelCase(undefined)).to.equal(undefined);
+  });
+  it('returns null for null input', () => {
+    expect(convertKeysToCamelCase(null)).to.equal(null);
+  });
+  it('returns a new object that has all keys in camelCase', () => {
+    const input = {
+      is_happy: true,
+      'is-angry': false,
+      isHungry: false,
+    };
+    expect(convertKeysToCamelCase(input)).to.deep.equal({
+      isHappy: true,
+      isAngry: false,
+      isHungry: false,
+    });
+  });
+  it('throws error if input is not a plain object', () => {
+    expect(() => { convertKeysToCamelCase({}); }).to.not.throw();
+    expect(() => { convertKeysToCamelCase(''); }).to.throw();
+    expect(() => { convertKeysToCamelCase(new Map()); }).to.throw();
+  });
+});
diff --git a/superset/assets/src/utils/convertKeysToCamelCase.js b/superset/assets/src/utils/convertKeysToCamelCase.js
new file mode 100644
index 0000000..c1071e6
--- /dev/null
+++ b/superset/assets/src/utils/convertKeysToCamelCase.js
@@ -0,0 +1,11 @@
+import { mapKeys, camelCase, isPlainObject } from 'lodash/fp';
+
+export default function convertKeysToCamelCase(object) {
+  if (object === null || object === undefined) {
+    return object;
+  }
+  if (isPlainObject(object)) {
+    return mapKeys(k => camelCase(k), object);
+  }
+  throw new Error(`Cannot convert input that is not a plain object: ${object}`);
+}
diff --git a/superset/assets/src/utils/createAdaptor.jsx b/superset/assets/src/utils/createAdaptor.jsx
new file mode 100644
index 0000000..0de1d25
--- /dev/null
+++ b/superset/assets/src/utils/createAdaptor.jsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import BasicChartInput from '../visualizations/models/BasicChartInput';
+
+const IDENTITY = x => x;
+
+export default function createAdaptor(Component, transformProps = IDENTITY) {
+  return function adaptor(slice, payload, setControlValue) {
+    const basicChartInput = new BasicChartInput(slice, payload, setControlValue);
+    ReactDOM.render(
+      <Component
+        width={slice.width()}
+        height={slice.height()}
+        {...transformProps(basicChartInput)}
+      />,
+      document.querySelector(slice.selector),
+    );
+  };
+}
diff --git a/superset/assets/src/utils/reactify.jsx b/superset/assets/src/utils/reactify.jsx
new file mode 100644
index 0000000..d52c816
--- /dev/null
+++ b/superset/assets/src/utils/reactify.jsx
@@ -0,0 +1,54 @@
+import React from 'react';
+
+export default function reactify(renderFn) {
+  class ReactifiedComponent extends React.Component {
+    constructor(props) {
+      super(props);
+      this.setContainerRef = this.setContainerRef.bind(this);
+    }
+
+    componentDidMount() {
+      this.execute();
+    }
+
+    componentDidUpdate() {
+      this.execute();
+    }
+
+    componentWillUnmount() {
+      this.container = null;
+    }
+
+    setContainerRef(c) {
+      this.container = c;
+    }
+
+    execute() {
+      if (this.container) {
+        renderFn(this.container, this.props);
+      }
+    }
+
+    render() {
+      const { id, className } = this.props;
+      return (
+        <div
+          id={id}
+          className={className}
+          ref={this.setContainerRef}
+        />
+      );
+    }
+  }
+
+  if (renderFn.displayName) {
+    ReactifiedComponent.displayName = renderFn.displayName;
+  }
+  if (renderFn.propTypes) {
+    ReactifiedComponent.propTypes = renderFn.propTypes;
+  }
+  if (renderFn.defaultProps) {
+    ReactifiedComponent.defaultProps = renderFn.defaultProps;
+  }
+  return ReactifiedComponent;
+}
diff --git a/superset/assets/src/visualizations/WorldMap/ReactWorldMap.js b/superset/assets/src/visualizations/WorldMap/ReactWorldMap.js
new file mode 100644
index 0000000..bc17f82
--- /dev/null
+++ b/superset/assets/src/visualizations/WorldMap/ReactWorldMap.js
@@ -0,0 +1,4 @@
+import reactify from '../../utils/reactify';
+import WorldMap from './WorldMap';
+
+export default reactify(WorldMap);
diff --git a/superset/assets/src/visualizations/world_map.css b/superset/assets/src/visualizations/WorldMap/WorldMap.css
similarity index 100%
rename from superset/assets/src/visualizations/world_map.css
rename to superset/assets/src/visualizations/WorldMap/WorldMap.css
diff --git a/superset/assets/src/visualizations/world_map.js b/superset/assets/src/visualizations/WorldMap/WorldMap.js
similarity index 86%
rename from superset/assets/src/visualizations/world_map.js
rename to superset/assets/src/visualizations/WorldMap/WorldMap.js
index 6c4948a..d83d794 100644
--- a/superset/assets/src/visualizations/world_map.js
+++ b/superset/assets/src/visualizations/WorldMap/WorldMap.js
@@ -1,7 +1,7 @@
 import d3 from 'd3';
 import PropTypes from 'prop-types';
 import Datamap from 'datamaps';
-import './world_map.css';
+import './WorldMap.css';
 
 const propTypes = {
   data: PropTypes.arrayOf(PropTypes.shape({
@@ -109,20 +109,4 @@ function WorldMap(element, props) {
 
 WorldMap.propTypes = propTypes;
 
-function adaptor(slice, payload) {
-  const { selector, formData } = slice;
-  const {
-    max_bubble_size: maxBubbleSize,
-    show_bubbles: showBubbles,
-  } = formData;
-  const element = document.querySelector(selector);
-
-  return WorldMap(element, {
-    data: payload.data,
-    height: slice.height(),
-    maxBubbleSize: parseInt(maxBubbleSize, 10),
-    showBubbles,
-  });
-}
-
-export default adaptor;
+export default WorldMap;
diff --git a/superset/assets/src/visualizations/WorldMap/adaptor.jsx b/superset/assets/src/visualizations/WorldMap/adaptor.jsx
new file mode 100644
index 0000000..30d0400
--- /dev/null
+++ b/superset/assets/src/visualizations/WorldMap/adaptor.jsx
@@ -0,0 +1,5 @@
+import createAdaptor from '../../utils/createAdaptor';
+import WorldMap from './ReactWorldMap';
+import transformProps from './transformProps';
+
+export default createAdaptor(WorldMap, transformProps);
diff --git a/superset/assets/src/visualizations/WorldMap/transformProps.js b/superset/assets/src/visualizations/WorldMap/transformProps.js
new file mode 100644
index 0000000..4e56b03
--- /dev/null
+++ b/superset/assets/src/visualizations/WorldMap/transformProps.js
@@ -0,0 +1,10 @@
+export default function transformProps(basicChartInput) {
+  const { formData, payload } = basicChartInput;
+  const { maxBubbleSize, showBubbles } = formData;
+
+  return {
+    data: payload.data,
+    maxBubbleSize: parseInt(maxBubbleSize, 10),
+    showBubbles,
+  };
+}
diff --git a/superset/assets/src/visualizations/index.js b/superset/assets/src/visualizations/index.js
index 31feffc..e924dd4 100644
--- a/superset/assets/src/visualizations/index.js
+++ b/superset/assets/src/visualizations/index.js
@@ -108,7 +108,7 @@ const vizMap = {
   [VIZ_TYPES.word_cloud]: () =>
     loadVis(import(/* webpackChunkName: "word_cloud" */ './wordcloud/WordCloud.js')),
   [VIZ_TYPES.world_map]: () =>
-    loadVis(import(/* webpackChunkName: "world_map" */ './world_map.js')),
+    loadVis(import(/* webpackChunkName: "world_map" */ './WorldMap/adaptor.jsx')),
   [VIZ_TYPES.dual_line]: loadNvd3,
   [VIZ_TYPES.event_flow]: () =>
     loadVis(import(/* webpackChunkName: "EventFlow" */ './EventFlow.jsx')),
diff --git a/superset/assets/src/visualizations/models/BasicChartInput.js b/superset/assets/src/visualizations/models/BasicChartInput.js
new file mode 100644
index 0000000..de4add5
--- /dev/null
+++ b/superset/assets/src/visualizations/models/BasicChartInput.js
@@ -0,0 +1,10 @@
+import convertKeysToCamelCase from '../../utils/convertKeysToCamelCase';
+
+export default class BasicChartInput {
+  constructor(slice, payload, setControlValue) {
+    this.annotationData = slice.annotationData;
+    this.formData = convertKeysToCamelCase(slice.formData);
+    this.payload = payload;
+    this.setControlValue = setControlValue;
+  }
+}
diff --git a/superset/assets/yarn.lock b/superset/assets/yarn.lock
index 317de4f..0c537bd 100644
--- a/superset/assets/yarn.lock
+++ b/superset/assets/yarn.lock
@@ -7487,6 +7487,10 @@ lodash@4.17.10, lodash@^4.0.1, lodash@^4.0.8, lodash@^4.13.1, lodash@^4.14.0,
lo
   version "4.17.10"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
 
+lodash@^4.17.11:
+  version "4.17.11"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
+
 log-symbols@2.2.0, log-symbols@^2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"


Mime
View raw message