github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/webui/src/pages/auth/groups/group/policies.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 {Link} from "../../../../lib/components/nav";
    21  import {useRouter} from "../../../../lib/hooks/router";
    22  
    23  
    24  const GroupPoliciesList = ({ groupId, 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.listGroupPolicies(groupId, after);
    31      }, [groupId, after, refresh]);
    32  
    33      useEffect(() => { setAttachError(null); }, [refresh, after]);
    34  
    35      let content;
    36      if (loading) content = <Loading/>;
    37      else if (error) content=  <AlertError error={error}/>;
    38      else content = (
    39              <>
    40                  {attachError && <AlertError error={attachError}/>}
    41  
    42                  <DataTable
    43                      keyFn={policy => policy.id}
    44                      rowFn={policy => [
    45                          <Link href={{pathname: '/auth/policies/:policyId', params: {policyId: policy.id}}}>{policy.id}</Link>,
    46                          <FormattedDate dateValue={policy.creation_date}/>
    47                      ]}
    48                      headers={['Policy ID', 'Created At']}
    49                      actions={[{
    50                          key: 'Detach',
    51                          buttonFn: policy => <ConfirmationButton
    52                              size="sm"
    53                              variant="outline-danger"
    54                              modalVariant="danger"
    55                              msg={<span>Are you sure you{'\''}d like to detach policy <strong>{policy.id}</strong>?</span>}
    56                              onConfirm={() => {
    57                                  auth.detachPolicyFromGroup(groupId, policy.id)
    58                                      .catch(error => alert(error))
    59                                      .then(() => { setRefresh(!refresh) })
    60                              }}>
    61                              Remove
    62                          </ConfirmationButton>
    63                      }]}
    64                      results={results}
    65                      emptyState={'No policies found'}
    66                  />
    67  
    68                  <Paginator onPaginate={onPaginate} after={after} nextPage={nextPage}/>
    69  
    70  
    71                  {showAddModal && <AttachModal
    72                      show={showAddModal}
    73                      emptyState={'No policies found'}
    74                      filterPlaceholder={'Find Policy...'}
    75                      modalTitle={'Attach Policies'}
    76                      addText={'Attach Policies'}
    77                      searchFn={prefix => auth.listPolicies(prefix, "", 5).then(res => res.results)}
    78                      onHide={() => setShowAddModal(false)}
    79                      onAttach={(selected) => {
    80                          Promise.all(selected.map(policy => auth.attachPolicyToGroup(groupId, policy.id)))
    81                              .then(() => { setRefresh(!refresh); setAttachError(null) })
    82                              .catch(error => { setAttachError(error) })
    83                              .finally(() => { setShowAddModal(false) })
    84                      }}/>
    85                  }
    86              </>
    87          );
    88  
    89      return (
    90          <>
    91              <GroupHeader groupId={groupId} page={'policies'}/>
    92  
    93              <ActionsBar>
    94                  <ActionGroup orientation="left">
    95                      <Button variant="success" onClick={() => setShowAddModal(true)}>Attach Policy</Button>
    96                  </ActionGroup>
    97  
    98                  <ActionGroup orientation="right">
    99                      <RefreshButton onClick={() => setRefresh(!refresh)}/>
   100                  </ActionGroup>
   101              </ActionsBar>
   102  
   103              <div className="mt-2">
   104                  {content}
   105              </div>
   106          </>
   107      );
   108  };
   109  
   110  const GroupPoliciesContainer = () => {
   111      const router = useRouter();
   112      const { after } = router.query;
   113      const { groupId } = router.params;
   114      return (!groupId) ? <></> : <GroupPoliciesList
   115          groupId={groupId}
   116          after={(after) ? after : ""}
   117          onPaginate={after => router.push({pathname: '/auth/groups/:groupId/policies', params: {groupId}, query: {after}})}
   118      />;
   119  };
   120  
   121  const GroupPoliciesPage = () => {
   122      const [setActiveTab] = useOutletContext();
   123      useEffect(() => setActiveTab('groups'), [setActiveTab]);
   124      return <GroupPoliciesContainer/>;
   125  };
   126  
   127  export default GroupPoliciesPage;