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 2f7f76261 RANGER-4283: GDS UI - updated request listing page, created 
history tab in dataset and datashare detail view
2f7f76261 is described below

commit 2f7f76261b579ffb5b672f9f052fd51efb3a8ddc
Author: Anand Nadar <[email protected]>
AuthorDate: Mon Jan 8 07:47:42 2024 -0800

    RANGER-4283: GDS UI - updated request listing page, created history tab in 
dataset and datashare detail view
    
    Signed-off-by: Madhan Neethiraj <[email protected]>
---
 .../react-webapp/src/images/history-details.svg    |   1 +
 .../GovernedData/Dataset/DatasetDetailLayout.jsx   | 206 ++++++++++++++++-
 .../GovernedData/Datashare/AddDatashareView.jsx    |  23 ++
 .../Datashare/AddSharedResourceComp.jsx            |   2 +
 .../Datashare/DatashareDetailLayout.jsx            | 247 +++++++++++++++++++--
 .../GovernedData/Datashare/MyDatashareListing.jsx  |   8 +-
 .../views/GovernedData/Request/RequestListing.jsx  | 151 ++++++++++---
 7 files changed, 567 insertions(+), 71 deletions(-)

diff --git 
a/security-admin/src/main/webapp/react-webapp/src/images/history-details.svg 
b/security-admin/src/main/webapp/react-webapp/src/images/history-details.svg
new file mode 100644
index 000000000..ce012c1dd
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/images/history-details.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; height="24" viewBox="0 -960 960 960" 
width="24"><path d="M324.616-184.617q-24.75 
0-42.374-17.625-17.625-17.624-17.625-42.374v-99.998h115.384v-110.002q-36.538 
3.001-72.269-8.961-35.731-11.961-61.731-38.577v-50.154h-51.385L73.847-673.076q35.231-38.692
 83.615-55.961 48.384-17.269 98.538-17.269 32.725 0 63.632 7.461 30.908 7.462 
60.369 24.616v-64.231h439.998v493.844q0 41.923-29.038 70.961-29.039 
29.038-70.961 29.038H324.616ZM440-344.614h240v59.998q0 17 [...]
\ No newline at end of file
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 a08faba49..cba038c8b 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
@@ -17,10 +17,18 @@
  * under the License.
  */
 
-import React, { useState, useEffect, useCallback, useReducer } from "react";
+import React, {
+  useState,
+  useEffect,
+  useCallback,
+  useReducer,
+  useRef
+} from "react";
 import withRouter from "Hooks/withRouter";
 import { fetchApi } from "../../../utils/fetchAPI";
 import dateFormat from "dateformat";
