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


The following commit(s) were added to refs/heads/RANGER-3923 by this push:
     new 0e36d4252 RANGER-4283: GDS UI - datashare detailed view updates
0e36d4252 is described below

commit 0e36d4252353b233a1f41348e5eb341c1939ce7c
Author: Anand Nadar <[email protected]>
AuthorDate: Fri Dec 29 11:17:57 2023 -0800

    RANGER-4283: GDS UI - datashare detailed view updates
    
    Signed-off-by: Madhan Neethiraj <[email protected]>
---
 .../main/webapp/react-webapp/src/utils/XAUtils.js  |   4 +
 .../views/GovernedData/Dataset/AccessGrantForm.jsx | 149 ++++++----
 .../GovernedData/Dataset/DatasetDetailLayout.jsx   |  71 +++--
 .../Dataset/PrinciplePermissionComp.jsx            | 109 +++----
 .../GovernedData/Datashare/AddDatashareView.jsx    |  13 +-
 .../Datashare/AddSharedResourceComp.jsx            |   3 +-
 .../Datashare/DatashareDetailLayout.jsx            | 327 ++++++++++++++++++---
 7 files changed, 493 insertions(+), 183 deletions(-)

diff --git a/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js 
b/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
index 030fb596f..f834f9795 100644
--- a/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
+++ b/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
@@ -1564,3 +1564,7 @@ export const getServiceDefIcon = (serviceDefName) => {
     </span>
   );
 };
+
+export const capitalizeFirstLetter = (str) => {
+  return str.charAt(0).toUpperCase() + str.slice(1);
+};
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx
index 203f40258..c8120bb68 100755
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx
@@ -28,7 +28,8 @@ import {
   drop,
   dragOver,
   getAllTimeZoneList,
-  policyConditionUpdatedJSON
+  policyConditionUpdatedJSON,
+  isSystemAdmin
 } from "../../../utils/XAUtils";
 import { fetchApi } from "Utils/fetchAPI";
 import { maxBy, find, isEmpty, isArray, isEqual, isObject } from "lodash";
@@ -66,7 +67,12 @@ function reducer(state, action) {
   }
 }
 
