all files / src/dashboard/components/ GridCell.jsx

42.59% Statements 23/54
27.27% Branches 6/22
12.5% Functions 1/8
38.78% Lines 19/49
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158                                                                                                                                                                                                                                                                                      
EI/* eslint-disable react/no-danger */
import React from 'react';
import PropTypes from 'prop-types';
 
import SliceHeader from './SliceHeader';
import ChartContainer from '../../chart/ChartContainer';
 
import '../../../stylesheets/dashboard.css';
 
const propTypes = {
  timeout: PropTypes.number,
  datasource: PropTypes.object,
  isLoading: PropTypes.bool,
  isCached: PropTypes.bool,
  cachedDttm: PropTypes.string,
  isExpanded: PropTypes.bool,
  widgetHeight: PropTypes.number,
  widgetWidth: PropTypes.number,
  slice: PropTypes.object,
  chartKey: PropTypes.string,
  formData: PropTypes.object,
  filters: PropTypes.object,
  forceRefresh: PropTypes.func,
  removeSlice: PropTypes.func,
  updateSliceName: PropTypes.func,
  toggleExpandSlice: PropTypes.func,
  exploreChart: PropTypes.func,
  exportCSV: PropTypes.func,
  addFilter: PropTypes.func,
  getFilters: PropTypes.func,
  clearFilter: PropTypes.func,
  removeFilter: PropTypes.func,
  editMode: PropTypes.bool,
  annotationQuery: PropTypes.object,
};
 
const defaultProps = {
  forceRefresh: () => ({}),
  removeSlice: () => ({}),
  updateSliceName: () => ({}),
  toggleExpandSlice: () => ({}),
  exploreChart: () => ({}),
  exportCSV: () => ({}),
  addFilter: () => ({}),
  getFilters: () => ({}),
  clearFilter: () => ({}),
  removeFilter: () => ({}),
  editMode: false,
};
 
class GridCell extends React.PureComponent {
  constructor(props) {
    super(props);
 
    const sliceId = this.props.slice.slice_id;
    this.addFilter = this.props.addFilter.bind(this, sliceId);
    this.getFilters = this.props.getFilters.bind(this, sliceId);
    this.clearFilter = this.props.clearFilter.bind(this, sliceId);
    this.removeFilter = this.props.removeFilter.bind(this, sliceId);
  }
 
  getDescriptionId(slice) {
    return 'description_' + slice.slice_id;
  }
 
  getHeaderId(slice) {
    return 'header_' + slice.slice_id;
  }
 
  width() {
    return this.props.widgetWidth - 10;
  }
 
  height(slice) {
    const widgetHeight = this.props.widgetHeight;
    const headerHeight = this.headerHeight(slice);
    const descriptionId = this.getDescriptionId(slice);
    let descriptionHeight = 0;
    if (this.props.isExpanded && this.refs[descriptionId]) {
      descriptionHeight = this.refs[descriptionId].offsetHeight + 10;
    }
 
    return widgetHeight - headerHeight - descriptionHeight;
  }
 
  headerHeight(slice) {
    const headerId = this.getHeaderId(slice);
    return this.refs[headerId] ? this.refs[headerId].offsetHeight : 30;
  }
 
  render() {
    const {
      isExpanded, isLoading, isCached, cachedDttm,
      removeSlice, updateSliceName, toggleExpandSlice, forceRefresh,
      chartKey, slice, datasource, formData, timeout, annotationQuery,
      exploreChart, exportCSV,
    } = this.props;
    return (
      <div
        className={isLoading ? 'slice-cell-highlight' : 'slice-cell'}
        id={`${slice.slice_id}-cell`}
      >
        <div ref={this.getHeaderId(slice)}>
          <SliceHeader
            slice={slice}
            isExpanded={isExpanded}
            isCached={isCached}
            cachedDttm={cachedDttm}
            removeSlice={removeSlice}
            updateSliceName={updateSliceName}
            toggleExpandSlice={toggleExpandSlice}
            forceRefresh={forceRefresh}
            editMode={this.props.editMode}
            annotationQuery={annotationQuery}
            exploreChart={exploreChart}
            exportCSV={exportCSV}
          />
        </div>
        {
        /* This usage of dangerouslySetInnerHTML is safe since it is being used to render
           markdown that is sanitized with bleach. See:
             https://github.com/apache/incubator-superset/pull/4390
           and
             https://github.com/apache/incubator-superset/commit/b6fcc22d5a2cb7a5e92599ed5795a0169385a825 */}
        <div
          className="slice_description bs-callout bs-callout-default"
          style={isExpanded ? {} : { display: 'none' }}
          ref={this.getDescriptionId(slice)}
          dangerouslySetInnerHTML={{ __html: slice.description_markeddown }}
        />
        <div className="row chart-container">
          <input type="hidden" value="false" />
          <ChartContainer
            containerId={`slice-container-${slice.slice_id}`}
            chartKey={chartKey}
            datasource={datasource}
            formData={formData}
            headerHeight={this.headerHeight(slice)}
            height={this.height(slice)}
            width={this.width()}
            timeout={timeout}
            vizType={slice.formData.viz_type}
            addFilter={this.addFilter}
            getFilters={this.getFilters}
            clearFilter={this.clearFilter}
            removeFilter={this.removeFilter}
          />
        </div>
      </div>
    );
  }
}
 
GridCell.propTypes = propTypes;
GridCell.defaultProps = defaultProps;
 
export default GridCell;