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 | 1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
| 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;
|