Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Widget component to React #4020

Merged
merged 40 commits into from
Sep 20, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a02ce8f
Improve sizing for Number inputs
gabrieldutra Aug 1, 2019
97bfcd3
Migrate WidgetDialog
gabrieldutra Jul 31, 2019
d415c5e
Start migrating Widget
gabrieldutra Jul 31, 2019
b7cbf80
Update textbox to use HtmlContent
gabrieldutra Jul 31, 2019
4413063
QueryLink migration and some updates
gabrieldutra Aug 6, 2019
1b9d002
Add visualization rendering
gabrieldutra Aug 6, 2019
673f6c8
Render widget
gabrieldutra Aug 8, 2019
0d95996
Add delete button
gabrieldutra Aug 12, 2019
dd9fd35
Update AutoHeight
gabrieldutra Aug 12, 2019
ca01216
Add widget bottom
gabrieldutra Aug 12, 2019
7738c9e
Add Drodpown button
gabrieldutra Aug 13, 2019
ffcb419
Split Widget component
gabrieldutra Aug 15, 2019
45618c3
Update with #4056 and trigger netlify
gabrieldutra Aug 18, 2019
3ba42c0
In progress: use composition
gabrieldutra Aug 19, 2019
a7f6d41
Add header and footer
gabrieldutra Aug 22, 2019
5021b44
Update widget actions positioning
gabrieldutra Aug 22, 2019
a34ad85
Re-render when refreshing from widget
gabrieldutra Aug 22, 2019
71f6e8f
Add workaround to force DashboardGrid re-render
gabrieldutra Aug 24, 2019
1622f84
VisualizationWidgetFooter component
gabrieldutra Aug 25, 2019
a5ab07d
VisualizationWidget menu
gabrieldutra Aug 27, 2019
5f66382
Separate RestrictedWidget
gabrieldutra Aug 27, 2019
8838e97
Update tests
gabrieldutra Aug 27, 2019
584200c
Update margin for Parameters
gabrieldutra Aug 27, 2019
daf21ac
Merge branch 'master' into react-widget
gabrieldutra Aug 27, 2019
9f269c1
Remove widget files
gabrieldutra Aug 27, 2019
7f6bcd7
Revert "Improve sizing for Number inputs"
gabrieldutra Aug 28, 2019
111b68e
Some cleanup
gabrieldutra Aug 29, 2019
b81a555
Merge branch 'master' into react-widget
gabrieldutra Aug 30, 2019
6d6f81a
Move refresh logic to the Dashboard
gabrieldutra Aug 31, 2019
83e7149
Add loadingWidgets logic to the public dashboard
gabrieldutra Sep 2, 2019
ade0b48
Merge branch 'master' into react-widget
gabrieldutra Sep 2, 2019
da6e93e
Add onLoadWidget
gabrieldutra Sep 2, 2019
5b3e9b9
Remove parameter from URL when empty
gabrieldutra Sep 2, 2019
7f24c27
Recreate widget array instead of loadingWidgets
gabrieldutra Sep 3, 2019
4716d4b
Add comment about re-rendering + whitespace missing
gabrieldutra Sep 3, 2019
72da894
Merge branch 'master' into react-widget
gabrieldutra Sep 11, 2019
cd69e16
CR changes
gabrieldutra Sep 11, 2019
80897e4
Use plain html instead of string syntax
gabrieldutra Sep 11, 2019
3f49b59
Merge branch 'master' into react-widget
gabrieldutra Sep 18, 2019
97f402a
Merge branch 'react-widget' of github.com:getredash/redash into react…
gabrieldutra Sep 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/app/components/Parameters.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,10 @@ export class Parameters extends React.Component {
this.setState(({ parameters }) => {
const parametersWithPendingValues = parameters.filter(p => p.hasPendingValue);
forEach(parameters, p => p.applyPendingValue());
onValuesChange(parametersWithPendingValues);
if (!disableUrlUpdate) {
updateUrl(parameters);
}
onValuesChange(parametersWithPendingValues);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Dashboard context it needs to have the url updated before triggering onValuesChange

return { parameters };
});
};
Expand Down
6 changes: 5 additions & 1 deletion client/app/components/dashboards/DashboardGrid.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class DashboardGrid extends React.Component {
widgets: PropTypes.arrayOf(WidgetType).isRequired,
filters: FiltersType,
onBreakpointChange: PropTypes.func,
onRefreshWidget: PropTypes.func,
onRemoveWidget: PropTypes.func,
onLayoutChange: PropTypes.func,
onParameterMappingsChange: PropTypes.func,
Expand All @@ -52,6 +53,7 @@ class DashboardGrid extends React.Component {
static defaultProps = {
isPublic: false,
filters: [],
onRefreshWidget: () => {},
onRemoveWidget: () => {},
onLayoutChange: () => {},
onBreakpointChange: () => {},
Expand Down Expand Up @@ -174,7 +176,8 @@ class DashboardGrid extends React.Component {

render() {
const className = cx('dashboard-wrapper', this.props.isEditing ? 'editing-mode' : 'preview-mode');
const { onRemoveWidget, onParameterMappingsChange, filters, dashboard, isPublic, widgets } = this.props;
const { onRefreshWidget, onRemoveWidget, onParameterMappingsChange,
filters, dashboard, isPublic, widgets } = this.props;

return (
<div className={className}>
Expand Down Expand Up @@ -212,6 +215,7 @@ class DashboardGrid extends React.Component {
<VisualizationWidget
{...widgetProps}
dashboard={dashboard}
onRefresh={() => onRefreshWidget(widget)}
onParameterMappingsChange={onParameterMappingsChange}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import cx from 'classnames';
import Menu from 'antd/lib/menu';
import { currentUser } from '@/services/auth';
import recordEvent from '@/services/recordEvent';
import { $location } from '@/services/ng';
import { formatDateTime } from '@/filters/datetime';
import HtmlContent from '@/components/HtmlContent';
import { Parameters } from '@/components/Parameters';
Expand Down Expand Up @@ -155,6 +154,7 @@ class VisualizationWidget extends React.Component {
filters: FiltersType,
isPublic: PropTypes.bool,
canEdit: PropTypes.bool,
onRefresh: PropTypes.func,
onDelete: PropTypes.func,
onParameterMappingsChange: PropTypes.func,
};
Expand All @@ -163,37 +163,22 @@ class VisualizationWidget extends React.Component {
filters: [],
isPublic: false,
canEdit: false,
onRefresh: () => {},
onDelete: () => {},
onParameterMappingsChange: () => {},
};

constructor(props) {
super(props);
const widgetQueryResult = props.widget.getQueryResult();
const widgetStatus = widgetQueryResult && widgetQueryResult.getStatus();

this.state = { widgetStatus, localParameters: props.widget.getLocalParameters() };
this.state = { localParameters: props.widget.getLocalParameters() };
}

componentDidMount() {
const { widget } = this.props;
recordEvent('view', 'query', widget.visualization.query.id, { dashboard: true });
recordEvent('view', 'visualization', widget.visualization.id, { dashboard: true });
this.loadWidget();
}

loadWidget = (refresh = false) => {
const { widget } = this.props;
const maxAge = $location.search().maxAge;
return widget.load(refresh, maxAge).then(({ status }) => {
this.setState({ widgetStatus: status });
}).catch(() => {
this.setState({ widgetStatus: 'failed' });
});
};

refreshWidget = () => this.loadWidget(true);

expandWidget = () => {
ExpandedWidgetDialog.showModal({ widget: this.props.widget });
};
Expand All @@ -215,8 +200,8 @@ class VisualizationWidget extends React.Component {

renderVisualization() {
const { widget, filters } = this.props;
const { widgetStatus } = this.state;
const widgetQueryResult = widget.getQueryResult();
const widgetStatus = widgetQueryResult && widgetQueryResult.getStatus();
switch (widgetStatus) {
case 'failed':
return (
Expand Down Expand Up @@ -250,7 +235,7 @@ class VisualizationWidget extends React.Component {
}

render() {
const { widget, isPublic, canEdit } = this.props;
const { widget, isPublic, canEdit, onRefresh } = this.props;
const { localParameters } = this.state;
const widgetQueryResult = widget.getQueryResult();
const isRefreshing = widget.loading && !!(widgetQueryResult && widgetQueryResult.getStatus());
Expand All @@ -266,14 +251,14 @@ class VisualizationWidget extends React.Component {
<VisualizationWidgetHeader
widget={widget}
parameters={localParameters}
onParametersUpdate={this.refreshWidget}
onParametersUpdate={onRefresh}
/>
)}
footer={(
<VisualizationWidgetFooter
widget={widget}
isPublic={isPublic}
onRefresh={this.refreshWidget}
onRefresh={onRefresh}
onExpand={this.expandWidget}
/>
)}
Expand Down
1 change: 1 addition & 0 deletions client/app/pages/dashboards/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ <h3>
refreshing-widgets="$ctrl.refreshingWidgets"
on-layout-change="$ctrl.onLayoutChange"
on-breakpoint-change="$ctrl.onBreakpointChanged"
on-refresh-widget="$ctrl.refreshWidget"
on-remove-widget="$ctrl.removeWidget"
on-parameter-mappings-change="$ctrl.extractGlobalParameters"
/>
Expand Down
14 changes: 9 additions & 5 deletions client/app/pages/dashboards/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,14 @@ function DashboardCtrl(
this.globalParameters = this.dashboard.getParametersDefs();
};

this.loadWidget = (widget, forceRefresh) => {
gabrieldutra marked this conversation as resolved.
Show resolved Hide resolved
widget.getParametersDefs(); // Force widget to read parameters values from URL
this.refreshingWidgets += 1;
return widget.load(forceRefresh).finally(() => { this.refreshingWidgets -= 1; });
};

this.refreshWidget = widget => this.loadWidget(widget, true);

const collectFilters = (dashboard, forceRefresh, updatedParameters = []) => {
const affectedWidgets = updatedParameters.length > 0 ? this.dashboard.widgets.filter(
widget => Object.values(widget.getParameterMappings()).filter(
Expand All @@ -143,11 +151,7 @@ function DashboardCtrl(
),
) : this.dashboard.widgets;

const queryResultPromises = _.compact(affectedWidgets.map((widget) => {
widget.getParametersDefs(); // Force widget to read parameters values from URL
this.refreshingWidgets += 1;
return widget.load(forceRefresh).finally(() => { this.refreshingWidgets -= 1; });
}));
const queryResultPromises = _.compact(affectedWidgets.map(widget => this.loadWidget(widget, forceRefresh)));

return $q.all(queryResultPromises).then((queryResults) => {
this.filters = collectDashboardFilters(dashboard, queryResults, $location.search());
Expand Down