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 1513655b2a845a54b54eacc6cff71610210f3794 Author: Anand Nadar <[email protected]> AuthorDate: Sun Dec 10 22:52:51 2023 -0800 RANGER-4283: GDS UI updates in dataShare pages Signed-off-by: Madhan Neethiraj <[email protected]> --- .../GovernedData/Dataset/DatasetDetailLayout.jsx | 3 +- .../Dataset/DatashareInDatasetListComp.jsx | 200 +++++++++++++++-- .../Dataset/PrinciplePermissionComp.jsx | 8 +- .../GovernedData/Datashare/AddDatashareView.jsx | 87 ++++++-- .../Datashare/AddSharedResourceComp.jsx | 2 +- .../Datashare/DatashareDetailLayout.jsx | 248 +-------------------- 6 files changed, 261 insertions(+), 287 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 5bbd99924..e234979d0 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 @@ -1445,7 +1445,8 @@ const DatasetDetailLayout = () => { > <Tab eventKey="All" title="All"> <DatashareInDatasetListComp - datasetId={Number(datasetId)} + id={Number(datasetId)} + type="dataset" setUpdateTable={setUpdateTable} updateTable={updateTable} userAclPerm={userAclPerm} 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 e7cd9bcda..35bb1fb0f 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 @@ -38,7 +38,8 @@ import { import { Button, Row, Col, Modal } from "react-bootstrap"; const DatashareInDatasetListComp = ({ - datasetId, + id, + type, setUpdateTable, updateTable, userAclPerm @@ -88,7 +89,11 @@ const DatashareInDatasetListComp = ({ const fetchId = ++fetchIdRef.current; let params = { ...searchFilterParams }; if (fetchId === fetchIdRef.current) { - params["datasetId"] = datasetId; + if (type == "dataset") { + params["datasetId"] = id; + } else if (type == "datashare") { + params["dataShareId"] = id; + } params["pageSize"] = pageSize; params["startIndex"] = state && state.showLastPage @@ -179,6 +184,132 @@ const DatashareInDatasetListComp = ({ } }; + const datasetReqColumns = React.useMemo( + () => [ + { + Header: "Name", + accessor: "dataShareId", + //width: 200, + Cell: (val) => { + return ( + <span + className="text-truncate" + title={val.value} + style={{ maxWidth: "240px", display: "inline-block" }} + > + Dataset {val.value} + </span> + ); + } + }, + { + Header: "Status", + accessor: "status", + width: 108, + Cell: (val) => { + return ( + <span + className={ + val.value === "REQUESTED" + ? "badge badge-light gds-requested-status" + : val.value === "GRANTED" + ? "badge badge-light gds-granted-status" + : val.value === "ACTIVE" + ? "badge badge-light gds-active-status" + : "badge badge-light gds-denied-status" + } + > + {val.value} + </span> + ); + } + }, + { + Header: "Last Updated", + accessor: "updateTime", + Cell: (rawValue) => { + return dateFormat(rawValue.value, "mm/dd/yyyy"); + }, + width: 108, + disableResizing: true, + getResizerProps: () => {} + }, + { + Header: "Approver", + accessor: "approver", + Cell: (rawValue) => { + return ( + <div className="position-relative text-center"> + <span>{rawValue.value}</span> + </div> + ); + }, + width: 108, + disableResizing: true, + getResizerProps: () => {} + }, + { + Header: "", + accessor: "actions", + Cell: ({ row: { original } }) => { + return ( + <div> + <Button + variant="outline-dark" + size="sm" + className="mr-2" + style={{ height: "31px" }} + title="View Request" + onClick={() => navigate(`/gds/request/detail/${original.id}`)} + data-name="viewRequest" + data-id={original.dataShareId} + > + <img src={viewRequestIcon} height="18px" width="18px" /> + </Button> + <Button + 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} + > + <i className="fa-fw fa fa-eye fa-fw fa fa-large"></i> + </Button> + + <> + {(isSystemAdmin() || userAclPerm == "ADMIN") && ( + <Button + variant="danger" + size="sm" + title="Delete" + onClick={() => + toggleConfirmModalForDelete( + original.id, + "Dummy", + original.status + ) + } + data-name="deleteDatashareRequest" + data-id={original.id} + data-cy={original.id} + > + <i className="fa-fw fa fa-trash fa-fw fa fa-large" /> + </Button> + )} + </> + </div> + ); + }, + disableSortBy: true + } + ], + [] + ); + const requestColumns = React.useMemo( () => [ { @@ -409,26 +540,51 @@ const DatashareInDatasetListComp = ({ return ( <> - <XATableLayout - data={requestListData} - columns={requestColumns} - fetchData={fetchRequestList} - totalCount={entries && entries.totalCount} - loading={loader} - pageCount={pageCount} - getRowProps={(row) => ({ - onClick: (e) => { - e.stopPropagation(); - //rowModal(row); - } - })} - currentpageIndex={currentpageIndex} - currentpageSize={currentpageSize} - columnHide={false} - columnResizable={false} - columnSort={true} - defaultSort={getDefaultSort} - /> + {type == "dataset" && ( + <XATableLayout + data={requestListData} + columns={requestColumns} + fetchData={fetchRequestList} + totalCount={entries && entries.totalCount} + loading={loader} + pageCount={pageCount} + getRowProps={(row) => ({ + onClick: (e) => { + e.stopPropagation(); + //rowModal(row); + } + })} + currentpageIndex={currentpageIndex} + currentpageSize={currentpageSize} + columnHide={false} + columnResizable={false} + columnSort={true} + defaultSort={getDefaultSort} + /> + )} + + {type == "datashare" && ( + <XATableLayout + data={requestListData} + columns={datasetReqColumns} + fetchData={fetchRequestList} + totalCount={entries && entries.totalCount} + loading={loader} + pageCount={pageCount} + getRowProps={(row) => ({ + onClick: (e) => { + e.stopPropagation(); + //rowModal(row); + } + })} + currentpageIndex={currentpageIndex} + currentpageSize={currentpageSize} + columnHide={false} + columnResizable={false} + columnSort={true} + defaultSort={getDefaultSort} + /> + )} <Modal show={showDatashareRequestDeleteConfirmModal} diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/PrinciplePermissionComp.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/PrinciplePermissionComp.jsx index 475ef1015..326433e66 100755 --- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/PrinciplePermissionComp.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/PrinciplePermissionComp.jsx @@ -80,17 +80,17 @@ const PrinciplePermissionComp = ({ const accessOptions = [ { value: "LIST", label: "LIST" }, { value: "VIEW", label: "VIEW" }, - { value: "ADMIN", label: "ADMIN" }, { value: "AUDIT", label: "AUDIT" }, - { value: "POLICY_ADMIN", label: "POLICY_ADMIN" } + { value: "POLICY_ADMIN", label: "POLICY_ADMIN" }, + { value: "ADMIN", label: "ADMIN" } ]; const accessOptionsWithRemove = [ { value: "LIST", label: "LIST" }, { value: "VIEW", label: "VIEW" }, - { value: "ADMIN", label: "ADMIN" }, { value: "AUDIT", label: "AUDIT" }, - { value: "POLICY_ADMIN", label: "POLICY_ADMIN" } + { value: "POLICY_ADMIN", label: "POLICY_ADMIN" }, + { value: "ADMIN", label: "ADMIN" } ]; if (isAdmin) { 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 e6a41c74c..6f45b4ed8 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 @@ -202,7 +202,8 @@ const AddDatashareView = () => { let serviceDefsResp = []; try { serviceDefsResp = await fetchApi({ - url: `plugins/definitions/name/${serviceDefName}` + url: `plugins/definitions/name/${serviceDefName}`, + skipNavigate: true }); } catch (error) { console.error( @@ -258,7 +259,8 @@ const AddDatashareView = () => { try { let serviceResp = await fetchApi({ url: "plugins/services", - params: params + params: params, + skipNavigate: true }); return serviceResp.data.services[0].type; } catch (error) { @@ -266,26 +268,70 @@ const AddDatashareView = () => { } }; + const filterServiceByName = async (inputValue) => { + let params = { serviceNamePrefix: inputValue || "" }; + let op = []; + let serviceResp = []; + if (selectedZone?.id) { + serviceResp = await fetchApi({ + url: `public/v2/api/zones/${selectedZone?.id}/service-headers`, + params: params + }); + } else { + serviceResp = await fetchApi({ + url: "/public/v2/api/service-headers", + params: params + }); + } + op = serviceResp.data; + return op.map((obj) => ({ + label: obj.name, + id: obj.id, + def: obj.type + })); + }; + + const filterZoneByName = async (inputValue) => { + let params = { zoneNamePrefix: inputValue || "" }; + let op = []; + let zoneResp = []; + if (selectedService?.id) { + zoneResp = await fetchApi({ + url: `public/v2/api/zones/zone-headers/for-service/${selectedService?.id}`, + params: params + }); + } else { + zoneResp = await fetchApi({ + url: "/public/v2/api/zone-headers", + params: params + }); + } + op = zoneResp.data; + return op.map((obj) => ({ + label: obj.name, + id: obj.id + })); + }; + const fetchService = async (zoneId) => { + let serviceResp = []; try { if (zoneId == undefined) { - let serviceResp = await fetchApi({ - url: "plugins/services" + serviceResp = await fetchApi({ + url: "public/v2/api/service-headers", + skipNavigate: true }); - return serviceResp.data.services.map(({ name, id, type }) => ({ - label: name, - id: id, - def: type - })); } else { - let serviceResp = await fetchApi({ - url: `public/v2/api/zones/${zoneId}/service-headers` + serviceResp = await fetchApi({ + url: `public/v2/api/zones/${zoneId}/service-headers`, + skipNavigate: true }); - return serviceResp.data.map(({ name, id }) => ({ - label: name, - id: id - })); } + return serviceResp.data.map(({ name, id, type }) => ({ + label: name, + id: id, + def: type + })); } catch (error) { console.error(`Error occurred while fetching service details ! ${error}`); } @@ -308,12 +354,14 @@ const AddDatashareView = () => { try { if (serviceId == undefined) { zoneResp = await fetchApi({ - url: "public/v2/api/zone-headers" + url: "public/v2/api/zone-headers", + skipNavigate: true }); console.log("test"); } else { zoneResp = await fetchApi({ - url: `public/v2/api/zones/zone-headers/for-service/${serviceId}` + url: `public/v2/api/zones/zone-headers/for-service/${serviceId}`, + skipNavigate: true }); } } catch (e) { @@ -586,13 +634,12 @@ const AddDatashareView = () => { render={({ input }) => ( <div className="gds-form-input"> <AsyncSelect - {...input} defaultOptions={defaultServiceOptions} onFocus={() => { onFocusServiceSelect(); }} value={selectedService} - loadOptions={fetchService} + loadOptions={filterServiceByName} onChange={(e) => onServiceChange(e, input)} isClearable={true} placeholder="Select Service" @@ -610,7 +657,7 @@ const AddDatashareView = () => { <AsyncSelect {...input} value={selectedZone} - loadOptions={fetchSecurityZone} + loadOptions={filterZoneByName} onFocus={() => { onFocusZoneSelect(); }} diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddSharedResourceComp.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddSharedResourceComp.jsx index 254e0d00e..8d4a1b7d9 100755 --- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddSharedResourceComp.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddSharedResourceComp.jsx @@ -291,7 +291,7 @@ const AddSharedResourceComp = ({ size="xl" > <Modal.Header closeButton> - <h5 className="mb-0">Add Resources</h5> + <h5 className="mb-0">{!isEdit ? "Add" : "Edit"} Resources</h5> </Modal.Header> <div> <div className="mb-2 gds-chips flex-wrap"> 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 945d4de8c..05baee319 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 @@ -62,6 +62,7 @@ import { import XATableLayout from "../../../components/XATableLayout"; import moment from "moment-timezone"; import { getServiceDef } from "../../../utils/appState"; +import DatashareInDatasetListComp from "../Dataset/DatashareInDatasetListComp"; const DatashareDetailLayout = () => { let { datashareId } = useParams(); @@ -134,6 +135,7 @@ const DatashareDetailLayout = () => { moment.now() ); const [datashareNameEditable, isDatashareNameEditable] = useState(false); + const [updateTable, setUpdateTable] = useState(moment.now()); useEffect(() => { fetchDatashareInfo(datashareId); @@ -1064,245 +1066,13 @@ const DatashareDetailLayout = () => { className="mg-b-10" > <Tab eventKey="All" title="All"> - <Card className="border-0"> - <div> - {dataShareRequestsList != undefined && - dataShareRequestsList.length > 0 ? ( - dataShareRequestsList.map( - (obj, index) => { - return ( - <div> - <Accordion - className="mg-b-10" - defaultActiveKey="0" - > - <div className="border-bottom"> - <Accordion.Toggle - as={Card.Header} - eventKey="1" - onClick={() => - onRequestAccordionChange( - obj.id - ) - } - className="border-bottom-0" - data-id="panel" - data-cy="panel" - > - <div className="d-flex justify-content-between align-items-center"> - <div className="d-flex align-items-center gap-half"> - {requestAccordionState[ - obj.id - ] ? ( - <i className="fa fa-angle-up fa-lg font-weight-bold"></i> - ) : ( - <i className="fa fa-angle-down fa-lg font-weight-bold"></i> - )} - <h6 className="m-0"> - {obj.name} Dataset{" "} - {obj.datasetId} - </h6> - </div> - <div className="d-flex align-items-center gap-half"> - <span - className={ - obj["status"] === - "REQUESTED" - ? "badge badge-light gds-requested-status" - : obj[ - "status" - ] === - "GRANTED" - ? "badge badge-light gds-granted-status" - : obj[ - "status" - ] === "ACTIVE" - ? "badge badge-light gds-active-status" - : "badge badge-light gds-denied-status" - } - > - {obj["status"]} - </span> - <Button - variant="outline-dark" - size="sm" - title="View" - onClick={() => - redirectToDatasetDetailView( - obj.datasetId - ) - } - data-name="viewDatashare" - data-id={obj["id"]} - > - <i className="fa-fw fa fa-eye fa-fw fa fa-large" /> - </Button> - {(isSystemAdmin() || - userAclPerm == - "ADMIN") && ( - <Button - variant="danger" - size="sm" - title="Delete" - onClick={() => - toggleRequestDeleteModal( - obj.id, - obj.datasetId, - obj.name, - obj.status - ) - } - data-name="deleteDatashareRequest" - data-id={ - obj["id"] - } - data-cy={ - obj["id"] - } - > - <i className="fa-fw fa fa-trash fa-fw fa fa-large" /> - </Button> - )} - </div> - </div> - </Accordion.Toggle> - <Accordion.Collapse eventKey="1"> - <Card.Body> - <div className="d-flex justify-content-between"> - <div></div> - {false && ( - <div className="gds-inline-field-grp"> - <div className="wrapper"> - <div - className="gds-left-inline-field" - height="30px" - > - Validity - Period - </div> - <div line-height="30px"> - { - obj[ - "service" - ] - } - </div> - </div> - {obj.validitySchedule != - undefined ? ( - <div className="gds-inline-field-grp"> - <div className="wrapper"> - <div className="gds-left-inline-field"> - <span className="gds-label-color"> - Start - Date{" "} - </span> - </div> - <span> - {dateFormat( - obj - .validitySchedule - .startTime, - "mm/dd/yyyy hh:MM:ss TT" - )} - </span> - <span className="gds-label-color pl-5"> - { - obj - .validitySchedule - .timeZone - } - </span> - </div> - <div className="wrapper"> - <div className="gds-left-inline-field"> - <span className="gds-label-color"> - {" "} - End Date{" "} - </span> - </div> - <span> - {dateFormat( - obj - .validitySchedule - .endTime, - "mm/dd/yyyy hh:MM:ss TT" - )} - </span> - </div> - </div> - ) : ( - <p>--</p> - )} - </div> - )} - <div className="gds-right-inline-field-grp"> - <div className="wrapper"> - <div>Added</div> - <div className="gds-right-inline-field"> - {dateFormat( - obj[ - "createTime" - ], - "mm/dd/yyyy hh:MM:ss TT" - )} - </div> - </div> - <div className="wrapper"> - <div>Updated</div> - <div className="gds-right-inline-field"> - {dateFormat( - obj[ - "updateTime" - ], - "mm/dd/yyyy hh:MM:ss TT" - )} - </div> - </div> - <div className="w-100 text-right"> - <div> - <Link - to={`/gds/request/detail/${obj.id}`} - > - View Request - </Link> - </div> - </div> - </div> - </div> - </Card.Body> - </Accordion.Collapse> - </div> - </Accordion> - </div> - ); - } - ) - ) : ( - <div></div> - )} - {datashareRequestTotalCount > - itemsPerPage && ( - <ReactPaginate - previousLabel={"Previous"} - nextLabel={"Next"} - pageClassName="page-item" - pageLinkClassName="page-link" - previousClassName="page-item" - previousLinkClassName="page-link" - nextClassName="page-item" - nextLinkClassName="page-link" - breakLabel={"..."} - pageCount={requestPageCount} - onPageChange={handleRequestPageClick} - breakClassName="page-item" - breakLinkClassName="page-link" - containerClassName="pagination" - activeClassName="active" - /> - )} - </div> - </Card> + <DatashareInDatasetListComp + id={Number(datashareId)} + type="datashare" + setUpdateTable={setUpdateTable} + updateTable={updateTable} + userAclPerm={userAclPerm} + /> </Tab> <Tab eventKey="Active" title="Active" /> <Tab eventKey="Requested" title="Requested" />
