<commit_before>import React from "react";
import { FolderAddOutlined } from "@ant-design/icons";
import { Button, Checkbox, Col, Row, Space, Table, Tag, Tooltip } from "antd";
import axios from "axios";
import { getAssociatedProjectForProject } from "../../../apis/projects/associated-projects";
import {
  getAllSampleIds,
  getPagedProjectSamples,
} from "../../../apis/projects/project-samples";
import { blue6 } from "../../../styles/colors";
import { getNewTagColor } from "../../../utilities/ant-utilities";
import { formatInternationalizedDateTime } from "../../../utilities/date-utilities";
import { formatSort } from "../../../utilities/table-utilities";
import { getProjectIdFromUrl } from "../../../utilities/url-utilities";

const formatCartItem = (item) => ({
  key: item.key,
  id: item.sample.id,
  projectId: item.project.id,
  sampleName: item.sample.sampleName,
  owner: item.owner,
});

export function SamplesTable() {
  const [loading, setLoading] = React.useState(true);
  const [samples, setSamples] = React.useState([]);
  const [selectedItems, setSelectedItems] = React.useState({});
  const [pagination, setPagination] = React.useState({
    current: 1,
    pageSize: 10,
  });
  const [filters, setFilters] = React.useState({ associated: null });
  const [associated, setAssociated] = React.useState([]);
  const [colors, setColors] = React.useState(() => {
    const colorString = localStorage.getItem("projectColors");
    return colorString ? JSON.parse(colorString) : {};
  });
  const projectId = getProjectIdFromUrl();

  React.useEffect(() => {
    const samplesPromise = getPagedProjectSamples(projectId, {
      ...pagination,
      order: [{ property: "sample.modifiedDate", direction: "desc" }],
    });

    const associatedPromise = getAssociatedProjectForProject(projectId);

    axios.all([samplesPromise, associatedPromise]).then(
      axios.spread((samplesResponse, associatedResponse) => {
        setSamples(samplesResponse.data.content);
        setPagination({ ...pagination, total: samplesResponse.data.total });
        setAssociated(
          associatedResponse.data.map((item) => ({
            text: item.label,
            value: item.id,
          }))
        );

        // Get colors for all associated projects
        const newColors = { ...colors };
        associatedResponse.data.forEach((project) => {
          if (!newColors[project.id]) {
            newColors[project.id] = getNewTagColor();
          }
        });
        setColors(newColors);
        localStorage.setItem("projectColors", JSON.stringify(newColors));
        setLoading(false);
      })
    );
  }, []);

  const selectRow = (event, item) => {
    const selected = event.target.checked;
    if (selected) {
      setSelectedItems({ ...selectedItems, [item.key]: formatCartItem(item) });
    } else {
      const updatedSelected = { ...selectedItems };
      delete updatedSelected[item.key];
      setSelectedItems(updatedSelected);
    }
  };

  const selectAll = async () => {
    const { data } = await getAllSampleIds(projectId, filters);
    const newSelected = {};
    data.forEach((item) => (newSelected[item.key] = item));
    setSelectedItems(newSelected);
  };

  const selectNone = () => setSelectedItems([]);

  const handleTableChange = async (pagination, newFilters, sorter) => {
    setLoading(true);
    // Save the filters for using when selecting all
    if (
      Object.entries(filters).toString() !==
      Object.entries(newFilters).toString()
    ) {
      setFilters(newFilters);

      // Clear selections since filters changed
      setSelectedItems([]);
    }

    // Handle Sort
    const order = formatSort(sorter);
    // Add associated projectIds here.

    const { data } = await getPagedProjectSamples(projectId, {
      ...pagination,
      order,
      filters: newFilters,
    });
    setSamples(data.content);
    setPagination({ ...pagination, total: data.total });
    setLoading(false);
  };

  const columns = [
    {
      title: "",
      dataIndex: "key",
      width: 40,
      render: (text, item) => {
        return (
          <Checkbox
            onChange={(e) => selectRow(e, item)}
            checked={selectedItems[item.key]}
          />
        );
      },
    },
    {
      title: "Name",
      dataIndex: ["sample", "sampleName"],
      key: "name",
      sorter: { multiple: 3 },
      render: (name, row, index) => <a>{name}</a>,
    },
    {
      title: "Organism",
      dataIndex: ["sample", "organism"],
      key: "organism",
      sorter: { multiple: true },
    },
    {
      title: "Project",
      dataIndex: ["project", "name"],
      sorter: { multiple: true },
      key: "associated",
      render: (name, row, index) => {
        return <Tag color={colors[row.project.id]}>{name}</Tag>;
      },
      filters: associated,
      filterIcon: () => (
        <Tooltip title={"Associated Projects"}>
          <FolderAddOutlined style={{ color: blue6 }} />
        </Tooltip>
      ),
    },
    {
      title: "Created",
      dataIndex: ["sample", "createdDate"],
      key: "created",
      sorter: { multiple: 2 },
      width: 230,
      render: (createdDate, row, index) => {
        return formatInternationalizedDateTime(createdDate);
      },
    },
    {
      title: "Modified",
      dataIndex: ["sample", "modifiedDate"],
      key: "modified",
      defaultSortOrder: "descend",
      sorter: { multiple: 1 },
      width: 230,
      render: (modifiedDate, row, index) => {
        return formatInternationalizedDateTime(modifiedDate);
      },
    },
  ];

  return (
    <Row gutter={[16, 16]}>
      <Col span={24}>
        <Space>
          <Button onClick={selectAll}>Select All</Button>
          <Button onClick={selectNone}>Select None</Button>
        </Space>
      </Col>
      <Col span={24}>
        <Table
          loading={loading}
          columns={columns}
          dataSource={samples}
          pagination={pagination}
          onChange={handleTableChange}
          summary={() => (
            <Table.Summary.Row>
              <Table.Summary.Cell colSpan={5}>
                {`Selected: ${Object.keys(selectedItems).length} of
                ${pagination.total}`}
              </Table.Summary.Cell>
            </Table.Summary.Row>
          )}
        />
      </Col>
    </Row>
  );
}
<commit_msg>Show loading<commit_after>import React from "react";
import { FolderAddOutlined } from "@ant-design/icons";
import { Button, Checkbox, Col, Row, Space, Table, Tag, Tooltip } from "antd";
import axios from "axios";
import { getAssociatedProjectForProject } from "../../../apis/projects/associated-projects";
import {
  getAllSampleIds,
  getPagedProjectSamples,
} from "../../../apis/projects/project-samples";
import { blue6 } from "../../../styles/colors";
import { getNewTagColor } from "../../../utilities/ant-utilities";
import { formatInternationalizedDateTime } from "../../../utilities/date-utilities";
import { formatSort } from "../../../utilities/table-utilities";
import { getProjectIdFromUrl } from "../../../utilities/url-utilities";

