mirror of
https://github.com/arangodb/kube-arangodb.git
synced 2024-12-14 11:57:37 +00:00
Improved backend polling behavior
This commit is contained in:
parent
f2274a58a0
commit
06bda8c7fe
8 changed files with 131 additions and 49 deletions
20
dashboard/package-lock.json
generated
20
dashboard/package-lock.json
generated
|
@ -2691,6 +2691,16 @@
|
|||
"sha.js": "^2.4.8"
|
||||
}
|
||||
},
|
||||
"create-react-class": {
|
||||
"version": "15.6.3",
|
||||
"resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz",
|
||||
"integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==",
|
||||
"requires": {
|
||||
"fbjs": "^0.8.9",
|
||||
"loose-envify": "^1.3.1",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
|
||||
|
@ -10269,6 +10279,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"react-timeout": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-timeout/-/react-timeout-1.1.1.tgz",
|
||||
"integrity": "sha512-zEJYHb3WvVq0/RdAOw5KHaOjTrN5Sm4fssJMPhqcu3efunecgQLfLfrKG5tfRM4IdjNJ3FCPI5hEKv62IHyZTw==",
|
||||
"requires": {
|
||||
"create-react-class": "^15.5.2",
|
||||
"hoist-non-react-statics": "^2.3.1",
|
||||
"object-assign": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"react-dom": "^16.4.1",
|
||||
"react-emotion": "^9.2.4",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"react-timeout": "^1.1.1",
|
||||
"semantic-ui-less": "^2.2.12",
|
||||
"semantic-ui-react": "^0.81.3"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, { Component } from 'react';
|
||||
import ReactTimeout from 'react-timeout';
|
||||
import DeploymentOperator from './deployment/DeploymentOperator.js';
|
||||
import NoOperator from './NoOperator.js';
|
||||
import Loading from './util/Loading.js';
|
||||
|
@ -15,11 +16,13 @@ const PodInfoView = ({pod, namespace}) => (
|
|||
</Segment>
|
||||
);
|
||||
|
||||
const OperatorsView = ({deployment, pod, namespace}) => (
|
||||
<div>
|
||||
{deployment ? <DeploymentOperator pod-info={<PodInfoView pod={pod} namespace={namespace}/>}/> : <NoOperator />}
|
||||
</div>
|
||||
);
|
||||
const OperatorsView = ({error, deployment, pod, namespace}) => {
|
||||
const podInfoView = (<PodInfoView pod={pod} namespace={namespace}/>);
|
||||
if (deployment) {
|
||||
return (<DeploymentOperator podInfoView={podInfoView} error={error}/>);
|
||||
}
|
||||
return (<NoOperator podInfoView={podInfoView} error={error}/>);
|
||||
}
|
||||
|
||||
const LoadingView = () => (
|
||||
<Container>
|
||||
|
@ -28,25 +31,29 @@ const LoadingView = () => (
|
|||
);
|
||||
|
||||
class App extends Component {
|
||||
state = {};
|
||||
state = {
|
||||
operators: undefined,
|
||||
error: undefined
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.intervalId = setInterval(this.reloadOperators, 5000);
|
||||
this.reloadOperators();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.intervalId);
|
||||
}
|
||||
|
||||
reloadOperators = async() => {
|
||||
const operators = await api.get('/api/operators');
|
||||
this.setState({operators});
|
||||
try {
|
||||
const operators = await api.get('/api/operators');
|
||||
this.setState({operators, error: undefined});
|
||||
} catch (e) {
|
||||
this.setState({error: e.message});
|
||||
}
|
||||
this.props.setTimeout(this.reloadOperators, 10000);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.operators) {
|
||||
return <OperatorsView
|
||||
error={this.state.error}
|
||||
deployment={this.state.operators.deployment}
|
||||
pod={this.state.operators.pod}
|
||||
namespace={this.state.operators.namespace}
|
||||
|
@ -56,4 +63,4 @@ class App extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
export default ReactTimeout(App);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { Component } from 'react';
|
||||
import logo from './logo.svg';
|
||||
import './App.css';
|
||||
import { Message } from 'semantic-ui-react';
|
||||
|
||||
class NoOperator extends Component {
|
||||
render() {
|
||||
|
@ -13,7 +14,8 @@ class NoOperator extends Component {
|
|||
<p className="App-intro">
|
||||
There are no operators available yet.
|
||||
</p>
|
||||
{this.props["pod-info"]}
|
||||
{this.props.podInfoView}
|
||||
{(this.props.error) ? <Message error content={this.props.error}/> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { Component } from 'react';
|
||||
import api from '../api/api.js';
|
||||
import Login from './Login.js';
|
||||
import Loading from '../util/Loading.js';
|
||||
import LogoutContext from './LogoutContext.js';
|
||||
import { getSessionItem, setSessionItem } from "../util/Storage.js";
|
||||
|
||||
|
@ -9,6 +10,7 @@ const tokenSessionKey = "auth-token";
|
|||
class Auth extends Component {
|
||||
state = {
|
||||
authenticated: false,
|
||||
showLoading: true,
|
||||
token: getSessionItem(tokenSessionKey) || ""
|
||||
};
|
||||
|
||||
|
@ -18,11 +20,13 @@ class Auth extends Component {
|
|||
await api.get('/api/operators');
|
||||
this.setState({
|
||||
authenticated: true,
|
||||
showLoading: false,
|
||||
token: api.token
|
||||
});
|
||||
} catch (e) {
|
||||
this.setState({
|
||||
authenticated: false,
|
||||
showLoading: false,
|
||||
token: ''
|
||||
});
|
||||
}
|
||||
|
@ -65,9 +69,10 @@ class Auth extends Component {
|
|||
render() {
|
||||
return (
|
||||
<LogoutContext.Provider value={this.handleLogout}>
|
||||
{(!this.state.authenticated) ?
|
||||
<Login doLogin={this.handleLogin} error={this.state.error}/> :
|
||||
this.props.children
|
||||
{(this.state.showLoading) ? <Loading/> :
|
||||
(!this.state.authenticated) ?
|
||||
<Login doLogin={this.handleLogin} error={this.state.error}/> :
|
||||
this.props.children
|
||||
}
|
||||
</LogoutContext.Provider>
|
||||
);
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
import ReactTimeout from 'react-timeout';
|
||||
import React, { Component } from 'react';
|
||||
import api from '../api/api.js';
|
||||
import Loading from '../util/Loading.js';
|
||||
import MemberList from './MemberList.js';
|
||||
import styled from 'react-emotion';
|
||||
import { Loader } from 'semantic-ui-react';
|
||||
|
||||
const LoaderBox = styled('span')`
|
||||
float: right;
|
||||
width: 0;
|
||||
padding-right: 1em;
|
||||
margin-right: 1em;
|
||||
margin-top: 1em;
|
||||
max-width: 0;
|
||||
display: inline-block;
|
||||
`;
|
||||
|
||||
const MemberGroupsView = ({memberGroups, namespace}) => (
|
||||
<div>
|
||||
|
@ -15,21 +28,31 @@ const MemberGroupsView = ({memberGroups, namespace}) => (
|
|||
);
|
||||
|
||||
class DeploymentDetails extends Component {
|
||||
state = {};
|
||||
state = {
|
||||
loading: true,
|
||||
error: undefined
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.intervalId = setInterval(this.reloadDeployment, 5000);
|
||||
this.reloadDeployment();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.intervalId);
|
||||
}
|
||||
|
||||
reloadDeployment = async() => {
|
||||
// TODO
|
||||
const result = await api.get(`/api/deployment/${this.props.name}`);
|
||||
this.setState({deployment:result});
|
||||
try {
|
||||
this.setState({loading:true});
|
||||
const result = await api.get(`/api/deployment/${this.props.name}`);
|
||||
this.setState({
|
||||
deployment: result,
|
||||
loading: false,
|
||||
error: undefined
|
||||
});
|
||||
} catch (e) {
|
||||
this.setState({
|
||||
loading: false,
|
||||
error: e.message
|
||||
});
|
||||
}
|
||||
this.props.setTimeout(this.reloadDeployment, 5000);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -39,10 +62,11 @@ class DeploymentDetails extends Component {
|
|||
}
|
||||
return (
|
||||
<div>
|
||||
<LoaderBox><Loader size="mini" active={this.state.loading} inline/></LoaderBox>
|
||||
<MemberGroupsView memberGroups={d.member_groups} namespace={d.namespace}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DeploymentDetails;
|
||||
export default ReactTimeout(DeploymentDetails);
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
import React, { Component } from 'react';
|
||||
import api from '../api/api.js';
|
||||
import { Icon, Popup, Table } from 'semantic-ui-react';
|
||||
import Loading from '../util/Loading.js';
|
||||
import CommandInstruction from '../util/CommandInstruction.js';
|
||||
import { Icon, Loader, Popup, Table } from 'semantic-ui-react';
|
||||
import { Link } from "react-router-dom";
|
||||
import api from '../api/api.js';
|
||||
import CommandInstruction from '../util/CommandInstruction.js';
|
||||
import Loading from '../util/Loading.js';
|
||||
import React, { Component } from 'react';
|
||||
import ReactTimeout from 'react-timeout';
|
||||
import styled from 'react-emotion';
|
||||
|
||||
const HeaderView = () => (
|
||||
const LoaderBox = styled('span')`
|
||||
float: right;
|
||||
width: 0;
|
||||
padding-right: 1em;
|
||||
max-width: 0;
|
||||
display: inline-block;
|
||||
`;
|
||||
|
||||
const HeaderView = ({loading}) => (
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>State</Table.HeaderCell>
|
||||
|
@ -15,7 +25,10 @@ const HeaderView = () => (
|
|||
<Table.HeaderCell><Popup trigger={<span>Pods</span>}>Ready / Total</Popup></Table.HeaderCell>
|
||||
<Table.HeaderCell><Popup trigger={<span>Volumes</span>}>Bound / Total</Popup></Table.HeaderCell>
|
||||
<Table.HeaderCell>StorageClass</Table.HeaderCell>
|
||||
<Table.HeaderCell>Actions</Table.HeaderCell>
|
||||
<Table.HeaderCell>
|
||||
Actions
|
||||
<LoaderBox><Loader size="mini" active={loading} inline/></LoaderBox>
|
||||
</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
);
|
||||
|
@ -83,9 +96,9 @@ const RowView = ({name, mode, environment, stateColor, version, license, readyPo
|
|||
</Table.Row>
|
||||
);
|
||||
|
||||
const ListView = ({items}) => (
|
||||
const ListView = ({items, loading}) => (
|
||||
<Table striped celled>
|
||||
<HeaderView/>
|
||||
<HeaderView loading={loading}/>
|
||||
<Table.Body>
|
||||
{
|
||||
(items) ? items.map((item) =>
|
||||
|
@ -138,20 +151,29 @@ function getStateColorDescription(stateColor) {
|
|||
}
|
||||
|
||||
class DeploymentList extends Component {
|
||||
state = {};
|
||||
state = {
|
||||
items: undefined,
|
||||
error: undefined,
|
||||
loading: true
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.intervalId = setInterval(this.reloadDeployments, 5000);
|
||||
this.reloadDeployments();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.intervalId);
|
||||
}
|
||||
|
||||
reloadDeployments = async() => {
|
||||
const result = await api.get('/api/deployment');
|
||||
this.setState({items:result.deployments});
|
||||
try {
|
||||
this.setState({loading: true});
|
||||
const result = await api.get('/api/deployment');
|
||||
this.setState({
|
||||
items: result.deployments,
|
||||
loading: false,
|
||||
error: undefined
|
||||
});
|
||||
} catch (e) {
|
||||
this.setState({error: e.message, loading: false});
|
||||
}
|
||||
this.props.setTimeout(this.reloadDeployments, 5000);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -162,8 +184,8 @@ class DeploymentList extends Component {
|
|||
if (items.length === 0) {
|
||||
return (<EmptyView/>);
|
||||
}
|
||||
return (<ListView items={items}/>);
|
||||
return (<ListView items={items} loading={this.state.loading}/>);
|
||||
}
|
||||
}
|
||||
|
||||
export default DeploymentList;
|
||||
export default ReactTimeout(DeploymentList);
|
||||
|
|
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
|||
import LogoutContext from '../auth/LogoutContext.js';
|
||||
import DeploymentDetails from './DeploymentDetails.js';
|
||||
import DeploymentList from './DeploymentList.js';
|
||||
import { Header, Menu, Segment } from 'semantic-ui-react';
|
||||
import { Header, Menu, Message, Segment } from 'semantic-ui-react';
|
||||
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
|
||||
import styled from 'react-emotion';
|
||||
|
||||
|
@ -62,7 +62,8 @@ class DeploymentOperator extends Component {
|
|||
<Route path="/deployment/:name" component={DetailView} />
|
||||
</div>
|
||||
</Segment>
|
||||
{this.props["pod-info"]}
|
||||
{this.props.podInfoView}
|
||||
{(this.props.error) ? <Segment basic><Message error content={this.props.error}/></Segment> : null}
|
||||
</StyledContentBox>
|
||||
</div>
|
||||
</Router>
|
||||
|
|
Loading…
Reference in a new issue