<commit_before>/**
 * Copyright 2020 Google LLC
 *
 * 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.
 */

/**
 * Wrapper around the statvar menu. We only want the user to choose two statvars.
 * Pops up a modal if three statvars are selected and forces the user to choose
 * two of the three.
 */

import axios from "axios";
import _ from "lodash";
import React, { useContext, useEffect, useState } from "react";
import {
  Button,
  Container,
  FormGroup,
  Input,
  Label,
  Modal,
  ModalBody,
  ModalFooter,
  ModalHeader,
} from "reactstrap";

import { getStatVarInfo, StatVarInfo } from "../../shared/stat_var";
import { StatVarHierarchyType } from "../../shared/types";
import { DrawerToggle } from "../../stat_var_hierarchy/drawer_toggle";
import { StatVarHierarchy } from "../../stat_var_hierarchy/stat_var_hierarchy";
import { AxisWrapper, Context } from "./context";

// Number of enclosed places to sample when filtering the stat vars in the
// stat var menu
// Use a large sample size here. Performance wise this is okay. When the filtered
// stat vars are set, mixer can use the existence cache to check if stat vars
// exist for the place, which is only a point read.
const SAMPLE_SIZE = 50;

interface StatVar {
  // Always contains a single statvar.
  info: StatVarInfo;
  dcid: string;
}

const emptyStatVar: StatVar = Object.freeze({
  info: {},
  dcid: "",
});

interface ModalSelected {
  x: boolean;
  y: boolean;
}

const defaultModalSelected: ModalSelected = Object.freeze({
  x: true,
  y: false,
});

