<commit_before>import { Button, Table } from "antd";
import React from "react";
import {
  addMemberToUserGroup,
  getAvailableUsersForUserGroup,
  removeMemberFromUserGroup,
  updateUserRoleOnUserGroups,
} from "../../../apis/users/groups";
import {
  AddMemberButton,
  RemoveTableItemButton,
} from "../../../components/Buttons";
import { GroupRole } from "../../../components/roles/GroupRole";
import { SPACE_XS } from "../../../styles/spacing";
import { formatInternationalizedDateTime } from "../../../utilities/date-utilities";
import { stringSorter } from "../../../utilities/table-utilities";
import { setBaseUrl } from "../../../utilities/url-utilities";

/**
 * Custom sorter for the name column since this is NOT paged server side.
 * @type {function(*, *): number}
 */
const nameSorter = stringSorter("name");

/**
 * React component to render a table to display user group members
 * @param {array} members
 * @param {boolean} canManage can the current user manage members
 * @param {number} groupId identifier for teh current user group
 * @param {function} updateTable - method to refresh the contents of the table
 * @returns {string|*}
 * @constructor
 */
export default function UserGroupMembersTable({
  members,
  canManage,
  groupId,
  updateTable,
}) {
  const columns = [
    {
      dataIndex: "name",
      title: i18n("UserGroupMembersTable.name"),
      sorter: nameSorter,
      render(text, user) {
        return (
          <Button type="link" href={setBaseUrl(`/users/${user.id}`)}>
            {text}
          </Button>
        );
      },
    },
    {
      title: i18n("UserGroupMembersTable.role"),
      dataIndex: "role",
      width: 200,
      render(text, user) {
        return (
          <GroupRole
            item={user}
            canManage={canManage}
            updateRoleFn={updateMemberRole}
          />
        );
      },
    },
    {
      title: i18n("UserGroupMembersTable.joined"),
      dataIndex: "createdDate",
      width: 230,
      render(text) {
        return formatInternationalizedDateTime(text);
      },
    },
  ];

  if (canManage) {
    columns.push({
      align: "right",
      width: 50,
      render(user) {
        return (
          <RemoveTableItemButton
            onRemove={() =>
              removeMemberFromUserGroup({ groupId, userId: user.id })
            }
            onRemoveSuccess={updateTable}
            tooltipText={i18n("UserGroupMembersTable.remove-tooltip")}
            confirmText={i18n("UserGroupMembersTable.remove-confirm")}
          />
        );
      },
    });
  }

  const getAvailableMembers = (query) =>
    getAvailableUsersForUserGroup({ id: groupId, query });

  const addMember = ({ id, role }) => {
    return addMemberToUserGroup({ groupId, userId: id, role });
  };

  async function updateMemberRole({ userId, role }) {
    return updateUserRoleOnUserGroups({ groupId, userId, role });
  }

  return (
    <>
      <div style={{ display: "flex", marginBottom: SPACE_XS }}>
        <div style={{ flex: 1 }}>
          {canManage ? (
            <AddMemberButton
              defaultRole="GROUP_MEMBER"
              label={i18n("UserGroupMembersTable.add")}
              modalTitle={i18n("UserGroupMembersTable.add.title")}
              addMemberFn={addMember}
              addMemberSuccessFn={updateTable}
              getAvailableMembersFn={getAvailableMembers}
            />
          ) : null}
        </div><commit_msg>:bulb: Updated JSDoc for UserGroupMembersTable.jsx<commit_after>import { Button, Table } from "antd";
import React from "react";
import {
  addMemberToUserGroup,
  getAvailableUsersForUserGroup,
  removeMemberFromUserGroup,
  updateUserRoleOnUserGroups,
} from "../../../apis/users/groups";
import {
  AddMemberButton,
  RemoveTableItemButton,
} from "../../../components/Buttons";
import { GroupRole } from "../../../components/roles/GroupRole";
import { SPACE_XS } from "../../../styles/spacing";
import { formatInternationalizedDateTime } from "../../../utilities/date-utilities";
import { stringSorter } from "../../../utilities/table-utilities";
import { setBaseUrl } from "../../../utilities/url-utilities";

/**
 * Custom sorter for the name column since this is NOT paged server side.
 * @type {function(*, *): number}
 */
const nameSorter = stringSorter("name");

/**
 * React component to render a table to display user group members
 * @param {array} members
 * @param {boolean} canManage can the current user manage members
 * @param {number} groupId identifier for teh current user group
 * @param {function} updateTable - method to refresh the contents of the table
 * @returns {string|*}
 * @constructor
 */
export default function UserGroupMembersTable({
  members,
  canManage,
  groupId,
  updateTable,
}) {
  const columns = [
    {
      dataIndex: "name",
      title: i18n("UserGroupMembersTable.name"),
      sorter: nameSorter,
      render(text, user) {
        return (
          <Button type="link" href={setBaseUrl(`/users/${user.id}`)}>
            {text}
          </Button>
        );
      },
    },
    {
      title: i18n("UserGroupMembersTable.role"),
      dataIndex: "role",
      width: 200,
      render(text, user) {
        return (
          <GroupRole
            item={user}
            canManage={canManage}
            updateRoleFn={updateMemberRole}
          />
        );
      },
    },
    {
      title: i18n("UserGroupMembersTable.joined"),
      dataIndex: "createdDate",
      width: 230,
      render(text) {
        return formatInternationalizedDateTime(text);
      },
    },
  ];

  if (canManage) {
    columns.push({
      align: "right",
      width: 50,
      render(user) {
        return (
          <RemoveTableItemButton
            onRemove={() =>
              removeMemberFromUserGroup({ groupId, userId: user.id })
            }
            onRemoveSuccess={updateTable}
            tooltipText={i18n("UserGroupMembersTable.remove-tooltip")}
            confirmText={i18n("UserGroupMembersTable.remove-confirm")}
          />
        );
      },
    });
  }

  /**
   * Get the available users for a group based on a search parameter
   *
   * @param {string} query - search parameter for the user
   * @returns {Promise<AxiosResponse<*>>}
   */
  const getAvailableMembers = (query) =>
    getAvailableUsersForUserGroup({ id: groupId, query });

  /**
   * Add a member to this groups
   *
   * @param {number} id - identifier for the user to add
   * @param {string} role - group role to set the user to
   * @returns {Promise<AxiosResponse<*>>}
   */
  const addMember = ({ id, role }) => {
    return addMemberToUserGroup({ groupId, userId: id, role });
  };

  /**
   * Update a member role on this group
   *
   * @param {number} userId - identifier for the member to update
   * @param {string} role - group role to update the user to
   * @returns {Promise<AxiosResponse<*>>}
   */
  async function updateMemberRole({ userId, role }) {
    return updateUserRoleOnUserGroups({ groupId, userId, role });
  }

  return (
    <>
      <div style={{ display: "flex", marginBottom: SPACE_XS }}>
        <div style={{ flex: 1 }}>
          {canManage ? (
            <AddMemberButton
              defaultRole="GROUP_MEMBER"
              label={i18n("UserGroupMembersTable.add")}
              modalTitle={i18n("UserGroupMembersTable.add.title")}
              addMemberFn={addMember}
              addMemberSuccessFn={updateTable}
              getAvailableMembersFn={getAvailableMembers}
            />
          ) : null}
        </div>
{'fraction_non_alphanumeric': 0.13555291319857313, 'fraction_numerical': 0.00607742105958515, 'mean_word_length': 2.4346642468239565, 'pattern_counts': {'":': 0, '<': 27, '<?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': '6545298', 'n_tokens_mistral': 2192, 'n_tokens_neox': 2168, 'n_words': 516}