http://git-wip-us.apache.org/repos/asf/ambari/blob/cf5c068c/contrib/views/storm/src/main/resources/ui/app/scripts/components/Editable.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/ui/app/scripts/components/Editable.jsx b/contrib/views/storm/src/main/resources/ui/app/scripts/components/Editable.jsx deleted file mode 100644 index 03005ae..0000000 --- a/contrib/views/storm/src/main/resources/ui/app/scripts/components/Editable.jsx +++ /dev/null @@ -1,127 +0,0 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at -* - http://www.apache.org/licenses/LICENSE-2.0 -* - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -**/ - -import React, {Component} from 'react'; -import ReactDOM, {findDOMNode} from 'react-dom'; -import {Overlay, Popover, Button} from 'react-bootstrap'; - -export default class Editable extends Component { - state = { - edit: false, - errorMsg: '' - }; - - handleClick = () => { - let state = this.state; - state.edit = true; - this.setState(state); - } - - handleResolve = () => { - const {resolve} = this.props; - if (resolve) { - resolve(this); - } - } - - handleReject = () => { - const {reject} = this.props; - if (reject) { - reject(this); - } else { - this.hideEditor(); - } - } - - hideEditor = () => { - let state = this.state; - state.edit = false; - this.setState(state); - } - - getValueString() { - const {children} = this.props; - - if (children.type == 'input' || children.type == 'textarea') { - return children.props.value || children.props.defaultValue; - } else if (children.type == 'select') {} else { - var fn = children.getStringValue; - if (fn) { - return fn(); - } else { - console.error('Custom component must have getValueString() function.'); - } - } - } - - anchorStyle = { - textDecoration: 'none', - borderBottom: 'dashed 1px #0088cc', - cursor: 'pointer', - color: '#323133' - }; - - render() { - const {children, showButtons, inline, placement, title} = this.props; - const {edit, errorMsg} = this.state; - - const buttons = showButtons - ? ([<Button className="btn-primary btn-sm" onClick={this.handleResolve} key="resolve" style={{margin : "0 0 3px 5px"}}> - <i className="fa fa-check"></i></Button>, - <Button className="btn-default btn-sm" onClick={this.handleReject} key="reject" style={{margin : "0 3px"}}> - <i className="fa fa-times"></i> - </Button> - ]) - : null; - - const error = errorMsg - ? ( - <div className="editable-error">{errorMsg}</div> - ) - : null; - - const popover = ( - <Popover id="popover-positioned-left" title={title || ''}> - {children} - {buttons} - {error} - </Popover> - ); - - return ( - <div className="editable-container" style={{display: 'inline'}} id={this.props.id || ''}> - {edit && inline - ? null - : <a ref="target" onClick={this.handleClick} style={this.anchorStyle}>{this.getValueString()}</a> -} - {edit && inline - ? [children, buttons, error] - : <Overlay show={edit} target={() => ReactDOM.findDOMNode(this.refs.target)} {...this.props}> - {popover} - </Overlay> -} - </div> - ); - } -} - -Editable.defaultProps = { - showButtons: true, - inline: false, - placement: "top" -};
http://git-wip-us.apache.org/repos/asf/ambari/blob/cf5c068c/contrib/views/storm/src/main/resources/ui/app/scripts/components/FSModel.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/ui/app/scripts/components/FSModel.jsx b/contrib/views/storm/src/main/resources/ui/app/scripts/components/FSModel.jsx deleted file mode 100644 index 14cb17d..0000000 --- a/contrib/views/storm/src/main/resources/ui/app/scripts/components/FSModel.jsx +++ /dev/null @@ -1,149 +0,0 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at -* - http://www.apache.org/licenses/LICENSE-2.0 -* - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -**/ - -import React, {Component} from 'react'; -import {Modal, Button} from 'react-bootstrap'; - -const defaultState = { - show: false, - title: '', - btnOkText: 'Ok', - btnCancelText: 'Cancel' -}; - -export default class FSModal extends Component { - state = defaultState; - show() { - var state = state || {}; - state.show = true; - this.setState(state); - } - sure() { - let resolve = this.props["data-resolve"]; - if (resolve) { - resolve(); - } - } - cancel() { - let reject = this.props["data-reject"]; - if (reject) { - reject(); - } else { - this.hide(); - } - } - hide() { - this.setState({show: false}); - } - header() { - return ( - <Modal.Header closeButton> - <Modal.Title> - {this.props["data-title"]} - </Modal.Title> - </Modal.Header> - ); - } - body() { - return ( - <Modal.Body> - {this.props.children} - </Modal.Body> - ); - } - footer() { - return ( - <Modal.Footer> - { - this.props.hideCloseBtn - ? null - : <Button bsStyle='default' onClick={this.cancel.bind(this)} data-stest="cancelbtn"> - {this.props.closeLabel || this.state.btnCancelText} - </Button> - } - { - this.props.hideOkBtn - ? null - : <Button bsStyle='success' onClick={this.sure.bind(this)} data-stest="okbtn" disabled={this.props.btnOkDisabled}> - {this.props.okLabel || this.state.btnOkText} - </Button> - } - </Modal.Footer> - ); - } - render() { - return ( - <Modal aria-labelledby='contained-modal-title' backdrop="static" keyboard={true} onHide={this.cancel.bind(this)} show={this.state.show} {...this.props}> - {this.props.hideHeader - ? '' - : this.header()} - {this.body()} - {this.props.hideFooter - ? '' - : this.footer()} - </Modal> - ); - } -} - -var _resolve; -var _reject; - -export class Confirm extends FSModal { - show(state) { - var state = state || {}; - state.show = true; - this.setState(state); - let promise = new Promise(function(resolve, reject) { - _resolve = resolve; - _reject = reject; - }); - return promise; - } - sure() { - _resolve(this); - } - cancel() { - _reject(this); - this.setState(defaultState); - } - header() { - return ( - <Modal.Header closeButton> - <Modal.Title> - {this.state.title} - </Modal.Title> - </Modal.Header> - ); - } - body() { - return ''; - } - footer() { - return ( - <Modal.Footer> - <Button bsStyle='danger' onClick={this.cancel.bind(this)} data-stest="confirmBoxCancelBtn"> - {this.state.btnCancelText || 'No'} - </Button> - <Button bsStyle='success' onClick={this.sure.bind(this)} data-stest="confirmBoxOkBtn"> - {this.state.btnOkText || 'Yes'} - </Button> - </Modal.Footer> - ); - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/cf5c068c/contrib/views/storm/src/main/resources/ui/app/scripts/components/LogLevelComponent.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/ui/app/scripts/components/LogLevelComponent.jsx b/contrib/views/storm/src/main/resources/ui/app/scripts/components/LogLevelComponent.jsx deleted file mode 100644 index fb8e10b..0000000 --- a/contrib/views/storm/src/main/resources/ui/app/scripts/components/LogLevelComponent.jsx +++ /dev/null @@ -1,236 +0,0 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at -* - http://www.apache.org/licenses/LICENSE-2.0 -* - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -**/ - -import React, {Component} from 'react'; -import TopologyREST from '../rest/TopologyREST'; -import { - Table, - Thead, - Th, - Tr, - Td, - unsafe -} from 'reactable'; -import CommonPagination from './CommonPagination'; -import {toastOpt,pageSize} from '../utils/Constants'; -import Select from 'react-select'; -import FSReactToastr from './FSReactToastr'; -import CommonNotification from './CommonNotification'; -import Editable from './Editable'; - -export default class LogLevelComponent extends Component{ - constructor(props){ - super(props); - this.state = { - logLevelObj : {}, - traceOption : this.populateTraceOptions(), - selectedKeyName : 'com.your.organization.LoggerName', - selectedTrace : 'ALL', - selectedTimeOut : 30 - }; - this.fetchData(); - this.keyName = ''; - this.timeChange=''; - } - - fetchData = () => { - const {topologyId} = this.props; - TopologyREST.getLogConfig(topologyId).then((result) => { - if(result.errorMessage !== undefined){ - FSReactToastr.error( - <CommonNotification flag="error" content={result.errorMessage}/>, '', toastOpt); - } else { - let stateObj={}; - stateObj.selectedKeyName = 'com.your.organization.LoggerName'; - stateObj.selectedTrace = 'ALL'; - stateObj.selectedTimeOut = 30; - stateObj.logLevelObj = result.namedLoggerLevels; - this.setState(stateObj); - } - }); - } - - populateTraceOptions = () => { - let temp=[]; - const arr = ['ALL','TRACE','DEBUG','INFO','WARN','ERROR','FATAL','OFF']; - _.map(arr, (a) => { - temp.push({label : a, value : a}); - }); - return temp; - } - - handleNameChange = (e) => { - this.keyName = e.target.value.trim(); - } - - handleTimeChange = (e) => { - this.timeChange = e.target.value.trim(); - } - - traceLavelChange = (type,key,addRow,obj) => { - let tempObj = _.cloneDeep(this.state.logLevelObj); - let tempKeyName = 'ALL'; - if(!!addRow){ - tempKeyName = obj.value; - } else{ - tempObj[type][key] = obj.value; - } - this.setState({logLevelObj : tempObj,selectedTrace : tempKeyName}); - } - - modifyCommonObjValue = (refType,type,key,action,addRow) => { - let logObj = _.cloneDeep(this.state.logLevelObj); - let tempTimeOut = _.cloneDeep(this.state.selectedTimeOut); - const timeValue = (this.timeChange === '' || this.timeChange === undefined) ? parseInt(this.refs[refType].defaultValue || 0,10) : parseInt(this.timeChange,10); - if(action === 'save' && addRow === null){ - logObj[type][key] = timeValue; - } else if(action === 'save' && !!addRow){ - tempTimeOut = timeValue; - this.timeChange = ''; - }else if(action === 'reject'){ - this.timeChange = parseInt(this.refs[refType].defaultValue || 0,10); - } - this.refs[refType].hideEditor(); - this.setState({logLevelObj : logObj ,selectedTimeOut :tempTimeOut }); - } - - getDateFormat = (str) => { - const d = new Date(str); - return d.toLocaleDateString() + ' ' + d.toLocaleTimeString(); - } - - saveAndClearLogConfig = (type,action) => { - let tempObj = _.cloneDeep(this.state.logLevelObj); - let obj={},namedLoggerLevels={}; - obj.namedLoggerLevels={}; - if(action === 'clear'){ - obj.namedLoggerLevels[type] = {}; - obj.namedLoggerLevels[type].timeout = 0; - obj.namedLoggerLevels[type].target_level = null; - } else { - obj.namedLoggerLevels[type] = tempObj[type]; - } - obj.namedLoggerLevels[type].reset_level = 'INFO'; - delete obj.namedLoggerLevels[type].timeout_epoch; - - this.callLogConfigAPI(obj,null,action); - } - - callLogConfigAPI = (obj,addRow,action) => { - const {topologyId,logConfig} = this.props; - const {logLevelObj} = this.state; - TopologyREST.postLogConfig(topologyId, {body : JSON.stringify(obj)}).then((result) => { - if(result.errorMessage !== undefined){ - this.setState({logLevelObj : logConfig}); - FSReactToastr.error( - <CommonNotification flag="error" content={result.errorMessage}/>, '', toastOpt); - } else { - let msg = !!addRow ? "Log configuration added successfully" : (action === 'save' ? "Log configuration applied successfully." : "Log configuration cleared successfully."); - FSReactToastr.success(<strong>{msg}</strong>); - this.fetchData(); - } - }); - } - - addLoggerName = (refType,action) => { - let tempName = _.cloneDeep(this.state.selectedKeyName); - if(action === 'save'){ - tempName = !!this.keyName ? this.keyName : tempName; - }else if(action === 'reject'){ - this.keyName = this.refs[refType].defaultValue || tempName; - } - this.refs[refType].hideEditor(); - this.setState({selectedKeyName : tempName}); - } - - addLogRow = () => { - const {selectedKeyName,selectedTrace,selectedTimeOut} = this.state; - let obj={}; - obj.namedLoggerLevels = {}; - obj.namedLoggerLevels[selectedKeyName] = {}; - obj.namedLoggerLevels[selectedKeyName].target_level = selectedTrace; - obj.namedLoggerLevels[selectedKeyName].reset_level = 'INFO'; - obj.namedLoggerLevels[selectedKeyName].timeout = selectedTimeOut; - this.callLogConfigAPI(obj,'addRow'); - } - - render(){ - const {logLevelObj,traceOption,selectedKeyName,selectedTrace,selectedTimeOut} = this.state; - return( - <div className={`boxAnimated`}> - <hr/> - <h4 className="col-sm-offset-5">Change Log Level</h4> - <p>Modify the logger levels for topology. Note that applying a setting restarts the timer in the workers. To configure the root logger, use the name ROOT.</p> - <Table className="table no-margin"> - <Thead> - <Th column="logger" title="Logger">Logger</Th> - <Th column="target_level" title="Level">Level</Th> - <Th column="timeout" title="Timeout">Timeout</Th> - <Th column="timeout_epoch" title="Expires At">Expires At</Th> - <Th column="action" title="Action">Action</Th> - </Thead> - { - _.map(_.keys(logLevelObj), (logKey, i) => { - return <Tr key={i}> - <Td column="logger"> - <a href="javascript:void(0)">{logKey}</a> - </Td> - <Td column="target_level">{} - <Select value={logLevelObj[logKey].target_level} options={traceOption} onChange={this.traceLavelChange.bind(this,logKey,'target_level',null)} required={true} clearable={false} /> - </Td> - <Td column="timeout"> - <Editable ref={`logKey${i}`} inline={true} resolve={this.modifyCommonObjValue.bind(this,`logKey${i}`,logKey,'timeout','save',null)} reject={this.modifyCommonObjValue.bind(this,`logKey${i}`,logKey,'timeout','reject',null)}> - <input className="form-control input-sm editInput" ref={this.focusInput} defaultValue={logLevelObj[logKey].timeout} onChange={this.handleTimeChange.bind(this)}/> - </Editable> - </Td> - <Td column="timeout_epoch">{this.getDateFormat(logLevelObj[logKey].timeout_epoch)}</Td> - <Td column="action"> - <span> - <a href="javascript:void(0)" className="btn btn-success btn-xs" onClick={this.saveAndClearLogConfig.bind(this,logKey,'save')}><i className="fa fa-check"></i></a> - <a href="javascript:void(0)" className="btn btn-danger btn-xs" onClick={this.saveAndClearLogConfig.bind(this,logKey,'clear')}><i className="fa fa-times"></i></a> - </span> - </Td> - </Tr>; - }) - } - <Tr key={Math.random()}> - <Td column="logger"> - <Editable ref="addRowRef" inline={true} resolve={this.addLoggerName.bind(this,'addRowRef','save')} reject={this.addLoggerName.bind(this,"addRowRef",'reject')}> - <input className="form-control input-sm editInput" ref={this.focusInput} defaultValue={selectedKeyName} onChange={this.handleNameChange.bind(this)}/> - </Editable> - </Td> - <Td column="target_level"> - <Select value={selectedTrace} options={traceOption} onChange={this.traceLavelChange.bind(this,null,'target_level','ADD')} required={true} clearable={false} /> - </Td> - <Td column="timeout"> - <Editable ref={"timeoutRef"} inline={true} resolve={this.modifyCommonObjValue.bind(this,"timeoutRef",null,'timeout','save','ADD')} reject={this.modifyCommonObjValue.bind(this,"timeoutRef",null,'timeout','reject','ADD')}> - <input className="form-control input-sm editInput" ref={this.focusInput} defaultValue={selectedTimeOut} onChange={this.handleTimeChange.bind(this)}/> - </Editable> - </Td> - <Td column="timeout_epoch"> </Td> - <Td column="action"> - <span> - <a href="javascript:void(0)" className="btn btn-primary btn-xs" onClick={this.addLogRow.bind(this,'save')}><i className="fa fa-check"></i></a> - </span> - </Td> - </Tr> - </Table> - </div> - ); - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/cf5c068c/contrib/views/storm/src/main/resources/ui/app/scripts/components/ProfilingView.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/ui/app/scripts/components/ProfilingView.jsx b/contrib/views/storm/src/main/resources/ui/app/scripts/components/ProfilingView.jsx deleted file mode 100644 index eedf0dd..0000000 --- a/contrib/views/storm/src/main/resources/ui/app/scripts/components/ProfilingView.jsx +++ /dev/null @@ -1,168 +0,0 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at -* - http://www.apache.org/licenses/LICENSE-2.0 -* - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -**/ - -import React, {Component} from 'react'; -import TopologyREST from '../rest/TopologyREST'; -import { - Table, - Thead, - Th, - Tr, - Td, - unsafe -} from 'reactable'; -import {toastOpt,pageSize} from '../utils/Constants'; -import Utils from '../utils/Utils'; -import FSReactToastr from '../components/FSReactToastr'; -import CommonNotification from '../components/CommonNotification'; -import _ from 'lodash'; - -export default class ProfilingView extends Component{ - constructor(props){ - super(props); - this.state = { - currentPage : 1, - executorArr : this.props.executorStats ? this.fetchData() : [], - selectedWorker : [], - selectAll : false, - warnMsg : false, - successMsg : false, - errorMsg : false - }; - } - - fetchData = () => { - const {executorStats} = this.props; - let data = {},executorArr=[]; - _.map(executorStats, (o) => { - const hostPort = o.host + ":" + o.port; - if(!data[hostPort]){ - data[hostPort] = {}; - } - if(!data[hostPort].idArr){ - data[hostPort].idArr = []; - } - data[hostPort].idArr.push(o.id); - }); - let keys = this.hostPortArr = _.keys(data); - _.map(keys, (k) => { - executorArr.push({ - hostPort: k, - executorId: data[k].idArr, - checked : false - }); - }); - return executorArr; - } - - commonBtnAction = (actionType) => { - const {selectedWorker} = this.state; - selectedWorker.length ? this.apiCallback(actionType) : this.setState({warnMsg : true,successMsg : false,errorMsg: false}); - } - - apiCallback = (actionType) => { - const {topologyId} = this.props; - const {selectedWorker} = this.state; - let promiseArr=[]; - _.map(selectedWorker, (w) => { - promiseArr.push(TopologyREST.getProfiling(topologyId,actionType,w.hostPort)); - }); - - Promise.all(promiseArr).then((results) => { - _.map(results, (r) => { - let tempErrorMsg= false,tempSuccessMsg=false; - if(r.errorMessage !== undefined){ - tempErrorMsg = true; - tempSuccessMsg: false; - } else { - tempErrorMsg = false; - tempSuccessMsg: true; - } - this.setState({successMsg : tempSuccessMsg,errorMsg: tempErrorMsg,warnMsg : false}); - }); - }); - } - - handleChange = (hostPort) => { - let tempSelect = _.cloneDeep(this.state.selectAll); - let tempExecutor=_.cloneDeep(this.state.executorArr); - let tempWorker = _.cloneDeep(this.state.selectedWorker); - if(!!hostPort){ - const ind = _.findIndex(tempExecutor, (e) => {return e.hostPort === hostPort; }); - const index = _.findIndex(tempWorker,(t) => {return t.hostPort === hostPort;}); - if(index === -1 && ind !== -1){ - tempWorker.push(tempExecutor[ind]); - } else { - tempWorker.splice(index,1); - } - tempExecutor[ind].checked = !tempExecutor[ind].checked; - } else { - tempSelect = !this.state.selectAll; - _.map(tempExecutor,(t) => { - t.checked = tempSelect; - }); - tempWorker = tempExecutor; - } - this.setState({selectedWorker : tempWorker,selectAll : tempSelect,executorArr :tempExecutor }); - } - - render(){ - const {currentPage,executorArr,selectAll,warnMsg,successMsg,errorMsg} = this.state; - return( - <div> - <div className={`alert alert-warning alert-dismissible warning-msg ${warnMsg ? '' : 'hidden'}`} role="alert"> - <strong>Warning!</strong> Please select atleast one worker to perform operation. - </div> - <div className={`alert alert-success alert-dismissible success-msg ${successMsg ? '' : 'hidden'}`} role="alert"> - <strong>Success!</strong> Action performed successfully. - </div> - <div className={`alert alert-danger alert-dismissible error-msg ${errorMsg ? '' : 'hidden'}`} role="alert"> - <strong>Error!</strong> Error occured while performing the action. - </div> - <div className="clearfix"> - <div className="btn-group btn-group-sm pull-right"> - <button type="button" className="btn btn-primary" onClick={this.commonBtnAction.bind(this,'dumpjstack')}>JStack</button> - <button type="button" className="btn btn-primary" onClick={this.commonBtnAction.bind(this,'restartworker')}>Restart Worker</button> - <button type="button" className="btn btn-primary" onClick={this.commonBtnAction.bind(this,'dumpheap')}>Heap</button> - </div> - </div> - <hr /> - <Table className="table table-bordered" columns={currentPage-1} noDataText="No workers found !"> - <Thead> - <Th column="checkbox"> - <input type="checkbox" name="single" onChange={this.handleChange.bind(this,null)}/> - </Th> - <Th column="hostPort" >Host:Port</Th> - <Th column="executorId" >Executor Id</Th> - </Thead> - { - _.map(executorArr , (e,i) => { - return <Tr key={i}> - <Td column="checkbox"> - <input type="checkbox" checked={e.checked} name="single" onChange={this.handleChange.bind(this,e.hostPort)}/> - </Td> - <Td column="hostPort">{e.hostPort}</Td> - <Td column="executorId">{e.executorId.join(',')}</Td> - </Tr>; - }) - } - </Table> - </div> - ); - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/cf5c068c/contrib/views/storm/src/main/resources/ui/app/scripts/components/RadialChart.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/ui/app/scripts/components/RadialChart.jsx b/contrib/views/storm/src/main/resources/ui/app/scripts/components/RadialChart.jsx deleted file mode 100644 index 4c4e8fc..0000000 --- a/contrib/views/storm/src/main/resources/ui/app/scripts/components/RadialChart.jsx +++ /dev/null @@ -1,134 +0,0 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at -* - http://www.apache.org/licenses/LICENSE-2.0 -* - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -**/ - -import React, {Component} from 'react'; -import PropTypes from 'prop-types'; -import ReactDOM from 'react-dom'; -import d3 from 'd3'; -import d3Tip from 'd3-tip'; - - -export default class RadialChart extends Component { - static propTypes = { - data: PropTypes.array.isRequired, - labels: PropTypes.array.isRequired, - width: PropTypes.number, - height: PropTypes.number, - innerRadius: PropTypes.number.isRequired, - outerRadius: PropTypes.number.isRequired, - color: PropTypes.array - } - constructor(props) { - super(props); - this.const = { - tau: 2 * Math.PI, - width: props.width || "44", - height: props.height || "52", - innerRadius: parseInt(props.innerRadius, 10) || 20, - outerRadius: parseInt(props.outerRadius, 10) || 25, - color: props.color || d3.scale.category20() - }; - this.arc = d3.svg.arc() - .innerRadius(this.const.innerRadius) - .outerRadius(this.const.outerRadius) - .startAngle(0); - } - componentDidUpdate() { - this.animateGraph(); - } - componentDidMount() { - const self = this; - this.tip = d3Tip() - .attr('class', 'd3-tip') - .offset([-10, 0]) - .html(function() { - var text = "<div class='summary'>" + this.props.labels[0] + ": " + this.props.data[0] + "</div>"; - text += "<div class='summary'>Free: " + (parseInt(this.props.data[1], 10) - parseInt(this.props.data[0], 10)) + "</div>"; - text += "<div class='summary'>" + this.props.labels[1] + ": " + this.props.data[1] + "</div>"; - return text; - }.bind(this)); - var svg = this.svg = d3.select(ReactDOM.findDOMNode(this)) - .attr('width', this.const.width + "px") - .attr('height', this.const.height + "px") - .append('g').attr('transform', 'translate(' + (this.const.width / 2) + ', ' + (this.const.height / 2) + ')'); - - this.text = svg.append("text") - .attr("y", "0.3em") - .attr("class", "graphVal") - .attr("text-anchor", "middle") - .attr("font-size", this.const.fontSize) - .on("mouseover", function(d){ - self.tip.show(d, this); - }) - .on("mouseout", function(d){ - self.tip.hide(d, this); - }) - .text("0"); - - var background = svg.append("path") - .datum({ - endAngle: this.const.tau - }) - .style("fill", this.const.color[0]) - .attr("d", this.arc); - - this.foreground = svg.append("path") - .datum({ - endAngle: 0 - }) - .style("fill", function(d, i) { - return this.const.color[1]; - }.bind(this)) - .attr("d", this.arc); - this.svg.call(this.tip); - // $('#container').append($('body > .d3-tip')); - this.animateGraph(); - } - animateGraph() { - var percent = (parseInt(this.props.data[0], 10) / parseInt(this.props.data[1], 10) * 100); - if (percent) { - percent = percent.toFixed(0) + ' %'; - } else { - percent = '0 %'; - } - - d3.select(ReactDOM.findDOMNode(this)).select('.graphVal').text(percent); - - var newValue = this.props.data[0] / this.props.data[1] * 100; - this.foreground.transition() - .duration(750) - .call(this._arcTween.bind(this), this.const.tau * (newValue / 100)); - } - _arcTween(transition, newAngle) { - var arc = this.arc; - transition.attrTween("d", function(d) { - var interpolate = d3.interpolate(d.endAngle, newAngle); - return function(t) { - d.endAngle = interpolate(t); - if (!d.endAngle) { - d.endAngle = 0; - } - return arc(d); - }; - - }); - } - render() { - return ( < svg className = "radial-chart" > < /svg>); - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/cf5c068c/contrib/views/storm/src/main/resources/ui/app/scripts/components/RebalanceTopology.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/ui/app/scripts/components/RebalanceTopology.jsx b/contrib/views/storm/src/main/resources/ui/app/scripts/components/RebalanceTopology.jsx deleted file mode 100644 index 43c7f78..0000000 --- a/contrib/views/storm/src/main/resources/ui/app/scripts/components/RebalanceTopology.jsx +++ /dev/null @@ -1,152 +0,0 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at -* - http://www.apache.org/licenses/LICENSE-2.0 -* - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -**/ - -import React, {Component} from 'react'; -import TopologyREST from '../rest/TopologyREST'; -import {toastOpt,pageSize} from '../utils/Constants'; -import Utils from '../utils/Utils'; -import FSReactToastr from './FSReactToastr'; -import CommonNotification from './CommonNotification'; -import _ from 'lodash'; - -export default class RebalanceTopology extends Component{ - constructor(props){ - super(props); - this.state = { - freeSlot : 0, - waitTime : 30, - rebalanceData : {} - }; - this.fetchData(); - } - - fetchData = () => { - const {topologyExecutors,spoutArr,boltArr} = this.props; - TopologyREST.getSummary('cluster').then((result) => { - if(result.errorMessage !== undefined){ - FSReactToastr.error( - <CommonNotification flag="error" content={result.errorMessage}/>, '', toastOpt); - } else { - let stateObj = {}; - stateObj.freeSlot = result.slotsFree; - stateObj.rebalanceData={}; - stateObj.rebalanceData.workers = topologyExecutors + stateObj.freeSlot; - this.totalWorker = stateObj.rebalanceData.workers; - _.map(spoutArr, (s) => { - stateObj.rebalanceData[s.spoutId] = s.executors; - }); - _.map(boltArr, (b) => { - stateObj.rebalanceData[b.boltId] = b.executors; - }); - this.setState(stateObj); - } - }); - } - - rebalanceValueChange = (type,e) => { - let data = _.cloneDeep(this.state.rebalanceData); - data[type] = +e.target.value; - this.setState({rebalanceData : data}); - } - - waitTimeChange = (e) => { - this.setState({waitTime : +e.target.value}); - } - - validateData = () => { - const {rebalanceData,waitTime} = this.state; - let errorFlag = []; - _.map(_.keys(rebalanceData), (key) => { - if(rebalanceData[key] === ''){ - errorFlag.push(false); - } - }); - if(waitTime === ''){ - errorFlag.push(false); - } - return errorFlag.length ? false : true; - } - - handleSave = () => { - const {rebalanceData,waitTime} = this.state; - const {topologyId} = this.props; - let finalData = { - "rebalanceOptions": { - "executors": {} - } - }; - _.map(_.keys(rebalanceData), (key) => { - if(key === "workers"){ - finalData.rebalanceOptions.numWorkers = rebalanceData[key]; - } else { - finalData.rebalanceOptions.executors[key] = rebalanceData[key]; - } - }); - - return TopologyREST.postActionOnTopology(topologyId,'rebalance',waitTime,{body : JSON.stringify(finalData)}); - } - - render(){ - const {freeSlot,waitTime,rebalanceData} = this.state; - const {spoutArr,boltArr}= this.props; - return( - <div> - <div className="form-group row"> - <div className="col-sm-3"> - <label>Workers:<span className="text-danger">*</span></label> - </div> - <div className="col-sm-7"> - <span style={{float : 'left'}}>0</span><input type="range" title={rebalanceData.workers +' workers selected.'} min={0} style={{width : '90%', float : 'left',margin : '6px 7px' }} max={this.totalWorker} onChange={this.rebalanceValueChange.bind(this,'workers')} /><span style={{float : 'left', clear : 'right'}}>{this.totalWorker}</span> - </div> - </div> - { - _.map(spoutArr, (s , i) => { - return <div className="form-group row" key={i}> - <div className="col-sm-3"> - <label>{s.spoutId}:<span className="text-danger">*</span></label> - </div> - <div className="col-sm-7"> - <input type="number" className="form-control" min={0} defaultValue={s.executors} onChange={this.rebalanceValueChange.bind(this,s.spoutId)} /> - </div> - </div>; - }) - } - { - _.map(boltArr, (b , n) => { - return <div className="form-group row" key={n}> - <div className="col-sm-3"> - <label>{b.boltId}:<span className="text-danger">*</span></label> - </div> - <div className="col-sm-7"> - <input type="number" className="form-control" min={0} defaultValue={b.executors} onChange={this.rebalanceValueChange.bind(this,b.boltId)} /> - </div> - </div>; - }) - } - <div className="form-group row"> - <div className="col-sm-3"> - <label>Wait Time:<span className="text-danger">*</span></label> - </div> - <div className="col-sm-7"> - <input type="number" className="form-control" min={0} value={waitTime} onChange={this.waitTimeChange.bind(this)} /> - </div> - </div> - </div> - ); - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/cf5c068c/contrib/views/storm/src/main/resources/ui/app/scripts/components/SearchLogs.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/ui/app/scripts/components/SearchLogs.jsx b/contrib/views/storm/src/main/resources/ui/app/scripts/components/SearchLogs.jsx deleted file mode 100644 index ebf1615..0000000 --- a/contrib/views/storm/src/main/resources/ui/app/scripts/components/SearchLogs.jsx +++ /dev/null @@ -1,84 +0,0 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at -* - http://www.apache.org/licenses/LICENSE-2.0 -* - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -**/ - -import React, {Component} from 'react'; -import ReactDOM from 'react-dom'; -import {baseUrl} from '../utils/Constants'; -import {DropdownButton, FormGroup, Checkbox} from 'react-bootstrap'; -import fetch from 'isomorphic-fetch'; - -export default class SearchLogs extends Component{ - render() { - return ( - <div className="col-md-3 pull-right searchbar"> - <div className="input-group"> - <input type="text" id="searchBox" className="form-control" placeholder="Search in Logs"/> - <div className="input-group-btn"> - <div className="btn-group" role="group"> - <div className="dropdown dropdown-lg"> - <DropdownButton title="" pullRight id="bg-nested-dropdown"> - <FormGroup> - <Checkbox id="searchArchivedLogs">Search archived logs</Checkbox> - </FormGroup> - <FormGroup> - <Checkbox id="deepSearch">Deep search</Checkbox> - </FormGroup> - </DropdownButton> - </div> - <button type="button" className="btn btn-default" onClick={this.handleSearch.bind(this)}> - <i className="fa fa-search"></i> - </button> - </div> - </div> - </div> - </div> - ); - } - handleSearch(){ - var searchBoxEl = document.getElementById('searchBox'); - var searchArchivedLogsEl = document.getElementById('searchArchivedLogs'); - var deepSearchEl = document.getElementById('deepSearch'); - var topologyId = this.props.id; - - fetch(baseUrl.replace('proxy?url=/api/v1/', 'storm_details'), {"credentials": "same-origin"}) - .then((response) => { - return response.json(); - }) - .then((response) => { - var url = response.hostdata+'/'; - if(deepSearchEl.checked == true){ - url += "deep_search_result.html"; - }else{ - url += "search_result.html"; - } - url += '?search='+searchBoxEl.value+'&id='+ topologyId +'&count=1'; - if(searchArchivedLogsEl.checked == true){ - if(deepSearchEl.checked == true){ - url += "&search-archived=on"; - }else{ - url += "&searchArchived=checked"; - } - } - window.open(url, '_blank'); - - searchBoxEl.value = ''; - searchArchivedLogsEl.checked = false; - deepSearchEl.checked = false; - }); - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/cf5c068c/contrib/views/storm/src/main/resources/ui/app/scripts/components/TopologyGraph.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/ui/app/scripts/components/TopologyGraph.jsx b/contrib/views/storm/src/main/resources/ui/app/scripts/components/TopologyGraph.jsx deleted file mode 100644 index 4cfc6bb..0000000 --- a/contrib/views/storm/src/main/resources/ui/app/scripts/components/TopologyGraph.jsx +++ /dev/null @@ -1,208 +0,0 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at -* - http://www.apache.org/licenses/LICENSE-2.0 -* - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -**/ - -import React, {Component} from 'react'; -import PropTypes from 'prop-types'; -import ReactDOM from 'react-dom'; -import d3 from 'd3'; -import d3Tip from 'd3-tip'; -import dagreD3 from 'dagre-d3/dist/dagre-d3'; - -export default class TopologyGraph extends Component{ - static propTypes = { - data: PropTypes.object.isRequired, - width: PropTypes.string, - height: PropTypes.string - } - constructor(props) { - super(props); - this.syncData(this.props.data); - this.updateFlag = true; - } - componentDidUpdate() { - if(!!this.updateFlag){ - this.syncData(this.props.data); - this.updateGraph(); - } - } - componentWillReceiveProps(nextProps){ - _.isEqual(nextProps.data,this.props.data) ? this.updateFlag = false : this.updateFlag = true; - } - componentDidMount(){ - var that = this; - this.svg = d3.select(ReactDOM.findDOMNode(this)); - //Set up tooltip - this.tooltip = d3Tip() - .attr('class', function() { - return 'd3-tip testing'; - }) - .offset([-10, 0]) - .html(function(data) { - var d = that.g.node(data); - var tip = "<ul>"; - if (d[":capacity"] !== null){ tip += "<li>Capacity: " + d[":capacity"].toFixed(2) + "</li>";} - if (d[":latency"] !== null){ tip += "<li>Latency: " + d[":latency"].toFixed(2) + "</li>";} - if (d[":transferred"] !== null){ tip += "<li>Transferred: " + d[":transferred"].toFixed(2) + "</li>";} - tip += "</ul>"; - return tip; - }); - //Set up zoom - this.zoom = d3.behavior.zoom() - .scaleExtent([0, 8]) - .on("zoom", this.zoomed.bind(this)); - } - zoomed(){ - this.inner.attr("transform", - "translate(" + this.zoom.translate() + ")" + - "scale(" + this.zoom.scale() + ")" - ); - } - // update graph (called when needed) - updateGraph(){ - var that = this; - var g = ReactDOM.findDOMNode(this).children[0]; - if(g){ - g.remove(); - } - var inner = this.inner = this.svg.append("g"); - // Create the renderer - var render = new dagreD3.render(); - render.arrows().arrowPoint = (parent, id, edge, type) => { - var marker = parent.append("marker") - .attr("id", id) - .attr("viewBox", "0 0 10 10") - .attr("refX", 5) - .attr("refY", 5) - .attr("markerUnits", "strokeWidth") - .attr("markerWidth", 6) - .attr("markerHeight", 6.5) - .attr("orient", "auto"); - var path = marker.append("path") - .attr("d", "M 0 0 L 10 5 L 0 10 z") - .style("stroke-width", 1) - .style("stroke-dasharray", "1,0") - .style("fill", "grey") - .style("stroke", "grey"); - dagreD3.util.applyStyle(path, edge[type + "Style"]); - }; - - render.shapes().img = (parent, bbox, node) => { - var shapeSvg; - if(parent){ - shapeSvg = parent.insert("image") - .attr("class", "nodeImage") - .attr("xlink:href", function(d) { - if (node) { - if(node.type === 'spout'){ - return "styles/img/icon-spout.png"; - } else if(node.type === 'bolt'){ - return "styles/img/icon-bolt.png"; - } - } - }).attr("x", "-12px") - .attr("y", "-12px") - .attr("width", "30px") - .attr("height", "30px"); - } - node.intersect = function(point) { - return dagreD3.intersect.circle(node, 20, point); - }; - return shapeSvg; - }; - this.svg.call(this.zoom).call(this.tooltip); - // Run the renderer. This is what draws the final graph. - render(inner, this.g); - - inner.selectAll("g.nodes image") - .on('mouseover', function(d) { - that.tooltip.show(d, this); - }) - .on('mouseout', function(d) { - that.tooltip.hide(this); - }); - inner.selectAll("g.nodes g.label") - .attr("transform", "translate(2,-30)"); - // Center the graph - var initialScale = 1; - var svgWidth = this.svg[0][0].parentNode.clientWidth; - var svgHeight = this.svg[0][0].parentNode.clientHeight; - if(this.linkArray.length > 0){ - this.zoom.translate([(svgWidth - this.g.graph().width * initialScale) / 2, (svgHeight - this.g.graph().height * initialScale) / 2]) - .scale(initialScale) - .event(this.svg); - } - } - syncData(data){ - this.nodeArray = []; - this.linkArray = []; - this.g = new dagreD3.graphlib.Graph().setGraph({ - nodesep: 50, - ranksep: 190, - rankdir: "LR", - marginx: 20, - marginy: 20 - // transition: function transition(selection) { - // return selection.transition().duration(500); - // } - }); - if(data){ - var keys = _.keys(data); - keys.map(function(key){ - if(!key.startsWith('__')){ - data[key].id = key; - data[key].type = data[key][":type"]; - this.nodeArray.push(data[key]); - } - }.bind(this)); - - var spoutObjArr = _.filter(this.nodeArray, { "type": "spout" }); - if (spoutObjArr.length > 1) { - for(var i = 0; i < spoutObjArr.length; i++){ - spoutObjArr[i].x = 50; - spoutObjArr[i].y = parseInt(i+'10', 10); - spoutObjArr[i].fixed = true; - } - } else if (spoutObjArr.length == 1) { - spoutObjArr[0].x = 50; - spoutObjArr[0].y = 100; - spoutObjArr[0].fixed = true; - } - - this.nodeArray.map(function(node){ - var inputArr = node[":inputs"] || []; - inputArr.map(function(input){ - if(!input[":component"].startsWith("__")){ - var sourceNode = _.find(this.nodeArray, {id: input[":component"]}); - this.linkArray.push({ - source: sourceNode, - target: node - }); - this.g.setNode(sourceNode.id, _.extend(sourceNode, {label: sourceNode.id, shape: 'img'})); - this.g.setNode(node.id, _.extend(node, {label: node.id, shape: 'img'})); - this.g.setEdge(sourceNode.id, node.id, {"arrowhead": 'arrowPoint'}); - } - }.bind(this)); - }.bind(this)); - } - } - render() { - return ( - <svg className="topology-graph" width="100%" height="300"></svg> - ); - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/cf5c068c/contrib/views/storm/src/main/resources/ui/app/scripts/containers/BaseContainer.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/ui/app/scripts/containers/BaseContainer.jsx b/contrib/views/storm/src/main/resources/ui/app/scripts/containers/BaseContainer.jsx deleted file mode 100644 index 62846b7..0000000 --- a/contrib/views/storm/src/main/resources/ui/app/scripts/containers/BaseContainer.jsx +++ /dev/null @@ -1,50 +0,0 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at -* - http://www.apache.org/licenses/LICENSE-2.0 -* - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -**/ - -import React, {Component} from 'react'; -import Footer from '../components/Footer'; -import {Confirm} from '../components/FSModel'; - -export default class BaseContainer extends Component { - - constructor(props) { - super(props); - } - - handleKeyPress = (event) => { - event.key === "Enter" - ? this.refs.Confirm.state.show - ? this.refs.Confirm.sure() - : '' - :event.key === "Escape" - ? this.refs.Confirm.state.show - ? this.refs.Confirm.cancel() - : '' - :''; - } - - render() { - return ( - <div className="container-fluid"> - {this.props.children} - <Confirm ref="Confirm" onKeyUp={this.handleKeyPress}/> - <Footer /> - </div> - ); - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/cf5c068c/contrib/views/storm/src/main/resources/ui/app/scripts/containers/ClusterSummary.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/ui/app/scripts/containers/ClusterSummary.jsx b/contrib/views/storm/src/main/resources/ui/app/scripts/containers/ClusterSummary.jsx deleted file mode 100644 index 904ed68..0000000 --- a/contrib/views/storm/src/main/resources/ui/app/scripts/containers/ClusterSummary.jsx +++ /dev/null @@ -1,125 +0,0 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at -* - http://www.apache.org/licenses/LICENSE-2.0 -* - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -**/ - -import React, {Component} from 'react'; -import RadialChart from '../components/RadialChart'; -import FSReactToastr from '../components/FSReactToastr'; -import {toastOpt} from '../utils/Constants'; -import TopologyREST from '../rest/TopologyREST'; -import NimbusSummary from './NimbusSummary'; -import CommonNotification from '../components/CommonNotification'; -import {OverlayTrigger, Tooltip} from 'react-bootstrap'; - -export default class ClusterSummary extends Component{ - constructor(props){ - super(props); - this.fetchData(); - this.state = { - entity :{} - }; - } - - fetchData = () => { - TopologyREST.getSummary('cluster').then((result) => { - if(result.errorMessage !== undefined){ - FSReactToastr.error( - <CommonNotification flag="error" content={result.errorMessage}/>, '', toastOpt); - } else { - this.setState({entity : result}); - } - }); - } - render(){ - const {entity} = this.state; - return( - <div> - <div className="row"> - <div className="col-sm-6"> - <OverlayTrigger placement="bottom" overlay={<Tooltip id="tooltip1">Executors are threads in a Worker process.</Tooltip>}> - <div className="tile primary"> - <div className="tile-header">Executor</div> - <div className="tile-body"> - <i className="fa fa-play-circle-o"></i> - <span className="count">{entity.executorsTotal}</span> - </div> - </div> - </OverlayTrigger> - </div> - <div className="col-sm-6"> - <OverlayTrigger placement="bottom" overlay={<Tooltip id="tooltip1">A Task is an instance of a Bolt or Spout. The number of Tasks is almost always equal to the number of Executors.</Tooltip>}> - <div className="tile warning"> - <div className="tile-header">Tasks</div> - <div className="tile-body"> - <i className="fa fa-tasks"></i> - <span className="count">{entity.tasksTotal}</span> - </div> - </div> - </OverlayTrigger> - </div> - </div> - <div className="row"> - <div className="col-sm-6"> - <OverlayTrigger placement="bottom" overlay={<Tooltip id="tooltip1">The number of nodes in the cluster currently.</Tooltip>}> - <div className="tile success"> - <div className="tile-header" style={{textAlign:"center"}}>Supervisor</div> - <div className="tile-body" style={{textAlign:"center"}}> - <div id="supervisorCount"> - <RadialChart - data={[entity.supervisors,entity.supervisors]} - labels={['Used','Total']} - width={100} - height={100} - innerRadius={46} - outerRadius={50} - color={["rgba(255,255,255,0.6)", "rgba(255,255,255,1)"]} - /> - </div> - </div> - </div> - </OverlayTrigger> - </div> - <div className="col-sm-6"> - <OverlayTrigger placement="bottom" overlay={<Tooltip id="tooltip1">Slots are Workers (processes).</Tooltip>}> - <div className="tile danger"> - <div className="tile-header" style={{textAlign:"center"}}>Slots</div> - <div className="tile-body" style={{textAlign:"center"}}> - <div id="slotsCount"> - <RadialChart - data={[entity.slotsUsed,entity.slotsTotal]} - labels={['Used','Total']} - width={100} - height={100} - innerRadius={46} - outerRadius={50} - color={["rgba(255,255,255,0.6)", "rgba(255,255,255,1)"]} - /> - </div> - </div> - </div> - </OverlayTrigger> - </div> - </div> - <div className="row"> - <div className="col-sm-12"> - <NimbusSummary fromDashboard={true}/> - </div> - </div> - </div> - ); - } -}
