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

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