blob: 48b815ad215e62181c05332721289059a5d7bd3a [file] [log] [blame]
// Licensed 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 from 'react';
import PropTypes from 'prop-types';
import { Popover, OverlayTrigger } from 'react-bootstrap';
export default class ExecutionStats extends React.Component {
constructor (props) {
super(props);
}
humanizeDuration(milliseconds) {
if (milliseconds < 1000) {
return Math.round(milliseconds) + ' ms';
}
let seconds = milliseconds / 1000;
if (seconds < 60) {
return Math.floor(seconds) + ' seconds';
}
const minutes = Math.floor(seconds / 60);
seconds = Math.floor(seconds - (minutes * 60));
const minuteText = minutes > 1 ? 'minutes' : 'minute';
const secondsText = seconds > 1 ? 'seconds' : 'second';
return [minutes, ' ', minuteText, ', ', seconds, ' ', secondsText].join('');
}
getWarning(warnings) {
if (warnings) {
const lines = warnings.split('\n').map((warnText, i) => {
return <React.Fragment key={i}>{warnText}<br/></React.Fragment>;
});
return <span>{lines}</span>;
}
}
warningPopupComponent(warningText) {
if (warningText) {
return (<div className="warning">
<i className="fonticon-attention-circled"></i> {warningText}
</div>);
}
}
executionStatsLine(title, value, alwaysShow = false, units = "") {
if (typeof value === 'number') {
const hasValue = value === 0 && !alwaysShow ? "false" : "true";
return <div data-status={hasValue}>{title + ": "}<span className="value">{value.toLocaleString()} {units}</span></div>;
}
return null;
}
executionStatsPopupComponent(executionStats) {
if (!executionStats) return null;
return (
<div className="execution-stats-popup-component">
{/* keys examined always 0 so hide it for now */}
{/* {this.executionStatsLine("keys examined", executionStats.total_keys_examined)} */}
{this.executionStatsLine("documents examined", executionStats.total_docs_examined)}
{this.executionStatsLine("documents examined (quorum)", executionStats.total_quorum_docs_examined)}
{this.executionStatsLine("results returned", executionStats.results_returned, true)}
{this.executionStatsLine("execution time", Math.round(executionStats.execution_time_ms), false, "ms")}
</div>
);
}
popup(executionStats, warningText) {
return (
<Popover id="popover-execution-stats" title="Execution Statistics">
<div className="execution-stats-popup">
{this.executionStatsPopupComponent(executionStats)}
{this.warningPopupComponent(warningText)}
</div>
</Popover>
);
}
render() {
const {
executionStats,
warning
} = this.props;
const warningText = this.getWarning(warning);
let warningComponent = null;
if (warningText) {
warningComponent = <i className="fonticon-attention-circled"></i>;
}
let executionStatsComponent = null;
if (executionStats) {
executionStatsComponent = (
<span className="execution-stats-component">Executed in {this.humanizeDuration(executionStats.execution_time_ms)}</span>
);
} else if (warningText) {
executionStatsComponent = (
<span className="execution-stats-component">Warning</span>
);
}
const popup = this.popup(executionStats, warningText);
return (
<OverlayTrigger trigger={['hover', 'focus', 'click']} placement="right" overlay={popup}>
<span className="execution-stats">
{warningComponent}
{executionStatsComponent}
</span>
</OverlayTrigger>
);
}
}
ExecutionStats.propTypes = {
executionStats: PropTypes.object,
warning: PropTypes.string
};