function StatVarChooser(): JSX.Element {
  const { x, y, place } = useContext(Context);

  // Temporary variable for storing an extra statvar.
  const [thirdStatVar, setThirdStatVar] = useState(emptyStatVar);
  // Records which two of the three statvars are wanted if a third statvar is selected.
  const [modalSelected, setModalSelected] = useState(defaultModalSelected);
  const [modalOpen, setModalOpen] = useState(false);
  const [samplePlaces, setSamplePlaces] = useState(
    _.sampleSize(place.value.enclosedPlaces, SAMPLE_SIZE)
  );
  useEffect(() => {
    setSamplePlaces(_.sampleSize(place.value.enclosedPlaces, SAMPLE_SIZE));
  }, [place.value.enclosedPlaces]);
  const menuSelected = [
    x.value.statVarDcid,
    y.value.statVarDcid,
    thirdStatVar.dcid,
  ].filter((sv) => !_.isEmpty(sv));
  const closeModal = () => {
    setThirdStatVar(emptyStatVar);
    setModalOpen(false);
  };

  useEffect(() => {
    const statVarsToGetInfo = [];
    if (!_.isEmpty(x.value.statVarDcid) && _.isNull(x.value.statVarInfo)) {
      statVarsToGetInfo.push(x.value.statVarDcid);
    }
    if (!_.isEmpty(y.value.statVarDcid) && _.isNull(y.value.statVarInfo)) {
      statVarsToGetInfo.push(y.value.statVarDcid);
    }
    if (_.isEmpty(statVarsToGetInfo)) {
      return;
    }
    getStatVarInfo(statVarsToGetInfo)
      .then((info) => {
        if (x.value.statVarDcid in info) {
          x.setStatVarInfo(info[x.value.statVarDcid]);
        }
        if (y.value.statVarDcid in info) {
          y.setStatVarInfo(info[y.value.statVarDcid]);
        }
      })
      .catch(() => {
        if (statVarsToGetInfo.indexOf(x.value.statVarDcid) > -1) {
          x.setStatVarInfo({});
        }
        if (statVarsToGetInfo.indexOf(y.value.statVarDcid) > -1) {
          y.setStatVarInfo({});
        }
      });<commit_msg>fix svinfo bug for scatter (#1412)<commit_after>/**
 * Copyright 2020 Google LLC
 *
 * 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.
 */

/**
 * Wrapper around the statvar menu. We only want the user to choose two statvars.
 * Pops up a modal if three statvars are selected and forces the user to choose
 * two of the three.
 */

import axios from "axios";
import _ from "lodash";
import React, { useContext, useEffect, useState } from "react";
import {
  Button,
  Container,
  FormGroup,
  Input,
  Label,
  Modal,
  ModalBody,
  ModalFooter,
  ModalHeader,
} from "reactstrap";

import { getStatVarInfo, StatVarInfo } from "../../shared/stat_var";
import { StatVarHierarchyType } from "../../shared/types";
import { DrawerToggle } from "../../stat_var_hierarchy/drawer_toggle";
import { StatVarHierarchy } from "../../stat_var_hierarchy/stat_var_hierarchy";
import { AxisWrapper, Context } from "./context";

// Number of enclosed places to sample when filtering the stat vars in the
// stat var menu
// Use a large sample size here. Performance wise this is okay. When the filtered
// stat vars are set, mixer can use the existence cache to check if stat vars
// exist for the place, which is only a point read.
const SAMPLE_SIZE = 50;

interface StatVar {
  // Always contains a single statvar.
  info: StatVarInfo;
  dcid: string;
}

const emptyStatVar: StatVar = Object.freeze({
  info: {},
  dcid: "",
});

interface ModalSelected {
  x: boolean;
  y: boolean;
}

const defaultModalSelected: ModalSelected = Object.freeze({
  x: true,
  y: false,
});

function StatVarChooser(): JSX.Element {
  const { x, y, place } = useContext(Context);

  // Temporary variable for storing an extra statvar.
  const [thirdStatVar, setThirdStatVar] = useState(emptyStatVar);
  // Records which two of the three statvars are wanted if a third statvar is selected.
  const [modalSelected, setModalSelected] = useState(defaultModalSelected);
  const [modalOpen, setModalOpen] = useState(false);
  const [samplePlaces, setSamplePlaces] = useState(
    _.sampleSize(place.value.enclosedPlaces, SAMPLE_SIZE)
  );
  useEffect(() => {
    setSamplePlaces(_.sampleSize(place.value.enclosedPlaces, SAMPLE_SIZE));
  }, [place.value.enclosedPlaces]);
  const menuSelected = [
    x.value.statVarDcid,
    y.value.statVarDcid,
    thirdStatVar.dcid,
  ].filter((sv) => !_.isEmpty(sv));
  const closeModal = () => {
    setThirdStatVar(emptyStatVar);
    setModalOpen(false);
  };

  useEffect(() => {
    const statVarsToGetInfo = [];
    if (!_.isEmpty(x.value.statVarDcid) && _.isNull(x.value.statVarInfo)) {
      statVarsToGetInfo.push(x.value.statVarDcid);
    }
    if (!_.isEmpty(y.value.statVarDcid) && _.isNull(y.value.statVarInfo)) {
      statVarsToGetInfo.push(y.value.statVarDcid);
    }
    if (_.isEmpty(statVarsToGetInfo)) {
      return;
    }
    getStatVarInfo(statVarsToGetInfo)
      .then((info) => {
        statVarsToGetInfo.forEach((sv) => {
          const svInfo = sv in info ? info[sv] : {};
          if (sv === x.value.statVarDcid) {
            x.setStatVarInfo(svInfo);
          } else {
            y.setStatVarInfo(svInfo);
          }
        });
      })
      .catch(() => {
        if (statVarsToGetInfo.indexOf(x.value.statVarDcid) > -1) {
          x.setStatVarInfo({});
        }
        if (statVarsToGetInfo.indexOf(y.value.statVarDcid) > -1) {
          y.setStatVarInfo({});
        }
      });
{'fraction_non_alphanumeric': 0.119881915030163, 'fraction_numerical': 0.0035938903863432167, 'mean_word_length': 3.2954796030871005, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 20, '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': '6797495', 'n_tokens_mistral': 2452, 'n_tokens_neox': 2453, 'n_words': 710}