github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/webui/src/pages/auth/groups/group/members.jsx (about)

     1  import React, {useEffect, useState} from "react";
     2  import { useOutletContext } from "react-router-dom";
     3  import Button from "react-bootstrap/Button";
     4  
     5  import {GroupHeader} from "../../../../lib/components/auth/nav";
     6  import {useAPIWithPagination} from "../../../../lib/hooks/api";
     7  import {auth} from "../../../../lib/api";
     8  import {Paginator} from "../../../../lib/components/pagination";
     9  import {AttachModal} from "../../../../lib/components/auth/forms";
    10  import {ConfirmationButton} from "../../../../lib/components/modals";
    11  import {
    12      ActionGroup,
    13      ActionsBar,
    14      DataTable,
    15      FormattedDate,
    16      Loading,
    17      AlertError,
    18      RefreshButton
    19  } from "../../../../lib/components/controls";
    20  import {useRouter} from "../../../../lib/hooks/router";
    21  import {Link} from "../../../../lib/components/nav";
    22  import {resolveDisplayName} from "../../../../lib/utils";
    23  
    24  
    25  const GroupMemberList = ({ groupId, after, onPaginate }) => {
    26      const [refresh, setRefresh] = useState(false);
    27      const [showAddModal, setShowAddModal] = useState(false);
    28      const [attachError, setAttachError] = useState(null);
    29  
    30      const {results, loading, error, nextPage} = useAPIWithPagination(() => {
    31          return auth.listGroupMembers(groupId, after);
    32      }, [groupId, after, refresh]);
    33  
    34      useEffect(() => {
    35          setAttachError(null);
    36      }, [refresh]);
    37  
    38      let content;
    39      if (loading) content = <Loading/>;
    40      else if (error) content=  <AlertError error={error}/>;
    41      else content = (
    42              <>
    43                  {attachError && <AlertError error={attachError}/>}
    44  
    45                  <DataTable
    46                      keyFn={user => user.id}
    47                      rowFn={user => [
    48                          <Link href={{pathname: '/auth/users/:userId', params: {userId: user.id}}}>{resolveDisplayName(user)}</Link>,
    49                          <FormattedDate dateValue={user.creation_date}/>
    50                      ]}
    51                      headers={['User ID', 'Created At']}
    52                      actions={[{
    53                          key: 'Remove',
    54                          buttonFn: user => <ConfirmationButton
    55                              size="sm"
    56                              variant="outline-danger"
    57                              msg={<span>Are you sure you{'\''}d like to remove user <strong>{resolveDisplayName(user)}</strong> from group <strong>{groupId}</strong>?</span>}
    58                              onConfirm={() => {
    59                                  auth.removeUserFromGroup(user.id, groupId)
    60                                      .catch(error => alert(error))
    61                                      .then(() => { setRefresh(!refresh) });
    62                              }}>
    63                              Remove
    64                          </ConfirmationButton>
    65                      }]}
    66                      results={results}
    67                      emptyState={'No users found'}
    68                  />
    69  
    70                  <Paginator onPaginate={onPaginate} after={after} nextPage={nextPage}/>
    71  
    72                  {showAddModal && <AttachModal
    73                      show={showAddModal}
    74                      emptyState={'No users found'}
    75                      filterPlaceholder={'Find User...'}
    76                      modalTitle={'Add to Group'}
    77                      addText={'Add to Group'}
    78                      searchFn={prefix => auth.listUsers(prefix, "", 5).then(res => res.results)}
    79                      onHide={() => setShowAddModal(false)}
    80                      onAttach={(selected) => {
    81                          Promise.all(selected.map(user => auth.addUserToGroup(user.id, groupId)))
    82                              .then(() => { setRefresh(!refresh); setAttachError(null) })
    83                              .catch(error => { setAttachError(error) })
    84                              .finally(() => { setShowAddModal(false) });
    85                      }}/>
    86                  }
    87              </>
    88          );
    89  
    90      return (
    91          <>
    92              <GroupHeader groupId={groupId} page={'members'}/>
    93  
    94              <ActionsBar>
    95                  <ActionGroup orientation="left">
    96                      <Button variant="success" onClick={() => setShowAddModal(true)}>Add Members</Button>
    97                  </ActionGroup>
    98  
    99                  <ActionGroup orientation="right">
   100                      <RefreshButton onClick={() => setRefresh(!refresh)}/>
   101                  </ActionGroup>
   102              </ActionsBar>
   103  
   104              <div className="mt-2">
   105                  {content}
   106              </div>
   107          </>
   108      );
   109  };
   110  
   111  const GroupMembersContainer = () => {
   112      const router = useRouter();
   113      const { after } = router.query;
   114      const { groupId } = router.params;
   115      return groupId && <GroupMemberList
   116          groupId={groupId}
   117          after={(after) ? after : ""}
   118          onPaginate={after => router.push({pathname: '/auth/groups/:groupId/members', params: {groupId},query: {after}})}
   119      />;
   120  };
   121  
   122  const GroupMembersPage = () => {
   123      const [setActiveTab] = useOutletContext();
   124      useEffect(() => setActiveTab('groups'), [setActiveTab]);
   125      return <GroupMembersContainer/>;
   126  };
   127  
   128  export default GroupMembersPage;