Skip to content

Commit a87fea7

Browse files
committed
Merged in master, various small fixes
2 parents 7a86092 + 4c5a2d3 commit a87fea7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+2122
-374
lines changed

.dockerignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ docs
55
pkg
66
tools
77
deps
8-
8+
dashboard

dashboard/assets.go

Lines changed: 51 additions & 62 deletions
Large diffs are not rendered by default.

dashboard/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"devDependencies": {
1717
"react-scripts": "1.1.4"
1818
},
19-
"proxy": "https://192.168.140.208:8528",
19+
"proxy": "https://192.168.140.212:8528",
2020
"scripts": {
2121
"start": "react-scripts start",
2222
"build": "react-scripts build",

dashboard/src/App.css

Lines changed: 0 additions & 28 deletions
This file was deleted.

dashboard/src/App.js

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import { Container, Segment, Menu, Message } from 'semantic-ui-react';
12
import React, { Component } from 'react';
23
import ReactTimeout from 'react-timeout';
3-
import DeploymentOperator from './deployment/DeploymentOperator.js';
4-
import NoOperator from './NoOperator.js';
5-
import Loading from './util/Loading.js';
6-
import api from './api/api.js';
7-
import { Container, Segment, Message } from 'semantic-ui-react';
8-
import './App.css';
4+
5+
import { withAuth } from './auth/Auth';
6+
import api, { isUnauthorized } from './api/api';
7+
import DeploymentOperator from './deployment/DeploymentOperator';
8+
import DeploymentReplicationOperator from './replication/DeploymentReplicationOperator';
9+
import Loading from './util/Loading';
10+
import NoOperator from './NoOperator';
11+
import StorageOperator from './storage/StorageOperator';
912

1013
const PodInfoView = ({pod, namespace}) => (
1114
<Segment basic>
@@ -16,14 +19,43 @@ const PodInfoView = ({pod, namespace}) => (
1619
</Segment>
1720
);
1821

19-
const OperatorsView = ({error, deployment, pod, namespace}) => {
20-
const podInfoView = (<PodInfoView pod={pod} namespace={namespace}/>);
21-
if (deployment) {
22-
return (<DeploymentOperator podInfoView={podInfoView} error={error}/>);
22+
const OperatorsView = ({error, deployment, deploymentReplication, storage, pod, namespace, otherOperators}) => {
23+
let commonMenuItems = otherOperators.map((item) => <Menu.Item><a href={item.url}>{operatorType2Name(item.type)}</a></Menu.Item>);
24+
if (commonMenuItems.length > 0) {
25+
commonMenuItems = (<Menu.Item>
26+
<Menu.Header>Other operators</Menu.Header>
27+
<Menu.Menu>{commonMenuItems}</Menu.Menu>
28+
</Menu.Item>);
2329
}
24-
return (<NoOperator podInfoView={podInfoView} error={error}/>);
30+
let Operator = NoOperator;
31+
if (deployment)
32+
Operator = DeploymentOperator;
33+
else if (deploymentReplication)
34+
Operator = DeploymentReplicationOperator;
35+
else if (storage)
36+
Operator = StorageOperator;
37+
return (
38+
<Operator
39+
podInfoView={<PodInfoView pod={pod} namespace={namespace} />}
40+
commonMenuItems={commonMenuItems}
41+
error={error}
42+
/>
43+
);
2544
}
2645

46+
const operatorType2Name = (oType) => {
47+
switch (oType) {
48+
case "deployment":
49+
return "Deployments";
50+
case "deployment_replication":
51+
return "Deployment replications";
52+
case "storage":
53+
return "Storage";
54+
default:
55+
return "";
56+
}
57+
};
58+
2759
const LoadingView = () => (
2860
<Container>
2961
<Loading/>
@@ -43,24 +75,35 @@ class App extends Component {
4375
reloadOperators = async() => {
4476
try {
4577
const operators = await api.get('/api/operators');
46-
this.setState({operators, error: undefined});
78+
this.setState({
79+
operators,
80+
error: undefined
81+
});
4782
} catch (e) {
48-
this.setState({error: e.message});
83+
this.setState({
84+
error: e.message
85+
});
86+
if (isUnauthorized(e)) {
87+
this.props.doLogout();
88+
}
4989
}
5090
this.props.setTimeout(this.reloadOperators, 10000);
5191
}
5292

5393
render() {
5494
if (this.state.operators) {
55-
return <OperatorsView
95+
return <OperatorsView
5696
error={this.state.error}
57-
deployment={this.state.operators.deployment}
58-
pod={this.state.operators.pod}
59-
namespace={this.state.operators.namespace}
60-
/>;
97+
deployment={this.state.operators.deployment}
98+
deploymentReplication={this.state.operators.deployment_replication}
99+
storage={this.state.operators.storage}
100+
otherOperators={this.state.operators.other || []}
101+
pod={this.state.operators.pod}
102+
namespace={this.state.operators.namespace}
103+
/>;
61104
}
62105
return (<LoadingView/>);
63106
}
64107
}
65108

66-
export default ReactTimeout(App);
109+
export default ReactTimeout(withAuth(App));

dashboard/src/App.test.js

Lines changed: 0 additions & 9 deletions
This file was deleted.

dashboard/src/NoOperator.js

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
1-
import React, { Component } from 'react';
2-
import logo from './logo.svg';
3-
import './App.css';
4-
import { Message } from 'semantic-ui-react';
1+
import { Container, Message, Modal, Segment } from 'semantic-ui-react';
2+
import React from 'react';
53

6-
class NoOperator extends Component {
7-
render() {
8-
return (
9-
<div className="App">
10-
<header className="App-header">
11-
<img src={logo} className="App-logo" alt="logo" />
12-
<h1 className="App-title">Welcome to Kube-ArangoDB</h1>
13-
</header>
14-
<p className="App-intro">
4+
const NoOperator = () => (
5+
<Container>
6+
<Modal open>
7+
<Modal.Header>Welcome to Kube-ArangoDB</Modal.Header>
8+
<Modal.Content>
9+
<Segment basic>
10+
<Message color="orange">
1511
There are no operators available yet.
16-
</p>
17-
{this.props.podInfoView}
18-
{(this.props.error) ? <Message error content={this.props.error}/> : null}
19-
</div>
20-
);
21-
}
22-
}
12+
</Message>
13+
</Segment>
14+
{this.props.podInfoView}
15+
{(this.props.error) ? <Message error content={this.props.error}/> : null}
16+
</Modal.Content>
17+
</Modal>
18+
</Container>
19+
);
2320

2421
export default NoOperator;

dashboard/src/api/api.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
1+
export function isUnauthorized(e) {
2+
return (e.status === 401);
3+
}
4+
15
export default {
26
token: '',
37

48
async decodeResults(result) {
59
const decoded = await result.json();
6-
if (result.status === 401) {
7-
throw Error(decoded.error || "Unauthorized")
8-
}
910
if (result.status !== 200) {
10-
throw Error(`Unexpected status ${result.status}`);
11+
let message = decoded.error;
12+
if (!message) {
13+
if (result.status === 401) {
14+
message = "Unauthorized";
15+
} else {
16+
message = `Unexpected status ${result.status}`;
17+
}
18+
}
19+
throw Object.assign(new Error(message), { status: result.status });
1120
}
1221
return decoded;
1322
},

dashboard/src/auth/Auth.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
import React, { Component } from 'react';
2-
import api from '../api/api.js';
3-
import Login from './Login.js';
4-
import Loading from '../util/Loading.js';
5-
import LogoutContext from './LogoutContext.js';
6-
import { getSessionItem, setSessionItem } from "../util/Storage.js";
2+
3+
import { getSessionItem, setSessionItem } from '../util/Storage';
4+
import api from '../api/api';
5+
import Loading from '../util/Loading';
6+
import Login from './Login';
7+
import LogoutContext from './LogoutContext';
78

89
const tokenSessionKey = "auth-token";
910

11+
// withAuth adds a doLogout property to the given component.
12+
export function withAuth(WrappedComponent) {
13+
return function AuthAwareComponent(props) {
14+
return (
15+
<LogoutContext.Consumer>
16+
{doLogout => <WrappedComponent {...props} doLogout={doLogout} />}
17+
</LogoutContext.Consumer>
18+
);
19+
}
20+
}
21+
1022
class Auth extends Component {
1123
state = {
1224
authenticated: false,

dashboard/src/auth/Login.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import React, { Component } from 'react';
21
import { Button, Container, Form, Icon, Message, Modal } from 'semantic-ui-react';
2+
import { css } from 'react-emotion';
3+
import React, { Component } from 'react';
34

45
const LoginView = ({username, password, onUsernameChanged, onPasswordChanged, doLogin, error}) => (
56
<Container>
@@ -12,6 +13,7 @@ const LoginView = ({username, password, onUsernameChanged, onPasswordChanged, do
1213
<label>Password</label>
1314
<input type="password" value={password} onChange={(e) => onPasswordChanged(e.target.value)}/>
1415
</Form.Field>
16+
<Form.Button className={css`display:none`} type="submit" />
1517
</Form>
1618
{(error) ? <Message error content={error}/> : null}
1719
</Container>

0 commit comments

Comments
 (0)