<commit_before>import { compact } from "lodash/fp";
import React from "react";

import { bulkImportRemoteSamples } from "~/api";
import { logAnalyticsEvent } from "~/api/analytics";
import List from "~/components/ui/List";
import PropTypes from "~/components/utils/propTypes";
import Input from "~ui/controls/Input";
import PrimaryButton from "~ui/controls/buttons/PrimaryButton";
import Notification from "~ui/notifications/Notification";

import {
  NO_TARGET_PROJECT_ERROR,
  NO_VALID_SAMPLES_FOUND_ERROR,
} from "./constants";
import cs from "./sample_upload_flow.scss";

class RemoteSampleFileUpload extends React.Component {
  state = {
    showInfo: false,
    remoteS3Path: "",
    lastPathChecked: "",
  };

  componentDidUpdate() {
    if (
      this.state.error === NO_TARGET_PROJECT_ERROR &&
      this.props.project !== null
    ) {
      this.setState({
        error: "",
      });
    }
  }

  toggleInfo = () => {
    this.setState(
      {
        showInfo: !this.state.showInfo,
      },
      () => {
        logAnalyticsEvent("RemoteSampleFileUpload_more-info-toggle_clicked", {
          showInfo: this.state.showInfo,
        });
      }
    );
  };

  handleRemotePathChange = remoteS3Path => {
    this.setState({
      remoteS3Path,
    });
  };

  handleConnect = async () => {
    if (!this.props.project) {
      this.setState({
        error: NO_TARGET_PROJECT_ERROR,
      });
      this.props.onNoProject();
      return;
    }

    this.setState({
      error: "",
      lastPathChecked: this.state.remoteS3Path,
    });

    try {
      let newSamples = await bulkImportRemoteSamples({
        projectId: this.props.project.id,
        hostGenomeId: "",
        bulkPath: this.state.remoteS3Path,
      });

      // Remove any nil files from input_file_attributes.
      // This happens when there is an R2 file without an R1 file.
      newSamples = newSamples.samples.map(sample => ({
        ...sample,
        input_files_attributes: compact(sample.input_files_attributes),
      }));

      this.props.onChange(newSamples);

      logAnalyticsEvent("RemoteSampleFileUpload_connect_succeeded", {
        projectId: this.props.project.id,
        bulkPath: this.state.remoteS3Path,
        newSamples: newSamples.length,
      });
    } catch (e) {
      if (e.status) {
        // Use error message provided by the backend if it exists
        this.setState({ error: e.status });
      } else {
        // Otherwise fallback to a generic error message<commit_msg>Display S3 upload error messages that return from the API (#1420)<commit_after>import { compact } from "lodash/fp";
import React from "react";

import { bulkImportRemoteSamples } from "~/api";
import { logAnalyticsEvent } from "~/api/analytics";
import List from "~/components/ui/List";
import PropTypes from "~/components/utils/propTypes";
import Input from "~ui/controls/Input";
import PrimaryButton from "~ui/controls/buttons/PrimaryButton";
import Notification from "~ui/notifications/Notification";

import {
  NO_TARGET_PROJECT_ERROR,
  NO_VALID_SAMPLES_FOUND_ERROR,
} from "./constants";
import cs from "./sample_upload_flow.scss";

class RemoteSampleFileUpload extends React.Component {
  state = {
    showInfo: false,
    remoteS3Path: "",
    lastPathChecked: "",
  };

  componentDidUpdate() {
    if (
      this.state.error === NO_TARGET_PROJECT_ERROR &&
      this.props.project !== null
    ) {
      this.setState({
        error: "",
      });
    }
  }

  toggleInfo = () => {
    this.setState(
      {
        showInfo: !this.state.showInfo,
      },
      () => {
        logAnalyticsEvent("RemoteSampleFileUpload_more-info-toggle_clicked", {
          showInfo: this.state.showInfo,
        });
      }
    );
  };

  handleRemotePathChange = remoteS3Path => {
    this.setState({
      remoteS3Path,
    });
  };

  handleConnect = async () => {
    if (!this.props.project) {
      this.setState({
        error: NO_TARGET_PROJECT_ERROR,
      });
      this.props.onNoProject();
      return;
    }

    this.setState({
      error: "",
      lastPathChecked: this.state.remoteS3Path,
    });

    try {
      let newSamples = await bulkImportRemoteSamples({
        projectId: this.props.project.id,
        hostGenomeId: "",
        bulkPath: this.state.remoteS3Path,
      });

      // Remove any nil files from input_file_attributes.
      // This happens when there is an R2 file without an R1 file.
      newSamples = newSamples.samples.map(sample => ({
        ...sample,
        input_files_attributes: compact(sample.input_files_attributes),
      }));

      this.props.onChange(newSamples);

      logAnalyticsEvent("RemoteSampleFileUpload_connect_succeeded", {
        projectId: this.props.project.id,
        bulkPath: this.state.remoteS3Path,
        newSamples: newSamples.length,
      });
    } catch (e) {
      if (e.data && e.data.status) {
        // Use error message provided by the backend if it exists
        this.setState({ error: e.data.status });
      } else if (e.status) {
        this.setState({ error: `Encountered an unexpected error with status code: ${e.status}` });
      } else {
        // Otherwise fallback to a generic error message
{'fraction_non_alphanumeric': 0.12389550518632347, 'fraction_numerical': 0.004033807145601229, 'mean_word_length': 2.633635729239358, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, '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': '7489855', 'n_tokens_mistral': 1578, 'n_tokens_neox': 1543, 'n_words': 327}