Skip to content

Commit

Permalink
Remove AngularJS and related dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
kravets-levko committed Jan 13, 2020
1 parent 824ef59 commit b2b504e
Show file tree
Hide file tree
Showing 18 changed files with 119 additions and 265 deletions.
1 change: 0 additions & 1 deletion client/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"@babel/preset-react"
],
"plugins": [
"angularjs-annotate",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-transform-object-assign",
["babel-plugin-transform-builtin-extend", {
Expand Down
2 changes: 0 additions & 2 deletions client/app/components/FavoritesControl.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from "react";
import PropTypes from "prop-types";
import { $rootScope } from "@/services/ng";

export default class FavoritesControl extends React.Component {
static propTypes = {
Expand All @@ -21,7 +20,6 @@ export default class FavoritesControl extends React.Component {
action().then(() => {
item.is_favorite = !savedIsFavorite;
this.forceUpdate();
$rootScope.$broadcast("reloadFavorites");
callback();
});
}
Expand Down
8 changes: 4 additions & 4 deletions client/app/components/queries/ApiKeyDialog/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Input from "antd/lib/input";
import Button from "antd/lib/button";
import { wrap as wrapDialog, DialogPropType } from "@/components/DialogWrapper";
import CodeBlock from "@/components/CodeBlock";
import { $http } from "@/services/ng";
import { axios } from "@/services/axios";
import { clientConfig } from "@/services/auth";
import notification from "@/services/notification";

Expand All @@ -18,13 +18,13 @@ function ApiKeyDialog({ dialog, ...props }) {

const regenerateQueryApiKey = useCallback(() => {
setUpdatingApiKey(true);
$http
axios
.post(`api/queries/${query.id}/regenerate_api_key`)
.success(data => {
.then(data => {
setUpdatingApiKey(false);
setQuery(extend(query.clone(), { api_key: data.api_key }));
})
.error(() => {
.catch(() => {
setUpdatingApiKey(false);
notification.error("Failed to update API key");
});
Expand Down
24 changes: 2 additions & 22 deletions client/app/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@ import "core-js/fn/typed/array-buffer";
import "@/assets/images/avatar.svg";

import * as Pace from "pace-progress";
import angular from "angular";
import ngRoute from "angular-route";
import { isFunction } from "lodash";

import DialogWrapper from "@/components/DialogWrapper";

import "./antd-spinner";
import moment from "moment";

Pace.options.shouldHandlePushState = (prevUrl, newUrl) => {
const link = document.createElement('a');
const link = document.createElement("a");
// Show pace progress bar only if URL path changed; when query params
// or hash changed - ignore that history event
link.href = prevUrl;
Expand Down Expand Up @@ -43,10 +39,6 @@ moment.updateLocale("en", {
},
});

const requirements = [ngRoute];

const ngModule = angular.module("app", requirements);

function registerAll(context) {
const modules = context
.keys()
Expand All @@ -56,7 +48,7 @@ function registerAll(context) {
return modules
.filter(isFunction)
.filter(f => f.init)
.map(f => f(ngModule));
.map(f => f());
}

function requireImages() {
Expand All @@ -70,23 +62,11 @@ function registerExtensions() {
registerAll(context);
}

function registerServices() {
const context = require.context("@/services", true, /^((?![\\/.]test[\\./]).)*\.js$/);
registerAll(context);
}

function registerVisualizations() {
const context = require.context("@/visualizations", true, /^((?![\\/.]test[\\./]).)*\.jsx?$/);
registerAll(context);
}

requireImages();
registerServices();
registerExtensions();
registerVisualizations();

ngModule.run($q => {
DialogWrapper.Promise = $q;
});

export default ngModule;
1 change: 0 additions & 1 deletion client/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

<body>
<section>
<div style="display: none" ng-app="app" ng-strict-di=""></div>
<div id="application-root"></div>
<div class="loading-indicator">
<div id="css-logo">
Expand Down
13 changes: 4 additions & 9 deletions client/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@ import React from "react";
import ReactDOM from "react-dom";
import ApplicationArea from "@/components/ApplicationArea";

// ANGULAR_REMOVE_ME Init angular app to make services working
import ngModule from "@/config";
import "@/config";

// ANGULAR_REMOVE_ME This setting should be enabled because otherwise it conflicts with `history` module
ngModule.config($locationProvider => {
$locationProvider.html5Mode(true);
});
import offlineListener from "@/services/offline-listener";

// ANGULAR_REMOVE_ME Wait for ng-app to start application so exports in @/services/*** will be initialized
ngModule.run(() => {
ReactDOM.render(<ApplicationArea />, document.getElementById("application-root"));
ReactDOM.render(<ApplicationArea />, document.getElementById("application-root"), () => {
offlineListener.init();
});
1 change: 0 additions & 1 deletion client/app/multi_org.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

<body>
<section>
<div style="display: none" ng-app="app" ng-strict-di=""></div>
<div id="application-root"></div>
<div class="loading-indicator">
<div id="css-logo">
Expand Down
2 changes: 1 addition & 1 deletion client/app/pages/queries/VisualizationEmbed.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ function VisualizationEmbed({ queryId, visualizationId, apiKey }) {

useEffect(() => {
let isCancelled = false;
Query.get({ id: queryId }).$promise.then(result => {
Query.get({ id: queryId }).then(result => {
if (!isCancelled) {
setQuery(result);
}
Expand Down
13 changes: 4 additions & 9 deletions client/app/pages/queries/hooks/useUnsavedChangesAlert.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useRef, useEffect } from "react";
import { $rootScope } from "@/services/ng";
import location from "@/services/location";

// TODO: This should be revisited and probably re-implemented when replacing Angular router with sth else
export default function useUnsavedChangesAlert(shouldShowAlert = false) {
Expand All @@ -16,14 +16,9 @@ export default function useUnsavedChangesAlert(shouldShowAlert = false) {
return shouldShowAlertRef.current ? unloadMessage : undefined;
};

// ANGULAR_REMOVE_ME
const unsubscribe = $rootScope.$on("$locationChangeStart", (event, next, current) => {
if (next.split("?")[0] === current.split("?")[0] || next.split("#")[0] === current.split("#")[0]) {
return;
}

if (shouldShowAlertRef.current && !window.confirm(confirmMessage)) {
event.preventDefault();
const unsubscribe = location.confirmChange((nextLocation, currentLocation) => {
if (shouldShowAlertRef.current && nextLocation.path !== currentLocation.path) {
return confirmMessage;
}
});

Expand Down
134 changes: 58 additions & 76 deletions client/app/services/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ import { includes, extend } from "lodash";
import location from "@/services/location";
import { axios } from "@/services/axios";

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

export const currentUser = {
canEdit(object) {
const userId = object.user_id || (object.user && object.user.id);
Expand Down Expand Up @@ -41,78 +38,63 @@ function updateSession(sessionData) {
extend(messages, session.messages);
}

function AuthService($window, $q) {
return {
isAuthenticated() {
return session.loaded && session.user.id;
},
login() {
const next = encodeURI(location.url);
logger("Calling login with next = %s", next);
window.location.href = `login?next=${next}`;
},
logout() {
logger("Logout.");
$window.location.href = "logout";
},
loadSession() {
logger("Loading session");
if (session.loaded && session.user.id) {
logger("Resolving with local value.");
return $q.resolve(session);
}
export const Auth = {
isAuthenticated() {
return session.loaded && session.user.id;
},
login() {
const next = encodeURI(location.url);
logger("Calling login with next = %s", next);
window.location.href = `login?next=${next}`;
},
logout() {
logger("Logout.");
window.location.href = "logout";
},
loadSession() {
logger("Loading session");
if (session.loaded && session.user.id) {
logger("Resolving with local value.");
return Promise.resolve(session);
}

this.setApiKey(null);
return axios.get("api/session").then(data => {
updateSession(data);
return session;
});
},
loadConfig() {
logger("Loading config");
return axios.get("/api/config").then(data => {
updateSession({ client_config: data.client_config, user: { permissions: [] }, messages: [] });
return data;
Auth.setApiKey(null);
return axios.get("api/session").then(data => {
updateSession(data);
return session;
});
},
loadConfig() {
logger("Loading config");
return axios.get("/api/config").then(data => {
updateSession({ client_config: data.client_config, user: { permissions: [] }, messages: [] });
return data;
});
},
setApiKey(apiKey) {
logger("Set API key to: %s", apiKey);
Auth.apiKey = apiKey;
},
getApiKey() {
return Auth.apiKey;
},
requireSession() {
logger("Requested authentication");
if (Auth.isAuthenticated()) {
return Promise.resolve(session);
}
return Auth.loadSession()
.then(() => {
if (Auth.isAuthenticated()) {
logger("Loaded session");
return session;
}
logger("Need to login, redirecting");
Auth.login();
})
.catch(() => {
logger("Need to login, redirecting");
Auth.login();
});
},
setApiKey(apiKey) {
logger("Set API key to: %s", apiKey);
this.apiKey = apiKey;
},
getApiKey() {
return this.apiKey;
},
requireSession() {
logger("Requested authentication");
if (this.isAuthenticated()) {
return $q.when(session);
}
return this.loadSession()
.then(() => {
if (this.isAuthenticated()) {
logger("Loaded session");
return session;
}
logger("Need to login, redirecting");
this.login();
})
.catch(() => {
logger("Need to login, redirecting");
this.login();
});
},
};
}

export default function init(ngModule) {
ngModule.factory("Auth", AuthService);
ngModule.value("currentUser", currentUser);
ngModule.value("clientConfig", clientConfig);
ngModule.value("messages", messages);

ngModule.run($injector => {
Auth = $injector.get("Auth");
});
}

init.init = true;
},
};
22 changes: 8 additions & 14 deletions client/app/services/axios.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import axiosLib from "axios";
import { Auth } from "@/services/auth";

export const axios = axiosLib.create();

Expand All @@ -7,18 +8,11 @@ const getResponse = ({ response }) => Promise.reject(response);

axios.interceptors.response.use(getData, getResponse);

// TODO: revisit this definition when auth is updated
export default function init(ngModule) {
ngModule.run($injector => {
axios.interceptors.request.use(config => {
const apiKey = $injector.get("Auth").getApiKey();
if (apiKey) {
config.headers.Authorization = `Key ${apiKey}`;
}
axios.interceptors.request.use(config => {
const apiKey = Auth.getApiKey();
if (apiKey) {
config.headers.Authorization = `Key ${apiKey}`;
}

return config;
});
});
}

init.init = true;
return config;
});
Loading

1 comment on commit b2b504e

@arikfr
Copy link
Member

@arikfr arikfr commented on b2b504e Jan 13, 2020

Choose a reason for hiding this comment

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

🤩

Please sign in to comment.