+import XATableLayout from "../../../components/XATableLayout";
+import { ClassTypes } from "../../../utils/XAEnums";
 import {
   Button,
   Tab,
@@ -44,6 +52,8 @@ import {
   useSearchParams
 } from "react-router-dom";
 import {
+  getTableSortBy,
+  getTableSortType,
   serverError,
   isSystemAdmin,
   parseSearchFilter
@@ -52,6 +62,7 @@ import Select from "react-select";
 import userColourIcon from "../../../images/user-colour.svg";
 import groupColourIcon from "../../../images/group-colour.svg";
 import roleColourIcon from "../../../images/role-colour.svg";
+import historyDetailsIcon from "../../../images/history-details.svg";
 import arrayMutators from "final-form-arrays";
 import { groupBy, isEmpty, isArray } from "lodash";
 import PrinciplePermissionComp from "./PrinciplePermissionComp";
@@ -59,6 +70,7 @@ import ReactPaginate from "react-paginate";
 import CustomBreadcrumb from "../../CustomBreadcrumb";
 import ErrorPage from "../../../views/ErrorPage";
 import DatashareInDatasetListComp from "./DatashareInDatasetListComp";
+import OperationAdminModal from "../../AuditEvent/OperationAdminModal";
 
 const initialState = {
   loader: false,
@@ -180,6 +192,19 @@ const DatasetDetailLayout = () => {
     ACTIVE: 0,
     DENIED: 0
   });
+  const [searchHistoryFilterParams, setSearchHistoryFilterParams] = useState(
+    []
+  );
+  const fetchIdRef = useRef(0);
+  const [historyListData, setHistoryListData] = useState([]);
+  const [historyLoader, setHistoryLoader] = useState(false);
+  const [entries, setEntries] = useState([]);
+  const [pageCount, setPageCount] = useState(
+    state && state.showLastPage ? state.addPageData.totalPage : 0
+  );
+  const [showrowmodal, setShowRowModal] = useState(false);
+  const [rowdata, setRowData] = useState([]);
+  const handleClosed = () => setShowRowModal(false);
 
   const fetchShareStatusMetrics = async (requestSearchFilterParams) => {
     try {
@@ -292,6 +317,124 @@ const DatasetDetailLayout = () => {
     return data;
   };
 
+  const historySearchFilterOptions = [
+    {
+      category: "owner",
+      label: "User",
+      urlLabel: "owner",
+      type: "text"
+    }
+  ];
+
+  const updateHistorySearchFilter = (filter) => {
+    let { searchFilterParam, searchParam } = parseSearchFilter(
+      filter,
+      historySearchFilterOptions
+    );
+    setSearchHistoryFilterParams(searchFilterParam);
+  };
+
+  const fetchHistoryList = useCallback(
+    async ({ pageSize, pageIndex, sortBy, gotoPage }) => {
+      setHistoryLoader(true);
+      let resp = [];
+      let historyList = [];
+      let totalCount = 0;
+      let page =
+        state && state.showLastPage
+          ? state.addPageData.totalPage - 1
+          : pageIndex;
+      let totalPageCount = 0;
+      const fetchId = ++fetchIdRef.current;
+      let params = { ...searchHistoryFilterParams };
+      if (fetchId === fetchIdRef.current) {
+        params["pageSize"] = pageSize;
+        params["startIndex"] =
+          state && state.showLastPage
+            ? (state.addPageData.totalPage - 1) * pageSize
+            : pageIndex * pageSize;
+        if (sortBy.length > 0) {
+          params["sortBy"] = getTableSortBy(sortBy);
+          params["sortType"] = getTableSortType(sortBy);
+        }
+        params["objectClassType"] = ClassTypes.CLASS_TYPE_RANGER_DATASET.value;
+        params["objectId"] = datasetId;
+        try {
+          resp = await fetchApi({
+            url: "assets/report",
+            params: params
+          });
+          historyList = resp.data.vXTrxLogs;
+          totalCount = resp.data.totalCount;
+        } catch (error) {
+          serverError(error);
+          console.error(
+            `Error occurred while fetching Dataset History! ${error}`
+          );
+        }
+        setHistoryListData(historyList);
+        setEntries(resp.data);
+        setPageCount(Math.ceil(totalCount / pageSize));
+        //setResetpage({ page: gotoPage });
+        setHistoryLoader(false);
+      }
+    },
+    [searchHistoryFilterParams]
+  );
+
+  const openOperationalModal = async (row) => {
+    setShowRowModal(true);
+    setRowData(row);
+  };
+
+  const historyColumns = React.useMemo(
+    () => [
+      {
+        Header: "Time",
+        accessor: "createDate",
+        Cell: (rawValue) => {
+          return dateFormat(rawValue.value, "mm/dd/yyyy h:MM:ss TT");
+        },
+        width: 170,
+        disableResizing: true,
+        getResizerProps: () => {}
+      },
+      {
+        Header: "User",
+        accessor: "owner",
+        width: 650,
+        disableResizing: true,
+        disableSortBy: true,
+        getResizerProps: () => {}
+      },
+      {
+        Header: "",
+        accessor: "actions",
+        width: 30,
+        Cell: ({ row: { original } }) => {
+          return (
+            <div className="d-flex gap-half align-items-start">
+              <div className="d-flex gap-half align-items-start">
+                <Button
+                  variant="outline-dark"
+                  size="sm"
+                  title="showDetails"
+                  onClick={() => openOperationalModal(original)}
+                  data-name="showDetails"
+                  data-id="showDetails"
+                >
+                  <img src={historyDetailsIcon} height="30px" width="30px" />
+                </Button>
+              </div>
+            </div>
+          );
+        },
+        disableSortBy: true
+      }
+    ],
+    []
+  );
+
   const requestSearchFilterOptions = [
     {
       category: "dataShareNamePartial",
@@ -1278,6 +1421,16 @@ const DatasetDetailLayout = () => {
     }
   };
 
+  const getDefaultSort = React.useMemo(
+    () => [
+      {
+        id: "createdDate",
+        desc: true
+      }
+    ],
+    []
+  );
+
   return (
     <>
       <React.Fragment>
@@ -1938,12 +2091,45 @@ const DatasetDetailLayout = () => {
                   </Tab>
                 )}
 
-                {false &&
-                  (isSystemAdmin() ||
-                    userAclPerm === "ADMIN" ||
-                    userAclPerm === "AUDIT") && (
-                    <Tab eventKey="history" title="HISTORY" />
-                  )}
+                {(isSystemAdmin() ||
+                  userAclPerm === "ADMIN" ||
+                  userAclPerm === "AUDIT") && (
+                  <Tab eventKey="history" title="HISTORY">
+                    {activeKey == "history" && (
+                      <div className="gds-request-content">
+                        <div className="mb-3">
+                          <div className="usr-grp-role-search-width mb-3 
mg-t-20">
+                            <StructuredFilter
+                              key="dataset-history-search-filter"
+                              placeholder="Search..."
+                              onChange={updateHistorySearchFilter}
+                              options={historySearchFilterOptions}
+                            />
+                          </div>
+                          <div className="gds-header-btn-grp"></div>
+                        </div>
+                        <XATableLayout
+                          data={historyListData}
+                          columns={historyColumns}
+                          fetchData={fetchHistoryList}
+                          totalCount={entries && entries.totalCount}
+                          loading={historyLoader}
+                          pageCount={pageCount}
+                          getRowProps={(row) => ({
+                            onClick: (e) => {
+                              e.stopPropagation();
+                              // rowModal(row);
+                            }
+                          })}
+                          columnHide={false}
+                          columnResizable={false}
+                          columnSort={true}
+                          defaultSort={getDefaultSort}
+                        />
+                      </div>
+                    )}
+                  </Tab>
+                )}
 
                 <Tab
                   eventKey="termsOfUse"
@@ -2179,6 +2365,12 @@ const DatasetDetailLayout = () => {
                 </Button>
               </Modal.Footer>
             </Modal>
+
+            <OperationAdminModal
+              show={showrowmodal}
+              data={rowdata}
+              onHide={handleClosed}
+            ></OperationAdminModal>
           </React.Fragment>
         )}
       </React.Fragment>
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 30be71988..4306864cb 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
@@ -196,6 +196,27 @@ const AddDatashareView = () => {
     }
   };
 
+  const serviceSelectTheme = (theme) => {
+    return {
+      ...theme,
+      colors: {
+        ...theme.colors,
+        primary: "#0081ab"
+      }
+    };
+  };
+
+  const customStyles = {
+    control: (provided) => ({
+      ...provided,
+      maxHeight: "40px",
+      width: "172px"
+    }),
+    indicatorsContainer: (provided) => ({
+      ...provided
+    })
+  };
+
   const fetchServiceDef = async (serviceDefName) => {
     let serviceDefsResp = [];
     try {
@@ -633,6 +654,8 @@ const AddDatashareView = () => {
                             onFocus={() => {
                               onFocusServiceSelect();
                             }}
+                            // theme={serviceSelectTheme}
+                            // styles={customStyles}
                             components={{
                               DropdownIndicator: () => null,
                               IndicatorSeparator: () => null
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 ecb14c7b2..23c34d2e7 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
@@ -209,6 +209,8 @@ const AddSharedResourceComp = ({
             ? values[`value-${level}`]?.map(({ value }) => value)
             : [values[`value-${level}`].value]
         };
+        data.resource[values[`resourceName-${level}`].name]["isRecursive"] =
+          values[`resourceName-${level}`].recursiveSupported;
       }
     }
     data.conditionExpr = values.booleanExpression;
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 57630ea5c..dfa3d4027 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
@@ -56,6 +56,8 @@ import AddSharedResourceComp from "./AddSharedResourceComp";
 import CustomBreadcrumb from "../../CustomBreadcrumb";
 import PolicyConditionsComp from "../../PolicyListing/PolicyConditionsComp";
 import {
+  getTableSortBy,
+  getTableSortType,
   isSystemAdmin,
   parseSearchFilter,
   serverError,
@@ -68,11 +70,14 @@ import { getServiceDef } from "../../../utils/appState";
 import DatashareInDatasetListComp from "../Dataset/DatashareInDatasetListComp";
 import { isEmpty, isObject, isEqual } from "lodash";
 import Select from "react-select";
+import OperationAdminModal from "../../AuditEvent/OperationAdminModal";
+import historyDetailsIcon from "../../../images/history-details.svg";
+import { ClassTypes } from "../../../utils/XAEnums";
 
 const DatashareDetailLayout = () => {
   let { datashareId } = useParams();
   const { state } = useLocation();
-  const userAclPerm = state?.userAclPerm;
+  const userAclPerm = state == null ? fetchDatashareSummary : 
state.userAclPerm;
   const [datashareName, setDatashareName] = useState(state?.datashareName);
   const [activeKey, setActiveKey] = useState("overview");
   const [datashareInfo, setDatashareInfo] = useState({});
@@ -153,11 +158,55 @@ const DatashareDetailLayout = () => {
   });
   const [accessTypeOptions, setAccessTypeOptions] = useState([]);
   const [accessType, setAccessType] = useState([]);
+  const [cancel, setCancel] = useState(true);
+  let cancelFlag = false;
+  let saveFlag = false;
+  const [showrowmodal, setShowRowModal] = useState(false);
+  const [rowdata, setRowData] = useState([]);
+  const handleClosed = () => setShowRowModal(false);
+  const [searchHistoryFilterParams, setSearchHistoryFilterParams] = useState(
+    []
+  );
+  const [historyListData, setHistoryListData] = useState([]);
+  const [historyEntries, setHistoryEntries] = useState([]);
+  const [historyLoader, setHistoryLoader] = useState(false);
+  const [pageCount, setPageCount] = useState(
+    state && state.showLastPage ? state.addPageData.totalPage : 0
+  );
+
+  const fetchDatashareSummary = async () => {
+    setLoader(false);
+    let resp = [];
+    let params = { ...searchFilterParams };
+    params["dataShareId"] = dataShareId;
+    try {
+      resp = await fetchApi({
+        url: "gds/datashare/summary",
+        params: params
+      });
+      return resp.data.list[0].permissionForCaller;
+    } catch (error) {
+      serverError(error);
+      console.error(
+        `Error occurred while fetching Datashare summary! ${error}`
+      );
+    }
+    setLoader(false);
+  };
 
   useEffect(() => {
     fetchDatashareInfo(datashareId);
   }, []);
 
+  const historySearchFilterOptions = [
+    {
+      category: "owner",
+      label: "User",
+      urlLabel: "owner",
+      type: "text"
+    }
+  ];
+
   const fetchShareStatusMetrics = async (requestSearchFilterOptions) => {
     try {
       setLoader(true);
@@ -231,6 +280,7 @@ const DatashareDetailLayout = () => {
 
   const onAccessTypeChange = (event, input) => {
     setAccessType(event);
+    showSaveCancelButton(true);
     input.onChange(event);
   };
 
@@ -239,7 +289,6 @@ const DatashareDetailLayout = () => {
       setShowConfirmModal(true);
     } else {
       if (key == "sharedWith") {
-        //fetchDatashareRequestList(undefined, 0, false);
         fetchShareStatusMetrics();
       }
       setActiveKey(key);
@@ -286,11 +335,12 @@ const DatashareDetailLayout = () => {
         `Error occurred while fetching datashare details ! ${error}`
       );
     }
-    if (datashareResp.data.conditionExpr !== undefined) {
+    if (datashareResp?.data?.conditionExpr !== undefined) {
       datashareResp.data.conditions = {
         expression: datashareResp.data.conditionExpr
       };
     }
+    setDatashareConditionExpr(datashareResp.data.conditionExpr);
     setAccessType(
       datashareResp.data.defaultAccessTypes?.map((item) => ({
         label: capitalizeFirstLetter(item),
@@ -535,12 +585,15 @@ const DatashareDetailLayout = () => {
     }
     isDatashareNameEditable(false);
     showSaveCancelButton(false);
+    saveFlag = true;
     setBlockUI(false);
     setShowConfirmModal(false);
   };
 
   const removeChanges = () => {
     fetchDatashareInfo(datashareId);
+    cancelFlag = true;
+    setCancel(true);
     showSaveCancelButton(false);
     setShowConfirmModal(false);
     isDatashareNameEditable(false);
@@ -689,6 +742,68 @@ const DatashareDetailLayout = () => {
     fetchShareStatusMetrics(searchFilterParam);
   };
 
+  const updateHistorySearchFilter = (filter) => {
+    let { searchFilterParam, searchParam } = parseSearchFilter(
+      filter,
+      historySearchFilterOptions
+    );
+    setSearchHistoryFilterParams(searchFilterParam);
+  };
+
+  const openOperationalModal = async (row) => {
+    setShowRowModal(true);
+    setRowData(row);
+  };
+
+  const fetchHistoryList = useCallback(
+    async ({ pageSize, pageIndex, sortBy, gotoPage }) => {
+      setHistoryLoader(true);
+      let resp = [];
+      let historyList = [];
+      let totalCount = 0;
+      let page =
+        state && state.showLastPage
+          ? state.addPageData.totalPage - 1
+          : pageIndex;
+      let totalPageCount = 0;
+      const fetchId = ++fetchIdRef.current;
+      let params = { ...searchHistoryFilterParams };
+      if (fetchId === fetchIdRef.current) {
+        params["pageSize"] = pageSize;
+        params["startIndex"] =
+          state && state.showLastPage
+            ? (state.addPageData.totalPage - 1) * pageSize
+            : pageIndex * pageSize;
+        if (sortBy.length > 0) {
+          params["sortBy"] = getTableSortBy(sortBy);
+          params["sortType"] = getTableSortType(sortBy);
+        }
+        params["objectClassType"] =
+          ClassTypes.CLASS_TYPE_RANGER_DATA_SHARE.value;
+        params["objectId"] = datashareId;
+        try {
+          resp = await fetchApi({
+            url: "assets/report",
+            params: params
+          });
+          historyList = resp.data.vXTrxLogs;
+          totalCount = resp.data.totalCount;
+        } catch (error) {
+          serverError(error);
+          console.error(
+            `Error occurred while fetching Datashare History! ${error}`
+          );
+        }
+        setHistoryListData(historyList);
+        setHistoryEntries(resp.data);
+        setPageCount(Math.ceil(totalCount / pageSize));
+        //setResetpage({ page: gotoPage });
+        setHistoryLoader(false);
+      }
+    },
+    [searchHistoryFilterParams]
+  );
+
   const fetchSharedResourcetList = useCallback(
     async ({ pageSize, pageIndex }) => {
       setResourceContentLoader(true);
@@ -874,7 +989,7 @@ const DatashareDetailLayout = () => {
 
   const FormChange = (props) => {
     const { isDirtyField, formValues } = props;
-    if (isDirtyField) {
+    if (isDirtyField && (!cancelFlag || !saveFlag)) {
       setDatashareConditionExpr(props.formValues.conditions?.expression);
       showSaveCancelButton(true);
     }
@@ -884,14 +999,64 @@ const DatashareDetailLayout = () => {
   const isDirtyFieldCheck = (values, initialValues) => {
     let modifiedVal = false;
     if (
-      !isEqual(values?.conditions, initialValues?.conditions) ||
-      !isEqual(values?.defaultAccessTypes, initialValues?.defaultAccessTypes)
+      values?.conditions?.expression &&
+      !isEqual(values?.conditions?.expression, datashareConditionExpr)
     ) {
       modifiedVal = true;
+      saveFlag = false;
+      cancelFlag = false;
     }
     return modifiedVal;
   };
 
+  const historyColumns = React.useMemo(
+    () => [
+      {
+        Header: "Time",
+        accessor: "createDate",
+        Cell: (rawValue) => {
+          return dateFormat(rawValue.value, "mm/dd/yyyy h:MM:ss TT");
+        },
+        width: 170,
+        disableResizing: true,
+        getResizerProps: () => {}
+      },
+      {
+        Header: "User",
+        accessor: "owner",
+        width: 650,
+        disableResizing: true,
+        disableSortBy: true,
+        getResizerProps: () => {}
+      },
+      {
+        Header: "",
+        accessor: "actions",
+        width: 30,
+        Cell: ({ row: { original } }) => {
+          return (
+            <div className="d-flex gap-half align-items-start">
+              <div className="d-flex gap-half align-items-start">
+                <Button
+                  variant="outline-dark"
+                  size="sm"
+                  title="showDetails"
+                  onClick={() => openOperationalModal(original)}
+                  data-name="showDetails"
+                  data-id="showDetails"
+                >
+                  <img src={historyDetailsIcon} height="30px" width="30px" />
+                </Button>
+              </div>
+            </div>
+          );
+        },
+        disableSortBy: true
+      }
+    ],
+    []
+  );
+
   return (
     <>
       <Form
@@ -1070,14 +1235,17 @@ const DatashareDetailLayout = () => {
                     <Tab eventKey="overview" title="OVERVIEW">
                       {activeKey == "overview" ? (
                         <div>
-                          <FormChange
-                            isDirtyField={
-                              dirty == true || !isEqual(initialValues, values)
-                                ? isDirtyFieldCheck(values, initialValues)
-                                : false
-                            }
-                            formValues={values}
-                          />
+                          {!cancelFlag && !saveFlag && (
+                            <FormChange
+                              isDirtyField={
+                                dirty == !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">
@@ -1240,7 +1408,7 @@ const DatashareDetailLayout = () => {
                           <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:
+                                Default access types
                               </p>
                             </div>
                             <div className="gds-flex mg-b-10 mg-t-20">
@@ -1298,7 +1466,7 @@ const DatashareDetailLayout = () => {
                       {activeKey == "resources" ? (
                         <div className="gds-request-content">
                           <div className="mb-3">
-                            <div className="w-100 d-flex gap-1 mb-3">
+                            <div className="w-100 d-flex gap-1 mb-3 mg-t-20">
                               <StructuredFilter
                                 key="shared-reource-search-filter"
                                 placeholder="Search resources..."
@@ -1480,12 +1648,41 @@ const DatashareDetailLayout = () => {
                       )}
                     </Tab>
 
-                    {false &&
-                      (isSystemAdmin() ||
-                        userAclPerm == "ADMIN" ||
-                        userAclPerm == "AUDIT") && (
-                        <Tab eventKey="history" title="HISTORY"></Tab>
-                      )}
+                    {(isSystemAdmin() ||
+                      userAclPerm == "ADMIN" ||
+                      userAclPerm == "AUDIT") && (
+                      <Tab eventKey="history" title="HISTORY">
+                        {activeKey == "history" && (
+                          <div className="gds-request-content">
+                            <div className="mb-3">
+                              <div className="usr-grp-role-search-width mb-3 
mg-t-20">
+                                <StructuredFilter
+                                  key="dataset-history-search-filter"
+                                  placeholder="Search..."
+                                  onChange={updateHistorySearchFilter}
+                                  options={historySearchFilterOptions}
+                                />
+                              </div>
+                              <div className="gds-header-btn-grp"></div>
+                            </div>
+                            <XATableLayout
+                              data={historyListData}
+                              columns={historyColumns}
+                              fetchData={fetchHistoryList}
+                              totalCount={
+                                historyEntries && historyEntries.totalCount
+                              }
+                              loading={historyLoader}
+                              pageCount={pageCount}
+                              columnHide={false}
+                              columnResizable={false}
+                              columnSort={true}
+                              defaultSort={getDefaultSort}
+                            />
+                          </div>
+                        )}
+                      </Tab>
+                    )}
 
                     <Tab eventKey="termsOfUse" title="TERMS OF USE">
                       <div className="gds-tab-content gds-content-border">
@@ -1689,6 +1886,12 @@ const DatashareDetailLayout = () => {
                   setResourceUpdateTable={setResourceUpdateTable}
                   resourceModalUpdateTable={resourceModalUpdateTable}
                 />
+
+                <OperationAdminModal
+                  show={showrowmodal}
+                  data={rowdata}
+                  onHide={handleClosed}
+                ></OperationAdminModal>
               </React.Fragment>
             )}
             <BlockUi isUiBlock={blockUI} />
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/MyDatashareListing.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/MyDatashareListing.jsx
index 15c3d5688..bf6732b17 100755
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/MyDatashareListing.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/MyDatashareListing.jsx
@@ -22,19 +22,13 @@ import XATableLayout from 
"../../../components/XATableLayout";
 import { Loader } from "../../../components/CommonComponents";
 import { Button, Row, Col } from "react-bootstrap";
 import StructuredFilter from 
"../../../components/structured-filter/react-typeahead/tokenizer";
-import {
-  useSearchParams,
-  useNavigate,
-  useLocation,
-  Link
-} from "react-router-dom";
+import { useSearchParams, useNavigate, useLocation } from "react-router-dom";
 import { fetchApi } from "../../../utils/fetchAPI";
 import dateFormat from "dateformat";
 import {
   getTableSortBy,
   getTableSortType,
   serverError,
-  isSystemAdmin,
   parseSearchFilter
 } from "../../../utils/XAUtils";
 import moment from "moment-timezone";
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestListing.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestListing.jsx
index b29b900a0..2ba7bc51a 100755
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestListing.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestListing.jsx
@@ -18,23 +18,19 @@
  */
 
 import React, { useState, useEffect, useCallback, useRef } from "react";
-import { useNavigate, useLocation } from "react-router-dom";
+import { useNavigate, useLocation, useSearchParams } from "react-router-dom";
 import { Row, Col, Button } from "react-bootstrap";
 import StructuredFilter from 
"../../../components/structured-filter/react-typeahead/tokenizer";
 import XATableLayout from "../../../components/XATableLayout";
 import { fetchApi } from "../../../utils/fetchAPI";
 import dateFormat from "dateformat";
-import {
-  CustomTooltip,
-  Loader,
-  BlockUi
-} from "../../../components/CommonComponents";
-import moment from "moment-timezone";
+import { Loader, BlockUi } from "../../../components/CommonComponents";
 import CustomBreadcrumb from "../../CustomBreadcrumb";
 import {
   getTableSortBy,
   getTableSortType,
-  serverError
+  serverError,
+  parseSearchFilter
 } from "../../../utils/XAUtils";
 
 const RequestListing = () => {
@@ -51,6 +47,78 @@ const RequestListing = () => {
     state && state.showLastPage ? state.addPageData.totalPage : 0
   );
   const { state } = useLocation();
+  const [searchParams, setSearchParams] = useSearchParams();
+  const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
+    []
+  );
+
+  const searchFilterOptions = [
+    {
+      category: "dataShareNamePartial",
+      label: "Datashare Name",
+      urlLabel: "dataShareNamePartial",
+      type: "text"
+    },
+    {
+      category: "datasetNamePartial",
+      label: "Dataset Name",
+      urlLabel: "datasetNamePartial",
+      type: "text"
+    },
+    {
+      category: "shareStatus",
+      label: "Status",
+      urlLabel: "shareStatus",
+      type: "textoptions",
+      options: () => {
+        return [
+          { value: "REQUESTED", label: "REQUESTED" },
+          { value: "GRANTED", label: "GRANTED" },
+          { value: "ACTIVE", label: "ACTIVE" },
+          { value: "DENIED", label: "DENIED" }
+        ];
+      }
+    },
+    {
+      category: "createdBy",
+      label: "Requested By",
+      urlLabel: "createdBy",
+      type: "text"
+    },
+    {
+      category: "approver",
+      label: "Approved By",
+      urlLabel: "approver",
+      type: "text"
+    }
+  ];
+
+  useEffect(() => {
+    let searchFilterParam = {};
+    let searchParam = {};
+    let defaultSearchFilterParam = [];
+
+    // Get Search Filter Params from current search params
+    const currentParams = Object.fromEntries([...searchParams]);
+    for (const param in currentParams) {
+      let category = param;
+      let value = currentParams[param];
+      searchFilterParam[category] = value;
+      defaultSearchFilterParam.push({
+        category: category,
+        value: value
+      });
+    }
+    setSearchParams({ ...currentParams, ...searchParam });
+    if (
+      JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+    ) {
+      setSearchFilterParams(searchFilterParam);
+    }
+    setDefaultSearchFilterParams(defaultSearchFilterParam);
+    setContentLoader(false);
+    localStorage.setItem("newDataAdded", state && state.showLastPage);
+  }, [searchParams]);
 
   const fetchRequestList = useCallback(
     async ({ pageSize, pageIndex, sortBy, gotoPage }) => {
@@ -77,14 +145,14 @@ const RequestListing = () => {
         }
         try {
           resp = await fetchApi({
-            url: "gds/datashare/dataset",
+            url: "gds/datashare/dataset/summary",
             params: params
           });
           requestList = resp.data.list;
           totalCount = resp.data.totalCount;
         } catch (error) {
           serverError(error);
-          console.error(`Error occurred while fetching Dataset list! 
${error}`);
+          console.error(`Error occurred while fetching Request list! 
${error}`);
         }
         setRequestListData(requestList);
         setEntries(resp.data);
@@ -103,7 +171,7 @@ const RequestListing = () => {
   const columns = React.useMemo(
     () => [
       {
-        Header: "Id",
+        Header: "ID",
         accessor: "id",
         width: 80,
         disableResizing: true,
@@ -135,16 +203,16 @@ const RequestListing = () => {
         }
       },
       {
-        Header: "Name",
-        accessor: "name",
+        Header: "For Datashare",
+        accessor: "dataShareName",
         width: 250,
         disableResizing: true,
         disableSortBy: true,
         getResizerProps: () => {}
       },
       {
-        Header: "Type",
-        accessor: "type",
+        Header: "Into Dataset",
+        accessor: "datasetName",
         width: 250,
         disableResizing: true,
         disableSortBy: true,
@@ -152,12 +220,28 @@ const RequestListing = () => {
       },
       {
         Header: "Status",
-        accessor: "status",
+        accessor: "shareStatus",
         width: 108,
         disableResizing: true,
         disableSortBy: true,
         getResizerProps: () => {}
       },
+      {
+        Header: "Requested By",
+        accessor: "createdBy",
+        width: 100,
+        disableResizing: true,
+        disableSortBy: true,
+        getResizerProps: () => {}
+      },
+      {
+        Header: "Approved By",
+        accessor: "approver",
+        width: 250,
+        disableResizing: true,
+        disableSortBy: true,
+        getResizerProps: () => {}
+      },
       {
         Header: "Created",
         accessor: "createTime",
@@ -177,22 +261,6 @@ const RequestListing = () => {
         width: 170,
         disableResizing: true,
         getResizerProps: () => {}
-      },
-      {
-        Header: "Created By",
-        accessor: "createdBy",
-        width: 100,
-        disableResizing: true,
-        disableSortBy: true,
-        getResizerProps: () => {}
-      },
-      {
-        Header: "Approver",
-        accessor: "approvedBy",
-        width: 250,
-        disableResizing: true,
-        disableSortBy: true,
-        getResizerProps: () => {}
       }
     ],
     []
@@ -208,6 +276,19 @@ const RequestListing = () => {
     []
   );
 
+  const updateSearchFilter = (filter) => {
+    let { searchFilterParam, searchParam } = parseSearchFilter(
+      filter,
+      searchFilterOptions
+    );
+    setSearchFilterParams(searchFilterParam);
+    setSearchParams(searchParam);
+
+    if (typeof resetPage?.page === "function") {
+      resetPage.page(0);
+    }
+  };
+
   return contentLoader ? (
     <Loader />
   ) : (
@@ -224,9 +305,9 @@ const RequestListing = () => {
               <StructuredFilter
                 key="user-listing-search-filter"
                 placeholder="Search..."
-                //options={sortBy(searchFilterOptions, ["label"])}
-                //onChange={updateSearchFilter}
-                //defaultSelected={defaultSearchFilterParams}
+                options={searchFilterOptions}
+                onChange={updateSearchFilter}
+                defaultSelected={defaultSearchFilterParams}
               />
             </Col>
           </Row>


Reply via email to