diff --git a/client/app/components/AutocompleteToggle.jsx b/client/app/components/AutocompleteToggle.jsx
index e74e0a9047..5a4c9bff20 100644
--- a/client/app/components/AutocompleteToggle.jsx
+++ b/client/app/components/AutocompleteToggle.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import Tooltip from 'antd/lib/tooltip';
import PropTypes from 'prop-types';
import '@/redash-font/style.less';
-import recordEvent from '@/lib/recordEvent';
+import recordEvent from '@/services/recordEvent';
export default function AutocompleteToggle({ state, disabled, onToggle }) {
let tooltipMessage = 'Live Autocomplete Enabled';
diff --git a/client/app/components/DateInput.jsx b/client/app/components/DateInput.jsx
index 695a2a1997..ff7812ed8e 100644
--- a/client/app/components/DateInput.jsx
+++ b/client/app/components/DateInput.jsx
@@ -3,12 +3,11 @@ import React from 'react';
import PropTypes from 'prop-types';
import { react2angular } from 'react2angular';
import DatePicker from 'antd/lib/date-picker';
+import { clientConfig } from '@/services/auth';
export function DateInput({
value,
onSelect,
- // eslint-disable-next-line react/prop-types
- clientConfig,
className,
}) {
const format = clientConfig.dateFormat || 'YYYY-MM-DD';
@@ -46,7 +45,7 @@ DateInput.defaultProps = {
};
export default function init(ngModule) {
- ngModule.component('dateInput', react2angular(DateInput, null, ['clientConfig']));
+ ngModule.component('dateInput', react2angular(DateInput));
}
init.init = true;
diff --git a/client/app/components/DateRangeInput.jsx b/client/app/components/DateRangeInput.jsx
index 1b1454bbb5..d8ccef48f7 100644
--- a/client/app/components/DateRangeInput.jsx
+++ b/client/app/components/DateRangeInput.jsx
@@ -4,14 +4,13 @@ import React from 'react';
import PropTypes from 'prop-types';
import { react2angular } from 'react2angular';
import DatePicker from 'antd/lib/date-picker';
+import { clientConfig } from '@/services/auth';
const { RangePicker } = DatePicker;
export function DateRangeInput({
value,
onSelect,
- // eslint-disable-next-line react/prop-types
- clientConfig,
className,
}) {
const format = clientConfig.dateFormat || 'YYYY-MM-DD';
@@ -53,7 +52,7 @@ DateRangeInput.defaultProps = {
};
export default function init(ngModule) {
- ngModule.component('dateRangeInput', react2angular(DateRangeInput, null, ['clientConfig']));
+ ngModule.component('dateRangeInput', react2angular(DateRangeInput));
}
init.init = true;
diff --git a/client/app/components/DateTimeInput.jsx b/client/app/components/DateTimeInput.jsx
index d95fd60884..92fb81f104 100644
--- a/client/app/components/DateTimeInput.jsx
+++ b/client/app/components/DateTimeInput.jsx
@@ -3,13 +3,12 @@ import React from 'react';
import PropTypes from 'prop-types';
import { react2angular } from 'react2angular';
import DatePicker from 'antd/lib/date-picker';
+import { clientConfig } from '@/services/auth';
export function DateTimeInput({
value,
withSeconds,
onSelect,
- // eslint-disable-next-line react/prop-types
- clientConfig,
className,
}) {
const format = (clientConfig.dateFormat || 'YYYY-MM-DD') +
@@ -51,7 +50,7 @@ DateTimeInput.defaultProps = {
};
export default function init(ngModule) {
- ngModule.component('dateTimeInput', react2angular(DateTimeInput, null, ['clientConfig']));
+ ngModule.component('dateTimeInput', react2angular(DateTimeInput));
}
init.init = true;
diff --git a/client/app/components/DateTimeRangeInput.jsx b/client/app/components/DateTimeRangeInput.jsx
index d0fa5ecb39..51f6c62ddc 100644
--- a/client/app/components/DateTimeRangeInput.jsx
+++ b/client/app/components/DateTimeRangeInput.jsx
@@ -4,6 +4,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { react2angular } from 'react2angular';
import DatePicker from 'antd/lib/date-picker';
+import { clientConfig } from '@/services/auth';
const { RangePicker } = DatePicker;
@@ -11,8 +12,6 @@ export function DateTimeRangeInput({
value,
withSeconds,
onSelect,
- // eslint-disable-next-line react/prop-types
- clientConfig,
className,
}) {
const format = (clientConfig.dateFormat || 'YYYY-MM-DD') +
@@ -58,7 +57,7 @@ DateTimeRangeInput.defaultProps = {
};
export default function init(ngModule) {
- ngModule.component('dateTimeRangeInput', react2angular(DateTimeRangeInput, null, ['clientConfig']));
+ ngModule.component('dateTimeRangeInput', react2angular(DateTimeRangeInput));
}
init.init = true;
diff --git a/client/app/components/Footer.jsx b/client/app/components/Footer.jsx
index bd1f06efda..7e45562fe1 100644
--- a/client/app/components/Footer.jsx
+++ b/client/app/components/Footer.jsx
@@ -1,11 +1,10 @@
import React from 'react';
-import PropTypes from 'prop-types';
-
import { react2angular } from 'react2angular';
+import { clientConfig, currentUser } from '@/services/auth';
import frontendVersion from '../version.json';
-export function Footer({ clientConfig, currentUser }) {
+export function Footer() {
const backendVersion = clientConfig.version;
const newVersionAvailable = clientConfig.newVersionAvailable && currentUser.isAdmin;
const separator = ' \u2022 ';
@@ -31,18 +30,8 @@ export function Footer({ clientConfig, currentUser }) {
);
}
-Footer.propTypes = {
- clientConfig: PropTypes.shape({
- version: PropTypes.string,
- newVersionAvailable: PropTypes.bool,
- }).isRequired,
- currentUser: PropTypes.shape({
- isAdmin: PropTypes.bool,
- }).isRequired,
-};
-
export default function init(ngModule) {
- ngModule.component('footer', react2angular(Footer, [], ['clientConfig', 'currentUser']));
+ ngModule.component('footer', react2angular(Footer));
}
init.init = true;
diff --git a/client/app/components/Footer.test.js b/client/app/components/Footer.test.js
index 81a157ebfc..519a9e5732 100644
--- a/client/app/components/Footer.test.js
+++ b/client/app/components/Footer.test.js
@@ -1,16 +1,19 @@
+import { extend } from 'lodash';
import React from 'react';
import renderer from 'react-test-renderer';
+import { clientConfig, currentUser } from '../services/auth';
import { Footer } from './Footer';
test('Footer renders', () => {
- const clientConfig = {
+ // TODO: Properly mock this
+ extend(clientConfig, {
version: '5.0.1',
newVersionAvailable: true,
- };
- const currentUser = {
- isAdmin: true,
- };
- const component = renderer.create();
+ });
+ extend(currentUser, {
+ permissions: ['admin'],
+ });
+ const component = renderer.create();
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
diff --git a/client/app/components/ParameterValueInput.jsx b/client/app/components/ParameterValueInput.jsx
index c16edcc7af..301e83fc91 100644
--- a/client/app/components/ParameterValueInput.jsx
+++ b/client/app/components/ParameterValueInput.jsx
@@ -31,99 +31,69 @@ export class ParameterValueInput extends React.Component {
};
renderDateTimeWithSecondsInput() {
- const {
- value,
- onSelect,
- clientConfig, // eslint-disable-line react/prop-types
- } = this.props;
+ const { value, onSelect } = this.props;
return (
);
}
renderDateTimeInput() {
- const {
- value,
- onSelect,
- clientConfig, // eslint-disable-line react/prop-types
- } = this.props;
+ const { value, onSelect } = this.props;
return (
);
}
renderDateInput() {
- const {
- value,
- onSelect,
- clientConfig, // eslint-disable-line react/prop-types
- } = this.props;
+ const { value, onSelect } = this.props;
return (
);
}
renderDateTimeRangeWithSecondsInput() {
- const {
- value,
- onSelect,
- clientConfig, // eslint-disable-line react/prop-types
- } = this.props;
+ const { value, onSelect } = this.props;
return (
);
}
renderDateTimeRangeInput() {
- const {
- value,
- onSelect,
- clientConfig, // eslint-disable-line react/prop-types
- } = this.props;
+ const { value, onSelect } = this.props;
return (
);
}
renderDateRangeInput() {
- const {
- value,
- onSelect,
- clientConfig, // eslint-disable-line react/prop-types
- } = this.props;
+ const { value, onSelect } = this.props;
return (
);
}
@@ -146,19 +116,13 @@ export class ParameterValueInput extends React.Component {
}
renderQueryBasedInput() {
- const {
- value,
- onSelect,
- queryId,
- Query, // eslint-disable-line react/prop-types
- } = this.props;
+ const { value, onSelect, queryId } = this.props;
return (
);
}
@@ -212,10 +176,7 @@ export default function init(ngModule) {
};
},
});
- ngModule.component(
- 'parameterValueInputImpl',
- react2angular(ParameterValueInput, null, ['clientConfig', 'Query']),
- );
+ ngModule.component('parameterValueInputImpl', react2angular(ParameterValueInput));
}
init.init = true;
diff --git a/client/app/components/QueryBasedParameterInput.jsx b/client/app/components/QueryBasedParameterInput.jsx
index f9ef4ebace..8c82bda54e 100644
--- a/client/app/components/QueryBasedParameterInput.jsx
+++ b/client/app/components/QueryBasedParameterInput.jsx
@@ -3,6 +3,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { react2angular } from 'react2angular';
import Select from 'antd/lib/select';
+import { Query } from '@/services/query';
const { Option } = Select;
@@ -79,7 +80,6 @@ export class QueryBasedParameterInput extends React.Component {
_loadOptions(queryId) {
if (queryId && (queryId !== this.state.queryId)) {
- const Query = this.props.Query; // eslint-disable-line react/prop-types
this.setState({ loading: true });
Query.resultById({ id: queryId }, (result) => {
if (this.props.queryId === queryId) {
@@ -117,7 +117,7 @@ export class QueryBasedParameterInput extends React.Component {
}
export default function init(ngModule) {
- ngModule.component('queryBasedParameterInput', react2angular(QueryBasedParameterInput, null, ['Query']));
+ ngModule.component('queryBasedParameterInput', react2angular(QueryBasedParameterInput));
}
init.init = true;
diff --git a/client/app/components/QueryEditor.jsx b/client/app/components/QueryEditor.jsx
index f9e2499f8f..c86b704a1c 100644
--- a/client/app/components/QueryEditor.jsx
+++ b/client/app/components/QueryEditor.jsx
@@ -14,6 +14,10 @@ import 'brace/mode/sql';
import 'brace/theme/textmate';
import 'brace/ext/searchbox';
+import { Query } from '@/services/query';
+import { QuerySnippet } from '@/services/query-snippet';
+import { KeyboardShortcuts } from '@/services/keyboard-shortcuts';
+
import localOptions from '@/lib/localOptions';
import AutocompleteToggle from '@/components/AutocompleteToggle';
import keywordBuilder from './keywordBuilder';
@@ -152,8 +156,7 @@ class QueryEditor extends React.Component {
}
});
- // eslint-disable-next-line react/prop-types
- this.props.QuerySnippet.query((snippets) => {
+ QuerySnippet.query((snippets) => {
const snippetManager = snippetsModule.snippetManager;
const m = {
snippetText: '',
@@ -194,7 +197,7 @@ class QueryEditor extends React.Component {
const selectedQueryText = (rawSelectedQueryText.length > 1) ? rawSelectedQueryText : null;
this.setState({ selectedQueryText });
this.props.updateSelectedQuery(selectedQueryText);
- }
+ };
updateQuery = (queryText) => {
this.props.updateQuery(queryText);
@@ -202,9 +205,7 @@ class QueryEditor extends React.Component {
};
formatQuery = () => {
- // eslint-disable-next-line react/prop-types
- const format = this.props.Query.format;
- format(this.props.dataSource.syntax || 'sql', this.props.queryText)
+ Query.format(this.props.dataSource.syntax || 'sql', this.props.queryText)
.then(this.updateQuery)
.catch(error => toastr.error(error));
};
@@ -212,11 +213,10 @@ class QueryEditor extends React.Component {
toggleAutocomplete = (state) => {
this.setState({ autocompleteQuery: state });
localOptions.set('liveAutocomplete', state);
- }
+ };
render() {
- // eslint-disable-next-line react/prop-types
- const modKey = this.props.KeyboardShortcuts.modKey;
+ const modKey = KeyboardShortcuts.modKey;
const isExecuteDisabled = this.props.queryExecuting || !this.props.canExecuteQuery();
@@ -320,7 +320,7 @@ class QueryEditor extends React.Component {
}
export default function init(ngModule) {
- ngModule.component('queryEditor', react2angular(QueryEditor, null, ['QuerySnippet', 'Query', 'KeyboardShortcuts']));
+ ngModule.component('queryEditor', react2angular(QueryEditor));
}
init.init = true;
diff --git a/client/app/components/dashboards/AddTextboxDialog.jsx b/client/app/components/dashboards/AddTextboxDialog.jsx
index 97fead0cc8..6d9510ae51 100644
--- a/client/app/components/dashboards/AddTextboxDialog.jsx
+++ b/client/app/components/dashboards/AddTextboxDialog.jsx
@@ -3,6 +3,8 @@ import { debounce } from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import { react2angular } from 'react2angular';
+import { toastr } from '@/services/ng';
+import { Widget } from '@/services/widget';
class AddTextboxDialog extends React.Component {
static propTypes = {
@@ -38,8 +40,6 @@ class AddTextboxDialog extends React.Component {
}
saveWidget() {
- const Widget = this.props.Widget; // eslint-disable-line react/prop-types
- const toastr = this.props.toastr; // eslint-disable-line react/prop-types
const dashboard = this.props.dashboard;
this.setState({ saveInProgress: true });
@@ -148,7 +148,7 @@ export default function init(ngModule) {
dismiss: '&',
},
});
- ngModule.component('addTextboxDialogImpl', react2angular(AddTextboxDialog, null, ['toastr', 'Widget']));
+ ngModule.component('addTextboxDialogImpl', react2angular(AddTextboxDialog));
}
init.init = true;
diff --git a/client/app/components/dashboards/AddWidgetDialog.jsx b/client/app/components/dashboards/AddWidgetDialog.jsx
index 6d51a35e90..ea351575f4 100644
--- a/client/app/components/dashboards/AddWidgetDialog.jsx
+++ b/client/app/components/dashboards/AddWidgetDialog.jsx
@@ -10,6 +10,10 @@ import {
editableMappingsToParameterMappings,
} from '@/components/ParameterMappingInput';
+import { toastr } from '@/services/ng';
+import { Widget } from '@/services/widget';
+import { Query } from '@/services/query';
+
const { Option, OptGroup } = Select;
class AddWidgetDialog extends React.Component {
@@ -38,7 +42,6 @@ class AddWidgetDialog extends React.Component {
};
// Don't show draft (unpublished) queries
- const Query = this.props.Query; // eslint-disable-line react/prop-types
Query.recent().$promise.then((items) => {
this.setState({
recentQueries: items.filter(item => !item.is_draft),
@@ -62,7 +65,6 @@ class AddWidgetDialog extends React.Component {
});
if (queryId) {
- const Query = this.props.Query; // eslint-disable-line react/prop-types
Query.get({ id: queryId }, (query) => {
if (query) {
const existingParamNames = map(
@@ -95,7 +97,6 @@ class AddWidgetDialog extends React.Component {
return;
}
- const Query = this.props.Query; // eslint-disable-line react/prop-types
Query.query({ q: term }, (results) => {
// If user will type too quick - it's possible that there will be
// several requests running simultaneously. So we need to check
@@ -117,8 +118,6 @@ class AddWidgetDialog extends React.Component {
}
saveWidget() {
- const Widget = this.props.Widget; // eslint-disable-line react/prop-types
- const toastr = this.props.toastr; // eslint-disable-line react/prop-types
const dashboard = this.props.dashboard;
this.setState({ saveInProgress: true });
@@ -278,9 +277,6 @@ class AddWidgetDialog extends React.Component {
}
render() {
- const clientConfig = this.props.clientConfig; // eslint-disable-line react/prop-types
- const Query = this.props.Query; // eslint-disable-line react/prop-types
-
const existingParams = map(
this.props.dashboard.getParametersDefs(),
({ name, type }) => ({ name, type }),
@@ -313,8 +309,6 @@ class AddWidgetDialog extends React.Component {
mappings={this.state.parameterMappings}
existingParams={existingParams}
onChange={mappings => this.updateParamMappings(mappings)}
- clientConfig={clientConfig}
- Query={Query}
/>,
]
}
@@ -358,8 +352,7 @@ export default function init(ngModule) {
dismiss: '&',
},
});
- ngModule.component('addWidgetDialogImpl', react2angular(AddWidgetDialog, null, [
- 'toastr', 'Widget', 'Query', 'clientConfig']));
+ ngModule.component('addWidgetDialogImpl', react2angular(AddWidgetDialog));
}
init.init = true;
diff --git a/client/app/components/dashboards/EditParameterMappingsDialog.jsx b/client/app/components/dashboards/EditParameterMappingsDialog.jsx
index 2230224933..776be76f6c 100644
--- a/client/app/components/dashboards/EditParameterMappingsDialog.jsx
+++ b/client/app/components/dashboards/EditParameterMappingsDialog.jsx
@@ -60,9 +60,6 @@ class EditParameterMappingsDialog extends React.Component {
}
render() {
- const clientConfig = this.props.clientConfig; // eslint-disable-line react/prop-types
- const Query = this.props.Query; // eslint-disable-line react/prop-types
-
const existingParams = map(
this.props.dashboard.getParametersDefs(),
({ name, type }) => ({ name, type }),
@@ -89,8 +86,6 @@ class EditParameterMappingsDialog extends React.Component {
mappings={this.state.parameterMappings}
existingParams={existingParams}
onChange={mappings => this.updateParamMappings(mappings)}
- clientConfig={clientConfig}
- Query={Query}
/>
}
@@ -134,8 +129,7 @@ export default function init(ngModule) {
dismiss: '&',
},
});
- ngModule.component('editParameterMappingsDialogImpl', react2angular(EditParameterMappingsDialog, null, [
- 'Query', 'clientConfig']));
+ ngModule.component('editParameterMappingsDialogImpl', react2angular(EditParameterMappingsDialog));
}
init.init = true;
diff --git a/client/app/components/dynamic-form/DynamicForm.jsx b/client/app/components/dynamic-form/DynamicForm.jsx
index a35ede9107..329e2493a7 100644
--- a/client/app/components/dynamic-form/DynamicForm.jsx
+++ b/client/app/components/dynamic-form/DynamicForm.jsx
@@ -8,7 +8,7 @@ import Button from 'antd/lib/button';
import Upload from 'antd/lib/upload';
import Icon from 'antd/lib/icon';
import { react2angular } from 'react2angular';
-import { toastr } from '@/services/toastr';
+import { toastr } from '@/services/ng';
import { Field, Action, AntdForm } from '../proptypes';
import helper from './dynamicFormHelper';
diff --git a/client/app/components/tags-control/DashboardTagsControl.jsx b/client/app/components/tags-control/DashboardTagsControl.jsx
index 1a535d4994..7337964308 100644
--- a/client/app/components/tags-control/DashboardTagsControl.jsx
+++ b/client/app/components/tags-control/DashboardTagsControl.jsx
@@ -6,7 +6,7 @@ export class DashboardTagsControl extends ModelTagsControl {
}
export default function init(ngModule) {
- ngModule.component('dashboardTagsControl', react2angular(DashboardTagsControl, null, ['$uibModal']));
+ ngModule.component('dashboardTagsControl', react2angular(DashboardTagsControl));
}
init.init = true;
diff --git a/client/app/components/tags-control/QueryTagsControl.jsx b/client/app/components/tags-control/QueryTagsControl.jsx
index cd071e2308..9b56c26700 100644
--- a/client/app/components/tags-control/QueryTagsControl.jsx
+++ b/client/app/components/tags-control/QueryTagsControl.jsx
@@ -6,7 +6,7 @@ export class QueryTagsControl extends ModelTagsControl {
}
export default function init(ngModule) {
- ngModule.component('queryTagsControl', react2angular(QueryTagsControl, null, ['$uibModal']));
+ ngModule.component('queryTagsControl', react2angular(QueryTagsControl));
}
init.init = true;
diff --git a/client/app/components/tags-control/TagsControl.jsx b/client/app/components/tags-control/TagsControl.jsx
index c486ac78af..0a28c0f98d 100644
--- a/client/app/components/tags-control/TagsControl.jsx
+++ b/client/app/components/tags-control/TagsControl.jsx
@@ -1,6 +1,7 @@
import { map, trim } from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
+import { $uibModal } from '@/services/ng';
export default class TagsControl extends React.Component {
static propTypes = {
@@ -20,7 +21,7 @@ export default class TagsControl extends React.Component {
};
editTags() {
- const { getAvailableTags, onEdit, $uibModal } = this.props; // eslint-disable-line react/prop-types
+ const { getAvailableTags, onEdit } = this.props; // eslint-disable-line react/prop-types
const tags = map(this.props.tags, trim);
getAvailableTags().then((availableTags) => {
diff --git a/client/app/index.js b/client/app/index.js
index 11699ee39c..5b24c90750 100644
--- a/client/app/index.js
+++ b/client/app/index.js
@@ -13,8 +13,7 @@ ngModule.config(($locationProvider, $compileProvider, uiSelectConfig, toastrConf
});
// Update ui-select's template to use Font-Awesome instead of glyphicon.
-// eslint-disable-next-line no-unused-vars
-ngModule.run(($templateCache, OfflineListener) => {
+ngModule.run(($templateCache) => {
const templateName = 'bootstrap/match.tpl.html';
let template = $templateCache.get(templateName);
template = template.replace('glyphicon glyphicon-remove', 'fa fa-remove');
diff --git a/client/app/pages/queries/view.js b/client/app/pages/queries/view.js
index 76fc36b991..d8c4f1aacb 100644
--- a/client/app/pages/queries/view.js
+++ b/client/app/pages/queries/view.js
@@ -1,6 +1,7 @@
import { pick, some, find, minBy, map, intersection, isArray, isObject } from 'lodash';
import { SCHEMA_NOT_SUPPORTED, SCHEMA_LOAD_ERROR } from '@/services/data-source';
import getTags from '@/services/getTags';
+import Notifications from '@/services/notifications';
import template from './query.html';
const DEFAULT_TAB = 'table';
@@ -16,7 +17,6 @@ function QueryViewCtrl(
KeyboardShortcuts,
Title,
AlertDialog,
- Notifications,
clientConfig,
toastr,
$uibModal,
diff --git a/client/app/services/alert-dialog.js b/client/app/services/alert-dialog.js
index c64b48c30c..84b1c410a2 100644
--- a/client/app/services/alert-dialog.js
+++ b/client/app/services/alert-dialog.js
@@ -1,3 +1,5 @@
+export let AlertDialog = null; // eslint-disable-line import/no-mutable-exports
+
const AlertDialogComponent = {
template: `