<commit_before>import React from "react";
import PropTypes from "prop-types";

import {
  Pipeline,
  Values,
  responseUpdatedEvent,
  valuesUpdatedEvent
} from "../../controllers";

import AutocompleteDropdownRenderer from "./AutocompleteDropdownRenderer";

const getState = (values, pipeline, qParam, numSuggestions) => {
  const text = values.get()[qParam] || "";
  if (!text) {
    return {
      text,
      displayText: text,
      suggestions: [],
      selectedIndex: -1
    };
  }
  const responseValues = pipeline.getResponse().getValues();
  const suggestions = responseValues
    ? (responseValues["q.suggestions"] || "")
        .split(",")
        .filter(s => s.length > 0)
        .slice(0, numSuggestions)
    : [];
  return { text, displayText: text, suggestions, selectedIndex: -1 };
};

class AutocompleteDropdownCommon extends React.Component {
  /**
   * propTypes
   * @property {Values} values Values object.
   * @property {Pipeline} pipeline Pipeline object.
   * @property {Values} forceSearchValues Values to use for forced search.
   * @property {Pipeline} forceSearchPipeline Pipeline to use for forced search.
   * @property {string} placeholder Placeholder to use for the input element.
   * @property {number} [numSuggestions=5] Maximum number of suggestion to show.
   * @property {string} [qParam="q"] Search parameter.
   * @property {string} [qOverrideParam="q.override"] Search override parameter.
   * @property {boolean} [autoFocus=false] Whether to focus the input element on creation.
   */
  static get propTypes() {
    return {
      values: PropTypes.instanceOf(Values).isRequired,
      pipeline: PropTypes.instanceOf(Pipeline).isRequired,
      forceSearchValues: PropTypes.instanceOf(Values),
      forceSearchPipeline: PropTypes.instanceOf(Pipeline),
      placeholder: PropTypes.string,
      numSuggestions: PropTypes.number,
      qParam: PropTypes.string,
      qOverrideParam: PropTypes.string,
      autoFocus: PropTypes.bool
    };
  }

  constructor(props) {
    super(props);

    this.state = getState(
      props.values,
      props.pipeline,
      props.qParam,
      props.numSuggestions
    );

    this.removeValuesListener = props.values.listen(
      valuesUpdatedEvent,
      this.valuesChanged
    );
    this.removeResponseListener = props.pipeline.listen(
      responseUpdatedEvent,
      this.valuesChanged
    );
  }

  componentWillUpdate(nextProps) {
    const { values: newValues, pipeline: newPipeline } = nextProps;
    const { values: oldValues, pipeline: oldPipeline } = this.props;
    if (newValues !== oldValues) {
      this.removeValuesListener();
      this.removeValuesListener = newValues.listen(
        valuesUpdatedEvent,
        this.valuesChanged
      );
    }
    if (newPipeline !== oldPipeline) {
      this.removeResponseListener();
      this.removeResponseListener = newPipeline.listen(
        responseUpdatedEvent,
        this.valuesChanged
      );
    }
  }

  componentWillUnmount() {
    this.removeValuesListener();
    this.removeResponseListener();
  }

  valuesChanged = () => {
    const { values, pipeline, qParam, numSuggestions } = this.props;
    this.setState(getState(values, pipeline, qParam, numSuggestions));
  };

  onSubmit = () => {};

  handleChange = event => {
    const { qParam, qOverrideParam, values, pipeline } = this.props;
    const newText = event.target.value;
    this.setState({ text: newText, displayText: newText });
    values.set({ [qParam]: newText, [qOverrideParam]: undefined });
    if (newText) {
      pipeline.search(values.get());
    } else {
      pipeline.clearResponse(values.get());
    }
  };

  handleEscape = () => {
    this.setState({ suggestions: [], selectedIndex: -1 });
  };

  handleReturn = () => {
    const { text, selectedIndex, suggestions } = this.state;
    if (selectedIndex >= 0) {
      this.submit(suggestions[selectedIndex]);
    } else {
      this.submit(text);
    }
  };

