Skip to content

Commit

Permalink
[Widget Params] Migrated edit params + new widget dialog to Ant Modal (
Browse files Browse the repository at this point in the history
  • Loading branch information
ranbena authored Feb 4, 2019
1 parent 933dd75 commit 3df3724
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 175 deletions.
121 changes: 44 additions & 77 deletions client/app/components/dashboards/AddWidgetDialog.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { debounce, each, values, map, includes, first } from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import { react2angular } from 'react2angular';
import Select from 'antd/lib/select';
import Modal from 'antd/lib/modal';
import ModalOpener from '@/hoc/ModalOpener';
import highlight from '@/lib/highlight';
import {
MappingType,
Expand All @@ -19,15 +20,14 @@ const { Option, OptGroup } = Select;

class AddWidgetDialog extends React.Component {
static propTypes = {
dashboard: PropTypes.object, // eslint-disable-line react/forbid-prop-types
close: PropTypes.func,
dismiss: PropTypes.func,
dashboard: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
onClose: PropTypes.func,
onConfirm: PropTypes.func,
};

static defaultProps = {
dashboard: null,
close: () => {},
dismiss: () => {},
onClose: () => {},
onConfirm: () => {},
};

constructor(props) {
Expand All @@ -40,12 +40,14 @@ class AddWidgetDialog extends React.Component {
searchedQueries: [],
selectedVis: null,
parameterMappings: [],
showModal: false, // show only after recent queries populated to avoid height "jump"
};

// Don't show draft (unpublished) queries in recent queries.
Query.recent().$promise.then((items) => {
this.setState({
recentQueries: items.filter(item => !item.is_draft),
showModal: true,
});
});

Expand All @@ -57,6 +59,10 @@ class AddWidgetDialog extends React.Component {
};
}

close = () => {
this.setState({ showModal: false });
}

selectQuery(queryId) {
// Clear previously selected query (if any)
this.setState({
Expand Down Expand Up @@ -143,7 +149,8 @@ class AddWidgetDialog extends React.Component {
.save()
.then(() => {
dashboard.widgets.push(widget);
this.props.close();
this.props.onConfirm();
this.close();
})
.catch(() => {
toastr.error('Widget can not be added');
Expand Down Expand Up @@ -290,77 +297,37 @@ class AddWidgetDialog extends React.Component {
);

return (
<div>
<div className="modal-header">
<button
type="button"
className="close"
disabled={this.state.saveInProgress}
aria-hidden="true"
onClick={this.props.dismiss}
>
&times;
</button>
<h4 className="modal-title">Add Widget</h4>
</div>
<div className="modal-body">
{this.renderQueryInput()}
{!this.state.selectedQuery && this.renderSearchQueryResults()}
{this.state.selectedQuery && this.renderVisualizationInput()}

{
(this.state.parameterMappings.length > 0) && [
<label key="parameters-title" htmlFor="parameter-mappings">Parameters</label>,
<ParameterMappingListInput
key="parameters-list"
id="parameter-mappings"
mappings={this.state.parameterMappings}
existingParams={existingParams}
onChange={mappings => this.updateParamMappings(mappings)}
/>,
]
}
</div>
<Modal
visible={this.state.showModal}
afterClose={this.props.onClose}
title="Add Widget"
onOk={() => this.saveWidget()}
okButtonProps={{
loading: this.state.saveInProgress,
disabled: !this.state.selectedQuery,
}}
okText="Add to Dashboard"
onCancel={this.close}
>
{this.renderQueryInput()}
{!this.state.selectedQuery && this.renderSearchQueryResults()}
{this.state.selectedQuery && this.renderVisualizationInput()}

<div className="modal-footer">
<button
type="button"
className="btn btn-default"
disabled={this.state.saveInProgress}
onClick={this.props.dismiss}
>
Close
</button>
<button
type="button"
className="btn btn-primary"
disabled={this.state.saveInProgress || !this.state.selectedQuery}
onClick={() => this.saveWidget()}
>
Add to Dashboard
</button>
</div>
</div>
{
(this.state.parameterMappings.length > 0) && [
<label key="parameters-title" htmlFor="parameter-mappings">Parameters</label>,
<ParameterMappingListInput
key="parameters-list"
id="parameter-mappings"
mappings={this.state.parameterMappings}
existingParams={existingParams}
onChange={mappings => this.updateParamMappings(mappings)}
/>,
]
}
</Modal>
);
}
}

export default function init(ngModule) {
ngModule.component('addWidgetDialog', {
template: `
<add-widget-dialog-impl
dashboard="$ctrl.resolve.dashboard"
close="$ctrl.close"
dismiss="$ctrl.dismiss"
></add-widget-dialog-impl>
`,
bindings: {
resolve: '<',
close: '&',
dismiss: '&',
},
});
ngModule.component('addWidgetDialogImpl', react2angular(AddWidgetDialog));
}

init.init = true;
export default ModalOpener(AddWidgetDialog);
104 changes: 32 additions & 72 deletions client/app/components/dashboards/EditParameterMappingsDialog.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { map } from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import { react2angular } from 'react2angular';
import Modal from 'antd/lib/modal';
import ModalOpener from '@/hoc/ModalOpener';
import {
ParameterMappingListInput,
parameterMappingsToEditableMappings,
Expand All @@ -10,17 +11,15 @@ import {

class EditParameterMappingsDialog extends React.Component {
static propTypes = {
dashboard: PropTypes.object, // eslint-disable-line react/forbid-prop-types
widget: PropTypes.object, // eslint-disable-line react/forbid-prop-types
close: PropTypes.func,
dismiss: PropTypes.func,
dashboard: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
widget: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
onClose: PropTypes.func,
onConfirm: PropTypes.func,
};

static defaultProps = {
dashboard: null,
widget: null,
close: () => {},
dismiss: () => {},
onClose: () => {},
onConfirm: () => {},
};

constructor(props) {
Expand All @@ -32,9 +31,14 @@ class EditParameterMappingsDialog extends React.Component {
props.widget.query.getParametersDefs(),
map(this.props.dashboard.getParametersDefs(), p => p.name),
),
showModal: true,
};
}

close = () => {
this.setState({ showModal: false });
}

saveWidget() {
const toastr = this.props.toastr; // eslint-disable-line react/prop-types
const widget = this.props.widget;
Expand All @@ -45,7 +49,8 @@ class EditParameterMappingsDialog extends React.Component {
widget
.save()
.then(() => {
this.props.close();
this.props.onConfirm();
this.close();
})
.catch(() => {
toastr.error('Widget cannot be updated');
Expand All @@ -66,69 +71,24 @@ class EditParameterMappingsDialog extends React.Component {
);

return (
<div>
<div className="modal-header">
<button
type="button"
className="close"
disabled={this.state.saveInProgress}
aria-hidden="true"
onClick={this.props.dismiss}
>
&times;
</button>
<h4 className="modal-title">Parameters</h4>
</div>
<div className="modal-body">
{(this.state.parameterMappings.length > 0) && (
<ParameterMappingListInput
mappings={this.state.parameterMappings}
existingParams={existingParams}
onChange={mappings => this.updateParamMappings(mappings)}
/>
)}
</div>

<div className="modal-footer">
<button
type="button"
className="btn btn-default"
disabled={this.state.saveInProgress}
onClick={this.props.dismiss}
>
Close
</button>
<button
type="button"
className="btn btn-primary"
disabled={this.state.saveInProgress}
onClick={() => this.saveWidget()}
>
Save
</button>
</div>
</div>
<Modal
visible={this.state.showModal}
afterClose={this.props.onClose}
title="Parameters"
onOk={() => this.saveWidget()}
okButtonProps={{ loading: this.state.saveInProgress }}
onCancel={this.close}
>
{(this.state.parameterMappings.length > 0) && (
<ParameterMappingListInput
mappings={this.state.parameterMappings}
existingParams={existingParams}
onChange={mappings => this.updateParamMappings(mappings)}
/>
)}
</Modal>
);
}
}

export default function init(ngModule) {
ngModule.component('editParameterMappingsDialog', {
template: `
<edit-parameter-mappings-dialog-impl
dashboard="$ctrl.resolve.dashboard"
widget="$ctrl.resolve.widget"
close="$ctrl.close"
dismiss="$ctrl.dismiss"
></edit-parameter-mappings-dialog-impl>
`,
bindings: {
resolve: '<',
close: '&',
dismiss: '&',
},
});
ngModule.component('editParameterMappingsDialogImpl', react2angular(EditParameterMappingsDialog));
}

init.init = true;
export default ModalOpener(EditParameterMappingsDialog);
4 changes: 3 additions & 1 deletion client/app/components/dashboards/widget.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@

<li ng-if="$ctrl.canViewQuery || ($ctrl.dashboard.canEdit() && $ctrl.hasParameters())" class="divider"></li>
<li ng-if="$ctrl.canViewQuery"><a ng-href="{{$ctrl.widget.getQuery().getUrl(true, $ctrl.widget.visualization.id)}}">View Query</a></li>
<li ng-if="$ctrl.dashboard.canEdit() && $ctrl.hasParameters()"><a ng-click="$ctrl.editParameterMappings()">Edit Parameters</a></li>
<li ng-if="$ctrl.dashboard.canEdit() && $ctrl.hasParameters()">
<li ng-if="$ctrl.dashboard.canEdit() && $ctrl.hasParameters()"><a ng-click="$ctrl.editParameterMappings()">Edit Parameters</a></li>
</li>

<li ng-if="$ctrl.dashboard.canEdit()" class="divider"></li>
<li ng-if="$ctrl.dashboard.canEdit()"><a ng-click="$ctrl.deleteWidget()">Remove from Dashboard</a></li>
Expand Down
11 changes: 4 additions & 7 deletions client/app/components/dashboards/widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { filter } from 'lodash';
import template from './widget.html';
import editTextBoxTemplate from './edit-text-box.html';
import widgetDialogTemplate from './widget-dialog.html';
import editParameterMappingsDialog from '@/components/dashboards/EditParameterMappingsDialog';
import './widget.less';
import './widget-dialog.less';

Expand Down Expand Up @@ -78,13 +79,9 @@ function DashboardWidgetCtrl($location, $uibModal, $window, $rootScope, Events,
this.hasParameters = () => this.widget.query.getParametersDefs().length > 0;

this.editParameterMappings = () => {
$uibModal.open({
component: 'editParameterMappingsDialog',
resolve: {
dashboard: this.dashboard,
widget: this.widget,
},
size: 'lg',
editParameterMappingsDialog.open({
dashboard: this.dashboard,
widget: this.widget,
}).result.then(() => {
this.localParameters = null;
$rootScope.$broadcast('dashboard.update-parameters');
Expand Down
36 changes: 36 additions & 0 deletions client/app/hoc/ModalOpener.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import ReactDOM from 'react-dom';

const ModalOpener = (WrappedComponent) => {
const container = document.createElement('div');

const render = (component) => {
ReactDOM.render(component, container);
document.body.appendChild(container);
};

const destroy = () => {
ReactDOM.unmountComponentAtNode(container);
document.body.removeChild(container);
};

const getResult = props => new Promise((resolve) => {
const component = (
<WrappedComponent
onClose={destroy}
onConfirm={resolve}
{...props}
/>
);

render(component);
});

return {
open: props => ({
result: getResult(props),
}),
};
};

export default ModalOpener;
Loading

0 comments on commit 3df3724

Please sign in to comment.