-function AccessGrantForm({ dataset, onDataChange, serviceCompDetails }) {
+function AccessGrantForm({
+  dataset,
+  onDataChange,
+  serviceCompDetails,
+  isAdmin
+}) {
   const [policyState, dispatch] = useReducer(reducer, initialState);
   const { loader, policyData, formData } = policyState;
   const [showModal, policyConditionState] = useState(false);
@@ -349,6 +355,15 @@ function AccessGrantForm({ dataset, onDataChange, 
serviceCompDetails }) {
           modifiedVal = true;
           break;
         }
+        if (
+          dirtyFieldVal == "policyItems" &&
+          values.policyItems.length == 1 &&
+          values.policyItems[0] == undefined
+        ) {
+        } else if (!isEqual(values.policyItems, initialValues.policyItems)) {
+          modifiedVal = true;
+          break;
+        }
       }
     }
     if (
@@ -475,29 +490,33 @@ function AccessGrantForm({ dataset, onDataChange, 
serviceCompDetails }) {
                         >
                           Grants
                         </p>
-                        <div className="d-flex gap-half">
-                          {(values.conditions == undefined ||
-                            isEmpty(values.conditions)) && (
-                            <Button
-                              className="btn btn-sm"
-                              onClick={() => {
-                                policyConditionState(true);
-                              }}
-                              data-js="customPolicyConditions"
-                              data-cy="customPolicyConditions"
-                              variant="secondary"
-                            >
-                              Add Conditions
-                            </Button>
-                          )}
-                          {(validityPeriod == undefined ||
-                            validityPeriod.length == 0) && (
-                            <PolicyValidityPeriodComp
-                              addPolicyItem={addPolicyItem}
-                              isGDS={true}
-                            />
-                          )}
-                        </div>
+                        {isAdmin ? (
+                          <div className="d-flex gap-half">
+                            {(values.conditions == undefined ||
+                              isEmpty(values.conditions)) && (
+                              <Button
+                                className="btn btn-sm"
+                                onClick={() => {
+                                  policyConditionState(true);
+                                }}
+                                data-js="customPolicyConditions"
+                                data-cy="customPolicyConditions"
+                                variant="secondary"
+                              >
+                                Add Conditions
+                              </Button>
+                            )}
+                            {(validityPeriod == undefined ||
+                              validityPeriod.length == 0) && (
+                              <PolicyValidityPeriodComp
+                                addPolicyItem={addPolicyItem}
+                                isGDS={true}
+                              />
+                            )}
+                          </div>
+                        ) : (
+                          <></>
+                        )}
                       </div>
                       <div className="drag-drop-wrap pt-3">
                         <FieldArray name="policyItems">
@@ -532,6 +551,7 @@ function AccessGrantForm({ dataset, onDataChange, 
serviceCompDetails }) {
                                                 {...input}
                                                 placeholder="Select users, 
groups, roles"
                                                 isMulti
+                                                isDisabled={!isAdmin}
                                                 
loadOptions={fetchPrincipleData}
                                                 
data-name="usersSeusersPrinciplelect"
                                                 data-cy="usersPrinciple"
@@ -553,6 +573,7 @@ function AccessGrantForm({ dataset, onDataChange, 
serviceCompDetails }) {
                                                 placeholder="Permissions"
                                                 isClearable
                                                 isMulti
+                                                isDisabled={!isAdmin}
                                               />
                                             </div>
                                           )}
@@ -595,21 +616,25 @@ function AccessGrantForm({ dataset, onDataChange, 
serviceCompDetails }) {
                                         )}
                                       </div>
                                     </div>
-                                    <div>
-                                      <Button
-                                        variant="danger"
-                                        size="sm"
-                                        title="Remove"
-                                        onClick={() => {
-                                          fields.remove(index);
-                                          onRemovingPolicyItem();
-                                        }}
-                                        data-action="delete"
-                                        data-cy="delete"
-                                      >
-                                        <i className="fa-fw fa fa-remove"></i>
-                                      </Button>
-                                    </div>
+                                    {isAdmin ? (
+                                      <div>
+                                        <Button
+                                          variant="danger"
+                                          size="sm"
+                                          title="Remove"
+                                          onClick={() => {
+                                            fields.remove(index);
+                                            onRemovingPolicyItem();
+                                          }}
+                                          data-action="delete"
+                                          data-cy="delete"
+                                        >
+                                          <i className="fa-fw fa 
fa-remove"></i>
+                                        </Button>
+                                      </div>
+                                    ) : (
+                                      <></>
+                                    )}
                                   </div>
                                 </tr>
                               </table>
@@ -617,17 +642,23 @@ function AccessGrantForm({ dataset, onDataChange, 
serviceCompDetails }) {
                           }
                         </FieldArray>
                       </div>
-                      <Button
-                        className="btn btn-sm mt-2 mg-l-32 mb-5"
-                        type="button"
-                        onClick={() => addPolicyItem("policyItems", undefined)}
-                        data-action="addGroup"
-                        data-cy="addGroup"
-                        title="Add"
-                        ref={addPolicyItemClickRef}
-                      >
-                        Add More
-                      </Button>
+                      {isAdmin ? (
+                        <Button
+                          className="btn btn-sm mt-2 mg-l-32 mb-5"
+                          type="button"
+                          onClick={() =>
+                            addPolicyItem("policyItems", undefined)
+                          }
+                          data-action="addGroup"
+                          data-cy="addGroup"
+                          title="Add"
+                          ref={addPolicyItemClickRef}
+                        >
+                          Add More
+                        </Button>
+                      ) : (
+                        <></>
+                      )}
 
                       {values?.conditions && !isEmpty(values.conditions) && (
                         <div className="gds-action-card mb-5 pl-0 pr-0">
@@ -685,7 +716,7 @@ function AccessGrantForm({ dataset, onDataChange, 
serviceCompDetails }) {
                           })}
                         </div>
                       )}
