import { Button, Chip, ChipGroup, Dropdown, DropdownItem, KebabToggle, OverflowMenu, OverflowMenuContent, OverflowMenuControl, OverflowMenuDropdownItem, OverflowMenuGroup, OverflowMenuItem, Spinner, } from "@patternfly/react-core"; import { EditAltIcon, ExternalLinkAltIcon, Remove2Icon, ShareAltIcon, } from "@patternfly/react-icons"; import { ExpandableRowContent, TableComposable, Tbody, Td, Th, Thead, Tr, } from "@patternfly/react-table"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { fetchPermission, fetchResources, updatePermissions } from "../api"; import { getPermissionRequests } from "../api/methods"; import { Links } from "../api/parse-links"; import { Permission, Resource } from "../api/representations"; import { ContinueCancelModal, useAlerts } from "ui-shared"; import { usePromise } from "../utils/usePromise"; import { EditTheResource } from "./EditTheResource"; import { PermissionRequest } from "./PermissionRequest"; import { ResourceToolbar } from "./ResourceToolbar"; import { SharedWith } from "./SharedWith"; import { ShareTheResource } from "./ShareTheResource"; type PermissionDetail = { contextOpen?: boolean; rowOpen?: boolean; shareDialogOpen?: boolean; editDialogOpen?: boolean; permissions?: Permission[]; }; type ResourcesTabProps = { isShared?: boolean; }; export const ResourcesTab = ({ isShared = false }: ResourcesTabProps) => { const { t } = useTranslation(); const { addAlert, addError } = useAlerts(); const [params, setParams] = useState>({ first: "0", max: "5", }); const [links, setLinks] = useState(); const [resources, setResources] = useState(); const [details, setDetails] = useState< Record >({}); const [key, setKey] = useState(1); const refresh = () => setKey(key + 1); usePromise( async (signal) => { const result = await fetchResources({ signal }, params, isShared); if (!isShared) await Promise.all( result.data.map( async (r) => (r.shareRequests = await getPermissionRequests(r._id, { signal, })), ), ); return result; }, ({ data, links }) => { setResources(data); setLinks(links); }, [params, key], ); if (!resources) { return ; } const fetchPermissions = async (id: string) => { let permissions = details[id]?.permissions || []; if (!details[id]) { permissions = await fetchPermission({}, id); } return permissions; }; const removeShare = async (resource: Resource) => { try { const permissions = (await fetchPermissions(resource._id)).map( ({ username }) => ({ username, scopes: [], }) as Permission, )!; await updatePermissions(resource._id, permissions); setDetails({}); addAlert(t("unShareSuccess")); } catch (error) { addError(t("unShareError", { error }).toString()); } }; const toggleOpen = async ( id: string, field: keyof PermissionDetail, open: boolean, ) => { const permissions = await fetchPermissions(id); setDetails({ ...details, [id]: { ...details[id], [field]: open, permissions }, }); }; return ( <> setParams({ ...params, name })} count={resources.length} first={parseInt(params["first"])} max={parseInt(params["max"])} onNextClick={() => setParams(links?.next || {})} onPreviousClick={() => setParams(links?.prev || {})} onPerPageSelect={(first, max) => setParams({ first: `${first}`, max: `${max}` }) } hasNext={!!links?.next} /> {t("resourceName")} {t("application")} {!isShared ? t("permissionRequests") : ""} {resources.map((resource, index) => ( toggleOpen( resource._id, "rowOpen", !details[resource._id]?.rowOpen, ), } : undefined } /> {resource.name} {resource.client.name || resource.client.clientId}{" "} {resource.shareRequests && resource.shareRequests.length > 0 && ( refresh()} /> )} setDetails({})} /> {details[resource._id]?.editDialogOpen && ( setDetails({})} /> )} {isShared ? ( {resource.scopes.length > 0 && ( {resource.scopes.map((scope) => ( {scope.displayName || scope.name} ))} )} ) : ( toggleOpen(resource._id, "contextOpen", open) } /> } isOpen={details[resource._id]?.contextOpen} isPlain dropdownItems={[ toggleOpen( resource._id, "editDialogOpen", true, ) } > {t("edit")} , {t("unShare")} } modalTitle={t("unShare")} continueLabel={t("confirm")} cancelLabel={t("cancel")} component={DropdownItem} onContinue={() => removeShare(resource)} isDisabled={ details[resource._id]?.permissions?.length === 0 } > {t("unShareAllConfirm")} , ]} /> toggleOpen(resource._id, "contextOpen", open) } /> } isOpen={details[resource._id]?.contextOpen} isPlain dropdownItems={[ toggleOpen(resource._id, "shareDialogOpen", true) } > {t("share")} , toggleOpen(resource._id, "editDialogOpen", true) } > {t("edit")} , {t("unShare")} } modalTitle={t("unShare")} continueLabel={t("confirm")} cancelLabel={t("cancel")} component={OverflowMenuDropdownItem} onContinue={() => removeShare(resource)} isDisabled={ details[resource._id]?.permissions?.length === 0 } > {t("unShareAllConfirm")} , ]} /> )} ))} ); };