You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2023/10/17 20:16:59 UTC
[ranger] branch RANGER-3923 updated (811c0ece1 -> 9d62eef59)
This is an automated email from the ASF dual-hosted git repository.
madhan pushed a change to branch RANGER-3923
in repository https://gitbox.apache.org/repos/asf/ranger.git
from 811c0ece1 Merge branch 'master' into RANGER-3923
new 3114b7d67 RANGER-4283: UI for GDS: Dataset and Datashare full view, download json, CSS
new 9d62eef59 RANGER-4410: dataShareName/partailName not working - #2
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../ranger/service/RangerGdsDatasetService.java | 4 +-
.../src/main/webapp/react-webapp/src/App.jsx | 14 +
.../main/webapp/react-webapp/src/styles/style.css | 46 ++
.../main/webapp/react-webapp/src/utils/XAEnums.js | 2 +
.../views/GovernedData/Dataset/AccessGrantForm.jsx | 401 ++++++---
.../GovernedData/Dataset/DatasetDetailFullView.jsx | 916 +++++++++++++++++++++
.../GovernedData/Dataset/DatasetDetailLayout.jsx | 879 +++++++++++---------
.../GovernedData/Dataset/DatasetPolicyItemComp.jsx | 93 ++-
.../GovernedData/Dataset/MyDatasetListing.jsx | 90 +-
.../Dataset/PrinciplePermissionComp.jsx | 174 ++--
.../GovernedData/Datashare/AddDatashareView.jsx | 17 +-
.../Datashare/AddSharedResourceComp.jsx | 7 +-
.../Datashare/DatashareDetailFullView.jsx | 659 +++++++++++++++
.../Datashare/DatashareDetailLayout.jsx | 583 ++++++-------
.../GovernedData/Datashare/MyDatashareListing.jsx | 90 +-
.../GovernedData/Request/RequestDetailView.jsx | 86 +-
16 files changed, 3055 insertions(+), 1006 deletions(-)
create mode 100644 security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailFullView.jsx
[ranger] 02/02: RANGER-4410: dataShareName/partailName not working - #2
Posted by ma...@apache.org.
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 9d62eef59a6bc1f25f035d1e5aac25c91a1b3d94
Author: root <pr...@gmail.com>
AuthorDate: Mon Oct 16 17:49:55 2023 +0530
RANGER-4410: dataShareName/partailName not working - #2
Signed-off-by: Madhan Neethiraj <ma...@apache.org>
---
.../main/java/org/apache/ranger/service/RangerGdsDatasetService.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetService.java
index 072889f1d..75833ea7b 100755
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetService.java
@@ -61,8 +61,8 @@ public class RangerGdsDatasetService extends RangerGdsBaseModelService<XXGdsData
searchFields.add(new SearchField(SearchFilter.PROJECT_NAME, "proj.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDatasetInProject dip, XXGdsProject proj", "obj.id = dip.datasetId and dip.projectId = proj.id"));
searchFields.add(new SearchField(SearchFilter.PROJECT_NAME_PARTIAL, "proj.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.PARTIAL, "XXGdsDatasetInProject dip, XXGdsProject proj", "obj.id = dip.datasetId and dip.projectId = proj.id"));
searchFields.add(new SearchField(SearchFilter.PROJECT_ID, "dip.projectId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsDatasetInProject dip", "obj.id = dip.datasetId"));
- searchFields.add(new SearchField(SearchFilter.DATA_SHARE_NAME, "ds.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDataset ds XXGdsDataShareInDataset dshid, XXGdsDataShare dsh", "obj.id = dshid.datasetId and dshid.dataShareId = dsh.id"));
- searchFields.add(new SearchField(SearchFilter.DATA_SHARE_NAME_PARTIAL, "ds.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.PARTIAL, "XXGdsDataset ds XXGdsDataShareInDataset dshid, XXGdsDataShare dsh", "obj.id = dshid.datasetId and dshid.dataShareId = dsh.id"));
+ searchFields.add(new SearchField(SearchFilter.DATA_SHARE_NAME, "dsh.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDataset ds, XXGdsDataShareInDataset dshid, XXGdsDataShare dsh", "obj.id = dshid.datasetId and dshid.dataShareId = dsh.id"));
+ searchFields.add(new SearchField(SearchFilter.DATA_SHARE_NAME_PARTIAL, "dsh.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.PARTIAL, "XXGdsDataset ds, XXGdsDataShareInDataset dshid, XXGdsDataShare dsh", "obj.id = dshid.datasetId and dshid.dataShareId = dsh.id"));
searchFields.add(new SearchField(SearchFilter.DATA_SHARE_ID, "dshid.dataShareId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShareInDataset dshid", "obj.id = dshid.datasetId"));
searchFields.add(new SearchField(SearchFilter.SERVICE_NAME, "s.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.FULL, "XXGdsDataShareInDataset dshid, XXGdsDataShare dsh, XXService s", "obj.id = dshid.datasetId and dshid.dataShareId = dsh.id and dsh.serviceId = s.id"));
searchFields.add(new SearchField(SearchFilter.SERVICE_NAME_PARTIAL, "s.name", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.PARTIAL, "XXGdsDataShareInDataset dshid, XXGdsDataShare dsh, XXService s", "obj.id = dshid.datasetId and dshid.dataShareId = dsh.id and dsh.serviceId = s.id"));
[ranger] 01/02: RANGER-4283: UI for GDS: Dataset and Datashare full view, download json, CSS
Posted by ma...@apache.org.
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 3114b7d6790c4a0f79d441ab2d5f29aed83a6612
Author: Anand Nadar <na...@gmail.com>
AuthorDate: Tue Oct 17 12:36:17 2023 -0700
RANGER-4283: UI for GDS: Dataset and Datashare full view, download json, CSS
Signed-off-by: Madhan Neethiraj <ma...@apache.org>
---
.../src/main/webapp/react-webapp/src/App.jsx | 14 +
.../main/webapp/react-webapp/src/styles/style.css | 46 ++
.../main/webapp/react-webapp/src/utils/XAEnums.js | 2 +
.../views/GovernedData/Dataset/AccessGrantForm.jsx | 401 ++++++---
.../GovernedData/Dataset/DatasetDetailFullView.jsx | 916 +++++++++++++++++++++
.../GovernedData/Dataset/DatasetDetailLayout.jsx | 879 +++++++++++---------
.../GovernedData/Dataset/DatasetPolicyItemComp.jsx | 93 ++-
.../GovernedData/Dataset/MyDatasetListing.jsx | 90 +-
.../Dataset/PrinciplePermissionComp.jsx | 174 ++--
.../GovernedData/Datashare/AddDatashareView.jsx | 17 +-
.../Datashare/AddSharedResourceComp.jsx | 7 +-
.../Datashare/DatashareDetailFullView.jsx | 659 +++++++++++++++
.../Datashare/DatashareDetailLayout.jsx | 583 ++++++-------
.../GovernedData/Datashare/MyDatashareListing.jsx | 90 +-
.../GovernedData/Request/RequestDetailView.jsx | 86 +-
15 files changed, 3053 insertions(+), 1004 deletions(-)
diff --git a/security-admin/src/main/webapp/react-webapp/src/App.jsx b/security-admin/src/main/webapp/react-webapp/src/App.jsx
index e8df96fbf..65c4b2c09 100755
--- a/security-admin/src/main/webapp/react-webapp/src/App.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/App.jsx
@@ -101,6 +101,9 @@ const CreateDatasetComp = lazy(() =>
const DatasetDetailLayoutComp = lazy(() =>
import("Views/GovernedData/Dataset/DatasetDetailLayout")
);
+const DatasetDetailFullViewComp = lazy(() =>
+ import("Views/GovernedData/Dataset/DatasetDetailFullView")
+);
const AccessGrantFormComp = lazy(() =>
import("Views/GovernedData/Dataset/AccessGrantForm")
);
@@ -113,6 +116,9 @@ const CreateDatashareComp = lazy(() =>
const DatashareDetailLayoutComp = lazy(() =>
import("Views/GovernedData/Datashare/DatashareDetailLayout")
);
+const DatashareDetailFullView = lazy(() =>
+ import("Views/GovernedData/Datashare/DatashareDetailFullView")
+);
const DatashareAddSharedResourceComp = lazy(() =>
import("Views/GovernedData/Datashare/AddSharedResourceComp")
);
@@ -391,6 +397,10 @@ export default class App extends Component {
path="mydatasharelisting"
element={<MyDatashareListingComp />}
/>
+ <Route
+ path="dataset/:datasetId/fullview"
+ element={<DatasetDetailFullViewComp />}
+ />
<Route
path="datashare/create"
element={<CreateDatashareComp />}
@@ -399,6 +409,10 @@ export default class App extends Component {
path="datashare/:datashareId/detail"
element={<DatashareDetailLayoutComp />}
/>
+ <Route
+ path="datashare/:datashareId/fullview"
+ element={<DatashareDetailFullView />}
+ />
<Route
path="datashare/resource/:datashareId"
element={<DatashareAddSharedResourceComp />}
diff --git a/security-admin/src/main/webapp/react-webapp/src/styles/style.css b/security-admin/src/main/webapp/react-webapp/src/styles/style.css
index be11597c3..f6f3f5529 100755
--- a/security-admin/src/main/webapp/react-webapp/src/styles/style.css
+++ b/security-admin/src/main/webapp/react-webapp/src/styles/style.css
@@ -2685,6 +2685,12 @@ li.list-group-item:hover {
margin-bottom: 2rem;
}
+.gds-inline-listing {
+ border-bottom: 1px solid #eee;
+ margin-bottom: 1rem;
+ padding-bottom: 1rem;
+}
+
.gds-right-inline-field-grp {
display: inline-flex;
flex-direction: column;
@@ -2726,6 +2732,10 @@ li.list-group-item:hover {
border-bottom: 1px solid #dddddd;
}
+.gds-card-heading-border {
+ border-bottom: 1px solid #dddddd;
+}
+
.gds-acc-card-header {
padding: 0.5rem 0.75rem;
}
@@ -2747,6 +2757,26 @@ li.list-group-item:hover {
padding: 1.5rem 1rem;
}
+.gds-action-card {
+ padding: 1.5rem 1rem;
+ border-radius: 16px;
+}
+
+.gds-action-card .gds-section-title {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ border-bottom: 1px solid #dddddd;
+ padding-bottom: 0.75rem;
+}
+
+.gds-action-card .gds-card-heading {
+ border: 0;
+ font-size: 1.125rem;
+ margin: 0;
+ padding: 0;
+}
+
.gds-principle-listing {
display: flex;
justify-content: space-between;
@@ -2904,3 +2934,19 @@ textarea.gds-placeholder::placeholder,
.gds-label-color {
color: #777777;
}
+
+.autoResizeTextarea {
+ width: 100%;
+ padding: 4px 36px 4px 10px;
+ resize: none;
+ overflow: hidden;
+ border: 1px solid #ccc;
+}
+
+.gds-info-tarea {
+ position: absolute;
+ font-size: 15px;
+ top: 8px;
+ right: 8px;
+ cursor: pointer;
+}
diff --git a/security-admin/src/main/webapp/react-webapp/src/utils/XAEnums.js b/security-admin/src/main/webapp/react-webapp/src/utils/XAEnums.js
index e8463ab3b..adb02d5ec 100755
--- a/security-admin/src/main/webapp/react-webapp/src/utils/XAEnums.js
+++ b/security-admin/src/main/webapp/react-webapp/src/utils/XAEnums.js
@@ -671,6 +671,7 @@ export const PathAssociateWithModule = {
"/gds/datasetlisting",
"/gds/create",
"/gds/dataset/:datasetId/detail",
+ "/gds/dataset/:datasetId/fullview",
"/gds/dataset/:datasetId/accessGrant",
"/gds/mydatasharelisting",
"/gds/datasharelisting",
@@ -678,6 +679,7 @@ export const PathAssociateWithModule = {
"/gds/request/list",
"/gds/request/detail/:requestId",
"/gds/datashare/:datashareId/detail",
+ "/gds/datashare/:datashareId/fullview",
"/gds/datashare/resource/:datashareId"
],
Permission: ["/permissions/models", "/permissions/:permissionId/edit"],
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 af63836ef..32c48046c 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
@@ -18,7 +18,7 @@
*/
import React, { useState, useEffect, useReducer } from "react";
-import { Form as FormB, Button } from "react-bootstrap";
+import { Form as FormB, Button, Card } from "react-bootstrap";
import { Form, Field } from "react-final-form";
import arrayMutators from "final-form-arrays";
import moment from "moment-timezone";
@@ -35,6 +35,7 @@ import PolicyConditionsComp from "../../PolicyListing/PolicyConditionsComp";
import { isEqual, isEmpty, isObject } from "lodash";
import { policyConditionUpdatedJSON } from "Utils/XAUtils";
import { Loader } from "Components/CommonComponents";
+import dateFormat from "dateformat";
const initialState = {
loader: true,
@@ -64,6 +65,7 @@ function AccessGrantForm({ dataset, onDataChange }) {
const [policyState, dispatch] = useReducer(reducer, initialState);
const { loader, serviceCompDetails, policyData, formData } = policyState;
const [showModal, policyConditionState] = useState(false);
+ const [validityPeriod, setValidityPeriod] = useState([]);
useEffect(() => {
fetchInitalData();
@@ -74,24 +76,32 @@ function AccessGrantForm({ dataset, onDataChange }) {
if (dataset.name) {
policyData = await fetchPolicyData();
}
- let serviceData = await fetchServiceDetails(policyData.service);
- let serviceCompData = await getServiceDefData(policyData.serviceType);
- dispatch({
- type: "SET_DATA",
- serviceDetails: serviceData,
- serviceCompDetails: serviceCompData,
- policyData: policyData || null,
- formData: generateFormData(policyData, serviceCompData)
- });
+ if (policyData != null) {
+ setValidityPeriod(policyData.validitySchedules);
+ let serviceData = await fetchServiceDetails(policyData.service);
+ let serviceCompData = await getServiceDefData(policyData.serviceType);
+ dispatch({
+ type: "SET_DATA",
+ serviceDetails: serviceData,
+ serviceCompDetails: serviceCompData,
+ policyData: policyData || null,
+ formData: generateFormData(policyData, serviceCompData)
+ });
+ }
};
const fetchPolicyData = async () => {
let data = null;
try {
+ policyState.loader = true;
const resp = await fetchApi({
url: `/gds/dataset/${dataset.id}/policy`
});
- data = resp.data[0];
+ if (resp.data.length > 0) {
+ data = resp.data[0];
+ data = resp.data[0];
+ policyState.loader = false;
+ }
} catch (error) {
console.error(
`Error occurred while fetching dataset policy details ! ${error}`
@@ -269,10 +279,16 @@ function AccessGrantForm({ dataset, onDataChange }) {
}
obj.principle = principle;
/* Policy Condition*/
+ // if (val?.conditions?.length > 0) {
+ // obj.conditions = {};
+ // for (let data of val.conditions) {
+ // obj.conditions[data.type] = data.values.join(", ");
+ // }
+ // }
if (val?.conditions?.length > 0) {
- obj.conditions = {};
+ obj.conditions = "";
for (let data of val.conditions) {
- obj.conditions[data.type] = data.values.join(", ");
+ obj.conditions = obj.conditions + data.values.join(", ");
}
}
return obj;
@@ -316,10 +332,16 @@ function AccessGrantForm({ dataset, onDataChange }) {
const FormChange = (props) => {
const { isDirtyField, formValues } = props;
- if (isDirtyField) onDataChange(formValues, policyData);
+ if (isDirtyField) {
+ onDataChange(formValues, policyData);
+ }
return null;
};
+ const onConditionChange = () => {
+ onDataChange(formValues, policyData);
+ };
+
const onRemovingPolicyItem = (index) => {
onDataChange(undefined, undefined);
};
@@ -386,115 +408,57 @@ function AccessGrantForm({ dataset, onDataChange }) {
}
formValues={values}
/>
- <div className="d-flex gap-1">
- <div className="gds-grant-det-cond gds-content-border">
- <div className="form-group">
- <p className="formHeader">Basic Details</p>{" "}
- </div>
- <div>
- <Field name="policyName">
- {({ input, meta }) => (
- <div className="form-group">
- <FormB.Control
- {...input}
- placeholder="Policy Name"
- id={
- meta.error && meta.touched ? "isError" : "name"
- }
- className={
- meta.error && meta.touched
- ? "form-control border-danger"
- : "form-control"
- }
- data-cy="policyName"
- />
- {meta.touched && meta.error && (
- <span className="invalid-field">
- {meta.error.text}
- </span>
- )}
- </div>
- )}
- </Field>
-
- <Field
- name="policyLabel"
- render={({ input, meta }) => (
- <FormB.Group>
- <div className="form-group">
- <div>
- <FormB.Label>
- <span className="pull-right fnt-14">
- Policy Label
- </span>
- </FormB.Label>
- <AsyncCreatableSelect
- {...input}
- isMulti
- data-cy="policyDescription"
- />
- </div>
- </div>
- </FormB.Group>
- )}
- />
+ <div className="datasetPolicyItem">
+ <DatasetPolicyItemComp
+ formValues={values}
+ addPolicyItem={addPolicyItem}
+ attrName="policyItems"
+ serviceCompDetails={serviceCompDetails}
+ fetchPrincipleData={fetchPrincipleData}
+ onRemovingPolicyItem={onRemovingPolicyItem}
+ />
+ </div>
- <Field name="description">
- {({ input, meta }) => (
- <div className="form-group">
- <div>
- <FormB.Control
- {...input}
- as="textarea"
- rows={3}
- placeholder="Policy Description"
- data-cy="policyDescription"
+ <div className="d-flex gap-1">
+ {/* <div>
+ <div className="form-group">
+ <p className="formHeader">Conditions</p>{" "}
+ </div>
+ <div className="mb-4">
+ <Button
+ className="pull-right btn btn-mini"
+ onClick={() => {
+ policyConditionState(true);
+ }}
+ data-js="customPolicyConditions"
+ data-cy="customPolicyConditions"
+ >
+ <i className="fa-fw fa fa-plus"></i>
+ </Button>
+ {showModal && (
+ <Field
+ className="form-control"
+ name="conditions"
+ render={({ input }) => (
+ <PolicyConditionsComp
+ policyConditionDetails={policyConditionUpdatedJSON(
+ serviceCompDetails.policyConditions
+ )}
+ inputVal={input}
+ showModal={showModal}
+ handleCloseModal={policyConditionState}
/>
- </div>
- </div>
+ )}
+ />
)}
- </Field>
- </div>
- </div>
-
- <div className=" gds-grant-det-cond gds-content-border">
- <div className="mb-4">
- <PolicyValidityPeriodComp addPolicyItem={addPolicyItem} />
+ </div>
</div>
- <br />
{serviceCompDetails?.policyConditions?.length > 0 && (
<div className="table-responsive">
<table className="table table-bordered condition-group-table">
<thead>
<tr>
<th colSpan="2">
- Policy Conditions :
- {showModal && (
- <Field
- className="form-control"
- name="conditions"
- render={({ input }) => (
- <PolicyConditionsComp
- policyConditionDetails={policyConditionUpdatedJSON(
- serviceCompDetails.policyConditions
- )}
- inputVal={input}
- showModal={showModal}
- handleCloseModal={policyConditionState}
- />
- )}
- />
- )}
- <Button
- className="pull-right btn btn-mini"
- onClick={() => {
- policyConditionState(true);
- }}
- data-js="customPolicyConditions"
- data-cy="customPolicyConditions"
- >
- <i className="fa-fw fa fa-plus"></i>
- </Button>
</th>
</tr>
</thead>
@@ -561,19 +525,206 @@ function AccessGrantForm({ dataset, onDataChange }) {
</tbody>
</table>
</div>
- )}
- </div>
- </div>
+ )} */}
+ <Card className="gds-action-card gds-grant-det-cond gds-bg-white">
+ <div className="gds-section-title">
+ <p className="gds-card-heading">Conditions</p>
+ <Button
+ className="btn btn-sm"
+ onClick={() => {
+ policyConditionState(true);
+ }}
+ data-js="customPolicyConditions"
+ data-cy="customPolicyConditions"
+ >
+ Add Conditions
+ </Button>
+ {/* <div> */}
+ {showModal && (
+ <Field
+ className="form-control"
+ name="conditions"
+ render={({ input }) => (
+ <PolicyConditionsComp
+ policyConditionDetails={policyConditionUpdatedJSON(
+ serviceCompDetails.policyConditions
+ )}
+ inputVal={input}
+ showModal={showModal}
+ handleCloseModal={policyConditionState}
+ />
+ )}
+ />
+ )}
+ </div>
+ <Card.Body className="px-0">
+ <>
+ {values?.conditions && !isEmpty(values.conditions) ? (
+ Object.keys(values.conditions).map((keyName) => {
+ if (
+ values.conditions[keyName] != "" &&
+ values.conditions[keyName] != null
+ ) {
+ let conditionObj = find(
+ serviceCompDetails?.policyConditions,
+ function (m) {
+ if (m.name == keyName) {
+ return m;
+ }
+ }
+ );
+ return (
+ <div>
+ {isObject(values.conditions[keyName]) ? (
+ <div>
+ <span>
+ {values.conditions[keyName].length > 1
+ ? values.conditions[keyName].map(
+ (m) => {
+ return ` ${m.label} `;
+ }
+ )
+ : values.conditions[keyName].label}
+ </span>
+ </div>
+ ) : (
+ <div>
+ <span>{values.conditions[keyName]}</span>
+ </div>
+ )}
+ </div>
+ );
+ }
+ })
+ ) : (
+ <tr>
+ <td>
+ <center> No Conditions </center>
+ </td>
+ </tr>
+ )}
+ </>
+ </Card.Body>
+ </Card>
- <div className="datasetPolicyItem">
- <DatasetPolicyItemComp
- formValues={values}
- addPolicyItem={addPolicyItem}
- attrName="policyItems"
- serviceCompDetails={serviceCompDetails}
- fetchPrincipleData={fetchPrincipleData}
- onRemovingPolicyItem={onRemovingPolicyItem}
- />
+ <Card className="gds-action-card gds-grant-det-cond gds-bg-white">
+ <div className="gds-section-title">
+ <p className="gds-card-heading">Validity Period</p>
+ <PolicyValidityPeriodComp addPolicyItem={addPolicyItem} />
+ </div>
+ <Card.Body className="px-0">
+ <>
+ {validityPeriod != undefined &&
+ validityPeriod.length > 0 ? (
+ validityPeriod.map((obj, index) => {
+ return (
+ <div className="gds-inline-field-grp gds-inline-listing w-100">
+ <div className="wrapper">
+ <div className="gds-left-inline-field">
+ <span className="gds-label-color">
+ Start Date{" "}
+ </span>
+ </div>
+ {obj?.startTime != undefined ? (
+ <span>
+ {dateFormat(
+ obj.startTime,
+ "mm/dd/yyyy hh:MM:ss TT"
+ )}
+ </span>
+ ) : (
+ <p className="mb-0">--</p>
+ )}
+ <span className="gds-label-color pl-5">
+ {obj?.timeZone}
+ </span>
+ </div>
+ <div className="wrapper ">
+ <div className="gds-left-inline-field">
+ <span className="gds-label-color">
+ {" "}
+ End Date{" "}
+ </span>
+ </div>
+ {obj?.endTime != undefined ? (
+ <span>
+ {dateFormat(
+ obj.endTime,
+ "mm/dd/yyyy hh:MM:ss TT"
+ )}
+ </span>
+ ) : (
+ <p className="mb-0">--</p>
+ )}
+ </div>
+ </div>
+ );
+ })
+ ) : (
+ <p className="mt-1">--</p>
+ )}
+ </>
+ </Card.Body>
+ </Card>
+
+ {/* <div className=" gds-grant-det-cond gds-content-border">
+ <div className="form-group">
+ <p className="formHeader">Validity Period</p>{" "}
+ </div>
+ <div className="mb-4">
+ <PolicyValidityPeriodComp addPolicyItem={addPolicyItem} />
+ </div>
+ <br />
+ {validityPeriod != undefined &&
+ validityPeriod.length > 0 ? (
+ validityPeriod.map((obj, index) => {
+ return (
+ <div className="gds-inline-field-grp">
+ <div className="wrapper">
+ <div className="gds-left-inline-field">
+ <span className="gds-label-color">
+ Start Date{" "}
+ </span>
+ </div>
+ {obj?.startTime != undefined ? (
+ <span>
+ {dateFormat(
+ obj.startTime,
+ "mm/dd/yyyy hh:MM:ss TT"
+ )}
+ </span>
+ ) : (
+ <p>--</p>
+ )}
+ <span className="gds-label-color pl-5">
+ {obj?.timeZone}
+ </span>
+ </div>
+ <div className="wrapper">
+ <div className="gds-left-inline-field">
+ <span className="gds-label-color">
+ {" "}
+ End Date{" "}
+ </span>
+ </div>
+ {obj?.endTime != undefined ? (
+ <span>
+ {dateFormat(
+ obj.endTime,
+ "mm/dd/yyyy hh:MM:ss TT"
+ )}
+ </span>
+ ) : (
+ <p>--</p>
+ )}
+ </div>
+ </div>
+ );
+ })
+ ) : (
+ <p className="mt-1">--</p>
+ )}
+ </div> */}
</div>
</div>
)}
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailFullView.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailFullView.jsx
index 881df96c9..25f830443 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailFullView.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailFullView.jsx
@@ -16,3 +16,919 @@
* specific language governing permissions and limitations
* under the License.
*/
+
+import React, { useEffect, useState } from "react";
+import { useParams, useNavigate, useLocation, Link } from "react-router-dom";
+import { fetchApi } from "../../../utils/fetchAPI";
+import { Loader } from "../../../components/CommonComponents";
+import CustomBreadcrumb from "../../CustomBreadcrumb";
+import PrinciplePermissionComp from "./PrinciplePermissionComp";
+import dateFormat from "dateformat";
+import { isSystemAdmin } from "../../../utils/XAUtils";
+import { Form } from "react-final-form";
+import ReactPaginate from "react-paginate";
+import { Button, Accordion, Card } from "react-bootstrap";
+import userColourIcon from "../../../images/user-colour.svg";
+import groupColourIcon from "../../../images/group-colour.svg";
+import roleColourIcon from "../../../images/role-colour.svg";
+import Select from "react-select";
+
+const DatasetDetailFullView = () => {
+ let { datasetId } = useParams();
+ const { state } = useLocation();
+ const userAclPerm = state?.userAclPerm;
+ const [loader, setLoader] = useState(true);
+ const [datasetInfo, setDatasetInfo] = useState({});
+ const [userList, setUserList] = useState([]);
+ const [groupList, setGroupList] = useState([]);
+ const [roleList, setRoleList] = useState([]);
+ const [dataShareRequestsList, setDatashareRequestsList] = useState([]);
+ const itemsPerPage = 5;
+ const [requestAccordionState, setRequestAccordionState] = useState({});
+ const [requestPageCount, setRequestPageCount] = useState();
+ const navigate = useNavigate();
+ const [sharedWithPrincipleName, setSharedWithPrincipleName] = useState();
+ const [serviceDef, setServiceDef] = useState({});
+ const [userSharedWithMap, setUserSharedWithMap] = useState(new Map());
+ const [groupSharedWithMap, setGroupSharedWithMap] = useState(new Map());
+ const [roleSharedWithMap, setRoleSharedWithMap] = useState(new Map());
+ const [filteredUserSharedWithMap, setFilteredUserSharedWithMap] = useState();
+ const [filteredGroupSharedWithMap, setFilteredGroupSharedWithMap] =
+ useState();
+ const [filteredRoleSharedWithMap, setFilteredRoleSharedWithMap] = useState();
+ const [sharedWithAccessFilter, setSharedWithAccessFilter] = useState();
+ const [userSharedWithAccordion, setUserSharedWithAccordion] = useState(false);
+ const [groupSharedWithAccordion, setGroupSharedWithAccordion] =
+ useState(false);
+ const [roleSharedWithAccordion, setRoleSharedWithAccordion] = useState(false);
+ const [completeDatashareRequestsList, setCompleteDatashareRequestsList] =
+ useState([]);
+
+ useEffect(() => {
+ fetchDatasetInfo(datasetId);
+ fetchDatashareRequestList(undefined, 0, false);
+ if (
+ isSystemAdmin() ||
+ userAclPerm == "POLICY_ADMIN" ||
+ userAclPerm == "ADMIN" ||
+ userAclPerm == "AUDIT"
+ )
+ fetchAccessGrantInfo();
+ fetchDatashareRequestList(undefined, 0, true);
+ }, []);
+
+ const fetchDatasetInfo = async (datasetId) => {
+ try {
+ setLoader(true);
+ const resp = await fetchApi({
+ url: `gds/dataset/${datasetId}`
+ });
+ setLoader(false);
+ setDatasetInfo(resp.data);
+ if (resp.data.acl != undefined) setPrincipleAccordianData(resp.data.acl);
+ setLoader(false);
+ } catch (error) {
+ setLoader(false);
+ if (error.response.status == 401 || error.response.status == 400) {
+ <ErrorPage errorCode="401" />;
+ }
+ console.error(`Error occurred while fetching dataset details ! ${error}`);
+ }
+ };
+
+ const fetchDatashareRequestList = async (
+ datashareName,
+ currentPage,
+ getCompleteList
+ ) => {
+ try {
+ let params = {};
+
+ params["page"] = currentPage;
+ let itemPerPageCount = getCompleteList ? 999999999 : itemsPerPage;
+ params["startIndex"] = currentPage * itemPerPageCount;
+ params["datasetId"] = datasetId;
+ params["pageSize"] = itemPerPageCount;
+ const resp = await fetchApi({
+ url: `gds/datashare/dataset`,
+ params: params
+ });
+ let accordianState = {};
+ resp.data.list.map(
+ (item) =>
+ (accordianState = { ...accordianState, ...{ [item.id]: false } })
+ );
+ setRequestAccordionState(accordianState);
+ setRequestPageCount(Math.ceil(resp.data.totalCount / itemPerPageCount));
+ if (!getCompleteList) {
+ setDatashareRequestsList(resp.data.list);
+ } else {
+ setCompleteDatashareRequestsList(resp.data.list);
+ }
+ } catch (error) {
+ console.error(
+ `Error occurred while fetching Datashare requests details ! ${error}`
+ );
+ }
+ };
+
+ const fetchAccessGrantInfo = async () => {
+ let policyData = {};
+ try {
+ const resp = await fetchApi({
+ url: `gds/dataset/${datasetId}/policy`
+ });
+ policyData = resp.data[0];
+ fetchServiceDef(policyData.serviceType);
+ let grantItems = policyData.policyItems;
+ const userMap = new Map();
+ const groupMap = new Map();
+ const roleMap = new Map();
+ grantItems.forEach((item) => {
+ if (item.users !== undefined) {
+ item.users.forEach((user) => {
+ let accessList = [];
+ if (userMap.get(user) !== undefined) {
+ accessList = userMap.get(user);
+ }
+ userMap.set(user, [...accessList, ...item.accesses]);
+ });
+ }
+
+ if (item.groups !== undefined) {
+ item.groups.forEach((group) => {
+ let accessList = [];
+ if (groupMap[group] !== undefined) {
+ accessList = groupMap[group];
+ }
+ groupMap.set(group, [...accessList, ...item.accesses]);
+ });
+ }
+
+ if (item.roles !== undefined) {
+ item.roles.forEach((role) => {
+ let accessList = [];
+ if (roleMap[role] !== undefined) {
+ accessList = roleMap[role];
+ }
+ roleMap.set(role, [...accessList, ...item.accesses]);
+ });
+ }
+ setUserSharedWithMap(userMap);
+ setGroupSharedWithMap(groupMap);
+ setRoleSharedWithMap(roleMap);
+ setFilteredUserSharedWithMap(userMap);
+ setFilteredGroupSharedWithMap(groupMap);
+ setFilteredRoleSharedWithMap(roleMap);
+ });
+ } catch (error) {
+ if (error.response.status == 404) {
+ }
+ console.error(
+ `Error occurred while fetching dataset access grant details ! ${error}`
+ );
+ }
+ };
+
+ const fetchServiceDef = async (serviceDefName) => {
+ let serviceDefsResp = [];
+ try {
+ serviceDefsResp = await fetchApi({
+ url: `plugins/definitions/name/${serviceDefName}`
+ });
+ } catch (error) {
+ console.error(
+ `Error occurred while fetching Service Definition or CSRF headers! ${error}`
+ );
+ }
+ let modifiedServiceDef = serviceDefsResp.data;
+ for (const obj of modifiedServiceDef.resources) {
+ obj.recursiveSupported = false;
+ obj.excludesSupported = false;
+ }
+ setServiceDef(modifiedServiceDef);
+ };
+
+ const setPrincipleAccordianData = (principle) => {
+ let userPrinciples = principle.users;
+ let groupPrinciples = principle.groups;
+ let rolePrinciples = principle.roles;
+
+ let tempUserList = [];
+ let tempGroupList = [];
+ let tempRoleList = [];
+ let userList = [];
+ let groupList = [];
+ let roleList = [];
+ if (userPrinciples != undefined) {
+ Object.entries(userPrinciples).map(([key, value]) => {
+ tempUserList.push({ name: key, type: "USER", perm: value });
+ });
+ }
+ if (groupPrinciples != undefined) {
+ Object.entries(groupPrinciples).map(([key, value]) => {
+ tempGroupList.push({ name: key, type: "GROUP", perm: value });
+ });
+ }
+ if (rolePrinciples != undefined) {
+ Object.entries(rolePrinciples).map(([key, value]) => {
+ tempRoleList.push({ name: key, type: "ROLE", perm: value });
+ });
+ }
+ setUserList([...userList, ...tempUserList]);
+ setGroupList([...groupList, ...tempGroupList]);
+ setRoleList([...roleList, ...tempRoleList]);
+ };
+
+ const handleSubmit = async (formData) => {};
+
+ const onRequestAccordionChange = (id) => {
+ setRequestAccordionState({
+ ...requestAccordionState,
+ ...{ [id]: !requestAccordionState[id] }
+ });
+ };
+
+ const viewDatashareDetail = (datashareId) => {
+ navigate(`/gds/datashare/${datashareId}/detail`);
+ };
+
+ const handleRequestPageClick = ({ selected }) => {
+ fetchDatashareRequestList(undefined, selected, false);
+ };
+
+ const onChangeSharedWithPrincipleName = (event) => {
+ setSharedWithPrincipleName(event.target.value);
+ filterSharedWithPrincipleList(event.target.value, true, undefined, false);
+ };
+
+ const filterSharedWithPrincipleList = (
+ name,
+ nameChange,
+ perm,
+ permChange
+ ) => {
+ if (name === undefined && !nameChange) {
+ name =
+ sharedWithPrincipleName != undefined &&
+ sharedWithPrincipleName.length > 0
+ ? sharedWithPrincipleName
+ : undefined;
+ }
+
+ if (perm === undefined && !permChange) {
+ perm =
+ sharedWithAccessFilter != undefined
+ ? sharedWithAccessFilter.name
+ : undefined;
+ }
+
+ let newUserMap = new Map();
+ let newGroupMap = new Map();
+ let newRoleMap = new Map();
+
+ const conditionFunction = (value, key) => {
+ if (name != undefined && perm != undefined) {
+ let accessMatch = false;
+ for (const accessObj of value) {
+ if (accessObj.type == perm) {
+ accessMatch = true;
+ }
+ }
+ return key.startsWith(name, 0) && accessMatch;
+ } else if (name != undefined) {
+ return key.startsWith(name, 0);
+ } else if (perm != undefined) {
+ for (const accessObj of value) {
+ if (accessObj.type == perm) return true;
+ }
+ } else {
+ return true;
+ }
+ };
+
+ userSharedWithMap.forEach((value, key) => {
+ if (conditionFunction(value, key)) {
+ newUserMap.set(key, value);
+ }
+ });
+
+ groupSharedWithMap.forEach((value, key) => {
+ if (conditionFunction(value, key)) {
+ newGroupMap.set(key, value);
+ }
+ });
+
+ roleSharedWithMap.forEach((value, key) => {
+ if (conditionFunction(value, key)) {
+ newRoleMap.set(key, value);
+ }
+ });
+
+ setFilteredUserSharedWithMap(newUserMap);
+ setFilteredGroupSharedWithMap(newGroupMap);
+ setFilteredRoleSharedWithMap(newRoleMap);
+ };
+
+ const serviceSelectTheme = (theme) => {
+ return {
+ ...theme,
+ colors: {
+ ...theme.colors,
+ primary: "#0081ab"
+ }
+ };
+ };
+
+ const customStyles = {
+ control: (provided) => ({
+ ...provided,
+ maxHeight: "40px",
+ width: "172px"
+ }),
+ indicatorsContainer: (provided) => ({
+ ...provided
+ })
+ };
+
+ const onUserSharedWithAccordianChange = () => {
+ setUserSharedWithAccordion(!userSharedWithAccordion);
+ };
+
+ const onGroupSharedWithAccordianChange = () => {
+ setGroupSharedWithAccordion(!groupSharedWithAccordion);
+ };
+
+ const onRoleSharedWithAccordianChange = () => {
+ setRoleSharedWithAccordion(!roleSharedWithAccordion);
+ };
+
+ const onSharedWithAccessFilterChange = (e) => {
+ setSharedWithAccessFilter(e);
+ filterSharedWithPrincipleList(
+ undefined,
+ false,
+ e != undefined ? e.label : undefined,
+ true
+ );
+ };
+
+ const downloadJsonFile = () => {
+ let jsonData = datasetInfo;
+ jsonData.datashares = completeDatashareRequestsList;
+ //jsonData.sharedWith = sharedShareRequestsList;
+ const jsonContent = JSON.stringify(jsonData);
+ const blob = new Blob([jsonContent], { type: "application/json" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = datasetInfo.name + ".json"; // Set the desired file name
+ a.click();
+ URL.revokeObjectURL(url);
+ };
+
+ const back = () => {
+ navigate(`/gds/dataset/${datasetId}/detail`);
+ };
+ return (
+ <>
+ {loader ? (
+ <Loader />
+ ) : (
+ <div>
+ <div className="gds-header-wrapper gap-half">
+ <Button
+ variant="light"
+ className="border-0 bg-transparent"
+ onClick={back}
+ size="sm"
+ data-id="back"
+ data-cy="back"
+ >
+ <i className="fa fa-angle-left fa-lg font-weight-bold" />
+ </Button>
+ <h3 className="gds-header bold">
+ <span
+ title={datasetInfo.name}
+ className="text-truncate"
+ style={{ maxWidth: "700px", display: "inline-block" }}
+ >
+ Dataset : {datasetInfo.name}
+ </span>
+ </h3>
+ <CustomBreadcrumb />
+ <span className="pipe"></span>
+ <div className="gds-header-btn-grp">
+ <Button
+ variant="primary"
+ onClick={() => downloadJsonFile()}
+ size="sm"
+ data-id="downloadJSON"
+ data-cy="downloadJSON"
+ >
+ Download JSON
+ </Button>
+ </div>
+ </div>
+ <Form
+ onSubmit={handleSubmit}
+ render={({}) => (
+ <div>
+ <div className="gds-tab-content gds-content-border">
+ <div className="gds-inline-field-grp">
+ <div className="wrapper">
+ <div className="gds-left-inline-field" height="30px">
+ <span className="gds-label-color">Date Updated</span>
+ </div>
+ <div line-height="30px">
+ {dateFormat(
+ datasetInfo.updateTime,
+ "mm/dd/yyyy hh:MM:ss TT"
+ )}
+ </div>
+ </div>
+
+ <div className="wrapper">
+ <div className="gds-left-inline-field" line-height="30px">
+ <span className="gds-label-color">Date Created</span>
+ </div>
+ <div line-height="30px">
+ {dateFormat(
+ datasetInfo.createTime,
+ "mm/dd/yyyy hh:MM:ss TT"
+ )}
+ </div>
+ </div>
+ </div>
+
+ <div>
+ <div>
+ <span className="gds-label-color">Description</span>
+ </div>
+ </div>
+ <div>
+ <div>
+ <textarea
+ placeholder="Dataset Description"
+ className="form-control gds-description"
+ id="description"
+ data-cy="description"
+ //onChange={datasetDescriptionChange}
+ value={datasetInfo.description}
+ rows={5}
+ />
+ </div>
+ </div>
+ </div>
+ {(isSystemAdmin() || userAclPerm == "ADMIN") && (
+ <PrinciplePermissionComp
+ userList={userList}
+ groupList={groupList}
+ roleList={roleList}
+ isEditable={false}
+ //onDataChange={handleDataChange}
+ />
+ )}
+
+ <div className="gds-tab-content gds-content-border">
+ <div className="gds-section-title">
+ <p className="gds-card-heading">Datashares</p>
+ </div>
+ <div>
+ {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"
+ >
+ {/* {obj["status"] == "GRANTED" ? (
+ <div>
+ <span>Data access granted.</span>
+ <Link
+ className="mb-3"
+ to=""
+ onClick={() =>
+ showActiveateRequestModal(obj)
+ }
+ >
+ Activate Datashare
+ </Link>
+ </div>
+ ) : (
+ <div></div>
+ )} */}
+ <div className="d-flex justify-content-between align-items-center">
+ <div className="d-flex align-items-center gap-1">
+ {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>
+ )}
+ <h5 className="gds-heading-5 m-0">
+ {/* {obj.name} */} Datashare{" "}
+ {obj.dataShareId}
+ </h5>
+ </div>
+ <div className="d-flex align-items-center gap-1">
+ <span
+ //className="badge badge-light gds-requested-status"
+ 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"
+ className="mr-2"
+ title="View"
+ data-name="viewDatashare"
+ onClick={() =>
+ viewDatashareDetail(obj.dataShareId)
+ }
+ 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={() =>
+ toggleConfirmModalForDelete(
+ obj.id,
+ 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 className="gds-inline-field-grp">
+ <div className="wrapper">
+ <div
+ className="gds-left-inline-field"
+ height="30px"
+ >
+ Service
+ </div>
+ <div line-height="30px">
+ {obj["service"]}
+ </div>
+ </div>
+ <div className="wrapper">
+ <div
+ className="gds-left-inline-field"
+ height="30px"
+ >
+ Zone
+ </div>
+ <div line-height="30px">
+ {obj["zone"]}
+ </div>
+ </div>
+ <div className="wrapper">
+ <div
+ className="gds-left-inline-field"
+ height="30px"
+ >
+ Resource Count
+ </div>
+ <div line-height="30px">
+ {obj["resourceCount"]}
+ </div>
+ </div>
+ </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">
+ <Link
+ to={`/gds/request/detail/${obj.id}`}
+ >
+ View Request
+ </Link>
+ </div>
+ </div>
+ </div>
+ </Card.Body>
+ </Accordion.Collapse>
+ </div>
+ </Accordion>
+ </div>
+ );
+ })
+ ) : (
+ <div></div>
+ )}
+ {requestPageCount > 1 && (
+ <ReactPaginate
+ previousLabel={"Prev"}
+ 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>
+ </div>
+
+ <div className="gds-tab-content gds-content-border">
+ <div>
+ <div className="usr-grp-role-search-width">
+ <p className="gds-content-header">Shared with</p>
+ </div>
+ <div className="gds-flex mg-b-10">
+ <input
+ type="search"
+ className="form-control gds-input"
+ placeholder="Search..."
+ onChange={(e) => onChangeSharedWithPrincipleName(e)}
+ value={sharedWithPrincipleName}
+ />
+
+ <Select
+ theme={serviceSelectTheme}
+ styles={customStyles}
+ options={serviceDef.accessTypes}
+ onChange={(e) => onSharedWithAccessFilterChange(e)}
+ value={sharedWithAccessFilter}
+ menuPlacement="auto"
+ placeholder="All Permissions"
+ isClearable
+ />
+ </div>
+
+ <Accordion className="mg-b-10" defaultActiveKey="0">
+ <Card>
+ <div className="border-bottom">
+ <Accordion.Toggle
+ as={Card.Header}
+ eventKey="1"
+ onClick={onUserSharedWithAccordianChange}
+ className="border-bottom-0 d-flex align-items-center justify-content-between gds-acc-card-header"
+ data-id="panel"
+ data-cy="panel"
+ >
+ <div className="d-flex align-items-center gap-half">
+ <img
+ src={userColourIcon}
+ height="30px"
+ width="30px"
+ />
+ Users (
+ {filteredUserSharedWithMap == undefined
+ ? 0
+ : filteredUserSharedWithMap.size}
+ )
+ </div>
+ {userSharedWithAccordion ? (
+ <i className="fa fa-angle-up fa-lg font-weight-bold"></i>
+ ) : (
+ <i className="fa fa-angle-down fa-lg font-weight-bold"></i>
+ )}
+ </Accordion.Toggle>
+ </div>
+ <Accordion.Collapse eventKey="1">
+ <Card.Body>
+ {filteredUserSharedWithMap != undefined &&
+ filteredUserSharedWithMap.size > 0 ? (
+ Array.from(filteredUserSharedWithMap).map(
+ ([key, value]) => (
+ <div
+ className="gds-principle-listing"
+ key={key}
+ >
+ <span title={key}>{key}</span>
+ <div className="gds-chips gap-one-fourth">
+ {value.map((accessObj) => (
+ <span
+ className="badge badge-light badge-sm"
+ title={accessObj.type}
+ key={accessObj.type}
+ >
+ {accessObj.type}
+ </span>
+ ))}
+ </div>
+ </div>
+ )
+ )
+ ) : (
+ <p className="mt-1">--</p>
+ )}
+ </Card.Body>
+ </Accordion.Collapse>
+ </Card>
+ </Accordion>
+
+ <Accordion className="mg-b-10" defaultActiveKey="0">
+ <Card>
+ <div className="border-bottom">
+ <Accordion.Toggle
+ as={Card.Header}
+ eventKey="1"
+ onClick={onGroupSharedWithAccordianChange}
+ className="border-bottom-0 d-flex align-items-center justify-content-between gds-acc-card-header"
+ data-id="panel"
+ data-cy="panel"
+ >
+ <div className="d-flex align-items-center gap-half">
+ <img
+ src={groupColourIcon}
+ height="30px"
+ width="30px"
+ />
+ Groups (
+ {filteredGroupSharedWithMap == undefined
+ ? 0
+ : filteredGroupSharedWithMap.size}
+ )
+ </div>
+ {groupSharedWithAccordion ? (
+ <i className="fa fa-angle-up fa-lg font-weight-bold"></i>
+ ) : (
+ <i className="fa fa-angle-down fa-lg font-weight-bold"></i>
+ )}
+ </Accordion.Toggle>
+ </div>
+ <Accordion.Collapse eventKey="1">
+ <Card.Body>
+ <Card.Body>
+ {filteredGroupSharedWithMap != undefined &&
+ filteredGroupSharedWithMap.size > 0 ? (
+ Array.from(filteredGroupSharedWithMap).map(
+ ([key, value]) => (
+ <div
+ className="gds-principle-listing"
+ key={key}
+ >
+ <span title={key}>{key}</span>
+ {value.map((accessObj) => (
+ <span
+ title={accessObj.type}
+ key={accessObj.type}
+ >
+ {accessObj.type}
+ </span>
+ ))}
+ </div>
+ )
+ )
+ ) : (
+ <p className="mt-1">--</p>
+ )}
+ </Card.Body>
+ </Card.Body>
+ </Accordion.Collapse>
+ </Card>
+ </Accordion>
+
+ <Accordion className="mg-b-10" defaultActiveKey="0">
+ <Card>
+ <div className="border-bottom">
+ <Accordion.Toggle
+ as={Card.Header}
+ eventKey="1"
+ onClick={onRoleSharedWithAccordianChange}
+ className="border-bottom-0 d-flex align-items-center justify-content-between gds-acc-card-header"
+ data-id="panel"
+ data-cy="panel"
+ >
+ <div className="d-flex align-items-center gap-half">
+ <img
+ src={roleColourIcon}
+ height="30px"
+ width="30px"
+ />
+ Roles (
+ {filteredRoleSharedWithMap == undefined
+ ? 0
+ : filteredRoleSharedWithMap.size}
+ )
+ </div>
+ {roleSharedWithAccordion ? (
+ <i className="fa fa-angle-up fa-lg font-weight-bold"></i>
+ ) : (
+ <i className="fa fa-angle-down fa-lg font-weight-bold"></i>
+ )}
+ </Accordion.Toggle>
+ </div>
+ <Accordion.Collapse eventKey="1">
+ <Card.Body>
+ <Card.Body>
+ {filteredRoleSharedWithMap != undefined &&
+ filteredRoleSharedWithMap.size > 0 ? (
+ Array.from(filteredRoleSharedWithMap).map(
+ ([key, value]) => (
+ <div
+ className="gds-principle-listing"
+ key={key}
+ >
+ <span title={key}>{key}</span>
+ {value.map((accessObj) => (
+ <span
+ title={accessObj.type}
+ key={accessObj.type}
+ >
+ {accessObj.type}
+ </span>
+ ))}
+ </div>
+ )
+ )
+ ) : (
+ <p className="mt-1">--</p>
+ )}
+ </Card.Body>
+ </Card.Body>
+ </Accordion.Collapse>
+ </Card>
+ </Accordion>
+ </div>
+ </div>
+ <div className="gds-tab-content gds-content-border">
+ <div>
+ <div className="usr-grp-role-search-width">
+ <p className="gds-content-header">Terms & Conditions</p>
+ </div>
+ </div>
+ <div>
+ <div>
+ <textarea
+ placeholder="Terms & Conditions"
+ className="form-control"
+ id="termsAndConditions"
+ data-cy="termsAndConditions"
+ //onChange={datasetTermsAndConditionsChange}
+ value={datasetInfo.termsOfUse}
+ rows={16}
+ />
+ </div>
+ </div>
+ </div>
+ </div>
+ )}
+ />
+ </div>
+ )}
+ </>
+ );
+};
+
+export default DatasetDetailFullView;
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 3dfc08624..779ab523b 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,13 +17,7 @@
* under the License.
*/
-import React, {
- useState,
- useEffect,
- useCallback,
- useRef,
- useReducer
-} from "react";
+import React, { useState, useEffect, useCallback, useReducer } from "react";
import withRouter from "Hooks/withRouter";
import { fetchApi } from "../../../utils/fetchAPI";
import dateFormat from "dateformat";
@@ -44,7 +38,7 @@ import { Form } from "react-final-form";
import { CustomTooltip, Loader } from "../../../components/CommonComponents";
import moment from "moment-timezone";
import { useParams, useNavigate, useLocation, Link } from "react-router-dom";
-import { serverError } from "../../../utils/XAUtils";
+import { serverError, isSystemAdmin } from "../../../utils/XAUtils";
import Select from "react-select";
import userColourIcon from "../../../images/user-colour.svg";
import groupColourIcon from "../../../images/group-colour.svg";
@@ -54,6 +48,7 @@ import { groupBy, isEmpty, isArray } from "lodash";
import PrinciplePermissionComp from "./PrinciplePermissionComp";
import ReactPaginate from "react-paginate";
import CustomBreadcrumb from "../../CustomBreadcrumb";
+import ErrorPage from "../../../views/ErrorPage";
const initialState = {
loader: false,
@@ -85,6 +80,8 @@ const datasetFormReducer = (state, action) => {
const DatasetDetailLayout = () => {
let { datasetId } = useParams();
+ const { state } = useLocation();
+ const userAclPerm = state?.userAclPerm;
const toastId = React.useRef(null);
const [loader, setLoader] = useState(true);
const [datasetInfo, setDatasetInfo] = useState({});
@@ -138,12 +135,17 @@ const DatasetDetailLayout = () => {
const [showDeleteDatasetModal, setShowDeleteDatasetModal] = useState(false);
const [requestCurrentPage, setRequestCurrentPage] = useState(0);
const [requestPageCount, setRequestPageCount] = useState();
+ const [datashareCurrentPage, setDatashareCurrentPage] = useState(0);
+ const [datasharePageCount, setDatasharePageCount] = useState();
const [requestAccordionState, setRequestAccordionState] = useState({});
const itemsPerPage = 5;
+ const datashareItemsPerPage = 10;
const [showActivateRequestModal, setShowActivateRequestModal] =
useState(false);
const [datashareInfo, setDatashareInfo] = useState();
const [datashareRequestInfo, setDatashareRequestInfo] = useState();
+ const [completeDatashareRequestsList, setCompleteDatashareRequestsList] =
+ useState([]);
const toggleConfirmModalForDatasetDelete = () => {
setShowDeleteDatasetModal(true);
@@ -173,14 +175,20 @@ const DatasetDetailLayout = () => {
useEffect(() => {
fetchDatasetInfo(datasetId);
+ fetchDatashareRequestList(undefined, 0, true);
}, []);
- const fetchDatashareRequestList = async (datashareName, currentPage) => {
+ const fetchDatashareRequestList = async (
+ datashareName,
+ currentPage,
+ getCompleteList
+ ) => {
try {
let params = {};
- params["pageSize"] = itemsPerPage;
+ let itemPerPageCount = getCompleteList ? 999999999 : itemsPerPage;
+ params["pageSize"] = itemPerPageCount;
params["page"] = currentPage;
- params["startIndex"] = currentPage * itemsPerPage;
+ params["startIndex"] = currentPage * itemPerPageCount;
params["datasetId"] = datasetId;
const resp = await fetchApi({
url: `gds/datashare/dataset`,
@@ -193,8 +201,12 @@ const DatasetDetailLayout = () => {
);
setRequestAccordionState(accordianState);
setRequestPageCount(Math.ceil(resp.data.totalCount / itemsPerPage));
- setDatashareRequestsList(resp.data.list);
- tabTitle.all = "All (" + resp.data.totalCount + ")";
+ if (!getCompleteList) {
+ setDatashareRequestsList(resp.data.list);
+ tabTitle.all = "All (" + resp.data.totalCount + ")";
+ } else {
+ setCompleteDatashareRequestsList(resp.data.list);
+ }
} catch (error) {
console.error(
`Error occurred while fetching Datashare requests details ! ${error}`
@@ -335,6 +347,9 @@ const DatasetDetailLayout = () => {
setLoader(false);
} catch (error) {
setLoader(false);
+ if (error.response.status == 401 || error.response.status == 400) {
+ <ErrorPage errorCode="401" />;
+ }
console.error(`Error occurred while fetching dataset details ! ${error}`);
}
};
@@ -357,7 +372,7 @@ const DatasetDetailLayout = () => {
const requestDatashare = () => {
setSelectedDatashareList([]);
- fetchDatashareList();
+ fetchDatashareList(undefined, 0);
};
const toggleClose = () => {
@@ -376,105 +391,109 @@ const DatasetDetailLayout = () => {
const updateDatashareSearch = (event) => {
setDatashareSearch(event.target.value);
- fetchDatashareList(event.target.value);
+ fetchDatashareList(event.target.value, datashareCurrentPage);
};
const submitDatashareRequest = async () => {
console.log("Selected datasharelist");
console.log(selectedDatashareList);
- let requestObj = {};
+ let payloadObj = [];
- requestObj["status"] = "REQUESTED";
- if (
- selectedDatashareList != undefined &&
- selectedDatashareList.length > 0
- ) {
- requestObj["dataShareId"] = selectedDatashareList[0]["id"];
+ for (let i = 0; i < selectedDatashareList.length; i++) {
+ let data = {};
+ data["datasetId"] = datasetId;
+ data["dataShareId"] = selectedDatashareList[i];
+ data["status"] = "REQUESTED";
+ payloadObj.push(data);
}
- requestObj["datasetId"] = datasetId;
- try {
- dispatch({
- type: "SET_BLOCK_UI",
- blockUI: true
- });
- const createDatasetResp = await fetchApi({
- url: `gds/datashare/dataset`,
- method: "post",
- data: requestObj
- });
- dispatch({
- type: "SET_BLOCK_UI",
- blockUI: false
- });
- toast.success("Request created successfully!!");
- setDatashareModal(false);
- fetchDatashareRequestList(undefined, requestCurrentPage);
- } catch (error) {
- dispatch({
- type: "SET_BLOCK_UI",
- blockUI: false
- });
- serverError(error);
- console.error(
- `Error occurred while creating Datashare request ${error}`
- );
+ if (payloadObj.length > 0) {
+ try {
+ dispatch({
+ type: "SET_BLOCK_UI",
+ blockUI: true
+ });
+ const createDatasetResp = await fetchApi({
+ url: `gds/dataset/${datasetId}/datashare`,
+ method: "post",
+ data: payloadObj
+ });
+ dispatch({
+ type: "SET_BLOCK_UI",
+ blockUI: false
+ });
+ toast.success("Request created successfully!!");
+ setDatashareModal(false);
+ fetchDatashareRequestList(undefined, requestCurrentPage, false);
+ } catch (error) {
+ dispatch({
+ type: "SET_BLOCK_UI",
+ blockUI: false
+ });
+ serverError(error);
+ console.error(
+ `Error occurred while creating Datashare request ${error}`
+ );
+ }
+ } else {
+ toast.error("Please select a datashare");
}
};
- const fetchDatashareList = useCallback(async (dataShareSearchObj) => {
- let resp = [];
- let totalCount = 0;
- let params = {};
- let dataShareName = "";
- if (dataShareSearchObj != undefined) {
- dataShareName = dataShareSearchObj;
- } else {
- dataShareName = datashareSearch;
- }
- try {
- params["dataShareName"] = dataShareName;
- resp = await fetchApi({
- url: "gds/datashare",
- params: params
- });
- setDatashareList(resp.data.list);
- totalCount = resp.data.totalCount;
- setDatashareModal(true);
- } catch (error) {
- serverError(error);
- console.error(`Error occurred while fetching Datashare list! ${error}`);
- }
- }, []);
+ const fetchDatashareList = useCallback(
+ async (dataShareSearchObj, datashareCurrentPage) => {
+ let resp = [];
+ let totalCount = 0;
+ let params = {};
+ let dataShareName = "";
+ params["pageSize"] = datashareItemsPerPage;
+ params["page"] = datashareCurrentPage;
+ params["startIndex"] = datashareCurrentPage * datashareItemsPerPage;
+ //params["dataShareName"] = datasetId;
+ if (dataShareSearchObj != undefined) {
+ dataShareName = dataShareSearchObj;
+ } else {
+ dataShareName = datashareSearch;
+ }
+ try {
+ params["dataShareNamePartial"] = dataShareName;
+ resp = await fetchApi({
+ url: "gds/datashare",
+ params: params
+ });
+ setDatashareList(resp.data.list);
+ setDatasharePageCount(
+ Math.ceil(resp.data.totalCount / datashareItemsPerPage)
+ );
+ //totalCount = resp.data.totalCount;
+ setDatashareModal(true);
+ } catch (error) {
+ serverError(error);
+ console.error(`Error occurred while fetching Datashare list! ${error}`);
+ }
+ },
+ []
+ );
const checkBocChange = (event) => {
- let dataShare = [
- {
- id: event.target.value,
- name: event.target.name
- }
- ];
- if (event.target.checked == true) {
- setSelectedDatashareList([...selectedDatashareList, ...dataShare]);
- } else if (event.target.checked == false) {
- let newArray = selectedDatashareList.filter(
- (item) => item["id"] !== event.target.value
+ if (
+ event.target.checked == true &&
+ !selectedDatashareList.includes(event.target.value)
+ ) {
+ setSelectedDatashareList([...selectedDatashareList, event.target.value]);
+ } else if (
+ event.target.checked == false &&
+ selectedDatashareList.includes(event.target.value)
+ ) {
+ setSelectedDatashareList(
+ selectedDatashareList.filter((item) => item !== event.target.value)
);
- setSelectedDatashareList(newArray);
}
};
const handleSubmit = async (formData) => {};
- const changeDatashareAccordion = (obj) => {
- let newArray = selectedDatashareList.filter(
- (item) => item["name"] == obj["name"]
- );
- console.log("newArray");
- console.log(newArray);
- };
-
const onUserSharedWithAccordianChange = () => {
setUserSharedWithAccordion(!userSharedWithAccordion);
};
@@ -600,16 +619,11 @@ const DatasetDetailLayout = () => {
if (key == "sharedWith") {
fetchAccessGrantInfo(datasetInfo.name);
} else if (key == "dataShares") {
- fetchDatashareRequestList(undefined, 0);
+ fetchDatashareRequestList(undefined, 0, false);
}
}
};
- const noneOptions = {
- label: "None",
- value: "none"
- };
-
const updateDatasetDetails = async () => {
datasetInfo.description = datasetDescription;
datasetInfo.termsOfUse = datasetTerms;
@@ -643,8 +657,6 @@ const DatasetDetailLayout = () => {
blockUI: false
});
toast.success("Dataset updated successfully!!");
- //self.location.hash = `#/gds/dataset/${datasetId}/detail`;
- //navigate(`/gds/dataset/${datasetId}/detail`);
showSaveCancelButton(false);
} catch (error) {
dispatch({
@@ -783,21 +795,45 @@ const DatasetDetailLayout = () => {
}
}
+ // if (key?.conditions) {
+ // obj.conditions = [];
+ // viewDatashareDetail;
+ // Object.entries(key.conditions).map(
+ // ([conditionKey, conditionValue]) => {
+ // return obj.conditions.push({
+ // type: conditionKey,
+ // values: !isArray(conditionValue)
+ // ? conditionValue?.split(",")
+ // : conditionValue.map((m) => {
+ // return m.value;
+ // })
+ // });
+ // }
+ // );
+ // }
+
if (key?.conditions) {
- obj.conditions = [];
- viewDatashareDetail;
- Object.entries(key.conditions).map(
- ([conditionKey, conditionValue]) => {
- return obj.conditions.push({
- type: conditionKey,
- values: !isArray(conditionValue)
- ? conditionValue?.split(",")
- : conditionValue.map((m) => {
- return m.value;
- })
- });
+ let value = key.conditions.split(",");
+
+ obj.conditions = [
+ {
+ type: "_expression",
+ values: value
}
- );
+ ];
+ // viewDatashareDetail;
+ // Object.entries(key.conditions).map(
+ // ([conditionKey, conditionValue]) => {
+ // return obj.conditions.push({
+ // type: "expression",
+ // values: !isArray(conditionValue)
+ // ? conditionValue?.split(",")
+ // : conditionValue.map((m) => {
+ // return m.value;
+ // })
+ // });
+ // }
+ // );
}
if (
@@ -860,8 +896,7 @@ const DatasetDetailLayout = () => {
}
setShowDatashareRequestDeleteConfirmModal(false);
toast.success(successMsg);
- fetchDatashareRequestList(undefined, requestCurrentPage);
- //fetchSharedResourceForDatashare(datashareInfo.name);
+ fetchDatashareRequestList(undefined, requestCurrentPage, false);
setLoader(false);
} catch (error) {
let errorMsg = "";
@@ -881,6 +916,32 @@ const DatasetDetailLayout = () => {
}
};
+ const downloadJsonFile = () => {
+ let jsonData = datasetInfo;
+ jsonData.datashares = completeDatashareRequestsList;
+ jsonData.sharedWith = { users: {}, groups: {}, roles: {} };
+ if (Object.keys(userSharedWithMap).length > 0) {
+ let newUserMap = {};
+ userSharedWithMap.forEach((value, key) => {
+ jsonData.sharedWith.users({
+ ...jsonData.sharedWith.users,
+ key: key,
+ value: value
+ });
+ newUserMap.set(key, value);
+ });
+ }
+ //jsonData.sharedWith = sharedShareRequestsList;
+ const jsonContent = JSON.stringify(jsonData);
+ const blob = new Blob([jsonContent], { type: "application/json" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = datasetInfo.name + ".json"; // Set the desired file name
+ a.click();
+ URL.revokeObjectURL(url);
+ };
+
const termsCheckBocChange = () => {
setAcceptTerms(true);
};
@@ -893,7 +954,12 @@ const DatasetDetailLayout = () => {
const handleRequestPageClick = ({ selected }) => {
setRequestCurrentPage(selected);
- fetchDatashareRequestList(undefined, selected);
+ fetchDatashareRequestList(undefined, selected, false);
+ };
+
+ const handleDatasharePageClick = ({ selected }) => {
+ setDatashareCurrentPage(selected);
+ fetchDatashareList(undefined, selected);
};
const onRequestAccordionChange = (id) => {
@@ -953,6 +1019,14 @@ const DatasetDetailLayout = () => {
setShowActivateRequestModal(false);
};
+ const navidateToFullViewPage = () => {
+ navigate(`/gds/dataset/${datasetId}/fullview`, {
+ state: {
+ userAclPerm: userAclPerm
+ }
+ });
+ };
+
return (
<>
<React.Fragment>
@@ -967,10 +1041,20 @@ const DatasetDetailLayout = () => {
>
<i className="fa fa-angle-left fa-lg font-weight-bold" />
</Button>
- <h3 className="gds-header bold"> Dataset : {datasetInfo.name}</h3>
+ <h3 className="gds-header bold">
+ <span
+ title={datasetInfo.name}
+ className="text-truncate"
+ style={{ maxWidth: "700px", display: "inline-block" }}
+ >
+ Dataset : {datasetInfo.name}
+ </span>
+ </h3>
<CustomBreadcrumb />
- <span className="pipe"></span>
- {saveCancelButtons ? (
+ {(isSystemAdmin() || userAclPerm == "ADMIN") && (
+ <span className="pipe"></span>
+ )}
+ {(isSystemAdmin() || userAclPerm == "ADMIN") && saveCancelButtons ? (
<div className="gds-header-btn-grp">
<Button
variant="primary"
@@ -996,16 +1080,20 @@ const DatasetDetailLayout = () => {
</Button>
</div>
) : (
- <div className="gds-header-btn-grp">
- <Button
- variant="primary"
- onClick={requestDatashare}
- size="sm"
- data-id="addADatashare"
- data-cy="addADatashare"
- >
- Add a Data Share
- </Button>
+ <div>
+ {(isSystemAdmin() || userAclPerm == "ADMIN") && (
+ <div className="gds-header-btn-grp">
+ <Button
+ variant="primary"
+ onClick={requestDatashare}
+ size="sm"
+ data-id="addADatashare"
+ data-cy="addADatashare"
+ >
+ Add a Data Share
+ </Button>
+ </div>
+ )}
</div>
)}
<div>
@@ -1017,9 +1105,9 @@ const DatasetDetailLayout = () => {
>
<Dropdown.Item
as="button"
- // onClick={() => {
- // showViewModal(serviceData?.id);
- // }}
+ onClick={() => {
+ navidateToFullViewPage();
+ }}
data-name="fullView"
data-id="fullView"
data-cy="fullView"
@@ -1039,9 +1127,7 @@ const DatasetDetailLayout = () => {
</Dropdown.Item>
<Dropdown.Item
as="button"
- // onClick={() => {
- // showViewModal(serviceData?.id);
- // }}
+ onClick={() => downloadJsonFile()}
data-name="downloadJson"
data-id="downloadJson"
data-cy="downloadJson"
@@ -1141,12 +1227,14 @@ const DatasetDetailLayout = () => {
</div>
</div>
</div>
- <PrinciplePermissionComp
- userList={userList}
- groupList={groupList}
- roleList={roleList}
- onDataChange={handleDataChange}
- />
+ {(isSystemAdmin() || userAclPerm == "ADMIN") && (
+ <PrinciplePermissionComp
+ userList={userList}
+ groupList={groupList}
+ roleList={roleList}
+ onDataChange={handleDataChange}
+ />
+ )}
</div>
)}
/>
@@ -1261,23 +1349,27 @@ const DatasetDetailLayout = () => {
>
<i className="fa-fw fa fa-eye fa-fw fa fa-large" />
</Button>
- <Button
- variant="danger"
- size="sm"
- title="Delete"
- onClick={() =>
- toggleConfirmModalForDelete(
- obj.id,
- 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>
+ {(isSystemAdmin() ||
+ userAclPerm ==
+ "ADMIN") && (
+ <Button
+ variant="danger"
+ size="sm"
+ title="Delete"
+ onClick={() =>
+ toggleConfirmModalForDelete(
+ obj.id,
+ 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>
@@ -1357,23 +1449,25 @@ const DatasetDetailLayout = () => {
) : (
<div></div>
)}
- <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"
- />
+ {requestPageCount > 1 && (
+ <ReactPaginate
+ previousLabel={"Prev"}
+ 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>
</Tab>
@@ -1388,147 +1482,94 @@ const DatasetDetailLayout = () => {
<div></div>
)}
</Tab>
- <Tab eventKey="sharedWith" title="SHARED WITH">
- {activeKey == "sharedWith" ? (
- <div className="gds-tab-content gds-content-border">
- <div>
- <div className="usr-grp-role-search-width">
- <p className="gds-content-header">Shared with</p>
- </div>
- <div className="gds-flex mg-b-10">
- <input
- type="search"
- className="form-control gds-input"
- placeholder="Search..."
- onChange={(e) => onChangeSharedWithPrincipleName(e)}
- value={sharedWithPrincipleName}
- />
+ {(isSystemAdmin() ||
+ userAclPerm === "ADMIN" ||
+ userAclPerm === "AUDIT" ||
+ userAclPerm === "POLICY_ADMIN") && (
+ <Tab eventKey="sharedWith" title="SHARED WITH">
+ {activeKey == "sharedWith" ? (
+ <div className="gds-tab-content gds-content-border">
+ <div>
+ <div className="usr-grp-role-search-width">
+ <p className="gds-content-header">Shared with</p>
+ </div>
+ <div className="gds-flex mg-b-10">
+ <input
+ type="search"
+ className="form-control gds-input"
+ placeholder="Search..."
+ onChange={(e) =>
+ onChangeSharedWithPrincipleName(e)
+ }
+ value={sharedWithPrincipleName}
+ />
- <Select
- theme={serviceSelectTheme}
- styles={customStyles}
- options={serviceDef.accessTypes}
- onChange={(e) => onSharedWithAccessFilterChange(e)}
- value={sharedWithAccessFilter}
- menuPlacement="auto"
- placeholder="All Permissions"
- isClearable
- />
- </div>
+ <Select
+ theme={serviceSelectTheme}
+ styles={customStyles}
+ options={serviceDef.accessTypes}
+ onChange={(e) =>
+ onSharedWithAccessFilterChange(e)
+ }
+ value={sharedWithAccessFilter}
+ menuPlacement="auto"
+ placeholder="All Permissions"
+ isClearable
+ />
+ </div>
- <Accordion className="mg-b-10" defaultActiveKey="0">
- <Card>
- <div className="border-bottom">
- <Accordion.Toggle
- as={Card.Header}
- eventKey="1"
- onClick={onUserSharedWithAccordianChange}
- className="border-bottom-0 d-flex align-items-center justify-content-between gds-acc-card-header"
- data-id="panel"
- data-cy="panel"
- >
- <div className="d-flex align-items-center gap-half">
- <img
- src={userColourIcon}
- height="30px"
- width="30px"
- />
- Users (
- {filteredUserSharedWithMap == undefined
- ? 0
- : filteredUserSharedWithMap.size}
- )
- </div>
- {userSharedWithAccordion ? (
- <i className="fa fa-angle-up fa-lg font-weight-bold"></i>
- ) : (
- <i className="fa fa-angle-down fa-lg font-weight-bold"></i>
- )}
- </Accordion.Toggle>
- </div>
- <Accordion.Collapse eventKey="1">
- <Card.Body>
- {filteredUserSharedWithMap != undefined &&
- filteredUserSharedWithMap.size > 0 ? (
- Array.from(filteredUserSharedWithMap).map(
- ([key, value]) => (
- <div
- className="gds-principle-listing"
- key={key}
- >
- <span title={key}>{key}</span>
- <div className="gds-chips gap-one-fourth">
- {value.map((accessObj) => (
- <span
- className="badge badge-light badge-sm"
- title={accessObj.type}
- key={accessObj.type}
- >
- {accessObj.type}
- </span>
- ))}
- </div>
- </div>
+ <Accordion className="mg-b-10" defaultActiveKey="0">
+ <Card>
+ <div className="border-bottom">
+ <Accordion.Toggle
+ as={Card.Header}
+ eventKey="1"
+ onClick={onUserSharedWithAccordianChange}
+ className="border-bottom-0 d-flex align-items-center justify-content-between gds-acc-card-header"
+ data-id="panel"
+ data-cy="panel"
+ >
+ <div className="d-flex align-items-center gap-half">
+ <img
+ src={userColourIcon}
+ height="30px"
+ width="30px"
+ />
+ Users (
+ {filteredUserSharedWithMap == undefined
+ ? 0
+ : filteredUserSharedWithMap.size}
)
- )
- ) : (
- <p className="mt-1">--</p>
- )}
- </Card.Body>
- </Accordion.Collapse>
- </Card>
- </Accordion>
-
- <Accordion className="mg-b-10" defaultActiveKey="0">
- <Card>
- <div className="border-bottom">
- <Accordion.Toggle
- as={Card.Header}
- eventKey="1"
- onClick={onGroupSharedWithAccordianChange}
- className="border-bottom-0 d-flex align-items-center justify-content-between gds-acc-card-header"
- data-id="panel"
- data-cy="panel"
- >
- <div className="d-flex align-items-center gap-half">
- <img
- src={groupColourIcon}
- height="30px"
- width="30px"
- />
- Groups (
- {filteredGroupSharedWithMap == undefined
- ? 0
- : filteredGroupSharedWithMap.size}
- )
- </div>
- {groupSharedWithAccordion ? (
- <i className="fa fa-angle-up fa-lg font-weight-bold"></i>
- ) : (
- <i className="fa fa-angle-down fa-lg font-weight-bold"></i>
- )}
- </Accordion.Toggle>
- </div>
- <Accordion.Collapse eventKey="1">
- <Card.Body>
+ </div>
+ {userSharedWithAccordion ? (
+ <i className="fa fa-angle-up fa-lg font-weight-bold"></i>
+ ) : (
+ <i className="fa fa-angle-down fa-lg font-weight-bold"></i>
+ )}
+ </Accordion.Toggle>
+ </div>
+ <Accordion.Collapse eventKey="1">
<Card.Body>
- {filteredGroupSharedWithMap != undefined &&
- filteredGroupSharedWithMap.size > 0 ? (
- Array.from(filteredGroupSharedWithMap).map(
+ {filteredUserSharedWithMap != undefined &&
+ filteredUserSharedWithMap.size > 0 ? (
+ Array.from(filteredUserSharedWithMap).map(
([key, value]) => (
<div
className="gds-principle-listing"
key={key}
>
<span title={key}>{key}</span>
- {value.map((accessObj) => (
- <span
- title={accessObj.type}
- key={accessObj.type}
- >
- {accessObj.type}
- </span>
- ))}
+ <div className="gds-chips gap-one-fourth">
+ {value.map((accessObj) => (
+ <span
+ className="badge badge-light badge-sm"
+ title={accessObj.type}
+ key={accessObj.type}
+ >
+ {accessObj.type}
+ </span>
+ ))}
+ </div>
</div>
)
)
@@ -1536,48 +1577,48 @@ const DatasetDetailLayout = () => {
<p className="mt-1">--</p>
)}
</Card.Body>
- </Card.Body>
- </Accordion.Collapse>
- </Card>
- </Accordion>
-
- <Accordion className="mg-b-10" defaultActiveKey="0">
- <Card>
- <div className="border-bottom">
- <Accordion.Toggle
- as={Card.Header}
- eventKey="1"
- onClick={onRoleSharedWithAccordianChange}
- className="border-bottom-0 d-flex align-items-center justify-content-between gds-acc-card-header"
- data-id="panel"
- data-cy="panel"
- >
- <div className="d-flex align-items-center gap-half">
- <img
- src={roleColourIcon}
- height="30px"
- width="30px"
- />
- Roles (
- {filteredRoleSharedWithMap == undefined
- ? 0
- : filteredRoleSharedWithMap.size}
- )
- </div>
- {roleSharedWithAccordion ? (
- <i className="fa fa-angle-up fa-lg font-weight-bold"></i>
- ) : (
- <i className="fa fa-angle-down fa-lg font-weight-bold"></i>
- )}
- </Accordion.Toggle>
- </div>
- <Accordion.Collapse eventKey="1">
- <Card.Body>
+ </Accordion.Collapse>
+ </Card>
+ </Accordion>
+
+ <Accordion className="mg-b-10" defaultActiveKey="0">
+ <Card>
+ <div className="border-bottom">
+ <Accordion.Toggle
+ as={Card.Header}
+ eventKey="1"
+ onClick={onGroupSharedWithAccordianChange}
+ className="border-bottom-0 d-flex align-items-center justify-content-between gds-acc-card-header"
+ data-id="panel"
+ data-cy="panel"
+ >
+ <div className="d-flex align-items-center gap-half">
+ <img
+ src={groupColourIcon}
+ height="30px"
+ width="30px"
+ />
+ Groups (
+ {filteredGroupSharedWithMap == undefined
+ ? 0
+ : filteredGroupSharedWithMap.size}
+ )
+ </div>
+ {groupSharedWithAccordion ? (
+ <i className="fa fa-angle-up fa-lg font-weight-bold"></i>
+ ) : (
+ <i className="fa fa-angle-down fa-lg font-weight-bold"></i>
+ )}
+ </Accordion.Toggle>
+ </div>
+ <Accordion.Collapse eventKey="1">
<Card.Body>
- {filteredRoleSharedWithMap != undefined &&
- filteredRoleSharedWithMap.size > 0 ? (
- Array.from(filteredRoleSharedWithMap).map(
- ([key, value]) => (
+ <Card.Body>
+ {filteredGroupSharedWithMap != undefined &&
+ filteredGroupSharedWithMap.size > 0 ? (
+ Array.from(
+ filteredGroupSharedWithMap
+ ).map(([key, value]) => (
<div
className="gds-principle-listing"
key={key}
@@ -1592,35 +1633,108 @@ const DatasetDetailLayout = () => {
</span>
))}
</div>
- )
+ ))
+ ) : (
+ <p className="mt-1">--</p>
+ )}
+ </Card.Body>
+ </Card.Body>
+ </Accordion.Collapse>
+ </Card>
+ </Accordion>
+
+ <Accordion className="mg-b-10" defaultActiveKey="0">
+ <Card>
+ <div className="border-bottom">
+ <Accordion.Toggle
+ as={Card.Header}
+ eventKey="1"
+ onClick={onRoleSharedWithAccordianChange}
+ className="border-bottom-0 d-flex align-items-center justify-content-between gds-acc-card-header"
+ data-id="panel"
+ data-cy="panel"
+ >
+ <div className="d-flex align-items-center gap-half">
+ <img
+ src={roleColourIcon}
+ height="30px"
+ width="30px"
+ />
+ Roles (
+ {filteredRoleSharedWithMap == undefined
+ ? 0
+ : filteredRoleSharedWithMap.size}
)
+ </div>
+ {roleSharedWithAccordion ? (
+ <i className="fa fa-angle-up fa-lg font-weight-bold"></i>
) : (
- <p className="mt-1">--</p>
+ <i className="fa fa-angle-down fa-lg font-weight-bold"></i>
)}
+ </Accordion.Toggle>
+ </div>
+ <Accordion.Collapse eventKey="1">
+ <Card.Body>
+ <Card.Body>
+ {filteredRoleSharedWithMap != undefined &&
+ filteredRoleSharedWithMap.size > 0 ? (
+ Array.from(filteredRoleSharedWithMap).map(
+ ([key, value]) => (
+ <div
+ className="gds-principle-listing"
+ key={key}
+ >
+ <span title={key}>{key}</span>
+ {value.map((accessObj) => (
+ <span
+ title={accessObj.type}
+ key={accessObj.type}
+ >
+ {accessObj.type}
+ </span>
+ ))}
+ </div>
+ )
+ )
+ ) : (
+ <p className="mt-1">--</p>
+ )}
+ </Card.Body>
</Card.Body>
- </Card.Body>
- </Accordion.Collapse>
- </Card>
- </Accordion>
+ </Accordion.Collapse>
+ </Card>
+ </Accordion>
+ </div>
</div>
- </div>
- ) : (
- <div></div>
- )}
- </Tab>
- <Tab eventKey="accessGrants" title="ACCESS GRANTS">
- <div className="wrap-gds">
- {activeKey == "accessGrants" ? (
- <AccessGrantForm
- dataset={datasetInfo}
- onDataChange={handleAccessGrantChange}
- />
) : (
<div></div>
)}
- </div>
- </Tab>
- <Tab eventKey="history" title="HISTORY" />
+ </Tab>
+ )}
+ {(isSystemAdmin() ||
+ userAclPerm === "ADMIN" ||
+ userAclPerm === "AUDIT" ||
+ userAclPerm === "POLICY_ADMIN") && (
+ <Tab eventKey="accessGrants" title="ACCESS GRANTS">
+ <div className="wrap-gds">
+ {activeKey == "accessGrants" ? (
+ <AccessGrantForm
+ dataset={datasetInfo}
+ onDataChange={handleAccessGrantChange}
+ />
+ ) : (
+ <div></div>
+ )}
+ </div>
+ </Tab>
+ )}
+
+ {(isSystemAdmin() ||
+ userAclPerm === "ADMIN" ||
+ userAclPerm === "AUDIT") && (
+ <Tab eventKey="history" title="HISTORY" />
+ )}
+
<Tab
eventKey="termsOfUse"
title="TERMS OF USE"
@@ -1728,6 +1842,10 @@ const DatasetDetailLayout = () => {
type="checkbox"
name={obj.name}
value={obj.id}
+ id={obj.id}
+ checked={selectedDatashareList.includes(
+ obj.id.toString()
+ )}
onChange={checkBocChange}
/>
<span
@@ -1752,6 +1870,27 @@ const DatasetDetailLayout = () => {
) : (
<div></div>
)}
+ {datasharePageCount > 1 && (
+ <div className="d-flex">
+ <ReactPaginate
+ previousLabel={"<"}
+ nextLabel={">"}
+ pageClassName="page-item"
+ pageLinkClassName="page-link"
+ previousClassName="page-item"
+ previousLinkClassName="page-link"
+ nextClassName="page-item"
+ nextLinkClassName="page-link"
+ breakLabel={"..."}
+ pageCount={datasharePageCount}
+ onPageChange={handleDatasharePageClick}
+ breakClassName="page-item"
+ breakLinkClassName="page-link"
+ containerClassName="pagination"
+ activeClassName="active"
+ />
+ </div>
+ )}
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" size="sm" onClick={toggleClose}>
@@ -1790,7 +1929,7 @@ const DatasetDetailLayout = () => {
<Modal show={showActivateRequestModal} onHide={toggleClose}>
<Modal.Header closeButton>
- <span className="text-word-break">Activate Datashare</span>
+ <h3 className="gds-header bold">Activate Datashare</h3>
</Modal.Header>
<Modal.Body>
<div>
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetPolicyItemComp.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetPolicyItemComp.jsx
index 1a43bcabe..6bc775143 100755
--- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetPolicyItemComp.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetPolicyItemComp.jsx
@@ -24,7 +24,7 @@ import {
dragEnter,
drop,
dragOver,
- policyConditionUpdatedJSON,
+ policyConditionUpdatedJSON
} from "../../../utils/XAUtils";
import AsyncSelect from "react-select/async";
import { Field } from "react-final-form";
@@ -32,6 +32,7 @@ import { Form as FormB, Button } from "react-bootstrap";
import { isEmpty, isArray } from "lodash";
import Select from "react-select";
import Editable from "Components/Editable";
+import { CustomTooltip, Loader } from "../../../components/CommonComponents";
const DatasetPolicyItemComp = (props) => {
const {
@@ -39,7 +40,7 @@ const DatasetPolicyItemComp = (props) => {
attrName,
serviceCompDetails,
fetchPrincipleData,
- onRemovingPolicyItem,
+ onRemovingPolicyItem
} = props;
const dragOverItem = useRef();
const dragItem = useRef();
@@ -48,14 +49,14 @@ const DatasetPolicyItemComp = (props) => {
let srcOp = serviceCompDetails.accessTypes;
return srcOp.map(({ label, name: value }) => ({
label,
- value,
+ value
}));
};
const accessTypes = [
{ value: "_CREATE", label: "_CREATE" },
{ value: "_MANAGE", label: "_MANAGE" },
- { value: "_DELETE", label: "_DELETE" },
+ { value: "_DELETE", label: "_DELETE" }
];
const requiredForPolicyItem = (fieldVals, index) => {
@@ -122,6 +123,14 @@ const DatasetPolicyItemComp = (props) => {
}
};
+ const textareas = document.querySelectorAll(".autoResizeTextarea");
+ textareas.forEach((textarea) => {
+ textarea.addEventListener("input", function () {
+ this.style.height = "auto";
+ this.style.height = this.scrollHeight + "px";
+ });
+ });
+
return (
<>
<div className="gds-grant-det-cond gds-content-border">
@@ -164,14 +173,31 @@ const DatasetPolicyItemComp = (props) => {
/>
</div>
+ <div className="d-flex gap-1 mg-b-10">
+ <Field
+ name={`${name}.accesses`}
+ render={({ input, meta }) => (
+ <div className="flex-1">
+ <Select
+ {...input}
+ options={getAccessTypeOptions()}
+ menuPlacement="auto"
+ placeholder="Permissions"
+ isClearable
+ isMulti
+ />
+ </div>
+ )}
+ />
+ </div>
<div className="d-flex gap-1 mg-b-10">
{serviceCompDetails?.policyConditions?.length > 0 && (
<td
key="Policy Conditions"
- className="align-middle"
+ className="align-middle w-100"
>
<Field
- className="form-control"
+ className="form-control "
name={`${name}.conditions`}
validate={(value, formValues) =>
requiredForPolicyItem(
@@ -180,36 +206,45 @@ const DatasetPolicyItemComp = (props) => {
)
}
render={({ input, meta }) => (
- <div className="table-editable">
- <Editable
+ // <div className="table-editable">
+ // <Editable
+ // {...input}
+ // placement="auto"
+ // type="custom"
+ // conditionDefVal={policyConditionUpdatedJSON(
+ // serviceCompDetails.policyConditions
+ // )}
+ // selectProps={{ isMulti: true }}
+ // />
+ // </div>
+ <div style={{ position: "relative" }}>
+ <textarea
{...input}
- placement="auto"
- type="custom"
- conditionDefVal={policyConditionUpdatedJSON(
- serviceCompDetails.policyConditions
- )}
- selectProps={{ isMulti: true }}
+ placeholder="Enter Boolean Expression"
+ className="form-control autoResizeTextarea"
+ id="boolExp"
+ data-cy="boolExp"
+ //onChange={() => onRemovingPolicyItem()}
+ //value={input.value.expression}
+ rows={1}
+ />
+ <CustomTooltip
+ placement="left"
+ content={
+ <p
+ className="pd-10"
+ style={{ fontSize: "small" }}
+ >
+ JavaScript example awd awdawd
+ </p>
+ }
+ icon="fa-fw fa fa-info-circle gds-opacity-lowest gds-info-tarea"
/>
</div>
)}
/>
</td>
)}
- <Field
- name={`${name}.accesses`}
- render={({ input, meta }) => (
- <div className="flex-1">
- <Select
- {...input}
- options={getAccessTypeOptions()}
- menuPlacement="auto"
- placeholder="All Permissions"
- isClearable
- isMulti
- />
- </div>
- )}
- />
</div>
</div>
<div>
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/MyDatasetListing.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/MyDatasetListing.jsx
index f6a7fd991..3bf4347cd 100755
--- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/MyDatasetListing.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/MyDatasetListing.jsx
@@ -23,7 +23,6 @@ import { Button, Row, Col } from "react-bootstrap";
import XATableLayout from "../../../components/XATableLayout";
import dateFormat from "dateformat";
import { fetchApi } from "../../../utils/fetchAPI";
-import { Link } from "react-router-dom";
import StructuredFilter from "../../../components/structured-filter/react-typeahead/tokenizer";
import { Loader, BlockUi } from "../../../components/CommonComponents";
import {
@@ -180,21 +179,49 @@ const MyDatasetListing = () => {
navigate("/gds/create");
};
+ const navigateToDetailPage = (datasetId, perm) => {
+ navigate(`/gds/dataset/${datasetId}/detail`, {
+ state: {
+ userAclPerm: perm
+ }
+ });
+ };
+
const myDatasetColumns = React.useMemo(
() => [
{
Header: "Id",
accessor: "id",
- width: 25,
+ width: 80,
disableResizing: true,
disableSortBy: true,
getResizerProps: () => {},
- Cell: (rawValue) => {
+ Cell: ({ row }) => {
+ const hiddenValue = row.original.permissionForCaller;
return (
<div className="position-relative text-center">
- <Link title="Edit" to={`/gds/dataset/${rawValue.value}/detail`}>
- {rawValue.value}
- </Link>
+ <Button
+ data-id="datasetId"
+ data-cy="datasetId"
+ onClick={() =>
+ navigateToDetailPage(
+ row.original.id,
+ row.original.permissionForCaller
+ )
+ }
+ style={{
+ lineHeight: 1,
+ padding: 0,
+ backgroundColor: "transparent",
+ color: "#0b7fad",
+ border: 0,
+ outline: "none",
+ fontSize: 13,
+ cursor: "pointer"
+ }}
+ >
+ {row.original.id}
+ </Button>
</div>
);
}
@@ -322,33 +349,38 @@ const MyDatasetListing = () => {
{
Header: "Id",
accessor: "id",
- width: 25,
+ width: 80,
disableResizing: true,
disableSortBy: true,
getResizerProps: () => {},
Cell: ({ row }) => {
- const permissionForCaller = row.original.permissionForCaller;
- if (
- permissionForCaller === "ADMIN" ||
- permissionForCaller === "VIEW"
- ) {
- return (
- <div className="position-relative text-center">
- <Link
- title="Edit"
- to={`/gds/dataset/${row.original.id}/detail`}
- >
- {row.original.id}
- </Link>
- </div>
- );
- } else {
- return (
- <div className="position-relative text-center">
- <span>{row.original.id}</span>
- </div>
- );
- }
+ return (
+ <div className="position-relative text-center">
+ <Button
+ data-id="datasetId"
+ data-cy="datasetId"
+ disabled={row.original.permissionForCaller == "LIST"}
+ onClick={() =>
+ navigateToDetailPage(
+ row.original.id,
+ row.original.permissionForCaller
+ )
+ }
+ style={{
+ lineHeight: 1,
+ padding: 0,
+ backgroundColor: "transparent",
+ color: "#0b7fad",
+ border: 0,
+ outline: "none",
+ fontSize: 13,
+ cursor: "pointer"
+ }}
+ >
+ {row.original.id}
+ </Button>
+ </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 b13f02177..d0b8fadf7 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
@@ -51,6 +51,7 @@ const PrinciplePermissionComp = ({
userList,
groupList,
roleList,
+ isEditable,
onDataChange
}) => {
const [userOgList, setUserList] = useState(userList);
@@ -64,6 +65,7 @@ const PrinciplePermissionComp = ({
const [userAccordion, setUserAccordion] = useState(false);
const [groupAccordion, setGroupAccordion] = useState(false);
const [roleAccordion, setRoleAccordion] = useState(false);
+ const isPrincipleEditable = isEditable == undefined ? true : isEditable;
const [principleDetails, dispatch] = useReducer(
principleFormReducer,
initialState
@@ -78,24 +80,32 @@ const PrinciplePermissionComp = ({
const accessOptions = [
{ value: "LIST", label: "LIST" },
{ value: "VIEW", label: "VIEW" },
- { value: "ADMIN", label: "ADMIN" }
+ { value: "ADMIN", label: "ADMIN" },
+ { value: "AUDIT", label: "AUDIT" },
+ { value: "POLICY_ADMIN", label: "POLICY_ADMIN" }
];
const accessOptionsWithRemove = [
{ value: "LIST", label: "LIST" },
{ value: "VIEW", label: "VIEW" },
{ value: "ADMIN", label: "ADMIN" },
- { value: "Remove Access", label: "Remove Access" }
+ { value: "AUDIT", label: "AUDIT" },
+ { value: "POLICY_ADMIN", label: "POLICY_ADMIN" }
];
+ if (isEditable) {
+ accessOptionsWithRemove.push({
+ value: "Remove Access",
+ label: "Remove Access"
+ });
+ }
+
const selectedPrincipal = (e, input) => {
dispatch({
type: "SET_SELECTED_PRINCIPLE",
selectedPrinciple: e
});
input.onChange(e);
- console.log("Adding to selectedPrinciple");
- console.log(selectedPrinciple);
};
const filterPrincipleOp = ({ data }) => {
@@ -191,11 +201,6 @@ const PrinciplePermissionComp = ({
setFilteredRoleList(tempRoleList);
}
- console.log("groupOgList");
- console.log(groupOgList);
- console.log("roleOgList");
- console.log(roleOgList);
-
onDataChange(tempUserList, tempGroupList, tempRoleList);
setSelectedAccess({ value: "LIST", label: "LIST" });
@@ -203,8 +208,6 @@ const PrinciplePermissionComp = ({
type: "SET_SELECTED_PRINCIPLE",
selectedPrinciple: []
});
- console.log("After clearing selectedPrinciple");
- console.log(selectedPrinciple);
};
const changeUserAccordion = () => {
@@ -367,78 +370,83 @@ const PrinciplePermissionComp = ({
};
return (
- <div className="gds-tab-content gds-content-border">
- <div className="gds-form-input">
- <Field
- className="form-control"
- name="selectedPrinciple"
- render={({ input, meta }) => (
- <div className="gds-add-principle">
- {" "}
- <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="Select Principals"
- data-name="usersSelect"
- data-cy="usersSelect"
- />
- <Field
- name="accessPermList"
- className="form-control"
- render={({ input }) => (
- <Select
- theme={serviceSelectTheme}
- styles={customStyles}
- options={accessOptions}
- onChange={(e) => setACL(e, input)}
- value={selectedAccess}
- menuPlacement="auto"
- isClearable
- />
- )}
- ></Field>
- <Button
- type="button"
- className="btn btn-primary"
- onClick={() => {
- userOgList;
- if (
- !selectedPrinciple ||
- selectedPrinciple[0].value == undefined ||
- selectedPrinciple.length === 0
- ) {
- toast.dismiss(toastId.current);
- toastId.current = toast.error("Please select principal!!");
- return false;
- }
- addInSelectedPrincipal(selectedPrinciple, input);
- filterPrincipleList(
- undefined,
- undefined,
- undefined,
- undefined
- );
- }}
- size="md"
- data-name="usersAddBtn"
- data-cy="usersAddBtn"
- >
- Add Principals
- </Button>
- </div>
- )}
- />
- </div>
+ <div className="gds-tab-content">
+ {isPrincipleEditable && (
+ <div className="gds-form-input">
+ <Field
+ className="form-control"
+ name="selectedPrinciple"
+ render={({ input, meta }) => (
+ <div className="gds-add-principle">
+ {" "}
+ <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="Select Principals"
+ data-name="usersSelect"
+ data-cy="usersSelect"
+ />
+ <Field
+ name="accessPermList"
+ className="form-control"
+ render={({ input }) => (
+ <Select
+ theme={serviceSelectTheme}
+ styles={customStyles}
+ options={accessOptions}
+ onChange={(e) => setACL(e, input)}
+ value={selectedAccess}
+ menuPlacement="auto"
+ isClearable
+ />
+ )}
+ ></Field>
+ <Button
+ type="button"
+ className="btn btn-primary"
+ onClick={() => {
+ userOgList;
+ if (
+ !selectedPrinciple ||
+ selectedPrinciple[0].value == undefined ||
+ selectedPrinciple.length === 0
+ ) {
+ toast.dismiss(toastId.current);
+ toastId.current = toast.error(
+ "Please select principal!!"
+ );
+ return false;
+ }
+ addInSelectedPrincipal(selectedPrinciple, input);
+ filterPrincipleList(
+ undefined,
+ undefined,
+ undefined,
+ undefined
+ );
+ }}
+ size="md"
+ data-name="usersAddBtn"
+ data-cy="usersAddBtn"
+ >
+ Add Principals
+ </Button>
+ </div>
+ )}
+ />
+ </div>
+ )}
+
<div>
<Card className="gds-section-card gds-bg-white">
<div className="gds-section-title">
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 0c75642e1..57194742d 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
@@ -232,7 +232,6 @@ const AddDatashareView = () => {
return;
} else {
fetchServiceDef(selectedService.def);
- fetchServiceByName(selectedService.label);
setStep(step + 1);
}
setStep(step + 1);
@@ -281,20 +280,6 @@ const AddDatashareView = () => {
setServiceDef(modifiedServiceDef);
};
- const fetchServiceByName = async (serviceName) => {
- let serviceResp = [];
- try {
- serviceResp = await fetchApi({
- url: "plugins/services/name/hase_service_1"
- });
- } catch (error) {
- console.error(
- `Error occurred while fetching Service or CSRF headers! ${error}`
- );
- }
- setService(serviceResp.data);
- };
-
const datashareNameChange = (event) => {
setName(event.target.value);
console.log("DatashareName is:", event.target.value);
@@ -714,7 +699,7 @@ const AddDatashareView = () => {
</div>
</div>
</div>
- {maskDef ? (
+ {false && maskDef ? (
<div className="gds-section-title">
<p className="gds-card-heading">
Tag Masking Configuration
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 a583e7d62..b6cc774ef 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
@@ -501,8 +501,7 @@ const AddSharedResourceComp = ({
<i className="fa fa-angle-down pull-down fa-lg font-weight-bold"></i>
)}
<Link to="">
- Add Default access type, row level filters and
- conditions (Optional)
+ Add permission and conditions (Optional)
</Link>
</Accordion.Toggle>
</div>
@@ -534,7 +533,7 @@ const AddSharedResourceComp = ({
)}
/>
</div>
- {showRowFilterInput ? (
+ {false && showRowFilterInput ? (
<div className="mb-3 form-group row">
<Col sm={3}>
<label className="form-label pull-right fnt-14">
@@ -561,7 +560,7 @@ const AddSharedResourceComp = ({
<div></div>
)}
- {showMaskInput ? (
+ {false && showMaskInput ? (
<div className="mb-3 form-group row">
<Col sm={3}>
<label className="form-label pull-right fnt-14">
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailFullView.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailFullView.jsx
new file mode 100644
index 000000000..a315de5e1
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailFullView.jsx
@@ -0,0 +1,659 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useState, useEffect } from "react";
+import { useParams, useNavigate, Link, useLocation } from "react-router-dom";
+import { Button, Accordion, Card, Col } from "react-bootstrap";
+import CustomBreadcrumb from "../../CustomBreadcrumb";
+import { Loader } from "../../../components/CommonComponents";
+import { Form } from "react-final-form";
+import { fetchApi } from "../../../utils/fetchAPI";
+import dateFormat from "dateformat";
+import PrinciplePermissionComp from "../Dataset/PrinciplePermissionComp";
+import ReactPaginate from "react-paginate";
+import { isSystemAdmin } from "../../../utils/XAUtils";
+
+const DatashareDetailFullView = () => {
+ let { datashareId } = useParams();
+ const { state } = useLocation();
+ const userAclPerm = state?.userAclPerm;
+ const datashareName = state?.datashareName;
+ const [loader, setLoader] = useState(true);
+ const [datashareInfo, setDatashareInfo] = useState({});
+ const [userList, setUserList] = useState([]);
+ const [groupList, setGroupList] = useState([]);
+ const [roleList, setRoleList] = useState([]);
+ const [filteredUserList, setFilteredUserList] = useState([]);
+ const [filteredGroupList, setFilteredGroupList] = useState([]);
+ const [filteredRoleList, setFilteredRoleList] = useState([]);
+ const navigate = useNavigate();
+ const [resourceAccordionState, setResourceAccordionState] = useState({});
+ const [sharedResourcePageCount, setSharedResourcePageCount] = useState();
+ const [sharedResources, setSharedResources] = useState([]);
+ const itemsPerPage = 5;
+ const [dataShareRequestsList, setDataShareRequestsList] = useState([]);
+ const [requestAccordionState, setRequestAccordionState] = useState({});
+ const [requestPageCount, setRequestPageCount] = useState();
+ const [completeSharedResourceList, setCompleteSharedResourceList] = useState(
+ []
+ );
+ const [completeDatashareRequestsList, setCompleteDatashareRequestsList] =
+ useState([]);
+
+ useEffect(() => {
+ fetchDatashareInfo(datashareId);
+ fetchSharedResourceForDatashare(datashareName, 0, true);
+ fetchDatashareRequestList(undefined, 0, true);
+ fetchDatashareRequestList(undefined, 0, false);
+ }, []);
+
+ const fetchDatashareInfo = async (datashareId) => {
+ try {
+ setLoader(true);
+ const resp = await fetchApi({
+ url: `gds/datashare/${datashareId}`
+ });
+ setLoader(false);
+ setDatashareInfo(resp.data);
+ if (resp.data.acl != undefined) setPrincipleAccordianData(resp.data.acl);
+ fetchSharedResourceForDatashare(resp.data.name, 0, false);
+ setLoader(false);
+ } catch (error) {
+ setLoader(false);
+ console.error(
+ `Error occurred while fetching datashare details ! ${error}`
+ );
+ }
+ };
+
+ const fetchSharedResourceForDatashare = async (
+ datashareName,
+ currentPage,
+ getCompleteList
+ ) => {
+ try {
+ let params = {};
+ let itemPerPageCount = getCompleteList ? 999999999 : itemsPerPage;
+ params["pageSize"] = itemPerPageCount;
+ params["page"] = currentPage;
+ params["startIndex"] = currentPage * itemPerPageCount;
+ params["dataShareId"] = datashareId;
+ const resp = await fetchApi({
+ url: `gds/resource`,
+ params: params
+ });
+ let accordianState = {};
+ resp.data.list.map(
+ (item) =>
+ (accordianState = { ...accordianState, ...{ [item.id]: false } })
+ );
+ setResourceAccordionState(accordianState);
+ setSharedResourcePageCount(
+ Math.ceil(resp.data.totalCount / itemPerPageCount)
+ );
+ if (getCompleteList) {
+ setCompleteSharedResourceList(resp.data.list);
+ } else {
+ setSharedResources(resp.data.list);
+ }
+ } catch (error) {
+ console.error(
+ `Error occurred while fetching shared resource details ! ${error}`
+ );
+ }
+ };
+
+ const fetchDatashareRequestList = async (
+ datasetName,
+ currentPage,
+ getCompleteList
+ ) => {
+ try {
+ let params = {};
+ let itemsPerPageCount = getCompleteList ? 999999999 : itemsPerPage;
+ params["pageSize"] = itemsPerPageCount;
+ params["page"] = currentPage;
+ params["startIndex"] = currentPage * itemsPerPageCount;
+ params["dataShareId"] = datashareId;
+ const resp = await fetchApi({
+ url: `gds/datashare/dataset`,
+ params: params
+ });
+ let accordianState = {};
+ resp.data.list.map(
+ (item) =>
+ (accordianState = { ...accordianState, ...{ [item.id]: false } })
+ );
+ setRequestAccordionState(accordianState);
+ setRequestPageCount(Math.ceil(resp.data.totalCount / itemsPerPageCount));
+ if (getCompleteList) {
+ setCompleteDatashareRequestsList(resp.data.list);
+ } else {
+ setDataShareRequestsList(resp.data.list);
+ }
+ } catch (error) {
+ console.error(
+ `Error occurred while fetching Datashare requests details ! ${error}`
+ );
+ }
+ };
+
+ const setPrincipleAccordianData = (principle) => {
+ let userPrinciples = principle.users;
+ let groupPrinciples = principle.groups;
+ let rolePrinciples = principle.roles;
+
+ let tempUserList = [];
+ let tempGroupList = [];
+ let tempRoleList = [];
+ let userList = [];
+ let groupList = [];
+ let roleList = [];
+ if (userPrinciples != undefined) {
+ Object.entries(userPrinciples).map(([key, value]) => {
+ tempUserList.push({ name: key, type: "USER", perm: value });
+ });
+ }
+ if (groupPrinciples != undefined) {
+ Object.entries(groupPrinciples).map(([key, value]) => {
+ tempGroupList.push({ name: key, type: "GROUP", perm: value });
+ });
+ }
+ if (rolePrinciples != undefined) {
+ Object.entries(rolePrinciples).map(([key, value]) => {
+ tempRoleList.push({ name: key, type: "ROLE", perm: value });
+ });
+ }
+ setUserList([...userList, ...tempUserList]);
+ setFilteredUserList([...filteredUserList, ...tempUserList]);
+ setGroupList([...groupList, ...tempGroupList]);
+ setFilteredGroupList([...filteredGroupList, ...tempGroupList]);
+ setRoleList([...roleList, ...tempRoleList]);
+ setFilteredRoleList([...filteredRoleList, ...tempRoleList]);
+ };
+
+ const back = () => {
+ navigate(`/gds/datashare/${datashareId}/detail`);
+ };
+
+ const onSharedResourceAccordionChange = (id) => {
+ setResourceAccordionState({
+ ...resourceAccordionState,
+ ...{ [id]: !resourceAccordionState[id] }
+ });
+ };
+
+ const handleSharedResourcePageClick = ({ selected }) => {
+ fetchSharedResourceForDatashare(datashareInfo.name, selected, false);
+ };
+
+ const handleRequestPageClick = ({ selected }) => {
+ fetchDatashareRequestList(undefined, selected, false);
+ };
+
+ const redirectToDatasetDetailView = (datasetId) => {
+ navigate(`/gds/dataset/${datasetId}/detail`);
+ };
+
+ const onRequestAccordionChange = (id) => {
+ setRequestAccordionState({
+ ...requestAccordionState,
+ ...{ [id]: !requestAccordionState[id] }
+ });
+ };
+
+ const downloadJsonFile = () => {
+ let jsonData = datashareInfo;
+ jsonData.resources = completeSharedResourceList;
+ jsonData.datasets = completeDatashareRequestsList;
+ const jsonContent = JSON.stringify(jsonData);
+ const blob = new Blob([jsonContent], { type: "application/json" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = datashareInfo.name + ".json"; // Set the desired file name
+ a.click();
+ URL.revokeObjectURL(url);
+ };
+
+ const handleSubmit = () => {};
+ return (
+ <>
+ <Form
+ onSubmit={handleSubmit}
+ render={({}) => (
+ <React.Fragment>
+ {loader ? (
+ <Loader />
+ ) : (
+ <>
+ <div className="gds-header-wrapper gap-half">
+ <Button
+ variant="light"
+ className="border-0 bg-transparent"
+ onClick={back}
+ size="sm"
+ data-id="back"
+ data-cy="back"
+ >
+ <i className="fa fa-angle-left fa-lg font-weight-bold" />
+ </Button>
+ <h3 className="gds-header bold">
+ <span
+ title={datashareInfo.name}
+ className="text-truncate"
+ style={{ maxWidth: "700px", display: "inline-block" }}
+ >
+ Datashare : {datashareInfo.name}
+ </span>
+ </h3>
+ <CustomBreadcrumb />
+ <span className="pipe"></span>
+ <div className="gds-header-btn-grp">
+ <Button
+ variant="primary"
+ onClick={() => downloadJsonFile()}
+ size="sm"
+ data-id="save"
+ data-cy="save"
+ >
+ Download JSON
+ </Button>
+ </div>
+ </div>
+ <div>
+ <div className="gds-tab-content gds-content-border px-3">
+ <div className="gds-inline-field-grp">
+ <div className="wrapper">
+ <div
+ className="gds-left-inline-field pl-1 fnt-14"
+ height="30px"
+ >
+ <span className="gds-label-color">Date Updated</span>
+ </div>
+ <div className="fnt-14" line-height="30px">
+ {dateFormat(
+ datashareInfo.updateTime,
+ "mm/dd/yyyy hh:MM:ss TT"
+ )}
+ </div>
+ </div>
+
+ <div className="wrapper">
+ <div
+ className="gds-left-inline-field pl-1 fnt-14"
+ line-height="30px"
+ >
+ <span className="gds-label-color">Date Created</span>
+ </div>
+ <div className="fnt-14" line-height="30px">
+ {dateFormat(
+ datashareInfo.createTime,
+ "mm/dd/yyyy hh:MM:ss TT"
+ )}
+ </div>
+ </div>
+ </div>
+ <div>
+ <div className="fnt-14 pl-1">
+ <span className="gds-label-color">Description</span>
+ </div>
+ </div>
+ <div>
+ <div>
+ <textarea
+ placeholder="Datashare Description"
+ className="form-control gds-description pl-1"
+ id="description"
+ data-cy="description"
+ value={datashareInfo.description}
+ rows={5}
+ />
+ </div>
+ </div>
+ </div>
+ {(isSystemAdmin() ||
+ userAclPerm == "ADMIN" ||
+ userAclPerm == "AUDIT") && (
+ <PrinciplePermissionComp
+ userList={userList}
+ groupList={groupList}
+ roleList={roleList}
+ isEditable={false}
+ />
+ )}
+ </div>
+ <div className="gds-tab-content gds-content-border">
+ <div className="gds-section-title">
+ <p className="gds-card-heading">Shared Resources</p>
+ </div>
+ {sharedResources.length > 0 ? (
+ sharedResources.map((obj, index) => {
+ return (
+ // <ResourceAccordian item={obj} />
+ <div>
+ <Accordion className="mg-b-10" defaultActiveKey="0">
+ <div className="border-bottom">
+ <Accordion.Toggle
+ as={Card.Header}
+ eventKey={obj.id}
+ onClick={() =>
+ onSharedResourceAccordionChange(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-1">
+ {resourceAccordionState[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>
+ )}
+ <div className="d-flex justify-content-between">
+ <h6 className="m-0">{obj.name}</h6>
+ </div>
+ </div>
+ </div>
+ </Accordion.Toggle>
+ <Accordion.Collapse eventKey={obj.id}>
+ <Card.Body>
+ <div className="gds-added-res-listing">
+ {Object.entries(obj.resource).map(
+ ([key, value]) => {
+ console.log(key);
+ console.log(value);
+ return (
+ <div className="mb-1 form-group row">
+ <Col sm={3}>
+ <label className="form-label fnt-14">
+ {key}
+ </label>
+ </Col>
+ <Col sm={9}>
+ {value.values.toString()}
+ </Col>
+ </div>
+ );
+ }
+ )}
+ <div className="mb-1 form-group row">
+ <Col sm={3}>
+ <label className="form-label gds-detail-label fnt-14">
+ Additional Info
+ </label>
+ </Col>
+ <Col sm={9}>
+ <Link
+ className="mb-3"
+ to=""
+ onClick={() =>
+ showConfitionModal(obj)
+ }
+ >
+ View Access Details
+ </Link>
+ </Col>
+ </div>
+ </div>
+ </Card.Body>
+ </Accordion.Collapse>
+ </div>
+ </Accordion>
+ </div>
+ );
+ })
+ ) : (
+ <div>--</div>
+ )}
+ {sharedResourcePageCount > 1 && (
+ <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={sharedResourcePageCount}
+ onPageChange={handleSharedResourcePageClick}
+ breakClassName="page-item"
+ breakLinkClassName="page-link"
+ containerClassName="pagination"
+ activeClassName="active"
+ />
+ )}
+ </div>
+
+ <div className="gds-tab-content gds-content-border">
+ <div className="gds-section-title">
+ <p className="gds-card-heading">Shared With</p>
+ </div>
+ <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>
+ </div>
+ </div>
+ </Accordion.Toggle>
+ <Accordion.Collapse eventKey="1">
+ <Card.Body>
+ <div className="d-flex justify-content-between">
+ {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>
+ ) : (
+ <div>--</div>
+ )}
+ </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>
+ )}
+ {requestPageCount > 1 && (
+ <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>
+ </div>
+ <div className="gds-tab-content gds-content-border">
+ <div>
+ <div className="usr-grp-role-search-width">
+ <p className="gds-content-header">Terms & Conditions</p>
+ </div>
+ </div>
+ <div>
+ <div>
+ <textarea
+ placeholder="Terms & Conditions"
+ className="form-control"
+ id="termsAndConditions"
+ data-cy="termsAndConditions"
+ value={datashareInfo.termsOfUse}
+ rows={16}
+ />
+ </div>
+ </div>
+ </div>
+ </>
+ )}
+ </React.Fragment>
+ )}
+ />
+ </>
+ );
+};
+
+export default DatashareDetailFullView;
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 8a798d923..c0c52aea6 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
@@ -18,7 +18,7 @@
*/
import React, { useState, useEffect } from "react";
-import { useParams, useNavigate, Link } from "react-router-dom";
+import { useParams, useNavigate, Link, useLocation } from "react-router-dom";
import { fetchApi } from "../../../utils/fetchAPI";
import { Loader } from "../../../components/CommonComponents";
import StructuredFilter from "../../../components/structured-filter/react-typeahead/tokenizer";
@@ -42,9 +42,13 @@ import arrayMutators from "final-form-arrays";
import ReactPaginate from "react-paginate";
import AddSharedResourceComp from "./AddSharedResourceComp";
import CustomBreadcrumb from "../../CustomBreadcrumb";
+import { isSystemAdmin } from "../../../utils/XAUtils";
const DatashareDetailLayout = () => {
let { datashareId } = useParams();
+ const { state } = useLocation();
+ const userAclPerm = state?.userAclPerm;
+ const datashareName = state?.datashareName;
const [activeKey, setActiveKey] = useState("overview");
const [datashareInfo, setDatashareInfo] = useState({});
const [datashareDescription, setDatashareDescription] = useState();
@@ -87,6 +91,11 @@ const DatashareDetailLayout = () => {
] = useState(false);
const [showDeleteDatashareModal, setShowDeleteDatashareModal] =
useState(false);
+ const [completeSharedResourceList, setCompleteSharedResourceList] = useState(
+ []
+ );
+ const [completeDatashareRequestsList, setCompleteDatashareRequestsList] =
+ useState([]);
const toggleConfirmModalForDatashareDelete = () => {
setShowDeleteDatashareModal(true);
@@ -98,6 +107,8 @@ const DatashareDetailLayout = () => {
useEffect(() => {
fetchDatashareInfo(datashareId);
+ fetchSharedResourceForDatashare(datashareName, 0, true);
+ fetchDatashareRequestList(undefined, 0, true);
}, []);
const handleTabSelect = (key) => {
@@ -105,9 +116,9 @@ const DatashareDetailLayout = () => {
setShowConfirmModal(true);
} else {
if (key == "resources") {
- fetchSharedResourceForDatashare(datashareInfo.name, 0);
+ fetchSharedResourceForDatashare(datashareInfo.name, 0, false);
} else if (key == "sharedWith") {
- fetchDatashareRequestList(undefined, 0);
+ fetchDatashareRequestList(undefined, 0, false);
}
setActiveKey(key);
}
@@ -178,15 +189,16 @@ const DatashareDetailLayout = () => {
const fetchSharedResourceForDatashare = async (
datashareName,
- currentPage
+ currentPage,
+ getCompleteList
) => {
try {
let params = {};
- params["pageSize"] = itemsPerPage;
+ let itemPerPageCount = getCompleteList ? 999999999 : itemsPerPage;
+ params["pageSize"] = itemPerPageCount;
params["page"] = currentPage;
- params["startIndex"] = currentPage * itemsPerPage;
- //params["startIndex"] = 0;
- params["dataShareName"] = datashareName;
+ params["startIndex"] = currentPage * itemPerPageCount;
+ params["dataShareId"] = datashareId;
setResourceContentLoader(true);
const resp = await fetchApi({
url: `gds/resource`,
@@ -200,14 +212,13 @@ const DatashareDetailLayout = () => {
);
setResourceAccordionState(accordianState);
setSharedResourcePageCount(
- Math.ceil(resp.data.totalCount / itemsPerPage)
+ Math.ceil(resp.data.totalCount / itemPerPageCount)
);
- //setSharedResourcePageCount(resp.data.totalCount);
- //setSharedResourcePageCount(Math.ceil(data.length / itemsPerPage));
- //const offset = currentPage * itemsPerPage;
- //const displayedData = data.slice(offset, offset + itemsPerPage);
- //setSharedResources(resp.data.list);
- setSharedResources(resp.data.list);
+ if (!getCompleteList) {
+ setSharedResources(resp.data.list);
+ } else {
+ setCompleteSharedResourceList(resp.data.list);
+ }
} catch (error) {
setResourceContentLoader(false);
console.error(
@@ -218,22 +229,26 @@ const DatashareDetailLayout = () => {
const handleSharedResourcePageClick = ({ selected }) => {
setCurrentPage(selected);
- fetchSharedResourceForDatashare(datashareInfo.name, selected);
+ fetchSharedResourceForDatashare(datashareInfo.name, selected, false);
};
const handleRequestPageClick = ({ selected }) => {
setRequestCurrentPage(selected);
- fetchDatashareRequestList(undefined, selected);
+ fetchDatashareRequestList(undefined, selected, false);
};
- const fetchDatashareRequestList = async (datasetName, currentPage) => {
+ const fetchDatashareRequestList = async (
+ datasetName,
+ currentPage,
+ getCompleteList
+ ) => {
try {
let params = {};
- params["pageSize"] = itemsPerPage;
+ let itemPerPageCount = getCompleteList ? 999999999 : itemsPerPage;
+ params["pageSize"] = itemPerPageCount;
params["page"] = currentPage;
- params["startIndex"] = currentPage * itemsPerPage;
+ params["startIndex"] = currentPage * itemPerPageCount;
params["dataShareId"] = datashareId;
- //params["datasetName"] = datasetName;
setRequestContentLoader(true);
const resp = await fetchApi({
url: `gds/datashare/dataset`,
@@ -241,14 +256,13 @@ const DatashareDetailLayout = () => {
});
setRequestContentLoader(false);
let accordianState = {};
- resp.data.list.map(
- (item) =>
- (accordianState = { ...accordianState, ...{ [item.id]: false } })
- );
setRequestAccordionState(accordianState);
- setRequestPageCount(Math.ceil(resp.data.totalCount / itemsPerPage));
-
- setDataShareRequestsList(resp.data.list);
+ setRequestPageCount(Math.ceil(resp.data.totalCount / itemPerPageCount));
+ if (!getCompleteList) {
+ setDataShareRequestsList(resp.data.list);
+ } else {
+ setCompleteDatashareRequestsList(resp.data.list);
+ }
} catch (error) {
setRequestContentLoader(false);
console.error(
@@ -296,7 +310,7 @@ const DatashareDetailLayout = () => {
});
setBlockUI(false);
toast.success(" Success! Shared resource deleted successfully");
- fetchSharedResourceForDatashare(datashareInfo.name, 0);
+ fetchSharedResourceForDatashare(datashareInfo.name, 0, false);
} catch (error) {
setBlockUI(false);
let errorMsg = "Failed to delete Shared resource : ";
@@ -342,7 +356,7 @@ const DatashareDetailLayout = () => {
};
const handleSharedResourceChange = () => {
- fetchSharedResourceForDatashare(datashareInfo.name, currentPage);
+ fetchSharedResourceForDatashare(datashareInfo.name, currentPage, false);
};
const updateDatashareDetails = async () => {
@@ -418,7 +432,7 @@ const DatashareDetailLayout = () => {
}
setShowDatashareRequestDeleteConfirmModal(false);
toast.success(successMsg);
- fetchDatashareRequestList(undefined, requestCurrentPage);
+ fetchDatashareRequestList(undefined, requestCurrentPage, false);
//fetchSharedResourceForDatashare(datashareInfo.name);
setLoader(false);
} catch (error) {
@@ -467,6 +481,27 @@ const DatashareDetailLayout = () => {
});
};
+ const navigateToFullView = () => {
+ navigate(`/gds/datashare/${datashareId}/fullview`, {
+ userAclPerm: userAclPerm,
+ datashareNamee: datashareName
+ });
+ };
+
+ const downloadJsonFile = () => {
+ let jsonData = datashareInfo;
+ jsonData.resources = completeSharedResourceList;
+ jsonData.datasets = completeDatashareRequestsList;
+ const jsonContent = JSON.stringify(jsonData);
+ const blob = new Blob([jsonContent], { type: "application/json" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = datashareInfo.name + ".json"; // Set the desired file name
+ a.click();
+ URL.revokeObjectURL(url);
+ };
+
return (
<>
<Form
@@ -489,44 +524,53 @@ const DatashareDetailLayout = () => {
</Button>
<h3 className="gds-header bold">
<span
+ title={datashareInfo.name}
className="text-truncate"
- style={{ maxWidth: "900px", display: "inline-block" }}
+ style={{ maxWidth: "700px", display: "inline-block" }}
>
Datashare : {datashareInfo.name}
</span>
</h3>
<CustomBreadcrumb />
- <span className="pipe"></span>
- {saveCancelButtons ? (
- <div className="gds-header-btn-grp">
- <Button
- variant="primary"
- 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>
+
+ {(isSystemAdmin() || userAclPerm == "ADMIN") && (
+ <span className="pipe"></span>
+ )}
+ {(isSystemAdmin() || userAclPerm == "ADMIN") && (
+ <div>
+ {saveCancelButtons ? (
+ <div className="gds-header-btn-grp">
+ <Button
+ variant="primary"
+ 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>
+ ) : (
+ <AddSharedResourceComp
+ datashareId={datashareId}
+ onSharedResourceDataChange={handleSharedResourceChange}
+ onToggleAddResourceClose={toggleAddResourceModalClose}
+ isEdit={false}
+ loadSharedResource={loadSharedResource}
+ />
+ )}
</div>
- ) : (
- <AddSharedResourceComp
- datashareId={datashareId}
- onSharedResourceDataChange={handleSharedResourceChange}
- onToggleAddResourceClose={toggleAddResourceModalClose}
- isEdit={false}
- loadSharedResource={loadSharedResource}
- />
)}
+
<div>
<DropdownButton
id="dropdown-item-button"
@@ -536,9 +580,7 @@ const DatashareDetailLayout = () => {
>
<Dropdown.Item
as="button"
- // onClick={() => {
- // showViewModal(serviceData?.id);
- // }}
+ onClick={() => navigateToFullView()}
data-name="fullView"
data-id="fullView"
data-cy="fullView"
@@ -558,9 +600,7 @@ const DatashareDetailLayout = () => {
</Dropdown.Item>
<Dropdown.Item
as="button"
- // onClick={() => {
- // showViewModal(serviceData?.id);
- // }}
+ onClick={() => downloadJsonFile()}
data-name="downloadJson"
data-id="downloadJson"
data-cy="downloadJson"
@@ -652,12 +692,16 @@ const DatashareDetailLayout = () => {
</div>
</div>
</div>
- <PrinciplePermissionComp
- userList={userList}
- groupList={groupList}
- roleList={roleList}
- onDataChange={handleDataChange}
- />
+ {(isSystemAdmin() ||
+ userAclPerm == "ADMIN" ||
+ userAclPerm == "AUDIT") && (
+ <PrinciplePermissionComp
+ userList={userList}
+ groupList={groupList}
+ roleList={roleList}
+ onDataChange={handleDataChange}
+ />
+ )}
</div>
) : (
<div></div>
@@ -718,60 +762,46 @@ const DatashareDetailLayout = () => {
</h6>
</div>
</div>
- <div className="d-flex gap-half align-items-start">
- <AddSharedResourceComp
- datashareId={
- datashareId
- }
- onSharedResourceDataChange={
- handleSharedResourceChange
- }
- onToggleAddResourceClose={
- toggleAddResourceModalClose
- }
- isEdit={true}
- sharedResourceId={
- obj.id
- }
- loadSharedResource={
- loadSharedResource
- }
- />
- {/* <Button
- variant="outline-dark"
- size="sm"
- title="Edit"
- onClick={(e) => {
- e.stopPropagation();
- setLoadSharedResource(
- obj
- );
- setShowAddResourceModal(
- true
- );
- }}
- data-name="editSharedResource"
- data-id={obj.id}
- >
- <i className="fa-fw fa fa-edit"></i>
- </Button> */}
- <Button
- variant="danger"
- size="sm"
- title="Delete"
- onClick={() =>
- toggleConfirmModalForDelete(
- obj.id,
- obj.name
- )
- }
- 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>
+ {(isSystemAdmin() ||
+ userAclPerm ==
+ "ADMIN") && (
+ <div className="d-flex gap-half align-items-start">
+ <AddSharedResourceComp
+ datashareId={
+ datashareId
+ }
+ onSharedResourceDataChange={
+ handleSharedResourceChange
+ }
+ onToggleAddResourceClose={
+ toggleAddResourceModalClose
+ }
+ isEdit={true}
+ sharedResourceId={
+ obj.id
+ }
+ loadSharedResource={
+ loadSharedResource
+ }
+ />
+ <Button
+ variant="danger"
+ size="sm"
+ title="Delete"
+ onClick={() =>
+ toggleConfirmModalForDelete(
+ obj.id,
+ obj.name
+ )
+ }
+ 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
@@ -831,23 +861,25 @@ const DatashareDetailLayout = () => {
</div>
)}
- <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={sharedResourcePageCount}
- onPageChange={handleSharedResourcePageClick}
- breakClassName="page-item"
- breakLinkClassName="page-link"
- containerClassName="pagination"
- activeClassName="active"
- />
+ {sharedResourcePageCount > 1 && (
+ <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={sharedResourcePageCount}
+ onPageChange={handleSharedResourcePageClick}
+ breakClassName="page-item"
+ breakLinkClassName="page-link"
+ containerClassName="pagination"
+ activeClassName="active"
+ />
+ )}
</div>
</Card>
</div>
@@ -947,126 +979,104 @@ const DatashareDetailLayout = () => {
>
<i className="fa-fw fa fa-eye fa-fw fa fa-large" />
</Button>
- <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>
+ {(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 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"]}
+ {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>
- </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{" "}
+ {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>
- <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{" "}
+ <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>
- <span>
- {dateFormat(
- obj
- .validitySchedule
- .endTime,
- "mm/dd/yyyy hh:MM:ss TT"
- )}
- </span>
- </div>
- </div>
- ) : (
- <p>--</p>
- )}
- {/* {obj.validitySchedule !==
- undefined ? (
- <div className="gds-flex">
- <div className="gds-right-inline-field">
- <span>
- Start Time:{" "}
- {dateFormat(
- obj
- .validitySchedule
- .startTime,
- "mm/dd/yyyy hh:MM:ss TT"
- )}
- </span>
- </div>
- <div className="gds-right-inline-field">
- <span>
- End Time:{" "}
- {dateFormat(
- obj
- .validitySchedule
- .endTime,
- "mm/dd/yyyy hh:MM:ss TT"
- )}
- </span>
- </div>
- <div>
- <span>
- {
- obj
- .validitySchedule
- .timeZone
- }
- </span>
</div>
- </div>
- ) : (
- <div>--</div>
- )} */}
- </div>
+ ) : (
+ <p>--</p>
+ )}
+ </div>
+ )}
<div className="gds-right-inline-field-grp">
<div className="wrapper">
<div>Added</div>
@@ -1112,23 +1122,25 @@ const DatashareDetailLayout = () => {
) : (
<div></div>
)}
- <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"
- />
+ {requestPageCount > 1 && (
+ <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>
</Tab>
@@ -1143,8 +1155,14 @@ const DatashareDetailLayout = () => {
<div></div>
)}
</Tab>
- <Tab eventKey="history" title="HISTORY"></Tab>
- <Tab eventKey="termsOfUser" title="TERMS OF USE">
+
+ {(isSystemAdmin() ||
+ userAclPerm == "ADMIN" ||
+ userAclPerm == "AUDIT") && (
+ <Tab eventKey="history" title="HISTORY"></Tab>
+ )}
+
+ <Tab eventKey="termsOfUse" title="TERMS OF USE">
<div className="gds-tab-content gds-content-border">
<div>
<div className="usr-grp-role-search-width">
@@ -1264,16 +1282,21 @@ const DatashareDetailLayout = () => {
: ""}
</div>
</div>
- <div className="wrapper">
- <div className="gds-left-inline-field" height="30px">
- Row Filter :
- </div>
- <div line-height="30px">
- {conditionModalData?.rowFilter != undefined
- ? conditionModalData.rowFilter.filterExpr
- : ""}
+ {false && (
+ <div className="wrapper">
+ <div
+ className="gds-left-inline-field"
+ height="30px"
+ >
+ Row Filter :
+ </div>
+ <div line-height="30px">
+ {conditionModalData?.rowFilter != undefined
+ ? conditionModalData.rowFilter.filterExpr
+ : ""}
+ </div>
</div>
- </div>
+ )}
</div>
</div>
</Modal.Body>
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 1d47384b2..cef56559c 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
@@ -144,21 +144,52 @@ const MyDatashareListing = () => {
[]
);
+ const navigateToDetailPage = (datashareId, perm, name) => {
+ if (perm != "LIST") {
+ navigate(`/gds/datashare/${datashareId}/detail`, {
+ state: {
+ userAclPerm: perm,
+ datashareName: name
+ }
+ });
+ }
+ };
+
const myDatashareColumns = React.useMemo(
() => [
{
Header: "Id",
accessor: "id",
- width: 25,
+ width: 80,
disableResizing: true,
disableSortBy: true,
getResizerProps: () => {},
- Cell: (rawValue) => {
+ Cell: ({ row }) => {
return (
<div className="position-relative text-center">
- <Link title="Edit" to={`/gds/datashare/${rawValue.value}/detail`}>
- {rawValue.value}
- </Link>
+ <Button
+ data-id="datashareId"
+ data-cy="datashareId"
+ onClick={() =>
+ navigateToDetailPage(
+ row.original.id,
+ row.original.permissionForCaller,
+ row.original.name
+ )
+ }
+ style={{
+ lineHeight: 1,
+ padding: 0,
+ backgroundColor: "transparent",
+ color: "#0b7fad",
+ border: 0,
+ outline: "none",
+ fontSize: 13,
+ cursor: "pointer"
+ }}
+ >
+ {row.original.id}
+ </Button>
</div>
);
}
@@ -276,28 +307,33 @@ const MyDatashareListing = () => {
disableSortBy: true,
getResizerProps: () => {},
Cell: ({ row }) => {
- const permissionForCaller = row.original.permissionForCaller;
- if (
- permissionForCaller === "ADMIN" ||
- permissionForCaller === "VIEW"
- ) {
- return (
- <div className="position-relative text-center">
- <Link
- title="Edit"
- to={`/gds/datashare/${row.original.id}/detail`}
- >
- {row.original.id}
- </Link>
- </div>
- );
- } else {
- return (
- <div className="position-relative text-center">
- <span>{row.original.id}</span>
- </div>
- );
- }
+ return (
+ <div className="position-relative text-center">
+ <Button
+ data-id="datashareId"
+ data-cy="datashareId"
+ disabled={row.original.permissionForCaller == "LIST"}
+ onClick={() =>
+ navigateToDetailPage(
+ row.original.id,
+ row.original.permissionForCaller
+ )
+ }
+ style={{
+ lineHeight: 1,
+ padding: 0,
+ backgroundColor: "transparent",
+ color: "#0b7fad",
+ border: 0,
+ outline: "none",
+ fontSize: 13,
+ cursor: "pointer"
+ }}
+ >
+ {row.original.id}
+ </Button>
+ </div>
+ );
}
},
{
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestDetailView.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestDetailView.jsx
index dcf118e6a..d6bfe7cf4 100755
--- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestDetailView.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestDetailView.jsx
@@ -300,50 +300,54 @@ const RequestDetailView = () => {
</div>
</div>
</div>
- <div className="mb-5">
- <hr className="m-0" />
- <div className="d-flex align-items-center justify-content-between mb-4 pt-4">
- <span className="gds-card-heading border-0 p-0">
- Validity Period
- </span>
- <PolicyValidityPeriodComp
- addPolicyItem={addPolicyItem}
- isGdsRequest={
- requestInfo.validitySchedule == undefined ? true : false
- }
- editValidityPeriod={editValidityPeriod}
- />
- </div>
- {requestInfo.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>
+ {false && (
+ <div className="mb-5">
+ <hr className="m-0" />
+ <div className="d-flex align-items-center justify-content-between mb-4 pt-4">
+ <span className="gds-card-heading border-0 p-0">
+ Validity Period
+ </span>
+ <PolicyValidityPeriodComp
+ addPolicyItem={addPolicyItem}
+ isGdsRequest={
+ requestInfo.validitySchedule == undefined
+ ? true
+ : false
+ }
+ editValidityPeriod={editValidityPeriod}
+ />
+ </div>
+ {requestInfo.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(
+ requestInfo.validitySchedule.startTime,
+ "mm/dd/yyyy hh:MM:ss TT"
+ )}
+ </span>
+ <span className="gds-label-color pl-5">
+ {requestInfo.validitySchedule.timeZone}
+ </span>
</div>
- <span>
- {dateFormat(
- requestInfo.validitySchedule.startTime,
- "mm/dd/yyyy hh:MM:ss TT"
- )}
- </span>
- <span className="gds-label-color pl-5">
- {requestInfo.validitySchedule.timeZone}
- </span>
- </div>
- <div className="wrapper">
- <div className="gds-left-inline-field">
- <span className="gds-label-color"> End Date </span>
+ <div className="wrapper">
+ <div className="gds-left-inline-field">
+ <span className="gds-label-color"> End Date </span>
+ </div>
+ <span>
+ {dateFormat(
+ requestInfo.validitySchedule.endTime,
+ "mm/dd/yyyy hh:MM:ss TT"
+ )}
+ </span>
</div>
- <span>
- {dateFormat(
- requestInfo.validitySchedule.endTime,
- "mm/dd/yyyy hh:MM:ss TT"
- )}
- </span>
</div>
- </div>
- )}
- </div>
+ )}
+ </div>
+ )}
<div className="mb-5">
<Card className="gds-section-card gds-bg-white">
<div className="gds-section-title">