williaster closed pull request #5893: [SIP-6] Add reactify function and convert 
world map to new directory structure.
URL: https://github.com/apache/incubator-superset/pull/5893
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/superset/assets/package.json b/superset/assets/package.json
index d5571e08bb..0b7dc9c8b5 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 0000000000..6cae3c1874
--- /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 0000000000..c1071e6494
--- /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 0000000000..0de1d25dc8
--- /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 0000000000..d52c81694f
--- /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 0000000000..bc17f82b0b
--- /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 6c4948a7dd..d83d79411b 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 0000000000..30d0400f35
--- /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 0000000000..4e56b03c06
--- /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 31feffc2ab..e924dd4d12 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 0000000000..de4add5336
--- /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 e0fc1ea6f1..b8c06f94a7 100644
--- a/superset/assets/yarn.lock
+++ b/superset/assets/yarn.lock
@@ -7487,6 +7487,10 @@ [email protected], 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";
+
 [email protected], log-symbols@^2.2.0:
   version "2.2.0"
   resolved 
"https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a";


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to