  handleUpArrow = () => {
    const { text, selectedIndex, suggestions } = this.state;
    if (selectedIndex >= 0) {
      this.setState({
        displayText: suggestions[selectedIndex - 1] || text,
        selectedIndex: selectedIndex - 1
      });
    }
  };

  handleDownArrow = () => {
    const { selectedIndex, suggestions } = this.state;
    if (selectedIndex < suggestions.length - 1) {
      this.setState({
        displayText: suggestions[selectedIndex + 1],
        selectedIndex: selectedIndex + 1
      });
    }
  };

  handleRightArrowOrTab = () => {
    const { selectedIndex, suggestions } = this.state;
    if (selectedIndex >= 0) {
      const newText = suggestions[selectedIndex];
      this.setState({
        text: newText,
        displayText: newText,
        selectedIndex: -1,
        suggestions: []
      });
    }
  };

  render() {
    const { text, displayText, suggestions, selectedIndex } = this.state;
    const { placeholder, autoFocus } = this.props;

    return (
      <AutocompleteDropdownRenderer
        submit={this.onSubmit}
        text={text}
        displayText={displayText}
        suggestions={suggestions}
        selectedIndex={selectedIndex}
        placeholder={placeholder}
        autoFocus={autoFocus}
        handleChange={this.handleChange}
        handleEscape={this.handleEscape}
        handleReturn={this.handleReturn}
        handleUpArrow={this.handleUpArrow}
        handleDownArrow={this.handleDownArrow}
        handleRightArrow={this.handleRightArrowOrTab}
        handleTab={this.handleRightArrowOrTab}
      />
    );
  }
}

AutocompleteDropdownCommon.defaultProps = {
  qParam: "q",
  qOverrideParam: "q.override",
  numSuggestions: 5
};

export default AutocompleteDropdownCommon;
<commit_msg>ui: rename submit, take forceSearch function in AutocompleteDropdownCommon<commit_after>import React from "react";
import PropTypes from "prop-types";

import {
  Pipeline,
  Values,
  responseUpdatedEvent,
  valuesUpdatedEvent
} from "../../controllers";

import AutocompleteDropdownRenderer from "./AutocompleteDropdownRenderer";

const getState = (values, pipeline, qParam, numSuggestions) => {
  const text = values.get()[qParam] || "";
  if (!text) {
    return {
      text,
      displayText: text,
      suggestions: [],
      selectedIndex: -1
    };
  }
  const responseValues = pipeline.getResponse().getValues();
  const suggestions = responseValues
    ? (responseValues["q.suggestions"] || "")
        .split(",")
        .filter(s => s.length > 0)
        .slice(0, numSuggestions)
    : [];
  return { text, displayText: text, suggestions, selectedIndex: -1 };
};

class AutocompleteDropdownCommon extends React.Component {
  /**
   * propTypes
   * @property {Values} values Values object.
   * @property {Pipeline} pipeline Pipeline object.
   * @property {Values} forceSearchValues Values to use for forced search.
   * @property {Pipeline} forceSearchPipeline Pipeline to use for forced search.
   * @property {string} placeholder Placeholder to use for the input element.
   * @property {Function} OnForceSearch Function to call when user forces a search
   * @property {number} [numSuggestions=5] Maximum number of suggestion to show.
   * @property {string} [qParam="q"] Search parameter.
   * @property {string} [qOverrideParam="q.override"] Search override parameter.
   * @property {boolean} [autoFocus=false] Whether to focus the input element on creation.
   */
  static get propTypes() {
    return {
      values: PropTypes.instanceOf(Values).isRequired,
      pipeline: PropTypes.instanceOf(Pipeline).isRequired,
      forceSearchValues: PropTypes.instanceOf(Values),
      forceSearchPipeline: PropTypes.instanceOf(Pipeline),
      placeholder: PropTypes.string,
      onForceSearch: PropTypes.func,
      numSuggestions: PropTypes.number,
      qParam: PropTypes.string,
      qOverrideParam: PropTypes.string,
      autoFocus: PropTypes.bool
    };
  }

  constructor(props) {
    super(props);

    this.state = getState(
      props.values,
      props.pipeline,
      props.qParam,
      props.numSuggestions
    );

    this.removeValuesListener = props.values.listen(
      valuesUpdatedEvent,
      this.valuesChanged
    );
    this.removeResponseListener = props.pipeline.listen(
      responseUpdatedEvent,
      this.valuesChanged
    );
  }

  componentWillUpdate(nextProps) {
    const { values: newValues, pipeline: newPipeline } = nextProps;
    const { values: oldValues, pipeline: oldPipeline } = this.props;
    if (newValues !== oldValues) {
      this.removeValuesListener();
      this.removeValuesListener = newValues.listen(
        valuesUpdatedEvent,
        this.valuesChanged
      );
    }
    if (newPipeline !== oldPipeline) {
      this.removeResponseListener();
      this.removeResponseListener = newPipeline.listen(
        responseUpdatedEvent,
        this.valuesChanged
      );
    }
  }

  componentWillUnmount() {
    this.removeValuesListener();
    this.removeResponseListener();
  }

  valuesChanged = () => {
    const { values, pipeline, qParam, numSuggestions } = this.props;
    this.setState(getState(values, pipeline, qParam, numSuggestions));
  };

  handleForceSearch = query => {
    this.setState(this.props.onForceSearch(query));
  };

  handleChange = event => {
    const { qParam, qOverrideParam, values, pipeline } = this.props;
    const newText = event.target.value;
    this.setState({ text: newText, displayText: newText });
    values.set({ [qParam]: newText, [qOverrideParam]: undefined });
    if (newText) {
      pipeline.search(values.get());
    } else {
      pipeline.clearResponse(values.get());
    }
  };

  handleEscape = () => {
    this.setState({ suggestions: [], selectedIndex: -1 });
  };

  handleReturn = () => {
    const { text, selectedIndex, suggestions } = this.state;
    if (selectedIndex >= 0) {
      this.handleForceSearch(suggestions[selectedIndex]);
    } else {
      this.handleForceSearch(text);
    }
  };

  handleUpArrow = () => {
    const { text, selectedIndex, suggestions } = this.state;
    if (selectedIndex >= 0) {
      this.setState({
        displayText: suggestions[selectedIndex - 1] || text,
        selectedIndex: selectedIndex - 1
      });
    }
  };

  handleDownArrow = () => {
    const { selectedIndex, suggestions } = this.state;
    if (selectedIndex < suggestions.length - 1) {
      this.setState({
        displayText: suggestions[selectedIndex + 1],
        selectedIndex: selectedIndex + 1
      });
    }
  };

  handleRightArrowOrTab = () => {
    const { selectedIndex, suggestions } = this.state;
    if (selectedIndex >= 0) {
      const newText = suggestions[selectedIndex];
      this.setState({
        text: newText,
        displayText: newText,
        selectedIndex: -1,
        suggestions: []
      });
    }
  };

  render() {
    const { text, displayText, suggestions, selectedIndex } = this.state;
    const { placeholder, autoFocus } = this.props;

    return (
      <AutocompleteDropdownRenderer
        submit={this.handleForceSearch}
        text={text}
        displayText={displayText}
        suggestions={suggestions}
        selectedIndex={selectedIndex}
        placeholder={placeholder}
        autoFocus={autoFocus}
        handleChange={this.handleChange}
        handleEscape={this.handleEscape}
        handleReturn={this.handleReturn}
        handleUpArrow={this.handleUpArrow}
        handleDownArrow={this.handleDownArrow}
        handleRightArrow={this.handleRightArrowOrTab}
        handleTab={this.handleRightArrowOrTab}
      />
    );
  }
}

AutocompleteDropdownCommon.defaultProps = {
  qParam: "q",
  qOverrideParam: "q.override",
  numSuggestions: 5
};

export default AutocompleteDropdownCommon;

{'fraction_non_alphanumeric': 0.11812366737739873, 'fraction_numerical': 0.0027292110874200426, 'mean_word_length': 3.0588438906195914, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '357274', 'n_tokens_mistral': 3319, 'n_tokens_neox': 3296, 'n_words': 712}