Skip to content

Commit

Permalink
feat: Cluster and repo pages can listen to websocket messages (#315)
Browse files Browse the repository at this point in the history
* Fix routes/api response error check
* Fix Layout component notifications,  remove sockMessage
* Fix all pages fallback error tips
* Remove `apiMsg`, `showMsg` in root store, delegate to notify message
  • Loading branch information
sunnywx authored Sep 5, 2018
1 parent 5be7c33 commit d9f3ec1
Show file tree
Hide file tree
Showing 43 changed files with 431 additions and 311 deletions.
Empty file removed .circleci/config.yml
Empty file.
15 changes: 8 additions & 7 deletions server/routes/api.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Router = require('koa-router');
const agent = require('superagent');
const debug = require('debug')('op-dash');
const get = require('lodash/get');

const router = new Router();

Expand All @@ -9,10 +10,10 @@ const header = {
'Content-Type': 'application/json'
};

const agentTimeout={
const agentTimeout = {
response: 5000,
deadline: 10000
}
};

router.post('/api/*', async ctx => {
let endpoint = ctx.url.replace(/^\/api\//, '');
Expand Down Expand Up @@ -55,19 +56,19 @@ router.post('/api/*', async ctx => {
}

// normalize response body
ctx.body = res.body || null;
ctx.body = (res && res.body) || null;
} catch (err) {
if(err.timeout){
ctx.body={
if (err.timeout) {
ctx.body = {
err: 'request timeout',
status: 400
}
};
}

ctx.body = {
err: err.message,
status: err.statusCode || err.status || 500,
errDetail: err.response.body.error
errDetail: get(err, 'response.body.error', '')
};
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/components/Base/Notification/item.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default class NotificationItem extends React.Component {
};

static defaultProps = {
type: 'error',
type: 'info',
title: 'Notification',
message: null,
timeOut: 3000,
Expand Down
6 changes: 3 additions & 3 deletions src/components/DetailCard/ClusterCard.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { PureComponent } from 'react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Link } from 'react-router-dom';
Expand All @@ -12,7 +12,7 @@ import CopyId from './CopyId';
import styles from './index.scss';

@translate()
export default class ClusterCard extends PureComponent {
export default class ClusterCard extends Component {
static propTypes = {
detail: PropTypes.object.isRequired,
appName: PropTypes.string,
Expand All @@ -38,7 +38,7 @@ export default class ClusterCard extends PureComponent {
)}
<li>
<span className={styles.name}>{t('Status')}</span>
<Status name={detail.status} type={detail.status} />
<Status type={detail.status} transition={detail.transition_status} />
</li>
<li>
<span className={styles.name}>{t('Runtime')}</span>
Expand Down
6 changes: 3 additions & 3 deletions src/components/DetailCard/RuntimeCard.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { PureComponent } from 'react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { translate } from 'react-i18next';
Expand All @@ -12,7 +12,7 @@ import CopyId from './CopyId';
import styles from './index.scss';

@translate()
export default class RuntimeCard extends PureComponent {
export default class RuntimeCard extends Component {
static propTypes = {
detail: PropTypes.object.isRequired,
appCount: PropTypes.number,
Expand All @@ -32,7 +32,7 @@ export default class RuntimeCard extends PureComponent {
<ul className={styles.detail}>
<li>
<span className={styles.name}>{t('Status')}</span>
<Status name={detail.status} type={detail.status} />
<Status type={detail.status} transition={detail.transition} />
</li>
<li>
<span className={styles.name}>{t('Runtime Provider')}</span>
Expand Down
11 changes: 8 additions & 3 deletions src/components/Layout/Card/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ import Panel from '../Panel';

import styles from './index.scss';

const Card = ({ className, children, ...others }) => (
<Panel className={classnames(styles.card, className)} {...others}>
const Card = ({ className, children, hasTable = false, ...others }) => (
<Panel
className={classnames(styles.card, className, { [styles.tableCard]: hasTable })}
{...others}
>
{children}
</Panel>
);

Card.propTypes = {
className: PropTypes.string
className: PropTypes.string,
children: PropTypes.node,
hasTable: PropTypes.bool
};

export default Card;
11 changes: 11 additions & 0 deletions src/components/Layout/Card/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,14 @@ $card-padding: 24px;
}
}
}

.tableCard {
padding: $card-padding;

:global {
.loadTable {
position: sticky !important;
margin-top: 0;
}
}
}
47 changes: 22 additions & 25 deletions src/components/Layout/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { inject } from 'mobx-react';
import { noop } from 'lodash';
import { noop, clone, isEmpty, get } from 'lodash';

import { Notification } from 'components/Base';
import TabsNav from 'components/TabsNav';
Expand All @@ -21,7 +21,6 @@ export default class Layout extends React.Component {
backBtn: PropTypes.node,
isLoading: PropTypes.bool,
loadClass: PropTypes.string,
sockMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
listenToJob: PropTypes.func,
isProfile: PropTypes.bool
};
Expand All @@ -31,7 +30,6 @@ export default class Layout extends React.Component {
noTabs: false,
noNotification: false,
backBtn: null,
sockMessage: '',
listenToJob: noop,
isProfile: false
};
Expand All @@ -43,10 +41,26 @@ export default class Layout extends React.Component {
}

componentDidMount() {
let { sock, listenToJob } = this.props;
const { sock, listenToJob } = this.props;

sock &&
sock.on('ops-resource', (payload = {}) => {
const { type } = payload;
const { resource = {} } = payload;

listenToJob({
op: `${type}:${resource.rtype}`,
type,
...resource
});
});
}

componentWillUnmount() {
const { sock } = this.props;

if (sock && !sock._events['ops-resource']) {
sock.on('ops-resource', listenToJob);
if (sock && !isEmpty(sock._events)) {
sock._events = {};
}
}

Expand All @@ -55,37 +69,21 @@ export default class Layout extends React.Component {
const normalLinks = [{ '': 'overview' }, 'apps', 'clusters', 'runtimes'];
if (isProfile) {
this.linkPrefix = '/profile';
this.availableLinks = [{ '': 'profile' }, { sshkeys: 'SSH Keys' }];
this.availableLinks = [{ '': 'profile' }, { ssh_keys: 'SSH Keys' }];
} else if (loginRole === 'normal') {
this.availableLinks = [...normalLinks];
this.availableLinks.splice(1, 1);
} else if (loginRole === 'developer') {
this.availableLinks = [...normalLinks, 'repos'];
} else if (loginRole === 'admin') {
this.availableLinks = [...normalLinks, 'repos', 'categories']; // hide user tab
this.availableLinks = [...normalLinks, 'repos', 'categories', 'users'];
}

const options = { prefix: this.linkPrefix };

return <TabsNav links={this.availableLinks} options={options} />;
}

renderSocketMessage() {
let { sockMessage } = this.props;

if (typeof sockMessage === 'object') {
sockMessage = sockMessage + '';
}

// if(!sockMessage){
// return null;
// }
// return <Notification type='info' message={`Socket Message: ${sockMessage}`} className={styles.socketMessage} />;

// todo: currently no need to implement job tips
return null;
}

render() {
const {
className,
Expand All @@ -103,7 +101,6 @@ export default class Layout extends React.Component {
{noTabs ? null : this.renderTabs(isProfile)}
{noNotification ? null : <Notification />}
{backBtn}
{this.renderSocketMessage()}
<Loading isLoading={isLoading} className={styles[loadClass]}>
{children}
</Loading>
Expand Down
11 changes: 7 additions & 4 deletions src/components/Loading/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ export default class Loading extends Component {

if (isLoading) {
return (
<div className={classnames(styles.loading, className)}>
<div className={styles.loadOuter}>
<div className={styles.loader} />
<Fragment>
<div className={classnames(styles.loading, className)}>
<div className={styles.loadOuter}>
<div className={styles.loader} />
</div>
</div>
</div>
{children}
</Fragment>
);
}

Expand Down
24 changes: 11 additions & 13 deletions src/components/Loading/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
}

.loading {
position: fixed;
position: relative;
top: $header-height;
bottom: 0;
left: 0;
Expand All @@ -17,7 +17,7 @@

.loadOuter{
position: absolute;
top: 50%;
top: 40%;
left: 50%;
margin: -3em 0 0 -3em;

Expand All @@ -31,10 +31,10 @@
font-size:10px;
position:relative;
text-indent:-9999em;
border-top:0.1em solid rgba($purple-light,0.2);
border-right:0.1em solid rgba($purple-light,0.2);
border-bottom:0.1em solid rgba($purple-light,0.2);
border-left:0.1em solid rgba($purple-light,1);
border-top:0.2em solid rgba($purple-light,0.2);
border-right:0.2em solid rgba($purple-light,0.2);
border-bottom:0.2em solid rgba($purple-light,0.2);
border-left:0.2em solid rgba($purple-light,1);

//-webkit-transform: translateZ(0);
//-ms-transform: translateZ(0);
Expand All @@ -49,15 +49,13 @@

:global {
.loadTable{
position: sticky;
background-color: #fff;
//margin-left: 192px;
}
.loadTable{
position: static;
position: fixed;
background-color: #fff;
opacity: 0.5;
margin-top: $header-height + $tabNavs-height + 5px;

.loadOuter{
position: static;
position: relative;
padding: 30px 0 50px;
.loader {
margin: 0 auto;
Expand Down
19 changes: 13 additions & 6 deletions src/components/Status/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,28 @@ export default class Status extends PureComponent {
'ceased',
'pending',
'suspended',
'deleted'
])
'successful',
'deleted',
'working' // job status
]),
transition: PropTypes.oneOf(['', 'starting', 'updating', 'stopping'])
};

static defaultProps = {
status: 'pending'
type: 'pending',
transition: ''
};

render() {
const { style, className, name, type, t } = this.props;
const { style, className, name, type, transition, t } = this.props;
let status = String(transition || type).toLowerCase();

const normalizeName = t(capitalize(name || status));

return (
<span className={classnames(styles.status, className)} style={style}>
<i className={classnames(styles.icon, styles[type])} />
{t(capitalize(name))}
<i className={classnames(styles.icon, styles[status])} />
{normalizeName}
</span>
);
}
Expand Down
Loading

0 comments on commit d9f3ec1

Please sign in to comment.