import * as React from 'react'; import { Card, Icon, Modal, Tooltip, Row, Col, Button, Divider, Badge, Breadcrumb, message } from 'antd'; import * as _ from 'lodash'; import * as dayjs from 'dayjs'; import { connect } from 'react-redux'; import * as child_process from 'child_process'; import * as qs from 'query-string'; import { Actions } from '../redux/redux'; import * as actions from '../redux/actions'; import ServiceItemPortForward from './ServiceItemPortForward'; import PodsBoard from './PodsBoard'; import { Service } from '../types/*'; export interface ServiceItemProps { service: Service; removeProfileService: (service: Service) => void; } function parseAge(startTime: string) { const seconds = dayjs().diff(dayjs(startTime), 'second'); if (seconds > 86400) { return `${Math.floor(seconds / 86400)}d`; } if (seconds > 3600) { return `${Math.floor(seconds / 3600)}h`; } if (seconds > 60) { return `${Math.floor(seconds / 60)}m`; } return `${seconds}s`; } class ServiceItem extends React.Component { state = { loading: true, watching: false, error: undefined, description: undefined, isPodsModalOpen: false, }; componentDidMount() { this.loadServiceDescription(this.props.service); } loadServiceDescription = ({ name, context, namespace }: Service) => { child_process.exec( `kubectl --context=${context} -n${namespace} get service ${name} -o=json`, (error, stdout, stderr) => { // console.log(error, stdout, stderr); if (stdout) { const json = JSON.parse(stdout); this.setState({ description: json, error: undefined, }); // TODO: show error msg and retry btn } else if (stderr) { const error = JSON.parse(stderr); message.error(`Failed to load service description. (${error})`); this.setState({ error, watching: false, }); } else if (error) { message.error(`Failed to load service description. (${error.message})`); this.setState({ error: error.message, watching: false, }); } this.setState({ loading: false, }); }, ); }; openPodsModal = () => { this.setState({ isPodsModalOpen: true, }); }; closePodsModal = () => { this.setState({ isPodsModalOpen: false, }); }; removeProfileService = () => { this.props.removeProfileService(this.props.service); }; timer: any = undefined; toggleWatch = () => { if (!this.state.watching) { this.timer = setInterval(() => { const { service } = this.props; this.loadServiceDescription(service); }, 1000); } else { if (this.timer) { clearInterval(this.timer); } } this.setState({ watching: !this.state.watching, }); }; reset = () => { this.setState({ loading: true, watching: false, error: undefined, }); }; reload = () => { this.reset(); this.loadServiceDescription(this.props.service); }; render() { const { service } = this.props; const { name, context, namespace } = service; const { description, loading, isPodsModalOpen, error, watching } = this.state; const age = description ? parseAge((description as any).metadata.creationTimestamp) : '?'; const selector = description ? qs.stringify((description as any).spec.selector) : ''; return ( {' '} , {' '} , ] } loading={loading} > {context} {namespace} service
{name}
{!loading && !error && ( {isPodsModalOpen && ( )} )} {error && ( {error} )}
); } } export default connect( undefined, (dispatch: React.Dispatch, props: { service: Service }) => ({ removeProfileService: () => { dispatch(actions.removeProfileService(props.service)); }, }), )(ServiceItem);