You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ma...@apache.org on 2017/10/16 06:38:47 UTC

[incubator-superset] branch master updated: Add a ColorPickerControl (#3653)

This is an automated email from the ASF dual-hosted git repository.

maximebeauchemin 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 d0b5b44  Add a ColorPickerControl (#3653)
d0b5b44 is described below

commit d0b5b449b281022d497f2079f83b103602c7077c
Author: Maxime Beauchemin <ma...@gmail.com>
AuthorDate: Sun Oct 15 23:38:38 2017 -0700

    Add a ColorPickerControl (#3653)
    
    * Add a ColorPickerControl
    
    * Tests
---
 .../components/controls/ColorPickerControl.jsx     | 92 ++++++++++++++++++++++
 .../explore/components/controls/index.js           |  2 +
 superset/assets/javascripts/explore/main.css       |  8 ++
 .../assets/javascripts/explore/stores/controls.jsx |  6 ++
 superset/assets/javascripts/modules/colors.js      |  2 +-
 superset/assets/package.json                       |  3 +-
 .../explore/components/ColorPickerControl_spec.jsx | 41 ++++++++++
 .../explore/components/ColorScheme_spec.jsx        | 25 ++++++
 8 files changed, 177 insertions(+), 2 deletions(-)

diff --git a/superset/assets/javascripts/explore/components/controls/ColorPickerControl.jsx b/superset/assets/javascripts/explore/components/controls/ColorPickerControl.jsx
new file mode 100644
index 0000000..ecccc8e
--- /dev/null
+++ b/superset/assets/javascripts/explore/components/controls/ColorPickerControl.jsx
@@ -0,0 +1,92 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { OverlayTrigger, Popover } from 'react-bootstrap';
+import { SketchPicker } from 'react-color';
+
+import ControlHeader from '../ControlHeader';
+import { bnbColors } from '../../../modules/colors';
+
+const propTypes = {
+  onChange: PropTypes.func,
+  value: PropTypes.object,
+};
+
+const defaultProps = {
+  onChange: () => {},
+};
+
+const swatchCommon = {
+  position: 'absolute',
+  width: '50px',
+  height: '20px',
+  top: '0px',
+  left: '0px',
+  right: '0px',
+  bottom: '0px',
+};
+
+const styles = {
+  swatch: {
+    width: '50px',
+    height: '20px',
+    position: 'relative',
+    padding: '5px',
+    borderRadius: '1px',
+    display: 'inline-block',
+    cursor: 'pointer',
+    boxShadow: 'rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset, rgba(0, 0, 0, 0.25) 0px 0px 4px inset',
+  },
+  color: {
+    ...swatchCommon,
+    borderRadius: '2px',
+  },
+  checkboard: {
+    ...swatchCommon,
+    background: 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==") left center',
+  },
+};
+export default class ColorPickerControl extends React.Component {
+  constructor(props) {
+    super(props);
+    this.onChange = this.onChange.bind(this);
+  }
+  onChange(col) {
+    this.props.onChange(col.rgb);
+  }
+  renderPopover() {
+    return (
+      <Popover id="filter-popover" className="color-popover">
+        <SketchPicker
+          color={this.props.value}
+          onChange={this.onChange}
+          presetColors={bnbColors.filter((s, i) => i < 7)}
+        />
+      </Popover>);
+  }
+  render() {
+    const c = this.props.value || { r: 0, g: 0, b: 0, a: 0 };
+    const colStyle = Object.assign(
+      {}, styles.color, { background: `rgba(${c.r}, ${c.g}, ${c.b}, ${c.a})` });
+    return (
+      <div>
+        <ControlHeader {...this.props} />
+        <OverlayTrigger
+          container={document.body}
+          trigger="click"
+          rootClose
+          ref="trigger"
+          placement="right"
+          overlay={this.renderPopover()}
+        >
+          <div style={styles.swatch}>
+            <div style={styles.checkboard} />
+            <div style={colStyle} />
+          </div>
+        </OverlayTrigger>
+      </div>
+    );
+  }
+}
+
+ColorPickerControl.propTypes = propTypes;
+ColorPickerControl.defaultProps = defaultProps;
diff --git a/superset/assets/javascripts/explore/components/controls/index.js b/superset/assets/javascripts/explore/components/controls/index.js
index e2840fb..876bc4a 100644
--- a/superset/assets/javascripts/explore/components/controls/index.js
+++ b/superset/assets/javascripts/explore/components/controls/index.js
@@ -1,6 +1,7 @@
 import BoundsControl from './BoundsControl';
 import CheckboxControl from './CheckboxControl';
 import CollectionControl from './CollectionControl';
+import ColorPickerControl from './ColorPickerControl';
 import ColorSchemeControl from './ColorSchemeControl';
 import DatasourceControl from './DatasourceControl';
 import DateFilterControl from './DateFilterControl';
@@ -17,6 +18,7 @@ const controlMap = {
   BoundsControl,
   CheckboxControl,
   CollectionControl,
+  ColorPickerControl,
   ColorSchemeControl,
   DatasourceControl,
   DateFilterControl,
diff --git a/superset/assets/javascripts/explore/main.css b/superset/assets/javascripts/explore/main.css
index bc67249..a6afe5e 100644
--- a/superset/assets/javascripts/explore/main.css
+++ b/superset/assets/javascripts/explore/main.css
@@ -113,3 +113,11 @@
 .list-group {
   margin-bottom: 10px;
 }
+.color-popover.popover {
+  border: none;
+  background-color: transparent;
+}
+.color-popover .popover-content {
+  padding: 0;
+  background-color: transparent;
+}
diff --git a/superset/assets/javascripts/explore/stores/controls.jsx b/superset/assets/javascripts/explore/stores/controls.jsx
index da8f22d..e926a47 100644
--- a/superset/assets/javascripts/explore/stores/controls.jsx
+++ b/superset/assets/javascripts/explore/stores/controls.jsx
@@ -1343,6 +1343,12 @@ export const controls = {
     description: t('The color for points and clusters in RGB'),
   },
 
+  color: {
+    type: 'ColorPickerControl',
+    label: t('Color'),
+    description: t('Pick a color'),
+  },
+
   ranges: {
     type: 'TextControl',
     label: t('Ranges'),
diff --git a/superset/assets/javascripts/modules/colors.js b/superset/assets/javascripts/modules/colors.js
index 803b683..663fd6e 100644
--- a/superset/assets/javascripts/modules/colors.js
+++ b/superset/assets/javascripts/modules/colors.js
@@ -3,7 +3,7 @@ import d3 from 'd3';
 export const brandColor = '#00A699';
 
 // Color related utility functions go in this object
-const bnbColors = [
+export const bnbColors = [
   '#ff5a5f', // rausch
   '#7b0051', // hackb
   '#007A87', // kazan
diff --git a/superset/assets/package.json b/superset/assets/package.json
index 06ae765..83c87fd 100644
--- a/superset/assets/package.json
+++ b/superset/assets/package.json
@@ -72,8 +72,9 @@
     "react-alert": "^2.3.0",
     "react-bootstrap": "^0.31.2",
     "react-bootstrap-table": "^4.0.2",
-    "react-dom": "^15.6.2",
+    "react-color": "^2.13.8",
     "react-datetime": "2.9.0",
+    "react-dom": "^15.6.2",
     "react-gravatar": "^2.6.1",
     "react-grid-layout": "^0.14.4",
     "react-map-gl": "^3.0.4",
diff --git a/superset/assets/spec/javascripts/explore/components/ColorPickerControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/ColorPickerControl_spec.jsx
new file mode 100644
index 0000000..9ce2f47
--- /dev/null
+++ b/superset/assets/spec/javascripts/explore/components/ColorPickerControl_spec.jsx
@@ -0,0 +1,41 @@
+/* eslint-disable no-unused-expressions */
+import React from 'react';
+import { expect } from 'chai';
+import { describe, it, beforeEach } from 'mocha';
+import { shallow } from 'enzyme';
+import { OverlayTrigger } from 'react-bootstrap';
+import { SketchPicker } from 'react-color';
+
+import ColorPickerControl from
+  '../../../../javascripts/explore/components/controls/ColorPickerControl';
+import ControlHeader from '../../../../javascripts/explore/components/ControlHeader';
+
+const defaultProps = {
+  value: { },
+};
+
+describe('ColorPickerControl', () => {
+  let wrapper;
+  let inst;
+  beforeEach(() => {
+    wrapper = shallow(<ColorPickerControl {...defaultProps} />);
+    inst = wrapper.instance();
+  });
+
+  it('renders a OverlayTrigger', () => {
+    const controlHeader = wrapper.find(ControlHeader);
+    expect(controlHeader).to.have.lengthOf(1);
+    expect(wrapper.find(OverlayTrigger)).to.have.length(1);
+  });
+
+  it('renders a OverlayTrigger', () => {
+    const controlHeader = wrapper.find(ControlHeader);
+    expect(controlHeader).to.have.lengthOf(1);
+    expect(wrapper.find(OverlayTrigger)).to.have.length(1);
+  });
+
+  it('renders a Popover with a SketchPicker', () => {
+    const popOver = shallow(inst.renderPopover());
+    expect(popOver.find(SketchPicker)).to.have.lengthOf(1);
+  });
+});
diff --git a/superset/assets/spec/javascripts/explore/components/ColorScheme_spec.jsx b/superset/assets/spec/javascripts/explore/components/ColorScheme_spec.jsx
new file mode 100644
index 0000000..1f5ee69
--- /dev/null
+++ b/superset/assets/spec/javascripts/explore/components/ColorScheme_spec.jsx
@@ -0,0 +1,25 @@
+/* eslint-disable no-unused-expressions */
+import React from 'react';
+import { expect } from 'chai';
+import { describe, it, beforeEach } from 'mocha';
+import { mount } from 'enzyme';
+import { Creatable } from 'react-select';
+
+import ColorSchemeControl from
+  '../../../../javascripts/explore/components/controls/ColorSchemeControl';
+import { ALL_COLOR_SCHEMES } from '../../../../javascripts/modules/colors';
+
+const defaultProps = {
+  options: Object.keys(ALL_COLOR_SCHEMES).map(s => ([s, s])),
+};
+
+describe('ColorSchemeControl', () => {
+  let wrapper;
+  beforeEach(() => {
+    wrapper = mount(<ColorSchemeControl {...defaultProps} />);
+  });
+
+  it('renders a Creatable', () => {
+    expect(wrapper.find(Creatable)).to.have.length(1);
+  });
+});

-- 
To stop receiving notification emails like this one, please contact
['"commits@superset.apache.org" <co...@superset.apache.org>'].