-                      {showModal && (
+                      {isAdmin && showModal && (
                         <Field
                           className="form-control"
                           name="conditions"
@@ -709,11 +740,15 @@ function AccessGrantForm({ dataset, onDataChange, 
serviceCompDetails }) {
                               <p className="gds-card-heading">
                                 Validity Period
                               </p>
-                              <PolicyValidityPeriodComp
-                                addPolicyItem={addPolicyItem}
-                                editValidityPeriod={true}
-                                isGDS={true}
-                              />
+                              {isAdmin ? (
+                                <PolicyValidityPeriodComp
+                                  addPolicyItem={addPolicyItem}
+                                  editValidityPeriod={true}
+                                  isGDS={true}
+                                />
+                              ) : (
+                                <></>
+                              )}
                             </div>
                             {validityPeriod.map((obj, index) => {
                               return (
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 95f06c93d..a08faba49 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
@@ -181,21 +181,46 @@ const DatasetDetailLayout = () => {
     DENIED: 0
   });
 
-  const fetchShareStatusMetrics = async () => {
+  const fetchShareStatusMetrics = async (requestSearchFilterParams) => {
     try {
       setLoader(true);
-      let params = {};
+      let requestList = [];
+      let params =
+        requestSearchFilterParams != undefined
+          ? { ...requestSearchFilterParams }
+          : {};
+      params["pageSize"] = 999999999;
       params["datasetId"] = datasetId;
-      const resp = await fetchApi({
-        url: `gds/dataset/summary`,
-        params: params
-      });
-      let datashareReqList = resp.data.list[0].dataShares;
+      try {
+        let 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 == datasetId) {
+                datashare.shareStatus = datashare.datasets[i].shareStatus;
+                datashare.requestId = datashare.datasets[i].id;
+                datashare.datasetName = datashare.datasets[i].datasetName;
+                break;
+              }
+            }
+          });
+        }
+      } catch (error) {
+        serverError(error);
+        console.error(
+          `Error occurred while fetching Datashare request metrics! ${error}`
+        );
+      }
+
       let activeCount = 0;
       let requestedCount = 0;
       let grantedCount = 0;
       let deniedCount = 0;
-      datashareReqList.forEach((request) => {
+      requestList.forEach((request) => {
         switch (request.shareStatus) {
           case "REQUESTED":
             requestedCount += 1;
@@ -212,7 +237,7 @@ const DatasetDetailLayout = () => {
         }
       });
       setShareStatusMetrics({
-        totalCount: datashareReqList.length,
+        totalCount: requestList.length,
         REQUESTED: requestedCount,
         GRANTED: grantedCount,
         ACTIVE: activeCount,
@@ -281,9 +306,9 @@ const DatasetDetailLayout = () => {
       type: "text"
     },
     {
-      category: "ZoneNamePartial",
+      category: "zoneNamePartial",
       label: "Zone",
-      urlLabel: "ZoneNamePartial",
+      urlLabel: "zoneNamePartial",
       type: "text"
     }
   ];
@@ -294,6 +319,7 @@ const DatasetDetailLayout = () => {
       requestSearchFilterOptions
     );
     setRequestSearchFilterParams(searchFilterParam);
+    fetchShareStatusMetrics(searchFilterParam);
   };
 
   useEffect(() => {
@@ -414,7 +440,7 @@ const DatasetDetailLayout = () => {
       const userMap = new Map();
       const groupMap = new Map();
       const roleMap = new Map();
-      grantItems.forEach((item) => {
+      grantItems?.forEach((item) => {
         if (item.users !== undefined) {
           item.users.forEach((user) => {
             let accessList = [];
@@ -748,7 +774,7 @@ const DatasetDetailLayout = () => {
   };
 
   const handleTabSelect = (key) => {
-    if (saveCancelButtons == true) {
+    if (saveCancelButtons == true && userAclPerm != "AUDIT") {
       setShowConfirmModal(true);
     } else {
       setActiveKey(key);
@@ -816,13 +842,15 @@ const DatasetDetailLayout = () => {
   };
 
   const handleAccessGrantChange = (accessGrantData, policyData) => {
-    if (accessGrantData != undefined) {
-      setAccessGrantFormValues(accessGrantData);
-    }
-    if (policyData != undefined) {
-      setPolicyData(policyData);
+    if (userAclPerm != "AUDIT") {
+      if (accessGrantData != undefined) {
+        setAccessGrantFormValues(accessGrantData);
+      }
+      if (policyData != undefined) {
+        setPolicyData(policyData);
+      }
+      showSaveCancelButton(true);
     }
-    showSaveCancelButton(true);
   };
 
   const updateDatasetAccessGrant = async () => {
@@ -1897,6 +1925,11 @@ const DatasetDetailLayout = () => {
                           dataset={datasetInfo}
                           onDataChange={handleAccessGrantChange}
                           serviceCompDetails={serviceDef}
+                          isAdmin={
+                            isSystemAdmin() ||
+                            userAclPerm == "ADMIN" ||
+                            userAclPerm == "POLICY_ADMIN"
+                          }
                         />
                       ) : (
                         <div></div>
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 326433e66..e3418ae64 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
@@ -31,6 +31,7 @@ import AsyncSelect from "react-select/async";
 import { fetchApi } from "../../../utils/fetchAPI";
 import { findIndex, remove } from "lodash";
 import { isSystemAdmin } from "../../../utils/XAUtils";
+import { toast } from "react-toastify";
 
 const initialState = {
   selectedPrinciple: []
@@ -90,16 +91,10 @@ const PrinciplePermissionComp = ({
     { value: "VIEW", label: "VIEW" },
     { value: "AUDIT", label: "AUDIT" },
     { value: "POLICY_ADMIN", label: "POLICY_ADMIN" },
-    { value: "ADMIN", label: "ADMIN" }
+    { value: "ADMIN", label: "ADMIN" },
+    { value: "Remove Access", label: "Remove Access" }
   ];
 
-  if (isAdmin) {
-    accessOptionsWithRemove.push({
-      value: "Remove Access",
-      label: "Remove Access"
-    });
-  }
-
   const selectedPrincipal = (e, input) => {
     dispatch({
       type: "SET_SELECTED_PRINCIPLE",
@@ -157,6 +152,10 @@ const PrinciplePermissionComp = ({
   };
 
   const addInSelectedPrincipal = (principle, input) => {
+    if (selectedAccess == undefined || selectedAccess.value == undefined) {
+      toast.error("Please select visibility!!");
+      return false;
+    }
     for (let i = 0; i < principle.length; i++) {
       let acl = { name: "", type: "", perm: "" };
       acl.name = principle[i].value;
@@ -352,19 +351,19 @@ const PrinciplePermissionComp = ({
         list[index]["perm"] = e.value;
         setUserList(list);
         setFilteredUserList(list);
-        tempUserList = [...tempUserList, ...list];
+        tempUserList = list;
       } else if (type == "GROUP") {
         let list = groupOgList;
         list[index]["perm"] = e.value;
         setGroupList(list);
         setFilteredGroupList(list);
-        tempGroupList = [...tempGroupList, ...list];
+        tempGroupList = list;
       } else if (type == "ROLE") {
         let list = roleOgList;
         list[index]["perm"] = e.value;
         setRoleList(list);
         setFilteredRoleList(list);
-        tempRoleList = [...tempRoleList, ...list];
+        tempRoleList = list;
       }
       input.onChange(e);
     }
@@ -436,13 +435,11 @@ const PrinciplePermissionComp = ({
                     userOgList;
                     if (
                       !selectedPrinciple ||
+                      selectedPrinciple[0] == undefined ||
                       selectedPrinciple[0].value == undefined ||
                       selectedPrinciple.length === 0
                     ) {
-                      toast.dismiss(toastId.current);
-                      toastId.current = toast.error(
-                        "Please select principal!!"
-                      );
+                      toast.error("Please select principal!!");
                       return false;
                     }
                     addInSelectedPrincipal(selectedPrinciple, input);
@@ -575,7 +572,6 @@ const PrinciplePermissionComp = ({
                                   { label: obj.perm, value: obj.perm }
                                 ]}
                                 isDisabled={isDetailView && !isAdmin}
-                                isClearable
                               />
                             )}
                           />
@@ -645,7 +641,6 @@ const PrinciplePermissionComp = ({
                                   { label: obj.perm, value: obj.perm }
                                 ]}
                                 isDisabled={isDetailView && !isAdmin}
-                                isClearable
                               />
                             )}
                           />
@@ -714,7 +709,6 @@ const PrinciplePermissionComp = ({
                                 defaultValue={[
                                   { label: obj.perm, value: obj.perm }
                                 ]}
-                                isClearable
                               />
                             )}
                           />
@@ -730,7 +724,11 @@ const PrinciplePermissionComp = ({
           </Accordion>
         </Card>
       </div>
-      <Modal show={showAddPrincipalModal} onHide={toggleAddPrincipalModal}>
+      <Modal
+        show={showAddPrincipalModal}
+        onHide={toggleAddPrincipalModal}
+        size="lg"
+      >
         <Modal.Header closeButton>
           <h3 className="gds-header bold">Add Principals</h3>
         </Modal.Header>
@@ -741,41 +739,43 @@ const PrinciplePermissionComp = ({
             render={({ input, meta }) => (
               <div>
                 <Modal.Body>
-                  <AsyncSelect
-                    {...input}
-                    className="flex-1 gds-text-input"
-                    onChange={(e) => selectedPrincipal(e, input)}
-                    value={selectedPrinciple}
-                    filterOption={filterPrincipleOp}
-                    loadOptions={fetchPrincipleOp}
-                    components={{
-                      DropdownIndicator: () => null,
-                      IndicatorSeparator: () => null
-                    }}
-                    defaultOptions
-                    isMulti
-                    placeholder="Type to select Principals"
-                    data-name="usersSelect"
-                    data-cy="usersSelect"
-                  />
-                  <Field
-                    name="accessPermList"
-                    className="form-control"
-                    render={({ input }) => (
-                      <Select
-                        {...input}
-                        theme={serviceSelectTheme}
-                        styles={customStyles}
-                        options={accessOptions}
-                        onChange={(e) => setACL(e, input)}
-                        ref={selectVisibilityLevelRef}
-                        //value={selectedAccess}
-                        menuPlacement="auto"
-                        isClearable
-                        placeholder="Visibility Level"
-                      />
-                    )}
-                  />
+                  <div className="d-flex gap-half">
+                    <AsyncSelect
+                      {...input}
+                      className="flex-1 gds-text-input"
+                      onChange={(e) => selectedPrincipal(e, input)}
+                      value={selectedPrinciple}
+                      filterOption={filterPrincipleOp}
+                      loadOptions={fetchPrincipleOp}
+                      components={{
+                        DropdownIndicator: () => null,
+                        IndicatorSeparator: () => null
+                      }}
+                      defaultOptions
+                      isMulti
+                      placeholder="Type to select Principals"
+                      data-name="usersSelect"
+                      data-cy="usersSelect"
+                    />
+                    <Field
+                      name="accessPermList"
+                      className="form-control"
+                      render={({ input }) => (
+                        <Select
+                          {...input}
+                          theme={serviceSelectTheme}
+                          styles={customStyles}
+                          options={accessOptions}
+                          onChange={(e) => setACL(e, input)}
+                          ref={selectVisibilityLevelRef}
+                          //value={selectedAccess}
+                          menuPlacement="auto"
+                          isClearable
+                          placeholder="Visibility Level"
+                        />
+                      )}
+                    />
+                  </div>
                 </Modal.Body>
                 <Modal.Footer>
                   <Button
@@ -792,6 +792,7 @@ const PrinciplePermissionComp = ({
                       userOgList;
                       if (
                         !selectedPrinciple ||
+                        selectedPrinciple[0] == undefined ||
                         selectedPrinciple[0].value == undefined ||
                         selectedPrinciple.length === 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 64819b502..30be71988 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
@@ -21,7 +21,7 @@ import React, { useState, useReducer } from "react";
 import { useNavigate } from "react-router-dom";
 import { Button, Form as FormB, Card } from "react-bootstrap";
 import Select from "react-select";
-import { groupBy } from "lodash";
+import { groupBy, filter } from "lodash";
 import AsyncSelect from "react-select/async";
 import { Form, Field } from "react-final-form";
 import { fetchApi } from "Utils/fetchAPI";
@@ -281,7 +281,7 @@ const AddDatashareView = () => {
         params: params
       });
     }
-    op = serviceResp.data;
+    op = filter(serviceResp.data, ["isTagService", false]);
     return op.map((obj) => ({
       label: obj.name,
       id: obj.id,
@@ -325,7 +325,8 @@ const AddDatashareView = () => {
           skipNavigate: true
         });
       }
-      return serviceResp.data.map(({ name, id, type }) => ({
+      let data = filter(serviceResp.data, ["isTagService", false]);
+      return data.map(({ name, id, type }) => ({
         label: name,
         id: id,
         def: type
@@ -632,12 +633,18 @@ const AddDatashareView = () => {
                             onFocus={() => {
                               onFocusServiceSelect();
                             }}
+                            components={{
+                              DropdownIndicator: () => null,
+                              IndicatorSeparator: () => null
+                            }}
                             value={selectedService}
                             loadOptions={filterServiceByName}
                             onChange={(e) => onServiceChange(e, input)}
                             isClearable={true}
                             placeholder="Select Service"
                             width="500px"
+                            data-name="serviceSelect"
+                            data-cy="serviceSelect"
                           />
                         </div>
                       )}
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 8d4a1b7d9..ecb14c7b2 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
@@ -37,6 +37,7 @@ import { groupBy, isArray, maxBy, find } from "lodash";
 import { toast } from "react-toastify";
 import moment from "moment-timezone";
 import { getServiceDef } from "../../../utils/appState";
+import { capitalizeFirstLetter } from "../../../utils/XAUtils";
 
 const AddSharedResourceComp = ({
   datashareId,
@@ -118,7 +119,7 @@ const AddSharedResourceComp = ({
     }
     if (obj?.accessTypes != undefined) {
       data.permission = obj.accessTypes.map((item) => ({
-        label: item,
+        label: capitalizeFirstLetter(item),
         value: item
       }));
     }
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 adbeca360..57630ea5c 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
@@ -49,20 +49,25 @@ import dateFormat from "dateformat";
 import { toast } from "react-toastify";
 import { BlockUi } from "../../../components/CommonComponents";
 import PrinciplePermissionComp from "../Dataset/PrinciplePermissionComp";
-import { Form } from "react-final-form";
+import { Form, Field } from "react-final-form";
 import arrayMutators from "final-form-arrays";
 import ReactPaginate from "react-paginate";
 import AddSharedResourceComp from "./AddSharedResourceComp";
 import CustomBreadcrumb from "../../CustomBreadcrumb";
+import PolicyConditionsComp from "../../PolicyListing/PolicyConditionsComp";
 import {
   isSystemAdmin,
   parseSearchFilter,
-  serverError
+  serverError,
+  policyConditionUpdatedJSON,
+  capitalizeFirstLetter
 } from "../../../utils/XAUtils";
 import XATableLayout from "../../../components/XATableLayout";
 import moment from "moment-timezone";
 import { getServiceDef } from "../../../utils/appState";
 import DatashareInDatasetListComp from "../Dataset/DatashareInDatasetListComp";
+import { isEmpty, isObject, isEqual } from "lodash";
+import Select from "react-select";
 
 const DatashareDetailLayout = () => {
   let { datashareId } = useParams();
@@ -72,6 +77,7 @@ const DatashareDetailLayout = () => {
   const [activeKey, setActiveKey] = useState("overview");
   const [datashareInfo, setDatashareInfo] = useState({});
   const [datashareDescription, setDatashareDescription] = useState();
+  const [datashareConditionExpr, setDatashareConditionExpr] = useState();
   const [datashareTerms, setDatashareTerms] = useState();
   const [loader, setLoader] = useState(true);
   const [resourceContentLoader, setResourceContentLoader] = useState(false);
@@ -113,6 +119,7 @@ const DatashareDetailLayout = () => {
   const [resourceSearchFilterParams, setResourceSearchFilterParams] = useState(
     []
   );
+  const [showModal, policyConditionState] = useState(false);
   const fetchIdRef = useRef(0);
   const [searchFilterParams, setSearchFilterParams] = useState([]);
   const [sharedResourceListData, setSharedResourceListData] = useState([]);
@@ -144,26 +151,54 @@ const DatashareDetailLayout = () => {
     ACTIVE: 0,
     DENIED: 0
   });
+  const [accessTypeOptions, setAccessTypeOptions] = useState([]);
+  const [accessType, setAccessType] = useState([]);
 
   useEffect(() => {
     fetchDatashareInfo(datashareId);
   }, []);
 
-  const fetchShareStatusMetrics = async () => {
+  const fetchShareStatusMetrics = async (requestSearchFilterOptions) => {
     try {
       setLoader(true);
-      let params = {};
+      let requestList = [];
+      let params =
+        requestSearchFilterParams != undefined
+          ? { ...requestSearchFilterOptions }
+          : {};
+      params["pageSize"] = 999999999;
       params["dataShareId"] = datashareId;
-      const resp = await fetchApi({
-        url: `gds/datashare/summary`,
-        params: params
-      });
-      let datasetReqList = resp.data.list[0].datasets;
+      try {
+        let 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 == datashareId) {
+                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;
+              }
+            }
+          });
+        }
+      } catch (error) {
+        serverError(error);
+        console.error(
+          `Error occurred while fetching Dataset request list! ${error}`
+        );
+      }
+
       let activeCount = 0;
       let requestedCount = 0;
       let grantedCount = 0;
       let deniedCount = 0;
-      datasetReqList.forEach((request) => {
+      requestList.forEach((request) => {
         switch (request.shareStatus) {
           case "REQUESTED":
             requestedCount += 1;
@@ -180,7 +215,7 @@ const DatashareDetailLayout = () => {
         }
       });
       setShareStatusMetrics({
-        totalCount: datasetReqList.length,
+        totalCount: requestList.length,
         REQUESTED: requestedCount,
         GRANTED: grantedCount,
         ACTIVE: activeCount,
@@ -194,6 +229,11 @@ const DatashareDetailLayout = () => {
     setLoader(false);
   };
 
+  const onAccessTypeChange = (event, input) => {
+    setAccessType(event);
+    input.onChange(event);
+  };
+
   const handleTabSelect = (key) => {
     if (saveCancelButtons == true) {
       setShowConfirmModal(true);
@@ -206,6 +246,18 @@ const DatashareDetailLayout = () => {
     }
   };
 
+  const DSpolicyConditions = [
+    {
+      itemId: 1,
+      name: "expression",
+      evaluator:
+        
"org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator",
+      evaluatorOptions: { engineName: "JavaScript", "ui.isMultiline": "true" },
+      label: "Enter boolean expression",
+      description: "Boolean expression"
+    }
+  ];
+
   const fetchDatashareInfo = async (datashareId) => {
     let datashareResp = {};
     let serviceResp = [];
@@ -219,15 +271,32 @@ const DatashareDetailLayout = () => {
       });
       const serviceDefs = getServiceDef();
       let serviceDef = serviceDefs?.allServiceDefs?.find((servicedef) => {
-        return servicedef.name == serviceResp.type;
+        return servicedef.name == serviceResp.data.type;
       });
       setServiceDef(serviceDef);
+      setAccessTypeOptions(
+        serviceDef.accessTypes.map(({ label, name: value }) => ({
+          label,
+          value
+        }))
+      );
     } catch (error) {
       setLoader(false);
       console.error(
         `Error occurred while fetching datashare details ! ${error}`
       );
     }
+    if (datashareResp.data.conditionExpr !== undefined) {
+      datashareResp.data.conditions = {
+        expression: datashareResp.data.conditionExpr
+      };
+    }
+    setAccessType(
+      datashareResp.data.defaultAccessTypes?.map((item) => ({
+        label: capitalizeFirstLetter(item),
+        value: item
+      }))
+    );
     setDatashareName(datashareResp.data.name);
     setService(serviceResp.data);
     setDatashareInfo(datashareResp.data);
@@ -431,6 +500,12 @@ const DatashareDetailLayout = () => {
     datashareInfo.name = datashareName;
     datashareInfo.description = datashareDescription;
     datashareInfo.termsOfUse = datashareTerms;
+    datashareInfo.conditionExpr = datashareConditionExpr;
+    datashareInfo.defaultAccessTypes = [];
+
+    accessType?.forEach((access) =>
+      datashareInfo.defaultAccessTypes.push(access.value)
+    );
 
     datashareInfo.acl = { users: {}, groups: {}, roles: {} };
 
@@ -454,12 +529,12 @@ const DatashareDetailLayout = () => {
         data: datashareInfo
       });
       toast.success("Datashare updated successfully!!");
-      isDatashareNameEditable(false);
-      showSaveCancelButton(false);
     } catch (error) {
       serverError(error);
       console.error(`Error occurred while updating datashare  ${error}`);
     }
+    isDatashareNameEditable(false);
+    showSaveCancelButton(false);
     setBlockUI(false);
     setShowConfirmModal(false);
   };
@@ -611,7 +686,7 @@ const DatashareDetailLayout = () => {
       requestSearchFilterOptions
     );
     setRequestSearchFilterParams(searchFilterParam);
-    //fetchDatashareRequestList(searchFilterParam, 0, false);
+    fetchShareStatusMetrics(searchFilterParam);
   };
 
   const fetchSharedResourcetList = useCallback(
@@ -723,7 +798,7 @@ const DatashareDetailLayout = () => {
                     title={accessObj}
                     key={accessObj}
                   >
-                    {accessObj}
+                    {capitalizeFirstLetter(accessObj)}
                   </span>
                 ))}
               </div>
@@ -738,7 +813,6 @@ const DatashareDetailLayout = () => {
         Cell: ({ row: { original } }) => {
           return (
             <div>
-              {console.log(serviceDef, "table")}
               {(isSystemAdmin() || userAclPerm == "ADMIN") && (
                 <div className="d-flex gap-half align-items-start">
                   {(isSystemAdmin() || userAclPerm == "ADMIN") && (
@@ -798,6 +872,26 @@ const DatashareDetailLayout = () => {
     setRequestActiveKey(key);
   };
 
+  const FormChange = (props) => {
+    const { isDirtyField, formValues } = props;
+    if (isDirtyField) {
+      setDatashareConditionExpr(props.formValues.conditions?.expression);
+      showSaveCancelButton(true);
+    }
+    return null;
+  };
+
+  const isDirtyFieldCheck = (values, initialValues) => {
+    let modifiedVal = false;
+    if (
+      !isEqual(values?.conditions, initialValues?.conditions) ||
+      !isEqual(values?.defaultAccessTypes, initialValues?.defaultAccessTypes)
+    ) {
+      modifiedVal = true;
+    }
+    return modifiedVal;
+  };
+
   return (
     <>
       <Form
@@ -805,7 +899,8 @@ const DatashareDetailLayout = () => {
         mutators={{
           ...arrayMutators
         }}
-        render={({}) => (
+        initialValues={datashareInfo}
+        render={({ values, dirty, initialValues }) => (
           <React.Fragment>
             <div
               className={
@@ -878,37 +973,36 @@ const DatashareDetailLayout = () => {
                   <span className="pipe" />
                 </>
               )}
-              {!datashareNameEditable ||
-                ((isSystemAdmin() ||
-                  userAclPerm == "ADMIN" ||
-                  userAclPerm == "POLICY_ADMIN") && (
-                  <div>
-                    {saveCancelButtons ? (
-                      <div className="gds-header-btn-grp">
-                        <Button
-                          variant="secondary"
-                          size="sm"
-                          onClick={() => removeChanges()}
-                          data-id="cancel"
-                          data-cy="cancel"
-                        >
-                          Cancel
-                        </Button>
-                        <Button
-                          variant="primary"
-                          onClick={updateDatashareDetails}
-                          size="sm"
-                          data-id="save"
-                          data-cy="save"
-                        >
-                          Save
-                        </Button>
-                      </div>
-                    ) : (
-                      <p></p>
-                    )}
-                  </div>
-                ))}
+              {(isSystemAdmin() ||
+                userAclPerm == "ADMIN" ||
+                userAclPerm == "POLICY_ADMIN") && (
+                <div>
+                  {saveCancelButtons ? (
+                    <div className="gds-header-btn-grp">
+                      <Button
+                        variant="secondary"
+                        size="sm"
+                        onClick={() => removeChanges()}
+                        data-id="cancel"
+                        data-cy="cancel"
+                      >
+                        Cancel
+                      </Button>
+                      <Button
+                        variant="primary"
+                        onClick={updateDatashareDetails}
+                        size="sm"
+                        data-id="save"
+                        data-cy="save"
+                      >
+                        Save
+                      </Button>
+                    </div>
+                  ) : (
+                    <p></p>
+                  )}
+                </div>
+              )}
 
               {!datashareNameEditable && !saveCancelButtons && (
                 <div>
@@ -976,6 +1070,14 @@ const DatashareDetailLayout = () => {
                     <Tab eventKey="overview" title="OVERVIEW">
                       {activeKey == "overview" ? (
                         <div>
+                          <FormChange
+                            isDirtyField={
+                              dirty == true || !isEqual(initialValues, values)
+                                ? isDirtyFieldCheck(values, initialValues)
+                                : false
+                            }
+                            formValues={values}
+                          />
                           <div className="gds-tab-content gds-content-border 
px-3">
                             <div className="gds-inline-field-grp">
                               <div className="wrapper">
@@ -1045,6 +1147,133 @@ const DatashareDetailLayout = () => {
                               </div>
                             </div>
                           </div>
+
+                          <div className="gds-action-card mb-5 gds-tab-content 
gds-content-border px-3">
+                            <div
+                              className={
+                                values.conditions == undefined
+                                  ? "gds-section-title border-0 p-0"
+                                  : "gds-section-title"
+                              }
+                            >
+                              <p className="gds-card-heading">
+                                Default Condition
+                              </p>
+                              {isSystemAdmin() || userAclPerm == "ADMIN" ? (
+                                <Button
+                                  className="btn btn-sm"
+                                  onClick={() => {
+                                    policyConditionState(true);
+                                  }}
+                                  data-js="customPolicyConditions"
+                                  data-cy="customPolicyConditions"
+                                  variant="secondary"
+                                >
+                                  {values.conditions !== undefined
+                                    ? "Modify Condition"
+                                    : "Set Condition"}
+                                </Button>
+                              ) : (
+                                <></>
+                              )}
+                            </div>
+                            {values.conditions !== undefined &&
+                              Object.keys(values.conditions).map((keyName) => {
+                                if (
+                                  values.conditions[keyName] != "" &&
+                                  values.conditions[keyName] != null
+                                ) {
+                                  let conditionObj = find(
+                                    DSpolicyConditions,
+                                    function (m) {
+                                      if (m.name == keyName) {
+                                        return m;
+                                      }
+                                    }
+                                  );
+                                  return (
+                                    <div className="pt-3">
+                                      {isObject(values.conditions[keyName]) ? (
+                                        <div>
+                                          <span className="fnt-14">
+                                            {values.conditions[keyName].length 
>
+                                            1
+                                              ? values.conditions[keyName].map(
+                                                  (m) => {
+                                                    return ` ${m.label} `;
+                                                  }
+                                                )
+                                              : values.conditions[keyName]
+                                                  .label}
+                                          </span>
+                                        </div>
+                                      ) : (
+                                        <div>
+                                          <span className="fnt-14">
+                                            {values.conditions[keyName]}
+                                          </span>
+                                        </div>
+                                      )}
+                                    </div>
+                                  );
+                                }
+                              })}
+                          </div>
+
+                          {showModal && (
+                            <Field
+                              className="form-control"
+                              name="conditions"
+                              render={({ input }) => (
+                                <PolicyConditionsComp
+                                  
policyConditionDetails={policyConditionUpdatedJSON(
+                                    DSpolicyConditions
+                                  )}
+                                  inputVal={input}
+                                  showModal={showModal}
+                                  handleCloseModal={policyConditionState}
+                                />
+                              )}
+                            />
+                          )}
+
+                          <div className="gds-action-card mb-5 gds-tab-content 
gds-content-border px-3">
+                            <div className="gds-section-title">
+                              <p className="gds-card-heading">
+                                Default access types:
+                              </p>
+                            </div>
+                            <div className="gds-flex mg-b-10 mg-t-20">
+                              <div className="w-100">
+                                <Field
+                                  name={`defaultAccessTypes`}
+                                  render={({ input, meta }) => (
+                                    <div>
+                                      <Select
+                                        {...input}
+                                        className="w-100"
+                                        options={accessTypeOptions}
+                                        onChange={(e) =>
+                                          onAccessTypeChange(e, input)
+                                        }
+                                        menuPortalTarget={document.body}
+                                        value={accessType}
+                                        isDisabled={
+                                          !isSystemAdmin() &&
+                                          userAclPerm != "ADMIN"
+                                        }
+                                        menuPlacement="auto"
+                                        placeholder="All Permissions"
+                                        isClearable
+                                        isMulti
+                                      />
+                                    </div>
+                                  )}
+                                />
+                              </div>
+                            </div>
+                          </div>
+
                           {(isSystemAdmin() || userAclPerm != "VIEW") && (
                             <PrinciplePermissionComp
                               userList={userList}

Reply via email to