removing old API dependencies
parent
0a583b2492
commit
3a0b233d04
|
@ -4,9 +4,6 @@ import SideNavContainer from 'src/side_nav';
|
|||
|
||||
const App = React.createClass({
|
||||
propTypes: {
|
||||
params: PropTypes.shape({
|
||||
clusterID: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
addFlashMessage: PropTypes.func.isRequired, // Injected by the `FlashMessages` wrapper
|
||||
children: PropTypes.node.isRequired,
|
||||
location: PropTypes.shape({
|
||||
|
@ -15,11 +12,9 @@ const App = React.createClass({
|
|||
},
|
||||
|
||||
render() {
|
||||
const {clusterID} = this.props.params;
|
||||
|
||||
return (
|
||||
<div className="enterprise-wrapper--flex">
|
||||
<SideNavContainer addFlashMessage={this.props.addFlashMessage} clusterID={clusterID} currentLocation={this.props.location.pathname} />
|
||||
<SideNavContainer addFlashMessage={this.props.addFlashMessage} currentLocation={this.props.location.pathname} />
|
||||
<div className="page-wrapper">
|
||||
{this.props.children && React.cloneElement(this.props.children, {
|
||||
addFlashMessage: this.props.addFlashMessage,
|
||||
|
|
|
@ -2,16 +2,13 @@ import React, {PropTypes} from 'react';
|
|||
import NoClusterError from 'shared/components/NoClusterError';
|
||||
import NoClusterLinksError from 'shared/components/NoClusterLinksError';
|
||||
import {webUserShape} from 'src/utils/propTypes';
|
||||
import {showCluster} from 'src/shared/apis';
|
||||
import {getSources} from 'src/shared/apis';
|
||||
|
||||
// Acts as a 'router middleware'. The main `App` component is responsible for
|
||||
// getting the list of data nodes, but not every page requires them to function.
|
||||
// Routes that do require data nodes can be nested under this component.
|
||||
const CheckDataNodes = React.createClass({
|
||||
propTypes: {
|
||||
params: PropTypes.shape({
|
||||
clusterID: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
addFlashMessage: PropTypes.func,
|
||||
children: PropTypes.node,
|
||||
},
|
||||
|
@ -44,8 +41,8 @@ const CheckDataNodes = React.createClass({
|
|||
},
|
||||
|
||||
componentDidMount() {
|
||||
const {clusterID} = this.props.params;
|
||||
showCluster(clusterID).then((resp) => {
|
||||
getSources().then((resp) => {
|
||||
// TODO: get this wired up correctly once getSources is working.
|
||||
const dataNodes = this.getHealthyDataNodes(resp.data.data);
|
||||
this.setState({
|
||||
dataNodes,
|
||||
|
|
|
@ -104,7 +104,7 @@ export const RolePageContainer = React.createClass({
|
|||
deleteRole(clusterID, roleSlug).then(() => {
|
||||
// TODO: add success notification when we're implementing them higher in the tree.
|
||||
// Right now the notification just gets swallowed when we transition to a new route.
|
||||
this.props.router.push(`/clusters/${clusterID}/roles`);
|
||||
this.props.router.push(`/roles`);
|
||||
}).catch(err => {
|
||||
console.error(err.toString()); // eslint-disable-line no-console
|
||||
this.addErrorNotification(err);
|
||||
|
|
|
@ -158,7 +158,7 @@ export function createExplorer(clusterID, push) {
|
|||
}).then((resp) => {
|
||||
const explorer = parseRawExplorer(resp.data);
|
||||
dispatch(loadExplorer(explorer));
|
||||
push(`/clusters/${clusterID}/chronograf/data_explorer/${explorer.id}`);
|
||||
push(`/chronograf/data_explorer/${explorer.id}`);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ export function deleteExplorer(clusterID, explorerID, push) {
|
|||
// explorer and should create a new one.
|
||||
if (explorer) {
|
||||
dispatch(loadExplorer(explorer));
|
||||
push(`/clusters/${clusterID}/chronograf/data_explorer/${explorer.id}`);
|
||||
push(`/chronograf/data_explorer/${explorer.id}`);
|
||||
} else {
|
||||
dispatch(createExplorer(clusterID, push));
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ export function fetchExplorers({clusterID, explorerID, push}) {
|
|||
if (!explorerID) {
|
||||
const explorer = _.maxBy(explorers, (ex) => ex.updated_at);
|
||||
dispatch(loadExplorer(explorer));
|
||||
push(`/clusters/${clusterID}/chronograf/data_explorer/${explorer.id}`);
|
||||
push(`/chronograf/data_explorer/${explorer.id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -306,7 +306,7 @@ export function chooseExplorer(clusterID, explorerID, push) {
|
|||
}).then((resp) => {
|
||||
const explorer = parseRawExplorer(resp.data);
|
||||
dispatch(loadExplorer(explorer));
|
||||
push(`/clusters/${clusterID}/chronograf/data_explorer/${explorerID}`);
|
||||
push(`/chronograf/data_explorer/${explorerID}`);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -235,7 +235,7 @@ export const ClusterAccountContainer = React.createClass({
|
|||
handleDeleteAccount() {
|
||||
const {clusterID, accountID} = this.props.params;
|
||||
deleteClusterAccount(clusterID, accountID).then(() => {
|
||||
this.props.router.push(`/clusters/${clusterID}/accounts`);
|
||||
this.props.router.push(`/accounts`);
|
||||
this.props.addFlashMessage({
|
||||
type: 'success',
|
||||
text: 'Cluster account deleted!',
|
||||
|
|
|
@ -8,7 +8,6 @@ const {number, string, shape, arrayOf, func} = PropTypes;
|
|||
|
||||
const DatabaseManager = React.createClass({
|
||||
propTypes: {
|
||||
clusterID: string.isRequired,
|
||||
database: string.isRequired,
|
||||
databases: arrayOf(shape({})).isRequired,
|
||||
dbStats: shape({
|
||||
|
@ -24,7 +23,7 @@ const DatabaseManager = React.createClass({
|
|||
},
|
||||
|
||||
render() {
|
||||
const {database, clusterID, databases, dbStats, queries, users,
|
||||
const {database, databases, dbStats, queries, users,
|
||||
replicationFactors, onClickDatabase, onCreateDatabase} = this.props;
|
||||
|
||||
return (
|
||||
|
@ -40,7 +39,7 @@ const DatabaseManager = React.createClass({
|
|||
<ul className="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
{
|
||||
databases.map((db) => {
|
||||
return <li onClick={() => onClickDatabase(db.Name)} key={db.Name}><Link to={`/clusters/${clusterID}/databases/manager/${db.Name}`}>{db.Name}</Link></li>;
|
||||
return <li onClick={() => onClickDatabase(db.Name)} key={db.Name}><Link to={`/databases/manager/${db.Name}`}>{db.Name}</Link></li>;
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
|
@ -96,7 +95,7 @@ const DatabaseManager = React.createClass({
|
|||
users.map((user) => {
|
||||
return (
|
||||
<tr key={user.name}>
|
||||
<td><Link title="Manage Access" to={`/clusters/${clusterID}/accounts/${user.name}`}>{user.name}</Link></td>
|
||||
<td><Link title="Manage Access" to={`/accounts/${user.name}`}>{user.name}</Link></td>
|
||||
<td>{user.roles}</td>
|
||||
</tr>
|
||||
);
|
||||
|
|
128
ui/src/index.js
128
ui/src/index.js
|
@ -1,4 +1,4 @@
|
|||
import React, {PropTypes} from 'react';
|
||||
import React from 'react';
|
||||
import {render} from 'react-dom';
|
||||
import {Provider} from 'react-redux';
|
||||
import {Router, Route, browserHistory} from 'react-router';
|
||||
|
@ -17,18 +17,12 @@ import {ClusterAccountsPage, ClusterAccountPage} from 'src/cluster_accounts';
|
|||
import {RolesPageContainer, RolePageContainer} from 'src/access_control';
|
||||
import AccountSettingsPage from 'src/account_settings';
|
||||
import NotFound from 'src/shared/components/NotFound';
|
||||
import InsufficientPermissions from 'src/shared/components/InsufficientPermissions';
|
||||
import NoClusterError from 'src/shared/components/NoClusterError';
|
||||
import configureStore from 'src/store/configureStore';
|
||||
import {webUserShape} from 'src/utils/propTypes';
|
||||
import {meShow, getClusterAccount, getRoles} from 'shared/apis';
|
||||
import {buildClusterAccounts} from 'src/shared/presenters';
|
||||
|
||||
import 'src/style/enterprise_style/application.scss';
|
||||
|
||||
const VIEW_CHRONOGRAF = 'ViewChronograf';
|
||||
const READ = 'ReadData';
|
||||
|
||||
const defaultTimeRange = {upper: null, lower: 'now() - 15m'};
|
||||
const lsTimeRange = window.localStorage.getItem('timeRange');
|
||||
const parsedTimeRange = JSON.parse(lsTimeRange) || {};
|
||||
|
@ -37,85 +31,75 @@ const timeRange = Object.assign(defaultTimeRange, parsedTimeRange);
|
|||
const store = configureStore({timeRange});
|
||||
const rootNode = document.getElementById('react-root');
|
||||
|
||||
function hasPermission(account, permission) {
|
||||
const hasNakedPermission = !!account.permissions.find(p => p.name === permission);
|
||||
const hasPermissionInRole = account.roles.some((role) => {
|
||||
return role.permissions.some(p => p.name === permission);
|
||||
});
|
||||
|
||||
return hasNakedPermission || hasPermissionInRole;
|
||||
}
|
||||
|
||||
const HTTP_SERVER_ERROR = 500;
|
||||
|
||||
const Root = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
me: null,
|
||||
canViewChronograf: false,
|
||||
isFetching: true,
|
||||
me: {
|
||||
id: 1,
|
||||
name: 'MrFusion',
|
||||
email: 'foo@example.com',
|
||||
admin: true,
|
||||
},
|
||||
isFetching: false,
|
||||
hasReadPermission: false,
|
||||
clusterStatus: null,
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
meShow().then(({data: me}) => {
|
||||
const match = window.location.pathname.match(/\/clusters\/(\d*)/);
|
||||
const clusterID = match && match[1];
|
||||
const clusterLink = me.cluster_links.find(link => link.cluster_id === clusterID);
|
||||
if (clusterLink) {
|
||||
Promise.all([
|
||||
getClusterAccount(clusterID, clusterLink.cluster_user),
|
||||
getRoles(clusterID),
|
||||
]).then(([{data: {users}}, {data: {roles}}]) => {
|
||||
const account = buildClusterAccounts(users, roles)[0];
|
||||
const canViewChronograf = hasPermission(account, VIEW_CHRONOGRAF);
|
||||
const hasReadPermission = hasPermission(account, READ);
|
||||
this.setState({
|
||||
me,
|
||||
canViewChronograf,
|
||||
isFetching: false,
|
||||
hasReadPermission,
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.error(err); // eslint-disable-line no-console
|
||||
this.setState({
|
||||
canViewChronograf: false,
|
||||
isFetching: false,
|
||||
clusterStatus: err.response.status,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
me,
|
||||
isFetching: false,
|
||||
});
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.error(err); // eslint-disable-line no-console
|
||||
this.setState({
|
||||
isFetching: false,
|
||||
});
|
||||
});
|
||||
// meShow().then(({data: me}) => {
|
||||
// const match = window.location.pathname.match(/\/clusters\/(\d*)/);
|
||||
// const clusterID = match && match[1];
|
||||
// const clusterLink = me.cluster_links.find(link => link.cluster_id === clusterID);
|
||||
// if (clusterLink) {
|
||||
// Promise.all([
|
||||
// getClusterAccount(clusterID, clusterLink.cluster_user),
|
||||
// getRoles(clusterID),
|
||||
// ]).then(([{data: {users}}, {data: {roles}}]) => {
|
||||
// const account = buildClusterAccounts(users, roles)[0];
|
||||
// const canViewChronograf = hasPermission(account, VIEW_CHRONOGRAF);
|
||||
// const hasReadPermission = hasPermission(account, READ);
|
||||
// this.setState({
|
||||
// me,
|
||||
// canViewChronograf,
|
||||
// isFetching: false,
|
||||
// hasReadPermission,
|
||||
// });
|
||||
// }).catch((err) => {
|
||||
// console.error(err); // eslint-disable-line no-console
|
||||
// this.setState({
|
||||
// canViewChronograf: false,
|
||||
// isFetching: false,
|
||||
// clusterStatus: err.response.status,
|
||||
// });
|
||||
// });
|
||||
// } else {
|
||||
// this.setState({
|
||||
// me,
|
||||
// isFetching: false,
|
||||
// });
|
||||
// }
|
||||
// }).catch((err) => {
|
||||
// console.error(err); // eslint-disable-line no-console
|
||||
// this.setState({
|
||||
// isFetching: false,
|
||||
// });
|
||||
// });
|
||||
},
|
||||
|
||||
childContextTypes: {
|
||||
me: webUserShape,
|
||||
canViewChronograf: PropTypes.bool,
|
||||
},
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
me: this.state.me,
|
||||
canViewChronograf: this.state.canViewChronograf,
|
||||
};
|
||||
},
|
||||
|
||||
render() {
|
||||
const {me, canViewChronograf} = this.state;
|
||||
const isAdmin = me && me.admin;
|
||||
|
||||
if (this.state.isFetching) {
|
||||
return null;
|
||||
}
|
||||
|
@ -124,29 +108,25 @@ const Root = React.createClass({
|
|||
return <NoClusterError />;
|
||||
}
|
||||
|
||||
if (me && !this.state.hasReadPermission) {
|
||||
return <InsufficientPermissions />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<Router history={browserHistory}>
|
||||
<Route path="/signup/admin/:step" component={SignUp} />
|
||||
<Route path="/clusters/:clusterID" component={App}>
|
||||
<Route path="/" component={App}>
|
||||
<Route component={CheckDataNodes}>
|
||||
<Route path="overview" component={OverviewPage} />
|
||||
<Route path="queries" component={QueriesPage} />
|
||||
{isAdmin ? <Route path="accounts" component={ClusterAccountsPage} /> : null}
|
||||
{isAdmin ? <Route path="accounts/:accountID" component={ClusterAccountPage} /> : null}
|
||||
{isAdmin ? <Route path="databases/manager/:database" component={DatabaseManager} /> : null}
|
||||
<Route path="accounts" component={ClusterAccountsPage} />
|
||||
<Route path="accounts/:accountID" component={ClusterAccountPage} />
|
||||
<Route path="databases/manager/:database" component={DatabaseManager} />
|
||||
<Route path="databases/retentionpolicies/:database" component={RetentionPoliciesPage} />
|
||||
{canViewChronograf ? <Route path="chronograf/data_explorer" component={DataExplorer} /> : null}
|
||||
{canViewChronograf ? <Route path="chronograf/data_explorer/:explorerID" component={DataExplorer} /> : null}
|
||||
<Route path="chronograf/data_explorer" component={DataExplorer} />
|
||||
<Route path="chronograf/data_explorer/:explorerID" component={DataExplorer} />
|
||||
<Route path="roles" component={RolesPageContainer} />
|
||||
<Route path="roles/:roleSlug" component={RolePageContainer} />
|
||||
</Route>
|
||||
{isAdmin ? <Route path="users" component={UsersPage} /> : null}
|
||||
{isAdmin ? <Route path="users/:userID" component={UserEditPage} /> : null}
|
||||
<Route path="users" component={UsersPage} />
|
||||
<Route path="users/:userID" component={UserEditPage} />
|
||||
<Route path="tasks" component={TasksPage} />
|
||||
<Route path="account/settings" component={AccountSettingsPage} />
|
||||
<Route path="*" component={NotFound} />
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import AJAX from 'utils/ajax';
|
||||
|
||||
export function showCluster(clusterID) {
|
||||
export function getSources() {
|
||||
return AJAX({
|
||||
url: metaProxy(clusterID, '/show-cluster'),
|
||||
url: '/chronograf/v1/sources',
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ export function createDatabase({database, rpName, duration, replicaN}) {
|
|||
|
||||
export function getClusters() {
|
||||
return AJAX({
|
||||
url: `/api/int/v1/clusters`,
|
||||
url: ``,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -64,9 +64,9 @@ export function meUpdate({firstName, lastName, email, password, confirmation, ol
|
|||
});
|
||||
}
|
||||
|
||||
export function getWebUsers(clusterID) {
|
||||
export function getWebUsers() {
|
||||
return AJAX({
|
||||
url: `/api/int/v1/clusters/${clusterID}/users`,
|
||||
url: `/api/int/v1/users`,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -242,7 +242,7 @@ export function deleteClusterAccount(clusterID, accountName) {
|
|||
}),
|
||||
// Remove any cluster user links that are tied to this cluster account.
|
||||
AJAX({
|
||||
url: `/api/int/v1/clusters/${clusterID}/user_links/batch/${accountName}`,
|
||||
url: `/api/int/v1/user_links/batch/${accountName}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
]);
|
||||
|
@ -383,20 +383,20 @@ export function deleteRole(clusterID, roleName) {
|
|||
|
||||
export function deleteUserClusterLink(clusterID, userClusterLinkID) {
|
||||
return AJAX({
|
||||
url: `/api/int/v1/clusters/${clusterID}/user_links/${userClusterLinkID}`,
|
||||
url: `/api/int/v1/user_links/${userClusterLinkID}`,
|
||||
method: `DELETE`,
|
||||
});
|
||||
}
|
||||
|
||||
export function getUserClusterLinks(clusterID) {
|
||||
export function getUserClusterLinks() {
|
||||
return AJAX({
|
||||
url: `/api/int/v1/clusters/${clusterID}/user_links`,
|
||||
url: `/api/int/v1/user_links`,
|
||||
});
|
||||
}
|
||||
|
||||
export function createUserClusterLink({userID, clusterID, clusterUser}) {
|
||||
return AJAX({
|
||||
url: `/api/int/v1/clusters/${clusterID}/user_links`,
|
||||
url: `/api/int/v1/user_links`,
|
||||
method: 'POST',
|
||||
data: {
|
||||
user_id: userID,
|
||||
|
@ -408,7 +408,7 @@ export function createUserClusterLink({userID, clusterID, clusterUser}) {
|
|||
|
||||
export function getWebUsersByClusterAccount(clusterID, clusterAccount) {
|
||||
return AJAX({
|
||||
url: `/api/int/v1/clusters/${clusterID}/user_links/batch/${encodeURIComponent(clusterAccount)}`,
|
||||
url: `/api/int/v1/user_links/batch/${encodeURIComponent(clusterAccount)}`,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -422,12 +422,12 @@ export function batchCreateUserClusterLink(userID, clusterLinks) {
|
|||
|
||||
export function addWebUsersToClusterAccount(clusterID, clusterAccount, userIDs) {
|
||||
return AJAX({
|
||||
url: `/api/int/v1/clusters/${clusterID}/user_links/batch/${encodeURIComponent(clusterAccount)}`,
|
||||
url: `/api/int/v1/user_links/batch/${encodeURIComponent(clusterAccount)}`,
|
||||
method: 'POST',
|
||||
data: userIDs,
|
||||
});
|
||||
}
|
||||
|
||||
function metaProxy(clusterID, slug) {
|
||||
return `/api/int/v1/clusters/${clusterID}/meta${slug}`;
|
||||
return `/api/int/v1/meta${slug}`;
|
||||
}
|
||||
|
|
|
@ -42,9 +42,9 @@ export function showRetentionPolicies(host, databases, clusterID) {
|
|||
return proxy(url, clusterID);
|
||||
}
|
||||
|
||||
export function showShards(clusterID) {
|
||||
export function showShards() {
|
||||
return AJAX({
|
||||
url: `/api/int/v1/clusters/${clusterID}/show-shards`,
|
||||
url: `/api/int/v1/show-shards`,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,10 @@ import {Link} from 'react-router';
|
|||
import PermissionsTable from 'src/shared/components/PermissionsTable';
|
||||
import {roleShape} from 'utils/propTypes';
|
||||
|
||||
const {arrayOf, string, bool, func} = PropTypes;
|
||||
const {arrayOf, bool, func} = PropTypes;
|
||||
const RolePanels = React.createClass({
|
||||
propTypes: {
|
||||
roles: arrayOf(roleShape).isRequired,
|
||||
clusterID: string.isRequired,
|
||||
showUserCount: bool,
|
||||
onRemoveAccountFromRole: func,
|
||||
},
|
||||
|
@ -19,7 +18,7 @@ const RolePanels = React.createClass({
|
|||
},
|
||||
|
||||
render() {
|
||||
const {roles, clusterID} = this.props;
|
||||
const {roles} = this.props;
|
||||
|
||||
if (!roles.length) {
|
||||
return (
|
||||
|
@ -58,7 +57,7 @@ const RolePanels = React.createClass({
|
|||
Remove
|
||||
</button>
|
||||
) : null}
|
||||
<Link to={`/clusters/${clusterID}/roles/${encodeURIComponent(role.name)}`} className="btn btn-xs btn-link">
|
||||
<Link to={`/roles/${encodeURIComponent(role.name)}`} className="btn btn-xs btn-link">
|
||||
Go To Role
|
||||
</Link>
|
||||
</div>
|
||||
|
|
|
@ -1,81 +1,43 @@
|
|||
import React, {PropTypes} from 'react';
|
||||
import RenameClusterModal from '../modals/RenameCluster';
|
||||
import {NavBar, NavBlock, NavHeader, NavListItem} from 'src/side_nav/components/NavItems';
|
||||
|
||||
const {func, string, arrayOf, shape, bool} = PropTypes;
|
||||
const {string} = PropTypes;
|
||||
const SideNav = React.createClass({
|
||||
propTypes: {
|
||||
isAdmin: bool.isRequired,
|
||||
canViewChronograf: bool.isRequired,
|
||||
clusterID: string.isRequired,
|
||||
location: string.isRequired,
|
||||
onRenameCluster: func.isRequired,
|
||||
onOpenRenameModal: func.isRequired,
|
||||
clusters: arrayOf(shape()).isRequired,
|
||||
},
|
||||
|
||||
handleOpenRenameModal(clusterID) {
|
||||
this.props.onOpenRenameModal(clusterID);
|
||||
},
|
||||
|
||||
render() {
|
||||
const {clusterID, location, onRenameCluster, clusters, isAdmin, canViewChronograf} = this.props;
|
||||
const {location} = this.props;
|
||||
|
||||
return (
|
||||
<NavBar location={location}>
|
||||
<div className="sidebar__logo">
|
||||
<span className="icon cubo-uniform"></span>
|
||||
</div>
|
||||
{
|
||||
isAdmin ?
|
||||
<NavBlock matcher={'users'} icon={"access-key"} link={`/clusters/${clusterID}/users`}>
|
||||
<NavHeader link={`/clusters/${clusterID}/users`} title="Web Admin" />
|
||||
<NavListItem matcher={'users'} link={`/clusters/${clusterID}/users`}>Users</NavListItem>
|
||||
</NavBlock>
|
||||
: null
|
||||
}
|
||||
<NavBlock matcher="overview" icon="crown" link={`/clusters/${clusterID}/overview`}>
|
||||
<NavHeader link={`/clusters/${clusterID}/overview`} title="Cluster" />
|
||||
<NavListItem matcher="overview" link={`/clusters/${clusterID}/overview`}>Overview</NavListItem>
|
||||
<NavListItem matcher="queries" link={`/clusters/${clusterID}/queries`}>Queries</NavListItem>
|
||||
<NavListItem matcher="tasks" link={`/clusters/${clusterID}/tasks`}>Tasks</NavListItem>
|
||||
<NavListItem matcher="roles" link={`/clusters/${clusterID}/roles`}>Roles</NavListItem>
|
||||
{isAdmin ? <NavListItem matcher="accounts" link={`/clusters/${clusterID}/accounts`}>Cluster Accounts</NavListItem> : null}
|
||||
{isAdmin ? <NavListItem matcher="manager" link={`/clusters/${clusterID}/databases/manager/_internal`}>Database Manager</NavListItem> : null}
|
||||
<NavListItem matcher="retentionpolicies" link={`/clusters/${clusterID}/databases/retentionpolicies/_internal`}>Retention Policies</NavListItem>
|
||||
<NavBlock matcher={'users'} icon={"access-key"} link={`/users`}>
|
||||
<NavHeader link={`/users`} title="Web Admin" />
|
||||
<NavListItem matcher={'users'} link={`/users`}>Users</NavListItem>
|
||||
</NavBlock>
|
||||
{
|
||||
canViewChronograf ?
|
||||
<NavBlock matcher="chronograf" icon="graphline" link={`/clusters/${clusterID}/chronograf/data_explorer`}>
|
||||
<NavHeader link={`/clusters/${clusterID}/chronograf/data_explorer`} title={'Chronograf'} />
|
||||
<NavListItem matcher={'data_explorer'} link={`/clusters/${clusterID}/chronograf/data_explorer`}>Data Explorer</NavListItem>
|
||||
</NavBlock>
|
||||
: null
|
||||
}
|
||||
<NavBlock matcher="settings" icon="user-outline" link={`/clusters/${clusterID}/account/settings`}>
|
||||
<NavHeader link={`/clusters/${clusterID}/account/settings`} title="My Account" />
|
||||
<NavListItem matcher="settings" link={`/clusters/${clusterID}/account/settings`}>Settings</NavListItem>
|
||||
<NavBlock matcher="overview" icon="crown" link={`/overview`}>
|
||||
<NavHeader link={`/overview`} title="Cluster" />
|
||||
<NavListItem matcher="overview" link={`/overview`}>Overview</NavListItem>
|
||||
<NavListItem matcher="queries" link={`/queries`}>Queries</NavListItem>
|
||||
<NavListItem matcher="tasks" link={`/tasks`}>Tasks</NavListItem>
|
||||
<NavListItem matcher="roles" link={`/roles`}>Roles</NavListItem>
|
||||
<NavListItem matcher="accounts" link={`/accounts`}>Cluster Accounts</NavListItem>
|
||||
<NavListItem matcher="manager" link={`/databases/manager/_internal`}>Database Manager</NavListItem>
|
||||
<NavListItem matcher="retentionpolicies" link={`/databases/retentionpolicies/_internal`}>Retention Policies</NavListItem>
|
||||
</NavBlock>
|
||||
<NavBlock matcher="chronograf" icon="graphline" link={`/chronograf/data_explorer`}>
|
||||
<NavHeader link={`/chronograf/data_explorer`} title={'Chronograf'} />
|
||||
<NavListItem matcher={'data_explorer'} link={`/chronograf/data_explorer`}>Data Explorer</NavListItem>
|
||||
</NavBlock>
|
||||
<NavBlock matcher="settings" icon="user-outline" link={`/account/settings`}>
|
||||
<NavHeader link={`/account/settings`} title="My Account" />
|
||||
<NavListItem matcher="settings" link={`/account/settings`}>Settings</NavListItem>
|
||||
<a className="sidebar__menu-item" href="/logout">Logout</a>
|
||||
</NavBlock>
|
||||
<NavBlock icon="server" className="sidebar__square-last" wrapperClassName="sidebar__menu-wrapper-bottom">
|
||||
{
|
||||
clusters.map(({cluster_id: id, display_name: displayName}, i) => {
|
||||
return (
|
||||
<NavListItem key={i} matcher={id} link={`/clusters/${id}/overview`}>
|
||||
{displayName || id}
|
||||
{
|
||||
isAdmin ?
|
||||
<button className="btn btn-sm js-open-rename-cluster-modal" onClick={() => this.handleOpenRenameModal(id)} data-toggle="modal" data-target="#rename-cluster-modal">
|
||||
<span className="icon pencil"></span>
|
||||
</button>
|
||||
: null
|
||||
}
|
||||
</NavListItem>
|
||||
);
|
||||
})
|
||||
}
|
||||
</NavBlock>
|
||||
{isAdmin ? <RenameClusterModal clusterID={clusterID} onRenameCluster={onRenameCluster}/> : null}
|
||||
</NavBar>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
import React, {PropTypes} from 'react';
|
||||
import {getClusters, updateCluster} from 'shared/apis';
|
||||
import SideNav from '../components/SideNav';
|
||||
import {webUserShape} from 'src/utils/propTypes';
|
||||
|
||||
const {func, string} = PropTypes;
|
||||
const SideNavApp = React.createClass({
|
||||
propTypes: {
|
||||
clusterID: string.isRequired,
|
||||
currentLocation: string.isRequired,
|
||||
addFlashMessage: func.isRequired,
|
||||
},
|
||||
|
||||
contextTypes: {
|
||||
me: webUserShape,
|
||||
canViewChronograf: PropTypes.bool,
|
||||
},
|
||||
|
||||
|
@ -23,49 +19,15 @@ const SideNavApp = React.createClass({
|
|||
};
|
||||
},
|
||||
|
||||
getPageData() {
|
||||
getClusters().then(({data: clusters}) => {
|
||||
this.setState({clusters});
|
||||
});
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
this.getPageData();
|
||||
},
|
||||
|
||||
handleRenameCluster(displayName) {
|
||||
const {addFlashMessage} = this.props;
|
||||
updateCluster(this.state.clusterToUpdate, displayName).then(() => {
|
||||
this.getPageData();
|
||||
addFlashMessage({
|
||||
type: 'success',
|
||||
text: 'Cluster name changed successully',
|
||||
});
|
||||
}).catch(() => {
|
||||
addFlashMessage({
|
||||
type: 'error',
|
||||
text: 'Something went wrong while renaming the cluster',
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
handleOpenRenameModal(clusterToUpdate) {
|
||||
this.setState({clusterToUpdate});
|
||||
},
|
||||
|
||||
render() {
|
||||
const {clusterID, currentLocation} = this.props;
|
||||
const {me, canViewChronograf} = this.context;
|
||||
const {currentLocation} = this.props;
|
||||
const {canViewChronograf} = this.context;
|
||||
|
||||
return (
|
||||
<SideNav
|
||||
isAdmin={!!me && me.admin}
|
||||
isAdmin={true}
|
||||
canViewChronograf={canViewChronograf}
|
||||
location={currentLocation}
|
||||
clusterID={clusterID}
|
||||
onRenameCluster={this.handleRenameCluster}
|
||||
onOpenRenameModal={this.handleOpenRenameModal}
|
||||
clusters={this.state.clusters}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -18,9 +18,9 @@ export function buildInfluxUrl({host, statement, database, retentionPolicy}) {
|
|||
return encodeURIComponent(url);
|
||||
}
|
||||
|
||||
export function proxy(url, clusterID) {
|
||||
export function proxy(url) {
|
||||
return AJAX({
|
||||
url: `/clusters/${clusterID}/proxy?proxy_url=${url}`,
|
||||
url: `/proxy?proxy_url=${url}`,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue