<commit_before>import PropTypes from 'prop-types';
import React from 'react';
import createReactClass from 'create-react-class';
import Reflux from 'reflux';
import {Link, browserHistory} from 'react-router';
import Cookies from 'js-cookie';
import {StickyContainer, Sticky} from 'react-sticky';
import classNames from 'classnames';

import SentryTypes from '../../proptypes';
import ApiMixin from '../../mixins/apiMixin';
import GroupStore from '../../stores/groupStore';
import EnvironmentStore from '../../stores/environmentStore';
import HookStore from '../../stores/hookStore';
import LoadingError from '../../components/loadingError';
import LoadingIndicator from '../../components/loadingIndicator';
import ProjectState from '../../mixins/projectState';
import Pagination from '../../components/pagination';
import StreamGroup from '../../components/stream/group';
import StreamActions from './../stream/actions';
import StreamFilters from './../stream/filters';
import StreamSidebar from './../stream/sidebar';
import TimeSince from '../../components/timeSince';
import utils from '../../utils';
import queryString from '../../utils/queryString';
import {logAjaxError} from '../../utils/logging';
import parseLinkHeader from '../../utils/parseLinkHeader';
import {t, tn, tct} from '../../locale';
import {setActiveEnvironment} from '../../actionCreators/environments';

const MAX_ITEMS = 25;
const DEFAULT_SORT = 'date';
const DEFAULT_STATS_PERIOD = '24h';
const STATS_PERIODS = new Set(['14d', '24h']);

const Stream = createReactClass({
  displayName: 'Stream',

  propTypes: {
    environment: SentryTypes.Environment,
    hasEnvironmentsFeature: PropTypes.bool,
    tags: PropTypes.object,
    tagsLoading: PropTypes.bool,
  },

  mixins: [Reflux.listenTo(GroupStore, 'onGroupChange'), ApiMixin, ProjectState],

  getInitialState() {
    let searchId = this.props.params.searchId || null;
    let project = this.getProject();
    let realtimeActiveCookie = Cookies.get('realtimeActive');
    let realtimeActive =
      typeof realtimeActiveCookie === 'undefined'
        ? project && !project.firstEvent
        : realtimeActiveCookie === 'true';

    let currentQuery = this.props.location.query || {};
    let sort = 'sort' in currentQuery ? currentQuery.sort : DEFAULT_SORT;

    let hasQuery = 'query' in currentQuery;
    let statsPeriod = STATS_PERIODS.has(currentQuery.statsPeriod)
      ? currentQuery.statsPeriod
      : DEFAULT_STATS_PERIOD;

    return {
      groupIds: [],
      isDefaultSearch: false,
      searchId: hasQuery ? null : searchId,
      // if we have no query then we can go ahead and fetch data
      loading: searchId || !hasQuery,
      savedSearchLoading: true,
      savedSearchList: [],
      selectAllActive: false,
      multiSelected: false,
      anySelected: false,
      statsPeriod,
      realtimeActive,
      pageLinks: '',
      queryCount: null,
      dataLoading: true,
      error: false,
      query: hasQuery ? currentQuery.query : '',
      sort,
      isSidebarVisible: false,
      processingIssues: null,
      environment: this.props.environment,
    };
  },

  componentWillMount() {
    this._streamManager = new utils.StreamManager(GroupStore);
    this._poller = new utils.CursorPoller({
      success: this.onRealtimePoll,
    });

    this.fetchSavedSearches();
    this.fetchProcessingIssues();
  },

  componentDidMount() {
    this.fetchData();
  },

  componentWillReceiveProps(nextProps) {
    if (nextProps.environment !== this.props.environment) {
      this.setState(
        {
          environment: nextProps.environment,
        },
        this.fetchData
      );
    }

    // you cannot apply both a query and a saved search (our routes do not
    // support it), so the searchId takes priority
    let nextSearchId = nextProps.params.searchId || null;

    let searchIdChanged = this.state.isDefaultSearch
      ? nextSearchId
      : nextSearchId !== this.state.searchId;

    if (searchIdChanged || nextProps.location.search !== this.props.location.search) {
      this.setState(this.getQueryState(nextProps), this.fetchData);
    }
  },

  componentDidUpdate(prevProps, prevState) {
    if (prevState.realtimeActive !== this.state.realtimeActive) {
      // User toggled realtime button
      if (this.state.realtimeActive) {
        this.resumePolling();
      } else {
        this._poller.disable();
      }
    }
  },

  componentWillUnmount() {
    this._poller.disable();<commit_msg>fix(stream): Do not refetch stream if only environment in query string changes (#7673)<commit_after>import PropTypes from 'prop-types';
import React from 'react';
import createReactClass from 'create-react-class';
import Reflux from 'reflux';
import {Link, browserHistory} from 'react-router';
import Cookies from 'js-cookie';
import {StickyContainer, Sticky} from 'react-sticky';
import classNames from 'classnames';
import {isEqual, omit} from 'lodash';

import SentryTypes from '../../proptypes';
import ApiMixin from '../../mixins/apiMixin';
import GroupStore from '../../stores/groupStore';
import EnvironmentStore from '../../stores/environmentStore';
import HookStore from '../../stores/hookStore';
import LoadingError from '../../components/loadingError';
import LoadingIndicator from '../../components/loadingIndicator';
import ProjectState from '../../mixins/projectState';
import Pagination from '../../components/pagination';
import StreamGroup from '../../components/stream/group';
import StreamActions from './../stream/actions';
import StreamFilters from './../stream/filters';
import StreamSidebar from './../stream/sidebar';
import TimeSince from '../../components/timeSince';
import utils from '../../utils';
import queryString from '../../utils/queryString';
import {logAjaxError} from '../../utils/logging';
import parseLinkHeader from '../../utils/parseLinkHeader';
import {t, tn, tct} from '../../locale';
import {setActiveEnvironment} from '../../actionCreators/environments';

const MAX_ITEMS = 25;
const DEFAULT_SORT = 'date';
const DEFAULT_STATS_PERIOD = '24h';
const STATS_PERIODS = new Set(['14d', '24h']);

const Stream = createReactClass({
  displayName: 'Stream',

  propTypes: {
    environment: SentryTypes.Environment,
    hasEnvironmentsFeature: PropTypes.bool,
    tags: PropTypes.object,
    tagsLoading: PropTypes.bool,
  },

  mixins: [Reflux.listenTo(GroupStore, 'onGroupChange'), ApiMixin, ProjectState],

  getInitialState() {
    let searchId = this.props.params.searchId || null;
    let project = this.getProject();
    let realtimeActiveCookie = Cookies.get('realtimeActive');
    let realtimeActive =
      typeof realtimeActiveCookie === 'undefined'
        ? project && !project.firstEvent
        : realtimeActiveCookie === 'true';

    let currentQuery = this.props.location.query || {};
    let sort = 'sort' in currentQuery ? currentQuery.sort : DEFAULT_SORT;

    let hasQuery = 'query' in currentQuery;
    let statsPeriod = STATS_PERIODS.has(currentQuery.statsPeriod)
      ? currentQuery.statsPeriod
      : DEFAULT_STATS_PERIOD;

    return {
      groupIds: [],
      isDefaultSearch: false,
      searchId: hasQuery ? null : searchId,
      // if we have no query then we can go ahead and fetch data
      loading: searchId || !hasQuery,
      savedSearchLoading: true,
      savedSearchList: [],
      selectAllActive: false,
      multiSelected: false,
      anySelected: false,
      statsPeriod,
      realtimeActive,
      pageLinks: '',
      queryCount: null,
      dataLoading: true,
      error: false,
      query: hasQuery ? currentQuery.query : '',
      sort,
      isSidebarVisible: false,
      processingIssues: null,
      environment: this.props.environment,
    };
  },

  componentWillMount() {
    this._streamManager = new utils.StreamManager(GroupStore);
    this._poller = new utils.CursorPoller({
      success: this.onRealtimePoll,
    });

    this.fetchSavedSearches();
    this.fetchProcessingIssues();
  },

  componentDidMount() {
    this.fetchData();
  },

  componentWillReceiveProps(nextProps) {
    if (nextProps.environment !== this.props.environment) {
      this.setState(
        {
          environment: nextProps.environment,
        },
        this.fetchData
      );
    }

    // you cannot apply both a query and a saved search (our routes do not
    // support it), so the searchId takes priority
    let nextSearchId = nextProps.params.searchId || null;

    let searchIdChanged = this.state.isDefaultSearch
      ? nextSearchId
      : nextSearchId !== this.state.searchId;

    // We omit environment when we check the the query has changed as we
    // handle environment changes separately
    let queryChanged = !isEqual(
      omit(nextProps.location.query, 'environment'),
      omit(this.props.location.query, 'environment')
    );

    if (searchIdChanged || queryChanged) {
      this.setState(this.getQueryState(nextProps), this.fetchData);
    }
  },

  componentDidUpdate(prevProps, prevState) {
    if (prevState.realtimeActive !== this.state.realtimeActive) {
      // User toggled realtime button
      if (this.state.realtimeActive) {
        this.resumePolling();
      } else {
        this._poller.disable();
      }
    }
  },

  componentWillUnmount() {
    this._poller.disable();
{'fraction_non_alphanumeric': 0.1288482238966631, 'fraction_numerical': 0.002152852529601722, 'mean_word_length': 3.2954230235783633, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '5039589', 'n_tokens_mistral': 2617, 'n_tokens_neox': 2614, 'n_words': 671}