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

Convert Angular services to CommonJS-style and use them in React components instead of injecting #3331

Merged
merged 10 commits into from
Jan 24, 2019
4 changes: 2 additions & 2 deletions client/app/components/AutocompleteToggle.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 { Events } from '@/services/events';

export default function AutocompleteToggle({ state, disabled, onToggle }) {
let tooltipMessage = 'Live Autocomplete Enabled';
Expand All @@ -18,7 +18,7 @@ export default function AutocompleteToggle({ state, disabled, onToggle }) {
}

const toggle = (newState) => {
recordEvent('toggle_autocomplete', 'screen', 'query_editor', { state: newState });
Events.record('toggle_autocomplete', 'screen', 'query_editor', { state: newState });
onToggle(newState);
};

Expand Down
2 changes: 1 addition & 1 deletion client/app/components/dynamic-form/DynamicForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down
3 changes: 1 addition & 2 deletions client/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
arikfr marked this conversation as resolved.
Show resolved Hide resolved
ngModule.run(($templateCache) => {
const templateName = 'bootstrap/match.tpl.html';
let template = $templateCache.get(templateName);
template = template.replace('glyphicon glyphicon-remove', 'fa fa-remove');
Expand Down
25 changes: 0 additions & 25 deletions client/app/lib/recordEvent.js

This file was deleted.

15 changes: 9 additions & 6 deletions client/app/services/alert-dialog.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export let AlertDialog = null; // eslint-disable-line import/no-mutable-exports

const AlertDialogComponent = {
template: `
<div class="modal-header">
Expand All @@ -23,8 +25,8 @@ const AlertDialogComponent = {
},
};

function AlertDialog($uibModal) {
const service = {
function AlertDialogService($uibModal) {
return {
open(title, message, confirm) {
return $uibModal.open({
component: 'alertDialog',
Expand All @@ -36,14 +38,15 @@ function AlertDialog($uibModal) {
}).result;
},
};

return service;
}

export default function init(ngModule) {
ngModule.component('alertDialog', AlertDialogComponent);
ngModule.factory('AlertDialog', AlertDialog);
ngModule.factory('AlertDialog', AlertDialogService);

ngModule.run(($injector) => {
AlertDialog = $injector.get('AlertDialog');
});
}

init.init = true;

14 changes: 9 additions & 5 deletions client/app/services/alert-subscription.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
function AlertSubscription($resource) {
const resource = $resource('api/alerts/:alertId/subscriptions/:subscriberId', { alertId: '@alert_id', subscriberId: '@id' });
return resource;
export let AlertSubscription = null; // eslint-disable-line import/no-mutable-exports

function AlertSubscriptionService($resource) {
return $resource('api/alerts/:alertId/subscriptions/:subscriberId', { alertId: '@alert_id', subscriberId: '@id' });
}

export default function init(ngModule) {
ngModule.factory('AlertSubscription', AlertSubscription);
ngModule.factory('AlertSubscription', AlertSubscriptionService);

ngModule.run(($injector) => {
AlertSubscription = $injector.get('AlertSubscription');
});
}

init.init = true;

15 changes: 9 additions & 6 deletions client/app/services/alert.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
function Alert($resource, $http) {
export let Alert = null; // eslint-disable-line import/no-mutable-exports

function AlertService($resource, $http) {
const actions = {
save: {
method: 'POST',
Expand All @@ -15,14 +17,15 @@ function Alert($resource, $http) {
}].concat($http.defaults.transformRequest),
},
};
const resource = $resource('api/alerts/:id', { id: '@id' }, actions);

return resource;
return $resource('api/alerts/:id', { id: '@id' }, actions);
}

export default function init(ngModule) {
ngModule.factory('Alert', Alert);
ngModule.factory('Alert', AlertService);

ngModule.run(($injector) => {
Alert = $injector.get('Alert');
});
}

init.init = true;

100 changes: 45 additions & 55 deletions client/app/services/auth.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,40 @@
import debug from 'debug';
import { includes, extend } from 'lodash';

const logger = debug('redash:auth');
kravets-levko marked this conversation as resolved.
Show resolved Hide resolved
const SESSION_ITEM = 'session';
const session = { loaded: false };
// eslint-disable-next-line import/no-mutable-exports
export let Auth = null;
// eslint-disable-next-line import/no-mutable-exports
export let currentUser = {
canEdit(object) {
const userId = object.user_id || (object.user && object.user.id);
return this.hasPermission('admin') || (userId && userId === this.id);
},

function storeSession(sessionData) {
logger('Updating session to be:', sessionData);
Object.assign(session, sessionData, { loaded: true });
}
hasPermission(permission) {
return includes(this.permissions, permission);
},

function getLocalSessionData() {
if (session.loaded) {
return session;
}
get isAdmin() {
return this.hasPermission('admin');
},
};
// eslint-disable-next-line import/no-mutable-exports
export let clientConfig = {};

const sessionData = window.sessionStorage.getItem(SESSION_ITEM);
if (sessionData) {
storeSession(JSON.parse(sessionData));
}
const logger = debug('redash:auth');
const session = { loaded: false };

return session;
function updateSession(sessionData) {
logger('Updating session to be:', sessionData);
extend(session, sessionData, { loaded: true });
extend(currentUser, session.user);
extend(clientConfig, session.client_config);
}

function AuthService($window, $location, $q, $http) {
const Auth = {
return {
isAuthenticated() {
const sessionData = getLocalSessionData();
return sessionData.loaded && sessionData.user.id;
return session.loaded && session.user.id;
},
login() {
const next = encodeURI($location.url());
Expand All @@ -35,27 +43,25 @@ function AuthService($window, $location, $q, $http) {
},
logout() {
logger('Logout.');
window.sessionStorage.removeItem(SESSION_ITEM);
$window.location.href = 'logout';
},
loadSession() {
logger('Loading session');
const sessionData = getLocalSessionData();
if (sessionData.loaded && sessionData.user.id) {
if (session.loaded && session.user.id) {
logger('Resolving with local value.');
return $q.resolve(sessionData);
return $q.resolve(session);
}

this.setApiKey(null);
return $http.get('api/session').then((response) => {
storeSession(response.data);
updateSession(response.data);
return session;
});
},
loadConfig() {
logger('Loading config');
return $http.get('/api/config').then((response) => {
storeSession({ client_config: response.data.client_config, user: { permissions: [] } });
updateSession({ client_config: response.data.client_config, user: { permissions: [] } });
return response.data;
});
},
Expand All @@ -68,14 +74,14 @@ function AuthService($window, $location, $q, $http) {
},
requireSession() {
logger('Requested authentication');
if (Auth.isAuthenticated()) {
return $q.when(getLocalSessionData());
if (this.isAuthenticated()) {
return $q.when(session);
}
return Auth.loadSession()
return this.loadSession()
.then(() => {
if (Auth.isAuthenticated()) {
if (this.isAuthenticated()) {
logger('Loaded session');
return getLocalSessionData();
return session;
}
logger('Need to login, redirecting');
this.login();
Expand All @@ -86,33 +92,12 @@ function AuthService($window, $location, $q, $http) {
});
},
};

return Auth;
}

function CurrentUserService() {
const sessionData = getLocalSessionData();
Object.assign(this, sessionData.user);

this.canEdit = (object) => {
const userId = object.user_id || (object.user && object.user.id);
return this.hasPermission('admin') || (userId && userId === this.id);
};

this.hasPermission = permission => this.permissions.indexOf(permission) !== -1;

this.isAdmin = this.hasPermission('admin');
}

function ClientConfigService() {
Object.assign(this, getLocalSessionData().client_config);
}

function apiKeyHttpInterceptor($injector) {
return {
request(config) {
const Auth = $injector.get('Auth');
const apiKey = Auth.getApiKey();
const apiKey = $injector.get('Auth').getApiKey();
if (apiKey) {
config.headers.Authorization = `Key ${apiKey}`;
}
Expand All @@ -124,14 +109,19 @@ function apiKeyHttpInterceptor($injector) {

export default function init(ngModule) {
ngModule.factory('Auth', AuthService);
ngModule.service('currentUser', CurrentUserService);
ngModule.service('clientConfig', ClientConfigService);
ngModule.value('currentUser', currentUser);
ngModule.value('clientConfig', clientConfig);
ngModule.factory('apiKeyHttpInterceptor', apiKeyHttpInterceptor);

ngModule.config(($httpProvider) => {
$httpProvider.interceptors.push('apiKeyHttpInterceptor');
});

ngModule.run(($injector) => {
Auth = $injector.get('Auth');
currentUser = $injector.get('currentUser');
clientConfig = $injector.get('clientConfig');
});
}

init.init = true;

11 changes: 8 additions & 3 deletions client/app/services/dashboard.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import _ from 'lodash';

export let Dashboard = null; // eslint-disable-line import/no-mutable-exports

function prepareWidgetsForDashboard(widgets) {
// Default height for auto-height widgets.
// Compute biggest widget size and choose between it and some magic number.
Expand Down Expand Up @@ -44,7 +46,7 @@ function prepareWidgetsForDashboard(widgets) {
return widgets;
}

function Dashboard($resource, $http, $location, currentUser, Widget, dashboardGridOptions) {
function DashboardService($resource, $http, $location, currentUser, Widget, dashboardGridOptions) {
function prepareDashboardWidgets(widgets) {
return prepareWidgetsForDashboard(_.map(widgets, widget => new Widget(widget)));
}
Expand Down Expand Up @@ -183,8 +185,11 @@ function Dashboard($resource, $http, $location, currentUser, Widget, dashboardGr
}

export default function init(ngModule) {
ngModule.factory('Dashboard', Dashboard);
ngModule.factory('Dashboard', DashboardService);

ngModule.run(($injector) => {
Dashboard = $injector.get('Dashboard');
});
}

init.init = true;

11 changes: 8 additions & 3 deletions client/app/services/data-source.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export const SCHEMA_NOT_SUPPORTED = 1;
export const SCHEMA_LOAD_ERROR = 2;

function DataSource($q, $resource, $http) {
export let DataSource = null; // eslint-disable-line import/no-mutable-exports

function DataSourceService($q, $resource, $http) {
function fetchSchema(dataSourceId, refresh = false) {
const params = {};

Expand Down Expand Up @@ -43,8 +45,11 @@ function DataSource($q, $resource, $http) {
}

export default function init(ngModule) {
ngModule.factory('DataSource', DataSource);
ngModule.factory('DataSource', DataSourceService);

ngModule.run(($injector) => {
DataSource = $injector.get('DataSource');
});
}

init.init = true;

Loading