This is an automated email from the ASF dual-hosted git repository. madhan pushed a commit to branch RANGER-3923 in repository https://gitbox.apache.org/repos/asf/ranger.git
commit d950460569ca7256e8c7ba0369b0dc46500c425a Author: Anand Nadar <[email protected]> AuthorDate: Thu Dec 14 08:24:30 2023 -0800 RANGER-4283: [WIP] UI for GDS: updated datashare tab in dataset detail view Signed-off-by: Madhan Neethiraj <[email protected]> --- .../GovernedData/Dataset/DatasetDetailLayout.jsx | 219 +++++++++++++++++++-- .../Dataset/DatashareInDatasetListComp.jsx | 197 ++++++++++++------ .../GovernedData/Dataset/MyDatasetListing.jsx | 1 - .../GovernedData/Datashare/AddDatashareView.jsx | 40 +--- .../Datashare/DatashareDetailLayout.jsx | 199 +++++++++++++++++-- 5 files changed, 527 insertions(+), 129 deletions(-) diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailLayout.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailLayout.jsx index e234979d0..95f06c93d 100755 --- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailLayout.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailLayout.jsx @@ -37,8 +37,17 @@ import { toast } from "react-toastify"; import { Form } from "react-final-form"; import { CustomTooltip, Loader } from "../../../components/CommonComponents"; import moment from "moment-timezone"; -import { useParams, useNavigate, useLocation, Link } from "react-router-dom"; -import { serverError, isSystemAdmin } from "../../../utils/XAUtils"; +import { + useParams, + useNavigate, + useLocation, + useSearchParams +} from "react-router-dom"; +import { + serverError, + isSystemAdmin, + parseSearchFilter +} from "../../../utils/XAUtils"; import Select from "react-select"; import userColourIcon from "../../../images/user-colour.svg"; import groupColourIcon from "../../../images/group-colour.svg"; @@ -161,6 +170,61 @@ const DatasetDetailLayout = () => { const [updateTable, setUpdateTable] = useState(moment.now()); const gdsServiceDefName = "gds"; const [datasetNameEditable, isDatasetNameEditable] = useState(false); + const [requestSearchFilterParams, setRequestSearchFilterParams] = useState( + [] + ); + const [shareStatusMetrics, setShareStatusMetrics] = useState({ + totalCount: 0, + REQUESTED: 0, + GRANTED: 0, + ACTIVE: 0, + DENIED: 0 + }); + + const fetchShareStatusMetrics = async () => { + try { + setLoader(true); + let params = {}; + params["datasetId"] = datasetId; + const resp = await fetchApi({ + url: `gds/dataset/summary`, + params: params + }); + let datashareReqList = resp.data.list[0].dataShares; + let activeCount = 0; + let requestedCount = 0; + let grantedCount = 0; + let deniedCount = 0; + datashareReqList.forEach((request) => { + switch (request.shareStatus) { + case "REQUESTED": + requestedCount += 1; + break; + case "GRANTED": + grantedCount += 1; + break; + case "ACTIVE": + activeCount += 1; + break; + case "DENIED": + deniedCount += 1; + break; + } + }); + setShareStatusMetrics({ + totalCount: datashareReqList.length, + REQUESTED: requestedCount, + GRANTED: grantedCount, + ACTIVE: activeCount, + DENIED: deniedCount + }); + } catch (error) { + console.error( + `Error occurred while fetching dataset summary details ! ${error}` + ); + } + setLoader(false); + }; const handleDatasetDeleteClick = async () => { toggleClose(); @@ -203,6 +267,35 @@ const DatasetDetailLayout = () => { return data; }; + const requestSearchFilterOptions = [ + { + category: "dataShareNamePartial", + label: "Name", + urlLabel: "dataShareNamePartial", + type: "text" + }, + { + category: "serviceNamePartial", + label: "Service", + urlLabel: "serviceNamePartial", + type: "text" + }, + { + category: "ZoneNamePartial", + label: "Zone", + urlLabel: "ZoneNamePartial", + type: "text" + } + ]; + + const updateRequestSearchFilter = (filter) => { + let { searchFilterParam, searchParam } = parseSearchFilter( + filter, + requestSearchFilterOptions + ); + setRequestSearchFilterParams(searchFilterParam); + }; + useEffect(() => { fetchDatasetInfo(datasetId); getServiceDefData(); @@ -466,6 +559,7 @@ const DatasetDetailLayout = () => { }); toast.success("Request created successfully!!"); setDatashareModal(false); + fetchShareStatusMetrics(); setUpdateTable(moment.now()); } catch (error) { dispatch({ @@ -660,6 +754,8 @@ const DatasetDetailLayout = () => { setActiveKey(key); if (key == "sharedWith") { fetchAccessGrantInfo(); + } else if (key == "datashares") { + fetchShareStatusMetrics(); } } }; @@ -1419,6 +1515,8 @@ const DatasetDetailLayout = () => { <StructuredFilter key="user-listing-search-filter" placeholder="Search datashares..." + onChange={updateRequestSearchFilter} + options={requestSearchFilterOptions} /> </div> {(isSystemAdmin() || userAclPerm == "ADMIN") && ( @@ -1443,19 +1541,112 @@ const DatasetDetailLayout = () => { activeKey={requestActiveKey} onSelect={handleRequestTabSelect} > - <Tab eventKey="All" title="All"> - <DatashareInDatasetListComp - id={Number(datasetId)} - type="dataset" - setUpdateTable={setUpdateTable} - updateTable={updateTable} - userAclPerm={userAclPerm} - /> + <Tab + eventKey="All" + title={ + "All (" + shareStatusMetrics.totalCount + ")" + } + > + {requestActiveKey == "All" && ( + <DatashareInDatasetListComp + id={Number(datasetId)} + type="dataset" + setUpdateTable={setUpdateTable} + updateTable={updateTable} + userAclPerm={userAclPerm} + searchFilter={requestSearchFilterParams} + fetchShareStatusMetrics={ + fetchShareStatusMetrics + } + /> + )} + </Tab> + <Tab + eventKey="Active" + title={ + "Active (" + shareStatusMetrics.ACTIVE + ")" + } + > + {requestActiveKey == "Active" && ( + <DatashareInDatasetListComp + id={Number(datasetId)} + type="dataset" + shareStatus="ACTIVE" + setUpdateTable={setUpdateTable} + updateTable={updateTable} + userAclPerm={userAclPerm} + searchFilter={requestSearchFilterParams} + fetchShareStatusMetrics={ + fetchShareStatusMetrics + } + /> + )} + </Tab> + <Tab + eventKey="Requested" + title={ + "Requested (" + + shareStatusMetrics.REQUESTED + + ")" + } + > + {requestActiveKey == "Requested" && ( + <DatashareInDatasetListComp + id={Number(datasetId)} + type="dataset" + shareStatus="REQUESTED" + setUpdateTable={setUpdateTable} + updateTable={updateTable} + userAclPerm={userAclPerm} + searchFilter={requestSearchFilterParams} + fetchShareStatusMetrics={ + fetchShareStatusMetrics + } + /> + )} + </Tab> + <Tab + eventKey="Granted" + title={ + "Granted (" + shareStatusMetrics.GRANTED + ")" + } + > + {requestActiveKey == "Granted" && ( + <DatashareInDatasetListComp + id={Number(datasetId)} + type="dataset" + shareStatus="GRANTED" + setUpdateTable={setUpdateTable} + updateTable={updateTable} + userAclPerm={userAclPerm} + searchFilter={requestSearchFilterParams} + fetchShareStatusMetrics={ + fetchShareStatusMetrics + } + /> + )} + </Tab> + <Tab + eventKey="Denied" + title={ + "Denied (" + shareStatusMetrics.DENIED + ")" + } + > + {requestActiveKey == "Denied" && ( + <DatashareInDatasetListComp + id={Number(datasetId)} + type="dataset" + shareStatus="DENIED" + setUpdateTable={setUpdateTable} + updateTable={updateTable} + userAclPerm={userAclPerm} + searchFilter={requestSearchFilterParams} + fetchShareStatusMetrics={ + fetchShareStatusMetrics + } + /> + )} </Tab> - <Tab eventKey="Active" title="Active"></Tab> - <Tab eventKey="Requested" title="Requested"></Tab> - <Tab eventKey="Granted" title="Granted"></Tab> - <Tab eventKey="Denied" title="Denied"></Tab> </Tabs> </div> </div> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatashareInDatasetListComp.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatashareInDatasetListComp.jsx index 35bb1fb0f..82a22de24 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatashareInDatasetListComp.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatashareInDatasetListComp.jsx @@ -22,8 +22,6 @@ import { useSearchParams, useNavigate, useLocation } from "react-router-dom"; import XATableLayout from "../../../components/XATableLayout"; import dateFormat from "dateformat"; import { fetchApi } from "../../../utils/fetchAPI"; -import StructuredFilter from "../../../components/structured-filter/react-typeahead/tokenizer"; -import { Loader, BlockUi } from "../../../components/CommonComponents"; import { toast } from "react-toastify"; import moment from "moment-timezone"; import viewRequestIcon from "../../../images/view-request.svg"; @@ -35,14 +33,17 @@ import { parseSearchFilter, isSystemAdmin } from "../../../utils/XAUtils"; -import { Button, Row, Col, Modal } from "react-bootstrap"; +import { Button, Modal } from "react-bootstrap"; const DatashareInDatasetListComp = ({ id, type, + shareStatus, setUpdateTable, updateTable, - userAclPerm + userAclPerm, + searchFilter, + fetchShareStatusMetrics }) => { const { state } = useLocation(); const [requestListData, setRequestListData] = useState([]); @@ -87,48 +88,118 @@ const DatashareInDatasetListComp = ({ : pageIndex; let totalPageCount = 0; const fetchId = ++fetchIdRef.current; - let params = { ...searchFilterParams }; + let params = { ...searchFilter }; if (fetchId === fetchIdRef.current) { + params["pageSize"] = 999999999; + if (sortBy.length > 0) { + if (getTableSortBy(sortBy) == "name") + params["sortBy"] = "datasetName"; + else params["sortBy"] = getTableSortBy(sortBy); + + params["sortType"] = getTableSortType(sortBy); + } if (type == "dataset") { params["datasetId"] = id; + try { + resp = await fetchApi({ + url: "gds/datashare/summary", + params: params + }); + if (resp.data.list.length > 0) { + requestList = resp.data.list; + requestList?.forEach((datashare) => { + for (let i = 0; i < datashare.datasets.length; i++) { + if (datashare.datasets[i].datasetId == id) { + datashare.shareStatus = datashare.datasets[i].shareStatus; + datashare.requestId = datashare.datasets[i].id; + datashare.datasetName = datashare.datasets[i].datasetName; + break; + } + } + }); + totalCount = requestList != undefined ? requestList.length : 0; + } + } catch (error) { + serverError(error); + console.error( + `Error occurred while fetching Datashare request list! ${error}` + ); + } + if (shareStatus != undefined) { + let tempReqList = requestList; + requestList = []; + tempReqList?.forEach((request) => { + if (request.shareStatus == shareStatus) { + requestList.push(request); + } + }); + totalCount = requestList.length; + } } else if (type == "datashare") { params["dataShareId"] = id; + try { + resp = await fetchApi({ + url: "gds/dataset/summary", + params: params + }); + if (resp.data.list.length > 0) { + requestList = resp.data.list; + requestList?.forEach((dataset) => { + for (let i = 0; i < dataset.dataShares.length; i++) { + if (dataset.dataShares[i].dataShareId == id) { + dataset.shareStatus = dataset.dataShares[i].shareStatus; + dataset.requestId = dataset.dataShares[i].id; + dataset.dataShareName = dataset.dataShares[i].dataShareName; + dataset.approver = dataset.dataShares[i].approver; + break; + } + } + }); + totalCount = requestList != undefined ? requestList.length : 0; + } + } catch (error) { + serverError(error); + console.error( + `Error occurred while fetching Dataset request list! ${error}` + ); + } + if (shareStatus != undefined) { + let tempReqList = requestList; + requestList = []; + tempReqList?.forEach((request) => { + if (request.shareStatus == shareStatus) { + requestList.push(request); + } + }); + totalCount = requestList.length; + } } + resp.data.totalCount = totalCount; + console.log("Total count: " + totalCount); params["pageSize"] = pageSize; - params["startIndex"] = + let startIndex = state && state.showLastPage ? (state.addPageData.totalPage - 1) * pageSize : pageIndex * pageSize; - if (sortBy.length > 0) { - params["sortBy"] = getTableSortBy(sortBy); - params["sortType"] = getTableSortType(sortBy); - } - - try { - resp = await fetchApi({ - url: "gds/datashare/dataset", - params: params - }); - requestList = resp.data.list; - totalCount = resp.data.totalCount; - } catch (error) { - serverError(error); - console.error( - `Error occurred while fetching Datashare list! ${error}` - ); - } + let endIndex = startIndex + pageSize; + requestList = requestList.slice(startIndex, endIndex); + // if (sortBy.length > 0) { + // params["sortBy"] = getTableSortBy(sortBy); + // params["sortType"] = getTableSortType(sortBy); + // } //setUpdateTable(moment.now()); + setTotalCount(totalCount); setRequestListData(requestList); setEntries(resp.data); setCurrentPageIndex(page); setCurrentPageSize(pageSize); setPageCount(Math.ceil(totalCount / pageSize)); - setResetpage({ page: gotoPage }); + //setResdatasetReqColumnsetpage({ page: gotoPage }); setLoader(false); } }, - [searchFilterParams, updateTable] + [searchFilter, updateTable] ); useEffect(() => { @@ -176,19 +247,13 @@ const DatashareInDatasetListComp = ({ ); setSearchFilterParams(searchFilterParam); - setSearchParams(searchParam); - //localStorage.setItem("bigData", JSON.stringify(searchParams)); - - if (typeof resetPage?.page === "function") { - resetPage.page(0); - } }; const datasetReqColumns = React.useMemo( () => [ { Header: "Name", - accessor: "dataShareId", + accessor: "name", //width: 200, Cell: (val) => { return ( @@ -197,15 +262,16 @@ const DatashareInDatasetListComp = ({ title={val.value} style={{ maxWidth: "240px", display: "inline-block" }} > - Dataset {val.value} + {val.value} </span> ); } }, { Header: "Status", - accessor: "status", + accessor: "shareStatus", width: 108, + disableSortBy: true, Cell: (val) => { return ( <span @@ -260,9 +326,11 @@ const DatashareInDatasetListComp = ({ className="mr-2" style={{ height: "31px" }} title="View Request" - onClick={() => navigate(`/gds/request/detail/${original.id}`)} + onClick={() => + navigate(`/gds/request/detail/${original.requestId}`) + } data-name="viewRequest" - data-id={original.dataShareId} + data-id={original.requestId} > <img src={viewRequestIcon} height="18px" width="18px" /> </Button> @@ -270,12 +338,10 @@ const DatashareInDatasetListComp = ({ variant="outline-dark" size="sm" className="mr-2" - title="View Datashare" - onClick={() => - navigate(`/gds/datashare/${original.dataShareId}/detail`) - } - data-name="viewDatashare" - data-id={original.dataShareId} + title="View Dataset" + onClick={() => navigate(`/gds/dataset/${original.id}/detail`)} + data-name="viewDataset" + data-id={original.id} > <i className="fa-fw fa fa-eye fa-fw fa fa-large"></i> </Button> @@ -288,9 +354,10 @@ const DatashareInDatasetListComp = ({ title="Delete" onClick={() => toggleConfirmModalForDelete( - original.id, - "Dummy", - original.status + original.requestId, + original.dataShareName, + original.name, + original.shareStatus ) } data-name="deleteDatashareRequest" @@ -314,7 +381,7 @@ const DatashareInDatasetListComp = ({ () => [ { Header: "Name", - accessor: "dataShareId", + accessor: "name", //width: 200, Cell: (val) => { return ( @@ -323,14 +390,14 @@ const DatashareInDatasetListComp = ({ title={val.value} style={{ maxWidth: "240px", display: "inline-block" }} > - Datashare {val.value} + {val.value} </span> ); } }, { Header: "Service", - accessor: "service", + accessor: "serviceName", //width: 200, Cell: (val) => { return ( @@ -346,7 +413,7 @@ const DatashareInDatasetListComp = ({ }, { Header: "Zone", - accessor: "zone", + accessor: "zoneName", // width: 200, Cell: (val) => { return ( @@ -364,6 +431,7 @@ const DatashareInDatasetListComp = ({ Header: "Resources", accessor: "resourceCount", width: 100, + disableSortBy: true, Cell: (val) => { return ( <span @@ -377,8 +445,9 @@ const DatashareInDatasetListComp = ({ }, { Header: "Status", - accessor: "status", + accessor: "shareStatus", width: 108, + disableSortBy: true, Cell: (val) => { return ( <span @@ -419,7 +488,9 @@ const DatashareInDatasetListComp = ({ className="mr-2" style={{ height: "31px" }} title="View Request" - onClick={() => navigate(`/gds/request/detail/${original.id}`)} + onClick={() => + navigate(`/gds/request/detail/${original.requestId}`) + } data-name="viewRequest" data-id={original.dataShareId} > @@ -430,9 +501,7 @@ const DatashareInDatasetListComp = ({ size="sm" className="mr-2" title="View Datashare" - onClick={() => - navigate(`/gds/datashare/${original.dataShareId}/detail`) - } + onClick={() => navigate(`/gds/datashare/${original.id}/detail`)} data-name="viewDatashare" data-id={original.dataShareId} > @@ -447,9 +516,10 @@ const DatashareInDatasetListComp = ({ title="Delete" onClick={() => toggleConfirmModalForDelete( - original.id, - "Dummy", - original.status + original.requestId, + original.name, + original.datasetName, + original.shareStatus ) } data-name="deleteDatashareRequest" @@ -473,12 +543,16 @@ const DatashareInDatasetListComp = ({ setShowDatashareRequestDeleteConfirmModal(false); }; - const toggleConfirmModalForDelete = (id, name, status) => { + const toggleConfirmModalForDelete = (id, name, datasetName, status) => { let deleteMsg = ""; if (status == "ACTIVE") { - deleteMsg = `Do you want to remove Datashare ${id} from ${name}`; + deleteMsg = `Do you want to remove Datashare: ${name} from ${datasetName}`; } else { - deleteMsg = `Do you want to delete request of Datashare ${id}`; + if (type == "datashare") { + deleteMsg = `Do you want to delete request of Dataset: ${datasetName}`; + } else { + deleteMsg = `Do you want to delete request of Datashare: ${name}`; + } } let data = { id: id, name: name, status: status, msg: deleteMsg }; setDeleteDatashareReqInfo(data); @@ -501,6 +575,7 @@ const DatashareInDatasetListComp = ({ setShowDatashareRequestDeleteConfirmModal(false); toast.success(successMsg); setUpdateTable(moment.now()); + fetchShareStatusMetrics(); // fetchDatashareRequestList( // undefined, diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/MyDatasetListing.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/MyDatasetListing.jsx index 87d808ae4..abc9dfa13 100755 --- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/MyDatasetListing.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/MyDatasetListing.jsx @@ -459,7 +459,6 @@ const MyDatasetListing = () => { setSearchFilterParams(searchFilterParam); setSearchParams(searchParam); - //localStorage.setItem("bigData", JSON.stringify(searchParams)); if (typeof resetPage?.page === "function") { resetPage.page(0); diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddDatashareView.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddDatashareView.jsx index 6f45b4ed8..64819b502 100755 --- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddDatashareView.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddDatashareView.jsx @@ -73,7 +73,6 @@ const AddDatashareView = () => { const [selectedShareMask, setSelectedShareMask] = useState({}); const [datashareTermsAndConditions, setDatashareTermsAndConditions] = useState(); - const [datashareConditionExpr, setDatashareConditionExpr] = useState(); const navigate = useNavigate(); const [defaultZoneOptions, setDefaultZoneOptions] = useState([]); const [defaultServiceOptions, setDefaultServiceOptions] = useState([]); @@ -105,7 +104,7 @@ const AddDatashareView = () => { }; const subhmitDatashareDetails = async (values) => { - if (step == 5) { + if (step == 4) { let dataShareInfo = { name: datashareName, acl: { @@ -116,7 +115,6 @@ const AddDatashareView = () => { service: selectedService.label, description: datashareDescription, termsOfUse: datashareTermsAndConditions, - conditionExpr: datashareConditionExpr, defaultAccessTypes: values.permission != undefined ? Object.entries(values.permission).map(([key, obj]) => { @@ -172,7 +170,7 @@ const AddDatashareView = () => { console.error(`Error occurred while creating datashare ${error}`); } setBlockUI(false); - } else if (step == 4) { + } else if (step == 3) { setSaveButtonText("Create Datashare"); setStep(step + 1); } else if (step == 1) { @@ -445,10 +443,6 @@ const AddDatashareView = () => { setRoleList(roleList); }; - const datashareBooleanExpression = (event) => { - setDatashareConditionExpr(event.target.value); - }; - const MaskingConfig = (props) => { const { addTagMaskingConfig } = props; return ( @@ -688,32 +682,6 @@ const AddDatashareView = () => { )} {step == 2 && ( - <div className="gds-form-wrap"> - <div className="gds-form-header"> - <h6 className="gds-form-step-num">Step 2</h6> - <h2 className="gds-form-step-name">Specify Conditions</h2> - </div> - <div> - <Card className="gds-section-card gds-bg-white"> - <div className="gds-section-title"> - <p className="gds-card-heading">Conditions</p> - </div> - <div className="gds-flex mg-b-10"> - <textarea - placeholder="Boolean Expression" - className="form-control" - id="dsBooleanExpression" - onChange={datashareBooleanExpression} - data-cy="dsBooleanExpression" - rows={4} - /> - </div> - </Card> - </div> - </div> - )} - - {step == 3 && ( <div className="gds-form-wrap"> <div className="gds-form-header"> <h6 className="gds-form-step-num">Step 3</h6> @@ -871,7 +839,7 @@ const AddDatashareView = () => { </div> )} - {step == 4 && ( + {step == 3 && ( <div className="gds-form-wrap"> <div className="gds-form-header"> <h6 className="gds-form-step-num">Step 4</h6> @@ -887,7 +855,7 @@ const AddDatashareView = () => { </div> )} - {step == 5 && ( + {step == 4 && ( <div className="gds-form-wrap"> <div className="gds-form-header"> <h6 className="gds-form-step-num">Step 5</h6> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailLayout.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailLayout.jsx index 05baee319..adbeca360 100755 --- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailLayout.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailLayout.jsx @@ -113,9 +113,6 @@ const DatashareDetailLayout = () => { const [resourceSearchFilterParams, setResourceSearchFilterParams] = useState( [] ); - const [requestSearchFilterParams, setRequestSearchFilterParams] = useState( - [] - ); const fetchIdRef = useRef(0); const [searchFilterParams, setSearchFilterParams] = useState([]); const [sharedResourceListData, setSharedResourceListData] = useState([]); @@ -136,17 +133,74 @@ const DatashareDetailLayout = () => { ); const [datashareNameEditable, isDatashareNameEditable] = useState(false); const [updateTable, setUpdateTable] = useState(moment.now()); + const [requestActiveKey, setRequestActiveKey] = useState("All"); + const [requestSearchFilterParams, setRequestSearchFilterParams] = useState( + [] + ); + const [shareStatusMetrics, setShareStatusMetrics] = useState({ + totalCount: 0, + REQUESTED: 0, + GRANTED: 0, + ACTIVE: 0, + DENIED: 0 + }); useEffect(() => { fetchDatashareInfo(datashareId); }, []); + const fetchShareStatusMetrics = async () => { + try { + setLoader(true); + let params = {}; + params["dataShareId"] = datashareId; + const resp = await fetchApi({ + url: `gds/datashare/summary`, + params: params + }); + let datasetReqList = resp.data.list[0].datasets; + let activeCount = 0; + let requestedCount = 0; + let grantedCount = 0; + let deniedCount = 0; + datasetReqList.forEach((request) => { + switch (request.shareStatus) { + case "REQUESTED": + requestedCount += 1; + break; + case "GRANTED": + grantedCount += 1; + break; + case "ACTIVE": + activeCount += 1; + break; + case "DENIED": + deniedCount += 1; + break; + } + }); + setShareStatusMetrics({ + totalCount: datasetReqList.length, + REQUESTED: requestedCount, + GRANTED: grantedCount, + ACTIVE: activeCount, + DENIED: deniedCount + }); + } catch (error) { + console.error( + `Error occurred while fetching dataset request metrics ! ${error}` + ); + } + setLoader(false); + }; + const handleTabSelect = (key) => { if (saveCancelButtons == true) { setShowConfirmModal(true); } else { if (key == "sharedWith") { - fetchDatashareRequestList(undefined, 0, false); + //fetchDatashareRequestList(undefined, 0, false); + fetchShareStatusMetrics(); } setActiveKey(key); } @@ -542,7 +596,14 @@ const DatashareDetailLayout = () => { setSearchFilterParams(searchFilterParam); }; - const requestSearchFilterOptions = []; + const requestSearchFilterOptions = [ + { + category: "datasetNamePartial", + label: "Name", + urlLabel: "datasetNamePartial", + type: "text" + } + ]; const updateRequestSearchFilter = (filter) => { let { searchFilterParam, searchParam } = parseSearchFilter( @@ -550,7 +611,7 @@ const DatashareDetailLayout = () => { requestSearchFilterOptions ); setRequestSearchFilterParams(searchFilterParam); - fetchDatashareRequestList(searchFilterParam, 0, false); + //fetchDatashareRequestList(searchFilterParam, 0, false); }; const fetchSharedResourcetList = useCallback( @@ -733,6 +794,10 @@ const DatashareDetailLayout = () => { } }; + const handleRequestTabSelect = (key) => { + setRequestActiveKey(key); + }; + return ( <> <Form @@ -1064,19 +1129,119 @@ const DatashareDetailLayout = () => { <Tabs id="datashareRequestTab" className="mg-b-10" + activeKey={requestActiveKey} + onSelect={handleRequestTabSelect} > - <Tab eventKey="All" title="All"> - <DatashareInDatasetListComp - id={Number(datashareId)} - type="datashare" - setUpdateTable={setUpdateTable} - updateTable={updateTable} - userAclPerm={userAclPerm} - /> + <Tab + eventKey="All" + title={ + "All (" + + shareStatusMetrics.totalCount + + ")" + } + > + {requestActiveKey == "All" && ( + <DatashareInDatasetListComp + id={Number(datashareId)} + type="datashare" + setUpdateTable={setUpdateTable} + updateTable={updateTable} + userAclPerm={userAclPerm} + searchFilter={requestSearchFilterParams} + fetchShareStatusMetrics={ + fetchShareStatusMetrics + } + /> + )} + </Tab> + <Tab + eventKey="Active" + title={ + "Active (" + shareStatusMetrics.ACTIVE + ")" + } + > + {requestActiveKey == "Active" && ( + <DatashareInDatasetListComp + id={Number(datashareId)} + type="datashare" + shareStatus="ACTIVE" + setUpdateTable={setUpdateTable} + updateTable={updateTable} + userAclPerm={userAclPerm} + searchFilter={requestSearchFilterParams} + fetchShareStatusMetrics={ + fetchShareStatusMetrics + } + /> + )} + </Tab> + <Tab + eventKey="Requested" + title={ + "Requested (" + + shareStatusMetrics.REQUESTED + + ")" + } + > + {requestActiveKey == "Requested" && ( + <DatashareInDatasetListComp + id={Number(datashareId)} + type="datashare" + shareStatus="REQUESTED" + setUpdateTable={setUpdateTable} + updateTable={updateTable} + userAclPerm={userAclPerm} + searchFilter={requestSearchFilterParams} + fetchShareStatusMetrics={ + fetchShareStatusMetrics + } + /> + )} + </Tab> + <Tab + eventKey="Granted" + title={ + "Granted (" + + shareStatusMetrics.GRANTED + + ")" + } + > + {requestActiveKey == "Granted" && ( + <DatashareInDatasetListComp + id={Number(datashareId)} + type="datashare" + shareStatus="GRANTED" + setUpdateTable={setUpdateTable} + updateTable={updateTable} + userAclPerm={userAclPerm} + searchFilter={requestSearchFilterParams} + fetchShareStatusMetrics={ + fetchShareStatusMetrics + } + /> + )} + </Tab> + <Tab + eventKey="Denied" + title={ + "Denied (" + shareStatusMetrics.DENIED + ")" + } + > + {requestActiveKey == "Denied" && ( + <DatashareInDatasetListComp + id={Number(datashareId)} + type="datashare" + shareStatus="DENIED" + setUpdateTable={setUpdateTable} + updateTable={updateTable} + userAclPerm={userAclPerm} + searchFilter={requestSearchFilterParams} + fetchShareStatusMetrics={ + fetchShareStatusMetrics + } + /> + )} </Tab> - <Tab eventKey="Active" title="Active" /> - <Tab eventKey="Requested" title="Requested" /> - <Tab eventKey="Granted" title="Granted" /> </Tabs> </div> </div>
