diff --git a/ui/Dockerfile b/ui/Dockerfile
deleted file mode 100644
index bd535c34a7..0000000000
--- a/ui/Dockerfile
+++ /dev/null
@@ -1,15 +0,0 @@
-FROM node
-
-RUN apt-get update -qq && apt-get install -y build-essential git-core
-
-ENV GOPATH=/go
-ENV APP_HOME=$GOPATH/src/github.com/influxdata/enterprise
-ENV UI_HOME=$APP_HOME/ui
-
-ARG GITHUB_TOKEN
-
-RUN git config --global url."https://${GITHUB_TOKEN}:x-oauth-basic@github.com/".insteadOf "https://github.com/"
-
-ADD . $APP_HOME
-WORKDIR $UI_HOME
-RUN npm install
diff --git a/ui/README.md b/ui/README.md
deleted file mode 100644
index 3c44aee275..0000000000
--- a/ui/README.md
+++ /dev/null
@@ -1,62 +0,0 @@
-# Enterprise UI
-
-Here lies a collection of React components used in the Enterprise web app.
-
-Currently they're organized per "page", with each separate directly having it's own components/containers folders, index.js, etc. For example:
-
-/ui
- /overview
- /components
- /containers
- index.js
- /chronograf
- /components
- /containers
- index.js
-
-## Getting started
-
-This project uses Node v5.
-
-It depends on at least one private Node module.
-In order to successfully `npm install`, you'll need an [npm authentication token](http://blog.npmjs.org/post/118393368555/deploying-with-npm-private-modules).
-
-There are two ways to get an npm token.
-
-1. You can copy someone else's token (have them give you a copy of their `~/.npmrc`).
-This is fine for most cases, and it's probably necessary for CI machines.
-2. You can create an npm account and coordinate with Mark R to join the `influxdata` npm org.
-You probably don't need this if you aren't ever going to create/publish a private Node module.
-
-### Development
-
-First, in the `ui/` folder run `npm install`.
-
-run `npm run build:dev` to start the webpack process which bundles the JS into `assets/javascripts/generated/`.
-
-### Tests
-
-We use mocha, sinon, chai, and React's TestUtils library.
-
-Run tests against jsdom from the command line:
-
-```
-npm run test # single run
-npm run test:watch # re-run tests on file changes
-```
-
-Run tests in the browser:
-
-```
-# This starts a webpack process that you'll need to leave running.
-# It rebuilds your tests on each file change.
-npm run test:browser
-# open http://localhost:7357/spec/test.html
-```
-
-### Production
-
-As before, `npm install` first.
-Then `npm run build` to generate a production build into the `assets/javascripts/generated/` folder.
-
-If you want to run tests against the production build, `npm run test` will build the test files and run the tests in a headless Phantom browser.
diff --git a/ui/spec/tasks/containers/TasksPageSpec.js b/ui/spec/tasks/containers/TasksPageSpec.js
deleted file mode 100644
index b3ed3527ec..0000000000
--- a/ui/spec/tasks/containers/TasksPageSpec.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import TasksPage from 'src/tasks/containers/TasksPage';
-import RebalanceModal from 'src/tasks/components/RebalanceModal';
-import React from 'react';
-import {mount, shallow} from 'enzyme';
-
-const clusterID = '1000';
-const JOBS = [
- {
- "source": "localhost:8088",
- "dest": "localhost:8188",
- "id": 20,
- "status": "Planned"
- },
- {
- "source": "localhost:8088",
- "dest": "localhost:8188",
- "id": 10,
- "status": "Planned"
- },
-];
-
-function setup(customProps = {}) {
- const props = Object.assign({}, {
- params: {clusterID},
- }, customProps);
- return mount();
-}
-
-function setupShallow(customProps = {}) {
- const props = Object.assign({}, {
- params: {clusterID},
- }, customProps);
- return shallow();
-}
-
-describe('Tasks.Containers.TasksPage', function() {
- before(function() { this.server = sinon.fakeServer.create(); });
- after(function() { this.server.restore() });
-
- beforeEach(function() {
- this.server.respondWith("GET", /\/api\/int\/v1\/clusters\/1000\/authorized/, [
- 200, { "Content-Type": "application/json" }, '']);
- this.server.respondWith("GET", '/api/v1/jobs', [
- 200, { "Content-Type": "application/json" }, '']);
- });
-
- describe('in intial state with no tasks', function() {
- it('renders a an empty state for the task list', function() {
- const wrapper = setupShallow();
-
- const table = wrapper.find('.tasks-empty-state');
- expect(table.text()).to.match(/No tasks/);
- });
-
- it('renders a legend', function() {
- const wrapper = setupShallow();
-
- const legend = wrapper.find('.dot-legend');
- expect(legend.text()).to.match(/Running/);
- expect(legend.text()).to.match(/Planned/);
- });
-
- it('renders a rebalance modal', function() {
- const wrapper = setupShallow();
-
- expect(wrapper.find(RebalanceModal).length).to.equal(1);
- });
-
- it('fetches a list of active tasks', function(done) {
- const wrapper = setup();
-
- this.server.respond();
-
- setTimeout(() => {
- const request = this.server.requests.find(r => r.url.match(/\/api\/v1\/jobs/));
- expect(request).to.be.ok;
- expect(request.method).to.equal('GET');
- done();
- });
- });
- });
-
- describe('when there are active tasks', function() {
- it('renders a table row for each task');
- });
-
- describe('with valid permissions', function() {
- it('renders the rebalance button', function() {
- const wrapper = setupShallow();
-
- // TODO: get this working with FakeServer. For some reason I can't
- // get it to respond and trigger the `then` block in componentDidMount.
- // Lots of async issues with testing containers like this :(.
- wrapper.setState({canRebalance: true});
- wrapper.update();
-
- const button = wrapper.find('button.rebalance');
-
- expect(button.length).to.equal(1);
- });
-
- it('sends a request to rebalance after the rebalance button is clicked');
- });
-
- describe('with invalid permissions', function() {
- it('doesn\'t render the rebalance button');
- });
-});
diff --git a/ui/src/index.js b/ui/src/index.js
index 08a439e640..84173bd462 100644
--- a/ui/src/index.js
+++ b/ui/src/index.js
@@ -8,7 +8,6 @@ import AlertsApp from 'src/alerts';
import CheckSources from 'src/CheckSources';
import {HostsPage, HostPage} from 'src/hosts';
import {KapacitorPage, KapacitorRulePage, KapacitorRulesPage, KapacitorTasksPage} from 'src/kapacitor';
-import TasksPage from 'src/tasks';
import DataExplorer from 'src/chronograf';
import {CreateSource, SourceForm, ManageSources} from 'src/sources';
import NotFound from 'src/shared/components/NotFound';
@@ -107,7 +106,6 @@ const Root = React.createClass({
-
diff --git a/ui/src/shared/apis/index.js b/ui/src/shared/apis/index.js
index b7c90c487e..76620ea455 100644
--- a/ui/src/shared/apis/index.js
+++ b/ui/src/shared/apis/index.js
@@ -35,435 +35,6 @@ export function deleteSource(source) {
});
}
-export function updateCluster(clusterID, displayName) {
- return AJAX({
- url: `/api/int/v1/clusters/${clusterID}`,
- method: 'PUT',
- data: {
- display_name: displayName,
- },
- });
-}
-
-export function getDatabaseManager(clusterID, dbName) {
- return AJAX({
- url: `/api/int/v1/${clusterID}/databases/${dbName}`,
- });
-}
-
-export function createDatabase({database, rpName, duration, replicaN}) {
- const params = new window.URLSearchParams();
- params.append('name', database);
- params.append('retention-policy', rpName);
- params.append('duration', duration);
- params.append('replication-factor', replicaN);
-
- return AJAX({
- url: `/api/int/v1/databases`,
- method: 'POST',
- headers: {'Content-Type': 'application/x-www-form-urlencoded'},
- data: params,
- });
-}
-
-export function getClusters() {
- return AJAX({
- url: ``,
- });
-}
-
-export function meShow() {
- return AJAX({
- url: `/api/int/v1/me`,
- });
-}
-
-export function meUpdate({firstName, lastName, email, password, confirmation, oldPassword}) {
- return AJAX({
- url: `/api/int/v1/me`,
- method: 'PUT',
- data: {
- first_name: firstName,
- last_name: lastName,
- email,
- password,
- confirmation,
- old_password: oldPassword,
- },
- });
-}
-
-export function getWebUsers() {
- return AJAX({
- url: `/api/int/v1/users`,
- });
-}
-
-export function createWebUser({firstName, lastName, email, password}) {
- return AJAX({
- url: `/api/int/v1/users`,
- method: 'POST',
- data: {
- first_name: firstName,
- last_name: lastName,
- email,
- password,
- },
- });
-}
-
-export function deleteWebUsers(userID) {
- return AJAX({
- url: `/api/int/v1/users/${userID}`,
- method: 'DELETE',
- });
-}
-
-export function showUser(userID) {
- return AJAX({
- url: `/api/int/v1/users/${userID}`,
- });
-}
-
-export function updateUser(userID, {firstName, lastName, email, password, confirmation, admin}) {
- return AJAX({
- url: `/api/int/v1/users/${userID}`,
- method: 'PUT',
- data: {
- first_name: firstName,
- last_name: lastName,
- email,
- password,
- confirmation,
- admin,
- },
- });
-}
-
-export function getClusterAccounts(clusterID) {
- return AJAX({
- url: metaProxy(clusterID, '/user'),
- });
-}
-
-// can only be used for initial app setup. will create first cluster user
-// with global admin permissions.
-export function createClusterUserAtSetup(clusterID, username, password) {
- return AJAX({
- url: `/api/v1/setup/cluster_user`,
- method: 'POST',
- data: {
- cluster_id: clusterID,
- username,
- password,
- },
- });
-}
-
-// can only be used for initial app setup
-export function createWebAdmin({firstName, lastName, email, password, confirmation, clusterLinks}) {
- return AJAX({
- url: `/api/v1/setup/admin`,
- method: 'POST',
- data: {
- first_name: firstName,
- last_name: lastName,
- email,
- password,
- confirmation,
- cluster_links: clusterLinks,
- },
- });
-}
-
-// can only be used for initial app setup
-export function updateClusterAtSetup(clusterID, displayName) {
- return AJAX({
- url: `/api/v1/setup/clusters/${clusterID}`,
- method: 'POST',
- data: {
- display_name: displayName,
- },
- });
-}
-
-export function createClusterUser(clusterID, name, password) {
- return AJAX({
- url: metaProxy(clusterID, '/user'),
- method: 'POST',
- data: {
- action: 'create',
- user: {
- name,
- password,
- },
- },
- });
-}
-
-export function addUsersToRole(clusterID, name, users) {
- return AJAX({
- url: metaProxy(clusterID, '/role'),
- method: 'POST',
- data: {
- action: 'add-users',
- role: {
- name,
- users,
- },
- },
- });
-}
-
-export function getClusterAccount(clusterID, accountID) {
- return AJAX({
- url: metaProxy(clusterID, `/user?name=${encodeURIComponent(accountID)}`),
- });
-}
-
-export function updateClusterAccountPassword(clusterID, name, password) {
- return AJAX({
- url: metaProxy(clusterID, '/user'),
- method: 'POST',
- data: {
- action: 'change-password',
- user: {
- name,
- password,
- },
- },
- });
-}
-
-
-export function getRoles(clusterID) {
- return AJAX({
- url: metaProxy(clusterID, '/role'),
- });
-}
-
-export function createRole(clusterID, roleName) {
- return AJAX({
- url: metaProxy(clusterID, '/role'),
- method: 'POST',
- data: {
- action: 'create',
- role: {
- name: roleName,
- },
- },
- });
-}
-
-// TODO: update usage on index page
-export function deleteClusterAccount(clusterID, accountName) {
- return Promise.all([
- // Remove the cluster account from plutonium.
- AJAX({
- url: metaProxy(clusterID, '/user'),
- method: `POST`,
- data: {
- action: 'delete',
- user: {
- name: accountName,
- },
- },
- }),
- // Remove any cluster user links that are tied to this cluster account.
- AJAX({
- url: `/api/int/v1/user_links/batch/${accountName}`,
- method: 'DELETE',
- }),
- ]);
-}
-
-export function createClusterAccount(clusterID, name, password) {
- return AJAX({
- url: metaProxy(clusterID, '/user'),
- method: `POST`,
- data: {
- action: 'create',
- user: {
- name,
- password,
- },
- },
- });
-}
-
-export function addAccountsToRole(clusterID, roleName, usernames) {
- return AJAX({
- url: metaProxy(clusterID, '/role'),
- method: 'POST',
- data: {
- action: 'add-users',
- role: {
- name: roleName,
- users: usernames,
- },
- },
- });
-}
-
-export function removeAccountsFromRole(clusterID, roleName, usernames) {
- return AJAX({
- url: metaProxy(clusterID, '/role'),
- method: 'POST',
- data: {
- action: 'remove-users',
- role: {
- name: roleName,
- users: usernames,
- },
- },
- });
-}
-
-export function addPermissionToRole(clusterID, roleName, permission) {
- const permissions = buildPermissionForPlutonium(permission);
- return AJAX({
- url: metaProxy(clusterID, '/role'),
- method: 'POST',
- data: {
- action: 'add-permissions',
- role: {
- name: roleName,
- permissions,
- },
- },
- });
-}
-
-export function removePermissionFromRole(clusterID, roleName, permission) {
- const permissions = buildPermissionForPlutonium(permission);
- return AJAX({
- url: metaProxy(clusterID, '/role'),
- method: 'POST',
- data: {
- action: 'remove-permissions',
- role: {
- name: roleName,
- permissions,
- },
- },
- });
-}
-
-export function removePermissionFromAccount(clusterID, username, permission) {
- const permissions = buildPermissionForPlutonium(permission);
- return AJAX({
- url: metaProxy(clusterID, '/user'),
- method: 'POST',
- data: {
- action: 'remove-permissions',
- user: {
- name: username,
- permissions,
- },
- },
- });
-}
-
-// The structure that plutonium expects for adding permissions is a little unorthodox,
-// where the permission(s) being added have to be under a resource key, e.g.
-// {
-// "db1": ["ViewAdmin"],
-// "": ["CreateRole"]
-// }
-// This transforms a more web client-friendly permissions object into something plutonium understands.
-function buildPermissionForPlutonium({name, resources}) {
- return resources.reduce((obj, resource) => {
- obj[resource] = [name];
- return obj;
- }, {});
-}
-
-export function addPermissionToAccount(clusterID, name, permission, resources) {
- const permissions = resources.reduce((obj, resource) => {
- obj[resource] = [permission];
- return obj;
- }, {});
-
- return AJAX({
- url: metaProxy(clusterID, '/user'),
- method: 'POST',
- data: {
- action: 'add-permissions',
- user: {
- name,
- permissions,
- },
- },
- });
-}
-
-export function deleteRole(clusterID, roleName) {
- return AJAX({
- url: metaProxy(clusterID, '/role'),
- method: 'POST',
- data: {
- action: 'delete',
- role: {
- name: roleName,
- },
- },
- });
-}
-
-export function deleteUserClusterLink(clusterID, userClusterLinkID) {
- return AJAX({
- url: `/api/int/v1/user_links/${userClusterLinkID}`,
- method: `DELETE`,
- });
-}
-
-export function getUserClusterLinks() {
- return AJAX({
- url: `/api/int/v1/user_links`,
- });
-}
-
-export function createUserClusterLink({userID, clusterID, clusterUser}) {
- return AJAX({
- url: `/api/int/v1/user_links`,
- method: 'POST',
- data: {
- user_id: userID,
- cluster_user: clusterUser,
- cluster_id: clusterID,
- },
- });
-}
-
-export function getWebUsersByClusterAccount(clusterID, clusterAccount) {
- return AJAX({
- url: `/api/int/v1/user_links/batch/${encodeURIComponent(clusterAccount)}`,
- });
-}
-
-export function batchCreateUserClusterLink(userID, clusterLinks) {
- return AJAX({
- url: `/api/int/v1/users/${userID}/cluster_links/batch`,
- method: 'POST',
- data: clusterLinks,
- });
-}
-
-export function addWebUsersToClusterAccount(clusterID, clusterAccount, userIDs) {
- return AJAX({
- url: `/api/int/v1/user_links/batch/${encodeURIComponent(clusterAccount)}`,
- method: 'POST',
- data: userIDs,
- });
-}
-
-function metaProxy(clusterID, slug) {
- return `/api/int/v1/meta${slug}`;
-}
-
-// Kapacitor functions
-// TODO: update kapacitor functions to assume only one kapacitor. waiting for @goller
-
export function getKapacitor(source) {
return AJAX({
url: source.links.kapacitors,
@@ -503,7 +74,6 @@ export function getKapacitorConfig(kapacitor) {
return kapacitorProxy(kapacitor, 'GET', '/kapacitor/v1/config', '');
}
-// updateKapacitorConfigSection will update one section in the Kapacitor config.
export function updateKapacitorConfigSection(kapacitor, section, properties) {
return AJAX({
method: 'POST',
diff --git a/ui/src/tasks/components/RebalanceModal.js b/ui/src/tasks/components/RebalanceModal.js
deleted file mode 100644
index 50da87b830..0000000000
--- a/ui/src/tasks/components/RebalanceModal.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import React, {PropTypes} from 'react';
-
-const {func} = PropTypes;
-const RebalanceModal = React.createClass({
- propTypes: {
- onConfirmRebalance: func.isRequired,
- },
-
- render() {
- return (
-
-
-
-
-
-
This is a potentially heavy operation.
Are you sure you want to rebalance?
-
-
-
-
-
-
-
-
- );
- },
-});
-
-export default RebalanceModal;
diff --git a/ui/src/tasks/components/Task.js b/ui/src/tasks/components/Task.js
deleted file mode 100644
index c451879f96..0000000000
--- a/ui/src/tasks/components/Task.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import React, {PropTypes} from 'react';
-
-const {shape, string, number} = PropTypes;
-const Task = React.createClass({
- propTypes: {
- task: shape({
- source: string,
- dest: string,
- id: number,
- status: string,
- }).isRequired,
- },
-
- render() {
- const {id, source, dest, status} = this.props.task;
- return (
-
- |
- Copy Shard | {/* TODO: Copy Shard is hardcoded, change when he have more types of tasks */}
- {source} |
- {dest} |
- {/* TODO: add killing a task into app when it exists in backend
- Kill |
- */}
-
- );
- },
-});
-
-export default Task;
diff --git a/ui/src/tasks/containers/TasksPage.js b/ui/src/tasks/containers/TasksPage.js
deleted file mode 100644
index f925d78bb5..0000000000
--- a/ui/src/tasks/containers/TasksPage.js
+++ /dev/null
@@ -1,185 +0,0 @@
-import React, {PropTypes} from 'react';
-import RebalanceModal from '../components/RebalanceModal';
-import Task from '../components/Task';
-import AJAX from 'utils/ajax';
-import {meShow} from 'shared/apis';
-
-const REFRESH_INTERVAL = 2000;
-const REBALANCE_PERMISSION = 'Rebalance';
-
-const Tasks = React.createClass({
- propTypes: {
- params: PropTypes.shape({
- clusterID: PropTypes.string.isRequired,
- }).isRequired,
- },
-
- getInitialState() {
- return {
- isRebalancing: false,
- canRebalance: false,
- tasks: [],
- };
- },
-
- componentDidMount() {
- this.fetchTasks();
- meShow().then(({data}) => {
- const clusterAccount = data.cluster_links.find((cl) => cl.cluster_id === this.props.params.clusterID);
-
- if (!clusterAccount) {
- return this.setState({canRebalance: false});
- }
-
- AJAX({
- url: `/api/int/v1/clusters/${this.props.params.clusterID}/meta/authorized?password=""&resource=""`,
- params: {
- name: clusterAccount.cluster_user,
- permission: REBALANCE_PERMISSION,
- },
- }).then(() => {
- this.setState({canRebalance: true});
- }).catch(() => {
- this.setState({canRebalance: false});
- });
- });
- },
-
- fetchTasks() {
- AJAX({
- url: '/api/v1/jobs',
- }).then((resp) => {
- const tasks = resp.data;
- this.setState({tasks});
-
- if (tasks.length) {
- this.setState({isRebalancing: true});
- if (!this.intervalID) {
- this.intervalID = setInterval(() => this.fetchTasks(), REFRESH_INTERVAL);
- }
- } else {
- this.setState({isRebalancing: false});
- clearInterval(this.intervalID);
- }
- });
- },
-
- handleRebalance() {
- AJAX({
- url: `/clusters/${this.props.params.clusterID}/rebalance`,
- method: 'POST',
- }).then(() => {
- this.fetchTasks();
- }).catch(() => {
- // TODO: render flash message
- });
- },
-
- renderRebalanceButton() {
- if (!this.state.canRebalance) {
- return null;
- }
-
- if (this.state.isRebalancing) {
- return (
-
- );
- }
-
- return (
-
- );
- },
-
- render() {
- const {tasks} = this.state;
- return (
-
-
-
-
-
- Tasks
-
-
-
- {this.renderRebalanceButton()}
-
-
-
-
-
-
-
-
-
-
Running Tasks
-
-
- {/* TODO: add back in when task histrory is introduced
- -
-
-
- Finished
-
- */}
- -
-
-
- Running
-
- -
-
-
- Planned
-
- {/* TODO: add back in when task histrory is introduced
- -
-
-
- Failed
-
- */}
-
-
-
- {tasks.length ?
-
-
-
-
- Status |
- Type |
- Source |
- Destination |
- |
-
-
-
- {tasks.map((task, index) => )}
-
-
-
:
-
-
-
-
No tasks running
-
-
- }
-
-
-
-
-
-
- );
- },
-});
-
-export default Tasks;
diff --git a/ui/src/tasks/index.js b/ui/src/tasks/index.js
deleted file mode 100644
index 82ba5db2ba..0000000000
--- a/ui/src/tasks/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import TasksPage from './containers/TasksPage';
-export default TasksPage;