/
WidgetGrid.js
125 lines (115 loc) · 4.95 KB
/
WidgetGrid.js
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
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import _get from 'lodash/get'
import _map from 'lodash/map'
import _isFunction from 'lodash/isFunction'
import ReactGridLayout, { WidthProvider } from 'react-grid-layout'
import { widgetComponent } from '../../services/Widget/Widget'
import WithWidgetManagement
from '../HOCs/WithWidgetManagement/WithWidgetManagement'
import WidgetPicker from '../WidgetPicker/WidgetPicker'
import "../../../node_modules/react-grid-layout/css/styles.css"
import "../../../node_modules/react-resizable/css/styles.css"
import './WidgetGrid.scss'
const GridLayout = WidthProvider(ReactGridLayout)
export class WidgetGrid extends Component {
render() {
// Setup each widget. Note that we assign a z-index to each widget so that
// widgets closer to the top of the page have a higher z-index than widgets
// closer to the bottom of the page. This is so that an open dropdown menu
// in a widget can extend below it and overlap the widget immediately
// below. The z-index is necessary because react-grid-layout starts a new
// stacking context for each widget, so by default widgets lower on the
// page would be rendered on top of widgets higher on the page since they
// appear lower in the DOM, thus breaking drop-down menus that extend below
// a widget
const highestY = Math.max(
..._map(this.props.workspace.widgets, (w, i) => this.props.workspace.layout[i].y)
)
const GridFilters = this.props.filterComponent
const conditionalWidgets = this.props.workspace.conditionalWidgets || []
const widgetInstances =
_map(this.props.workspace.widgets, (widgetConfiguration, index) => {
let widgetHidden = false
const WidgetComponent = widgetComponent(widgetConfiguration)
if (!WidgetComponent) {
throw new Error(`Missing component for widget: ${widgetConfiguration.widgetKey}`)
}
const widgetLayout = this.props.workspace.layout[index]
// Hide conditional widgets that shouldn't be shown
if (conditionalWidgets.indexOf(widgetConfiguration.widgetKey) !== -1) {
if (_isFunction(WidgetComponent.hideWidget) && WidgetComponent.hideWidget(this.props)) {
widgetHidden = true
if (widgetLayout.h > 0) {
widgetConfiguration.priorHeight = widgetLayout.h
widgetLayout.minH = 0
widgetLayout.h = 0
}
}
else if (widgetLayout.h === 0) {
widgetLayout.minH = widgetConfiguration.minHeight
widgetLayout.h = widgetConfiguration.priorHeight > 0 ?
widgetConfiguration.priorHeight :
widgetConfiguration.defaultHeight
}
}
return (
<div
key={widgetLayout.i}
className={classNames(
"mr-card-widget", {
'mr-card-widget--editing': this.props.isEditing,
'mr-card-widget--top-row': widgetLayout.y === 0,
})}
style={{
"zIndex": widgetHidden ? 0 : (highestY - widgetLayout.y), // higher values towards top of page
}}
>
<WidgetComponent {...this.props}
widgetLayout={widgetLayout}
widgetConfiguration={_get(widgetConfiguration, 'defaultConfiguration', {})}
updateWidgetConfiguration={conf => this.props.updateWidgetConfiguration(index, conf)}
widgetHidden={widgetHidden}
removeWidget={() => this.props.removeWidget(index)} />
</div>
)
})
return (
<div className={classNames("widget-grid", {"widget-grid--editing": this.props.isEditing})}>
<div className="widget-grid__controls">
{GridFilters && <GridFilters {...this.props} />}
{this.props.isEditing &&
<React.Fragment>
{this.props.editNameControl}
<WidgetPicker {...this.props} isRight onWidgetSelected={this.props.addWidget} />
{this.props.doneEditingControl}
</React.Fragment>
}
</div>
<GridLayout
className="widget-grid"
cols={this.props.workspace.cols || 12}
rowHeight={this.props.workspace.rowHeight || 30}
layout={this.props.workspace.layout || []}
margin={[16, 16]}
isDraggable={this.props.isEditing}
isResizable={this.props.isEditing}
onLayoutChange={this.props.onLayoutChange}
>
{widgetInstances}
</GridLayout>
</div>
)
}
}
WidgetGrid.propTypes = {
workspace: PropTypes.shape({
widgets: PropTypes.array.isRequired,
cols: PropTypes.number,
rowHeight: PropTypes.number,
layout: PropTypes.array,
}).isRequired,
onLayoutChange: PropTypes.func.isRequired,
}
export default WithWidgetManagement(WidgetGrid)