<commit_before>/**
 * @Author: <NAME> <wahaj>
 * @Date:   2018-04-06T14:15:28+10:00
 * @Email:  <EMAIL>
 * @Last modified by:   wahaj
 * @Last modified time: 2018-05-30T14:07:53+10:00
 *
 * dbKoda - a modern, open source code editor, for MongoDB.
 * Copyright (C) 2017-2018 Southbank Software
 *
 * This file is part of dbKoda.
 *
 * dbKoda is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * dbKoda is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with dbKoda.  If not, see <http://www.gnu.org/licenses/>.
 */

import * as React from 'react';
import { action } from 'mobx';
import { inject, observer } from 'mobx-react';
import SplitPane from 'react-split-pane';
import autobind from 'autobind-decorator';
import { debounce } from 'lodash';
import ExplainView from '#/ProfilingPanel/Views/ExplainView';
import ConnectionsView from './Views/Connections';
import OperationsView from './Views/Operations';
import OperationDetails from './Views/OperationDetails';

import './Panel.scss';

@inject(allStores => ({
  api: allStores.store.api,
  store: allStores.store
}))
@observer
export default class TopConnectionsPanel extends React.Component<Props> {
  timeoutUpdateId = null;

  lastSelectedConID = '';
  defaultOperationPaneSize = '100%';
  defaultConnectionPaneSize = '35%';
  constructor(props) {
    super(props);
    this.state = {
      autoRefreshTopCon: false,
      autoRefreshTimeout: 30,
      bottomSplitPos: window.innerWidth * 0.6 < 600 ? 600 : window.innerWidth * 0.6,
      topSplitPos: window.innerWidth - 61
    };
    this.props.api.getTopConnections();
  }
  componentDidMount() {
    window.addEventListener('resize', debounce(this.handleResize, 400));
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.handleResize);
  }

  @autobind
  updateTopConnections() {
    if (this.state.autoRefreshTopCon && this.state.autoRefreshTimeout > 0) {
      this.props.api.getTopConnections();
      this.setTimerForUpdate();
    }
  }

  @autobind
  handleResize() {
    this.setState({ topSplitPos: window.innerWidth - 61 });
  }

  @autobind
  updateBottomSplitPos(pos) {
    this.setState({ bottomSplitPos: pos });
  }

  @action.bound
  onConnectionSelection(selectedConnection) {
    this.props.store.topConnectionsPanel.selectedConnection = selectedConnection;
    this.props.store.topConnectionsPanel.operations = selectedConnection.ops;
    // this.props.store.topConnectionsPanel.bShowExplain = false;
    // this.props.store.topConnectionsPanel.selectedOperation = null;
  }

  @action.bound
  onOperationSelection(selectedOperation) {
    const { topConnectionsPanel } = this.props.store;
    if (topConnectionsPanel.selectedOperation !== selectedOperation) {
      topConnectionsPanel.selectedOperation = selectedOperation;
      if (
        selectedOperation &&
        selectedOperation.explainPlan &&
        selectedOperation.explainPlan.queryPlanner &&
        selectedOperation.explainPlan.queryPlanner.winningPlan
      ) {
        topConnectionsPanel.bShowExplain = true;
      } else {
        topConnectionsPanel.bShowExplain = false;
        topConnectionsPanel.bLoadingExplain = false;
      }
    }
  }

  @autobind
  setTimerForUpdate(timerValue = 0) {
    const autoRefreshTimeout = timerValue > 0 ? timerValue : this.state.autoRefreshTimeout;
    if (this.timeoutUpdateId) {
      clearTimeout(this.timeoutUpdateId);
      this.timeoutUpdateId = null;
    }
    this.timeoutUpdateId = setTimeout(this.updateTopConnections, autoRefreshTimeout * 1000);
  }

  @autobind
  onAutoRefreshCheckboxToggle(e) {
    const fieldValue = e.target.checked === true;
    const fieldName = e.target.id;
    l.info(fieldName, ':', fieldValue);
    this.setState({ autoRefreshTopCon: fieldValue });
    if (fieldValue && this.state.autoRefreshTimeout > 0) {
      this.setTimerForUpdate();
    }
    if (!fieldValue && this.timeoutUpdateId) {
      clearTimeout(this.timeoutUpdateId);
      this.timeoutUpdateId = null;
    }
    // this.props.updateValue(fieldName, fieldValue);
  }

  @autobind
  onAutoRefreshTimeoutChange(value) {
    l.info('onAutoRefreshTimeoutChange:', value);
    if (value < 5) {
      value = 5;
    }
    this.setState({ autoRefreshTimeout: value });
    if (value > 0 && this.state.autoRefreshTopCon) {
      this.setTimerForUpdate(value);
    }
  }

  render() {
    const splitPane2Style = {
      display: 'flex',
      flexDirection: 'column'
    };
    const bottomPane2Style = {
      width: this.state.topSplitPos - this.state.bottomSplitPos + 'px'
    };
    const { topConnectionsPanel } = this.props.store;
    const { selectedOperation, selectedConnection } = topConnectionsPanel;

    if (topConnectionsPanel.bShowExplain) {
      this.defaultOperationPaneSize = '50%';
      if (selectedOperation.suggestionText) {
        this.defaultConnectionPaneSize = '25%';
        this.defaultOperationPaneSize = '25%';<commit_msg>Minor Fix for exception in Top Connection Panel<commit_after>/**
 * @Author: <NAME> <wahaj>
 * @Date:   2018-04-06T14:15:28+10:00
 * @Email:  <EMAIL>
 * @Last modified by:   wahaj
 * @Last modified time: 2018-05-30T14:07:53+10:00
 *
 * dbKoda - a modern, open source code editor, for MongoDB.
 * Copyright (C) 2017-2018 Southbank Software
 *
 * This file is part of dbKoda.
 *
 * dbKoda is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * dbKoda is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with dbKoda.  If not, see <http://www.gnu.org/licenses/>.
 */

import * as React from 'react';
import { action } from 'mobx';
import { inject, observer } from 'mobx-react';
import SplitPane from 'react-split-pane';
import autobind from 'autobind-decorator';
import { debounce } from 'lodash';
import ExplainView from '#/ProfilingPanel/Views/ExplainView';
import ConnectionsView from './Views/Connections';
import OperationsView from './Views/Operations';
import OperationDetails from './Views/OperationDetails';

import './Panel.scss';

@inject(allStores => ({
  api: allStores.store.api,
  store: allStores.store
}))
@observer
export default class TopConnectionsPanel extends React.Component<Props> {
  timeoutUpdateId = null;

  lastSelectedConID = '';
  defaultOperationPaneSize = '100%';
  defaultConnectionPaneSize = '35%';
  constructor(props) {
    super(props);
    this.state = {
      autoRefreshTopCon: false,
      autoRefreshTimeout: 30,
      bottomSplitPos: window.innerWidth * 0.6 < 600 ? 600 : window.innerWidth * 0.6,
      topSplitPos: window.innerWidth - 61
    };
    this.props.api.getTopConnections();
  }
  componentDidMount() {
    window.addEventListener('resize', debounce(this.handleResize, 400));
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.handleResize);
  }

  @autobind
  updateTopConnections() {
    if (this.state.autoRefreshTopCon && this.state.autoRefreshTimeout > 0) {
      this.props.api.getTopConnections();
      this.setTimerForUpdate();
    }
  }

  @autobind
  handleResize() {
    this.setState({ topSplitPos: window.innerWidth - 61 });
  }

  @autobind
  updateBottomSplitPos(pos) {
    this.setState({ bottomSplitPos: pos });
  }

  @action.bound
  onConnectionSelection(selectedConnection) {
    this.props.store.topConnectionsPanel.selectedConnection = selectedConnection;
    this.props.store.topConnectionsPanel.operations = selectedConnection.ops;
    // this.props.store.topConnectionsPanel.bShowExplain = false;
    // this.props.store.topConnectionsPanel.selectedOperation = null;
  }

  @action.bound
  onOperationSelection(selectedOperation) {
    const { topConnectionsPanel } = this.props.store;
    if (topConnectionsPanel.selectedOperation !== selectedOperation) {
      topConnectionsPanel.selectedOperation = selectedOperation;
      if (
        selectedOperation &&
        selectedOperation.explainPlan &&
        selectedOperation.explainPlan.queryPlanner &&
        selectedOperation.explainPlan.queryPlanner.winningPlan
      ) {
        topConnectionsPanel.bShowExplain = true;
      } else {
        topConnectionsPanel.bShowExplain = false;
        topConnectionsPanel.bLoadingExplain = false;
      }
    }
  }

  @autobind
  setTimerForUpdate(timerValue = 0) {
    const autoRefreshTimeout = timerValue > 0 ? timerValue : this.state.autoRefreshTimeout;
    if (this.timeoutUpdateId) {
      clearTimeout(this.timeoutUpdateId);
      this.timeoutUpdateId = null;
    }
    this.timeoutUpdateId = setTimeout(this.updateTopConnections, autoRefreshTimeout * 1000);
  }

  @autobind
  onAutoRefreshCheckboxToggle(e) {
    const fieldValue = e.target.checked === true;
    const fieldName = e.target.id;
    l.info(fieldName, ':', fieldValue);
    this.setState({ autoRefreshTopCon: fieldValue });
    if (fieldValue && this.state.autoRefreshTimeout > 0) {
      this.setTimerForUpdate();
    }
    if (!fieldValue && this.timeoutUpdateId) {
      clearTimeout(this.timeoutUpdateId);
      this.timeoutUpdateId = null;
    }
    // this.props.updateValue(fieldName, fieldValue);
  }

  @autobind
  onAutoRefreshTimeoutChange(value) {
    l.info('onAutoRefreshTimeoutChange:', value);
    if (value < 5) {
      value = 5;
    }
    this.setState({ autoRefreshTimeout: value });
    if (value > 0 && this.state.autoRefreshTopCon) {
      this.setTimerForUpdate(value);
    }
  }

  render() {
    const splitPane2Style = {
      display: 'flex',
      flexDirection: 'column'
    };
    const bottomPane2Style = {
      width: this.state.topSplitPos - this.state.bottomSplitPos + 'px'
    };
    const { topConnectionsPanel } = this.props.store;
    const { selectedOperation, selectedConnection } = topConnectionsPanel;

    if (topConnectionsPanel.bShowExplain) {
      this.defaultOperationPaneSize = '50%';
      if (selectedOperation && selectedOperation.suggestionText) {
        this.defaultConnectionPaneSize = '25%';
        this.defaultOperationPaneSize = '25%';
{'fraction_non_alphanumeric': 0.10956120092378753, 'fraction_numerical': 0.01625866050808314, 'mean_word_length': 3.606808510638298, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2130612', 'n_tokens_mistral': 3346, 'n_tokens_neox': 3193, 'n_words': 739}