const formatCartItem = (item) => ({
  key: item.key,
  id: item.sample.id,
  projectId: item.project.id,
  sampleName: item.sample.sampleName,
  owner: item.owner,
});

export function SamplesTable() {
  const [loading, setLoading] = React.useState(true);
  const [samples, setSamples] = React.useState([]);
  const [selectedItems, setSelectedItems] = React.useState({});
  const [pagination, setPagination] = React.useState({
    current: 1,
    pageSize: 10,
  });
  const [filters, setFilters] = React.useState({ associated: null });
  const [associated, setAssociated] = React.useState([]);
  const [colors, setColors] = React.useState(() => {
    const colorString = localStorage.getItem("projectColors");
    return colorString ? JSON.parse(colorString) : {};
  });
  const projectId = getProjectIdFromUrl();

  React.useEffect(() => {
    const samplesPromise = getPagedProjectSamples(projectId, {
      ...pagination,
      order: [{ property: "sample.modifiedDate", direction: "desc" }],
    });

    const associatedPromise = getAssociatedProjectForProject(projectId);

    axios.all([samplesPromise, associatedPromise]).then(
      axios.spread((samplesResponse, associatedResponse) => {
        setSamples(samplesResponse.data.content);
        setPagination({ ...pagination, total: samplesResponse.data.total });
        setAssociated(
          associatedResponse.data.map((item) => ({
            text: item.label,
            value: item.id,
          }))
        );

        // Get colors for all associated projects
        const newColors = { ...colors };
        associatedResponse.data.forEach((project) => {
          if (!newColors[project.id]) {
            newColors[project.id] = getNewTagColor();
          }
        });
        setColors(newColors);
        localStorage.setItem("projectColors", JSON.stringify(newColors));
        setLoading(false);
      })
    );
  }, []);

  const selectRow = (event, item) => {
    const selected = event.target.checked;
    if (selected) {
      setSelectedItems({ ...selectedItems, [item.key]: formatCartItem(item) });
    } else {
      const updatedSelected = { ...selectedItems };
      delete updatedSelected[item.key];
      setSelectedItems(updatedSelected);
    }
  };

  const selectAll = async () => {
    setLoading(true);
    const { data } = await getAllSampleIds(projectId, filters);
    const newSelected = {};
    data.forEach((item) => (newSelected[item.key] = item));
    setSelectedItems(newSelected);
    setLoading(false);
  };

  const selectNone = () => setSelectedItems([]);

  const handleTableChange = async (pagination, newFilters, sorter) => {
    setLoading(true);
    // Save the filters for using when selecting all
    if (
      Object.entries(filters).toString() !==
      Object.entries(newFilters).toString()
    ) {
      setFilters(newFilters);

      // Clear selections since filters changed
      setSelectedItems([]);
    }

    // Handle Sort
    const order = formatSort(sorter);
    // Add associated projectIds here.

    const { data } = await getPagedProjectSamples(projectId, {
      ...pagination,
      order,
      filters: newFilters,
    });
    setSamples(data.content);
    setPagination({ ...pagination, total: data.total });
    setLoading(false);
  };

  const columns = [
    {
      title: "",
      dataIndex: "key",
      width: 40,
      render: (text, item) => {
        return (
          <Checkbox
            onChange={(e) => selectRow(e, item)}
            checked={selectedItems[item.key]}
          />
        );
      },
    },
    {
      title: "Name",
      dataIndex: ["sample", "sampleName"],
      key: "name",
      sorter: { multiple: 3 },
      render: (name, row, index) => <a>{name}</a>,
    },
    {
      title: "Organism",
      dataIndex: ["sample", "organism"],
      key: "organism",
      sorter: { multiple: true },
    },
    {
      title: "Project",
      dataIndex: ["project", "name"],
      sorter: { multiple: true },
      key: "associated",
      render: (name, row, index) => {
        return <Tag color={colors[row.project.id]}>{name}</Tag>;
      },
      filters: associated,
      filterIcon: () => (
        <Tooltip title={"Associated Projects"}>
          <FolderAddOutlined style={{ color: blue6 }} />
        </Tooltip>
      ),
    },
    {
      title: "Created",
      dataIndex: ["sample", "createdDate"],
      key: "created",
      sorter: { multiple: 2 },
      width: 230,
      render: (createdDate, row, index) => {
        return formatInternationalizedDateTime(createdDate);
      },
    },
    {
      title: "Modified",
      dataIndex: ["sample", "modifiedDate"],
      key: "modified",
      defaultSortOrder: "descend",
      sorter: { multiple: 1 },
      width: 230,
      render: (modifiedDate, row, index) => {
        return formatInternationalizedDateTime(modifiedDate);
      },
    },
  ];

  return (
    <Row gutter={[16, 16]}>
      <Col span={24}>
        <Space>
          <Button onClick={selectAll}>Select All</Button>
          <Button onClick={selectNone}>Select None</Button>
        </Space>
      </Col>
      <Col span={24}>
        <Table
          loading={loading}
          columns={columns}
          dataSource={samples}
          pagination={pagination}
          onChange={handleTableChange}
          summary={() => (
            <Table.Summary.Row>
              <Table.Summary.Cell colSpan={5}>
                {`Selected: ${Object.keys(selectedItems).length} of
                ${pagination.total}`}
              </Table.Summary.Cell>
            </Table.Summary.Row>
          )}
        />
      </Col>
    </Row>
  );
}

{'fraction_non_alphanumeric': 0.15647538413295703, 'fraction_numerical': 0.00391972405142678, 'mean_word_length': 2.48551912568306, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 91, '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': '1219620', 'n_tokens_mistral': 3714, 'n_tokens_neox': 3675, 'n_words': 771}