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 0a45ab730e7c22e9a002fc3228ca508829b6e7f8 Author: Anand Nadar <nadaranand...@gmail.com> AuthorDate: Thu Oct 12 20:32:05 2023 -0700 RANGER-4283: [WIP] UI for GDS: Added validity period changes. Multiple default tag datamask condition for datashare and CSS Signed-off-by: Madhan Neethiraj <mad...@apache.org> --- .../main/webapp/react-webapp/src/styles/style.css | 7 +- .../GovernedData/Dataset/DatasetDetailLayout.jsx | 56 ++- .../GovernedData/Dataset/MyDatasetListing.jsx | 30 +- .../GovernedData/Datashare/AddDatashareView.jsx | 408 +++++++++------- .../Datashare/AddSharedResourceComp.jsx | 519 ++++++++++----------- .../Datashare/DatashareDetailLayout.jsx | 147 ++++-- .../GovernedData/Datashare/MyDatashareListing.jsx | 88 +++- .../GovernedData/Request/RequestDetailView.jsx | 161 ++++--- .../views/GovernedData/Request/RequestListing.jsx | 6 +- .../PolicyListing/PolicyValidityPeriodComp.jsx | 3 +- .../react-webapp/src/views/SideBar/TopNavBar.jsx | 15 +- 11 files changed, 860 insertions(+), 580 deletions(-) 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 0ad5f27d0..be11597c3 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 @@ -2374,6 +2374,7 @@ div#ranger-content { padding-left: 0; padding-right: 0; color: rgb(33, 37, 41) !important; + text-align: right; } .header-wraper .last-response-time { padding-left: 1rem; @@ -2577,7 +2578,7 @@ li.list-group-item:hover { display: flex; justify-content: space-between; align-items: center; - padding: 1rem; + padding: 0 1rem; border-bottom: 1px solid #d6d6d6; position: sticky; top: 0; @@ -2899,3 +2900,7 @@ textarea.gds-placeholder::placeholder, .w-50 { width: 50% !important; } + +.gds-label-color { + color: #777777; +} 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 63ef239df..3dfc08624 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 @@ -53,6 +53,7 @@ import arrayMutators from "final-form-arrays"; import { groupBy, isEmpty, isArray } from "lodash"; import PrinciplePermissionComp from "./PrinciplePermissionComp"; import ReactPaginate from "react-paginate"; +import CustomBreadcrumb from "../../CustomBreadcrumb"; const initialState = { loader: false, @@ -967,6 +968,8 @@ const DatasetDetailLayout = () => { <i className="fa fa-angle-left fa-lg font-weight-bold" /> </Button> <h3 className="gds-header bold"> Dataset : {datasetInfo.name}</h3> + <CustomBreadcrumb /> + <span className="pipe"></span> {saveCancelButtons ? ( <div className="gds-header-btn-grp"> <Button @@ -1087,7 +1090,9 @@ const DatasetDetailLayout = () => { className="gds-left-inline-field" height="30px" > - Date Updated + <span className="gds-label-color"> + Date Updated + </span> </div> <div line-height="30px"> {dateFormat( @@ -1102,7 +1107,9 @@ const DatasetDetailLayout = () => { className="gds-left-inline-field" line-height="30px" > - Date Created + <span className="gds-label-color"> + Date Created + </span> </div> <div line-height="30px"> {dateFormat( @@ -1114,7 +1121,11 @@ const DatasetDetailLayout = () => { </div> <div> - <div>Description</div> + <div> + <span className="gds-label-color"> + Description + </span> + </div> </div> <div> <div> @@ -1207,9 +1218,9 @@ const DatasetDetailLayout = () => { {requestAccordionState[ obj.id ] ? ( - <i className="fa fa-angle-down fa-lg font-weight-bold"></i> - ) : ( <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} */}{" "} @@ -1328,7 +1339,11 @@ const DatasetDetailLayout = () => { </div> </div> <div className="w-100 text-right"> - <div>View Request</div> + <Link + to={`/gds/request/detail/${obj.id}`} + > + View Request + </Link> </div> </div> </div> @@ -1715,21 +1730,22 @@ const DatasetDetailLayout = () => { value={obj.id} onChange={checkBocChange} /> - <span title={obj.name} className="fnt-14"> - {obj.name}{" "} - <CustomTooltip - placement="right" - content={ - <p - className="pd-10" - style={{ fontSize: "small" }} - > - {obj.description} - </p> - } - icon="fa-fw fa fa-info-circle gds-opacity-lowest" - /> + <span + title={obj.name} + className="fnt-14 text-truncate" + style={{ maxWidth: "300px", display: "inline-block" }} + > + {obj.name} </span> + <CustomTooltip + placement="right" + content={ + <p className="pd-10" style={{ fontSize: "small" }}> + {obj.description} + </p> + } + icon="fa-fw fa fa-info-circle gds-opacity-lowest" + /> </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 a81aa2869..f6a7fd991 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 @@ -32,6 +32,7 @@ import { serverError, parseSearchFilter } from "../../../utils/XAUtils"; +import CustomBreadcrumb from "../../CustomBreadcrumb"; const MyDatasetListing = () => { const navigate = useNavigate(); @@ -202,9 +203,17 @@ const MyDatasetListing = () => { Header: "Name", accessor: "name", width: 470, - disableResizing: true, - disableSortBy: true, - getResizerProps: () => {} + Cell: (val) => { + return ( + <span + className="text-truncate" + title={val.value} + style={{ maxWidth: "240px", display: "inline-block" }} + > + {val.value} + </span> + ); + } }, { Header: "Created", @@ -346,9 +355,17 @@ const MyDatasetListing = () => { Header: "Name", accessor: "name", width: 600, - disableResizing: true, - disableSortBy: true, - getResizerProps: () => {} + Cell: (val) => { + return ( + <span + className="text-truncate" + title={val.value} + style={{ maxWidth: "240px", display: "inline-block" }} + > + {val.value} + </span> + ); + } }, { Header: "Permission", @@ -433,6 +450,7 @@ const MyDatasetListing = () => { <h3 className="gds-header bold"> {isMyDatasetPage ? "My" : ""} Datasets </h3> + <CustomBreadcrumb /> </div> <div className="wrap"> <React.Fragment> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddDatashareView.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddDatashareView.jsx index b18f5e432..0c75642e1 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 @@ -31,9 +31,10 @@ import AsyncSelect from "react-select/async"; import { Form, Field } from "react-final-form"; import { fetchApi } from "Utils/fetchAPI"; import PrinciplePermissionComp from "../Dataset/PrinciplePermissionComp"; - +import { FieldArray } from "react-final-form-arrays"; import AddSharedResourceComp from "./AddSharedResourceComp"; import { toast } from "react-toastify"; +import arrayMutators from "final-form-arrays"; const initialState = { loader: false, @@ -154,7 +155,6 @@ const AddDatashareView = () => { groups: {}, roles: {} }, - zone: selectedZone != undefined ? selectedZone.label : "", service: selectedService.label, description: datashareDescription, termsOfUse: datashareTermsAndConditions, @@ -164,25 +164,24 @@ const AddDatashareView = () => { ? Object.entries(values.permission).map(([key, obj]) => { return obj.value; }) - : [], - defaultMasks: {} + : [] }; - if (values.shareDataMaskInfo != undefined) { - let data = {}; - if (values.shareDataMaskInfo.valueExpr != undefined) { - data = { - [tagName]: { - dataMaskType: values.shareDataMaskInfo.value, - valueExpr: values.shareDataMaskInfo.valueExpr - } - }; - } else { - data = { - [tagName]: { dataMaskType: values.shareDataMaskInfo.value } - }; + if (selectedZone != undefined) { + dataShareInfo.zone = selectedZone.label; + } + + dataShareInfo.defaultTagMasks = []; + if (values.tagMaskInfo != undefined) { + for (let i = 0; i < values.tagMaskInfo.length; i++) { + let data = {}; + data.tagName = values.tagMaskInfo[i].tagName; + data.maskInfo = {}; + data.maskInfo.dataMaskType = values.tagMaskInfo[i].masking.value; + data.maskInfo.conditionExpr = + values.tagMaskInfo[i].shareDataMaskInfo?.valueExpr; + dataShareInfo.defaultTagMasks.push(data); } - dataShareInfo.defaultMasks = data; } userList.forEach((user) => { @@ -383,81 +382,6 @@ const AddDatashareView = () => { } }; - const showMoreOptionsComp = () => { - setShowMoreOptions(true); - }; - - const handleSubmit = async (values) => { - let data = {}; - let serviceCompRes = serviceDef.resources; - const grpResources = groupBy(serviceCompRes || [], "level"); - let grpResourcesKeys = []; - data.dataShareId = dataShareId; - //data.name = - for (const resourceKey in grpResources) { - grpResourcesKeys.push(+resourceKey); - } - grpResourcesKeys = grpResourcesKeys.sort(); - data.resources = {}; - for (const level of grpResourcesKeys) { - if ( - values[`resourceName-${level}`] && - values[`resourceName-${level}`].value !== noneOptions.value - ) { - let defObj = serviceCompRes.find(function (m) { - if (m.name == values[`resourceName-${level}`].name) { - return m; - } - }); - data.resources[values[`resourceName-${level}`].name] = { - values: isArray(values[`value-${level}`]) - ? values[`value-${level}`]?.map(({ value }) => value) - : [values[`value-${level}`].value] - }; - } - } - try { - setBlockUI(true); - const resp = await fetchApi({ - url: "plugins/policies", - method: "POST", - data - }); - let tblpageData = {}; - if (state && state != null) { - tblpageData = state.tblpageData; - if (state.tblpageData.pageRecords % state.tblpageData.pageSize == 0) { - tblpageData["totalPage"] = state.tblpageData.totalPage + 1; - } else { - if (tblpageData !== undefined) { - tblpageData["totalPage"] = state.tblpageData.totalPage; - } - } - } - setBlockUI(false); - toast.dismiss(toastId.current); - toastId.current = toast.success("Policy save successfully!!"); - navigate(`/service/${serviceId}/policies/${policyType}`, { - state: { - showLastPage: true, - addPageData: tblpageData - } - }); - } catch (error) { - setBlockUI(false); - let errorMsg = `Failed to save policy form`; - if (error?.response?.data?.msgDesc) { - errorMsg = `Error! ${error.response.data.msgDesc}`; - } - toast.error(errorMsg); - console.error(`Error while saving policy form! ${error}`); - } - }; - - const addResources = (resourceList) => { - setSharedResourceList(resourceList); - }; - const onAccessTypeChange = (event, input) => { setAccessType(event); input.onChange(event); @@ -493,11 +417,119 @@ const AddDatashareView = () => { setDatashareConditionExpr(event.target.value); }; - const fetchMaskOptions = () => { - return serviceDef.dataMaskDef.maskTypes.map(({ label, name: value }) => ({ - label, - value - })); + const MaskingConfig = (props) => { + const { addTagMaskingConfig } = props; + return ( + <div> + <FieldArray name="tagMaskInfo"> + {({ fields }) => + fields.map((name, index) => ( + <div> + <span>Tag Name : </span> + <div className="gds-form-input"> + <Field + name={`${name}.tagName`} + render={({ input, meta }) => ( + <input + {...input} + type="text" + //name={`${name}.tagName`} + className="form-control" + data-cy="tagName" + //onChange={tagNameChange} + //value={tagName} + /> + )} + /> + </div> + <span>Masking Type : </span> + <Field + className="form-control" + name={`${name}.shareDataMaskInfo`} + render={({ input, meta }) => ( + <div> + <Field + name={`maskType`} + render={({ input, meta }) => ( + <Field + name={`${name}.masking`} + render={({ input, meta }) => ( + <div className="d-flex "> + <div className="w-50"> + <Select + {...input} + defaultOptions + //value={selectedShareMask} + options={maskTypeOptions} + onChange={(e) => + onShareMaskChange(e, input) + } + isClearable={false} + width="500px" + /> + </div> + {fields?.value[index]?.masking?.label == + "Custom" && ( + <div className="pl-2 w-50"> + <Field + className="form-control" + name={`${name}.shareDataMaskInfo.valueExpr`} + //validate={required} + render={({ input, meta }) => ( + <> + <FormB.Control + type="text" + className="gds-input" + {...input} + placeholder="Enter masked value or expression..." + /> + {meta.error && ( + <span className="invalid-field"> + {meta.error} + </span> + )} + </> + )} + /> + </div> + )} + </div> + )} + /> + )} + /> + </div> + )} + /> + <Button + variant="danger" + size="sm" + title="Remove" + onClick={() => { + fields.remove(index); + }} + data-action="delete" + data-cy="delete" + > + <i className="fa-fw fa fa-remove"></i> + </Button> + </div> + )) + } + </FieldArray> + + <Button + className="btn btn-mini mt-2" + type="button" + onClick={() => addTagMaskingConfig("tagMaskInfo", undefined)} + data-action="addTagMaskInfo" + data-cy="addTagMaskInfo" + title="Add" + > + Add More + </Button> + </div> + ); }; return ( @@ -506,7 +538,18 @@ const AddDatashareView = () => { id="myform2" name="myform2" onSubmit={onSubmit} - render={({ handleSubmit, submitting, required, values }) => ( + mutators={{ + ...arrayMutators + }} + render={({ + handleSubmit, + submitting, + required, + values, + form: { + mutators: { push: addTagMaskingConfig, pop } + } + }) => ( <div> <div className="gds-form-header-wrapper"> <h3 className="gds-header bold">Create Datashare</h3> @@ -673,64 +716,117 @@ const AddDatashareView = () => { </div> {maskDef ? ( <div className="gds-section-title"> - <p className="gds-card-heading">Masking Configuration</p> - <div> - <span>Tag Name : </span> - <div className="gds-form-input"> - <input - type="text" - name="tagName" - className="form-control" - data-cy="tagName" - onChange={tagNameChange} - value={tagName} - /> - </div> - </div> - <div> - <span>Masking Type : </span> - <Field - className="form-control" - name={`shareDataMaskInfo`} - render={({ input, meta }) => ( - <div> - <Select - {...input} - defaultOptions - value={selectedShareMask} - options={maskTypeOptions} - onChange={(e) => onShareMaskChange(e, input)} - isClearable={false} - width="500px" - /> - {selectedShareMask != undefined && - selectedShareMask.label == "Custom" && ( - <> - <Field - className="form-control" - name={`shareDataMaskInfo.valueExpr`} - validate={required} - render={({ input, meta }) => ( - <> - <FormB.Control - type="text" - {...input} - placeholder="Enter masked value or expression..." + <p className="gds-card-heading"> + Tag Masking Configuration + </p> + + <MaskingConfig addTagMaskingConfig={addTagMaskingConfig} /> + {/* <div> + <FieldArray name="tagMaskInfo"> + {({ fields }) => + fields.map((name, index) => ( + <div> + <span>Tag Name : </span> + <div className="gds-form-input"> + <input + type="text" + name="tagName" + className="form-control" + data-cy="tagName" + onChange={tagNameChange} + value={tagName} + /> + </div> + <span>Masking Type : </span> + <Field + className="form-control" + name={`shareDataMaskInfo`} + render={({ input, meta }) => ( + <div> + <Field + name={`maskType`} + render={({ input, meta }) => ( + <Field + name="masking" + render={({ input, meta }) => ( + <div className="d-flex "> + <div className="w-50"> + <Select + {...input} + defaultOptions + value={selectedShareMask} + options={maskTypeOptions} + onChange={(e) => + onShareMaskChange(e, input) + } + isClearable={false} + width="500px" + /> + </div> + {selectedShareMask?.label == + "Custom" && ( + <div className="pl-2 w-50"> + <Field + className="form-control" + name={`shareDataMaskInfo.valueExpr`} + validate={required} + render={({ + input, + meta + }) => ( + <> + <FormB.Control + type="text" + className="gds-input" + {...input} + placeholder="Enter masked value or expression..." + /> + {meta.error && ( + <span className="invalid-field"> + {meta.error} + </span> + )} + </> + )} + /> + </div> + )} + </div> + )} /> - {meta.error && ( - <span className="invalid-field"> - {meta.error} - </span> - )} - </> - )} - /> - </> - )} - </div> - )} - /> - </div> + )} + /> + </div> + )} + /> + <Button + variant="danger" + size="sm" + title="Remove" + onClick={() => { + fields.remove(index); + }} + data-action="delete" + data-cy="delete" + > + <i className="fa-fw fa fa-remove"></i> + </Button> + </div> + )) + } + </FieldArray> + + <Button + className="btn btn-mini mt-2" + type="button" + onClick={() => push("tagMaskInfo", undefined)} + data-action="addTagMaskInfo" + data-cy="addTagMaskInfo" + title="Add" + > + Add More + </Button> + </div> */} </div> ) : ( <div></div> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddSharedResourceComp.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/AddSharedResourceComp.jsx index e5e16a8fe..a583e7d62 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 @@ -40,28 +40,24 @@ const AddSharedResourceComp = ({ datashareId, onSharedResourceDataChange, onToggleAddResourceClose, - loadSharedResource + isEdit, + sharedResourceId }) => { const [accessType, setAccessType] = useState(); - const [sharedResources, setSharedResources] = useState(); - const [conditionModalData, setConditionModalData] = useState(); - const [showConditionModal, setShowConditionModal] = useState(false); const [datashareInfo, setDatashareInfo] = useState({}); const [showMaskInput, setShowMaskInput] = useState(false); const [showRowFilterInput, setShowRowFilterInput] = useState(false); const [serviceDef, setServiceDef] = useState({}); const [serviceDetails, setService] = useState({}); - const [blockUI, setBlockUI] = useState(false); const [loader, setLoader] = useState(false); - const navigate = useNavigate(); + const [showAddResourceModal, setShowAddResourceModal] = useState(false); const [openConfigAccordion, setOpenConfigAccordion] = useState(false); const [formData, setFormData] = useState(); - //const [accessTypeOptions, setAccessTypeOptions] = useState([]); const [selectedResShareMask, setSelectedResShareMask] = useState({}); + const [loadSharedResource, setLoadSharedResource] = useState(); useEffect(() => { fetchDatashareInfo(datashareId); - fetchSharedResources(datashareId); }, []); const generateFormData = (obj, serviceDef) => { @@ -162,23 +158,20 @@ const AddSharedResourceComp = ({ setShowRowFilterInput(true); } - // setShowMaskInput(true); - // setShowRowFilterInput(true); setServiceDef(modifiedServiceDef); if (loadSharedResource != undefined) { setFormData(generateFormData(loadSharedResource, modifiedServiceDef)); } }; - const fetchSharedResources = async () => { + const fetchSharedResource = async (sharedResourceId) => { try { let params = {}; - params["dataShareId"] = datashareId; const resp = await fetchApi({ - url: `gds/resource`, - params: params + url: `gds/resource/${sharedResourceId}` }); - setSharedResources(resp.data.list); + setLoadSharedResource(resp.data); + setFormData(generateFormData(resp.data, serviceDef)); } catch (error) { console.error( `Error occurred while fetching shared resource details ! ${error}` @@ -270,9 +263,8 @@ const AddSharedResourceComp = ({ data.resourceMask = values.resourceMask; try { - setBlockUI(true); setLoader(true); - if (loadSharedResource != undefined) { + if (isEdit) { data.guid = loadSharedResource.guid; await fetchApi({ url: `gds/resource/${loadSharedResource.id}`, @@ -288,9 +280,7 @@ const AddSharedResourceComp = ({ }); toast.success("Shared resource created successfully!!"); } - setBlockUI(false); } catch (error) { - setBlockUI(false); setLoader(false); serverError(error); if (loadSharedResource != undefined) { @@ -305,26 +295,13 @@ const AddSharedResourceComp = ({ onSharedResourceDataChange(); setLoader(false); if (closeModal) { - onToggleAddResourceClose(); + setShowAddResourceModal(false); } console.log(data); }; - const showConfitionModal = (data) => { - setConditionModalData(data); - setShowConditionModal(true); - }; - - const toggleConditionModalClose = () => { - setShowConditionModal(false); - }; - - const back = () => { - navigate(`/gds/datashare/${datashareId}/detail`); - }; - const toggleAddResourceClose = () => { - onToggleAddResourceClose(); + setShowAddResourceModal(false); }; const onResShareMaskChange = (event, input) => { @@ -332,6 +309,15 @@ const AddSharedResourceComp = ({ input.onChange(event); }; + const addResource = () => { + //setLoadSharedResource(); + setShowAddResourceModal(true); + }; + + const toggleAddResourceModalClose = () => { + setShowAddResourceModal(false); + }; + return ( <> {/* <div className="gds-form-header-wrapper gap-half"> @@ -350,18 +336,69 @@ const AddSharedResourceComp = ({ {loader ? ( <Loader /> ) : ( - <div className="gds-form-wrap"> - <div className="gds-form-content pt-5"> + <> + <div className="gds-header-btn-grp"> + {!isEdit ? ( + <Button + variant="primary" + onClick={addResource} + size="sm" + data-id="save" + data-cy="save" + > + Add Resources + </Button> + ) : ( + <Button + variant="outline-dark" + size="sm" + title="Edit" + onClick={(e) => { + // e.stopPropagation(); + // setLoadSharedResource(obj); + fetchSharedResource(sharedResourceId); + setShowAddResourceModal(true); + }} + data-name="editSharedResource" + data-id="editSharedResource" + > + <i className="fa-fw fa fa-edit"></i> + </Button> + )} + </div> + <Modal + show={showAddResourceModal} + onHide={toggleAddResourceModalClose} + //className="mb-7" + size="xl" + > + <Modal.Header closeButton> + <h5 className="mb-0">Add Resources</h5> + </Modal.Header> + {/* <div className="gds-form-wrap"> */} + {/* <div className="gds-form-content"> */} <div> - <div className="mb-2 gds-chips"> - <span className="badge badge-light"> + <div className="mb-2 gds-chips flex-wrap"> + <span + title={datashareInfo.name} + className="badge badge-light text-truncate" + style={{ maxWidth: "250px", display: "inline-block" }} + > Datashare: {datashareInfo.name} </span> - <span className="badge badge-light"> + <span + title={datashareInfo.service} + className="badge badge-light text-truncate" + style={{ maxWidth: "250px", display: "inline-block" }} + > Service: {datashareInfo.service} </span> {datashareInfo.zone != undefined ? ( - <span className="badge badge-light"> + <span + title={datashareInfo.zone} + className="badge badge-light text-truncate" + style={{ maxWidth: "250px", display: "inline-block" }} + > Security Zone: {datashareInfo.zone} </span> ) : ( @@ -404,163 +441,162 @@ const AddSharedResourceComp = ({ } }); } - handleSubmit(); }} > - <div className="mb-4 mt-4"> - <h6>Resource Details</h6> - <hr className="mt-1 mb-1 gds-hr" /> - </div> - <div className="mb-3 form-group row"> - <Col sm={3}> - <label className="form-label pull-right fnt-14"> - Shared Resource Name - </label> - <span className="compulsory-resource top-0">*</span> - </Col> - <Col sm={9}> - <Field - name="shareName" - render={({ input, meta }) => ( - <div className="flex-1"> - <input - {...input} - type="text" - name="shareName" - className="form-control" - data-cy="shareName" - /> - </div> - )} + <Modal.Body> + <div className="mb-4 mt-4"> + <h6>Resource Details</h6> + <hr className="mt-1 mb-1 gds-hr" /> + </div> + <div className="mb-3 form-group row"> + <Col sm={3}> + <label className="form-label pull-right fnt-14"> + Shared Resource Name + </label> + <span className="compulsory-resource top-0">*</span> + </Col> + <Col sm={9}> + <Field + name="shareName" + render={({ input, meta }) => ( + <div className="flex-1"> + <input + {...input} + type="text" + name="shareName" + className="form-control" + data-cy="shareName" + /> + </div> + )} + /> + </Col> + </div> + <div className="gds-resource-hierarchy"> + <ResourceComp + serviceDetails={serviceDetails} + serviceCompDetails={serviceDef} + formValues={values} + policyType={0} + policyItem={false} + policyId={0} + isGds={true} /> - </Col> - </div> - <div className="gds-resource-hierarchy"> - <ResourceComp - serviceDetails={serviceDetails} - serviceCompDetails={serviceDef} - formValues={values} - policyType={0} - policyItem={false} - policyId={0} - isGds={true} - /> - </div> + </div> - <Accordion className="mb-3" defaultActiveKey="0"> - <Card className="border-0 gds-resource-options"> - <div> - <Accordion.Toggle - as={Card.Header} - eventKey="1" - onClick={onAccessConfigAccordianChange} - className="d-flex align-items-center gds-res-acc-header gap-half" - data-id="panel" - data-cy="panel" - > - {openConfigAccordion ? ( - <i className="fa fa-angle-up pull-up fa-lg font-weight-bold"></i> - ) : ( - <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) - </Link> - </Accordion.Toggle> - </div> - <Accordion.Collapse eventKey="1"> - <Card.Body className="gds-res-card-body"> - <div className="mb-3 form-group row"> - <Col sm={3}> - <label className="form-label pull-right fnt-14"> - Add Permissions - </label> - </Col> - <Field - name="permission" - render={({ input, meta }) => ( - <Col sm={9}> - <Select - {...input} - options={getAccessTypeOptions(values)} - onChange={(e) => - onAccessTypeChange(e, input) - } - //menuPortalTarget={document.body} - //value={accessType} - menuPlacement="auto" - isClearable - isMulti - /> - </Col> - )} - /> - </div> - {showRowFilterInput ? ( + <Accordion className="mb-3" defaultActiveKey="0"> + <Card className="border-0 gds-resource-options"> + <div> + <Accordion.Toggle + as={Card.Header} + eventKey="1" + onClick={onAccessConfigAccordianChange} + className="d-flex align-items-center gds-res-acc-header gap-half" + data-id="panel" + data-cy="panel" + > + {openConfigAccordion ? ( + <i className="fa fa-angle-up pull-up fa-lg font-weight-bold"></i> + ) : ( + <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) + </Link> + </Accordion.Toggle> + </div> + <Accordion.Collapse eventKey="1"> + <Card.Body className="gds-res-card-body"> <div className="mb-3 form-group row"> <Col sm={3}> <label className="form-label pull-right fnt-14"> - Row Filter + Add Permissions </label> </Col> - <Field - name={`rowFilter`} + name="permission" render={({ input, meta }) => ( <Col sm={9}> - <input + <Select {...input} - type="text" - name="rowFilter" - className="form-control gds-placeholder" - data-cy="rowFilter" + options={getAccessTypeOptions(values)} + onChange={(e) => + onAccessTypeChange(e, input) + } + //menuPortalTarget={document.body} + //value={accessType} + menuPlacement="auto" + isClearable + isMulti /> </Col> )} /> </div> - ) : ( - <div></div> - )} + {showRowFilterInput ? ( + <div className="mb-3 form-group row"> + <Col sm={3}> + <label className="form-label pull-right fnt-14"> + Row Filter + </label> + </Col> - {showMaskInput ? ( - <div className="mb-3 form-group row"> - <Col sm={3}> - <label className="form-label pull-right fnt-14"> - Mask - </label> - </Col> + <Field + name={`rowFilter`} + render={({ input, meta }) => ( + <Col sm={9}> + <input + {...input} + type="text" + name="rowFilter" + className="form-control gds-placeholder" + data-cy="rowFilter" + /> + </Col> + )} + /> + </div> + ) : ( + <div></div> + )} - <Field - name={`maskType`} - render={({ input, meta }) => ( - <Col sm={9}> - <Field - name="masking" - render={({ input, meta }) => ( - <div> - <Col sm={9}> - <Select - {...input} - options={ - serviceDef.dataMaskDef - .maskTypes - } - onChange={(e) => - onResShareMaskChange( - e, - input - ) - } - menuPlacement="auto" - isClearable - /> - </Col> - <div> + {showMaskInput ? ( + <div className="mb-3 form-group row"> + <Col sm={3}> + <label className="form-label pull-right fnt-14"> + Mask + </label> + </Col> + + <Field + name={`maskType`} + render={({ input, meta }) => ( + <Col sm={9}> + <Field + name="masking" + render={({ input, meta }) => ( + <div className="d-flex "> + <div className="w-50"> + <Select + {...input} + options={ + serviceDef.dataMaskDef + .maskTypes + } + onChange={(e) => + onResShareMaskChange( + e, + input + ) + } + menuPlacement="auto" + isClearable + /> + </div> {selectedResShareMask?.label == "Custom" && ( - <> + <div className="pl-2 w-50"> <Field className="form-control" name={`resShareDataMaskInfo.valueExpr`} @@ -572,6 +608,7 @@ const AddSharedResourceComp = ({ <> <FormB.Control type="text" + className="gds-input" {...input} placeholder="Enter masked value or expression..." /> @@ -583,50 +620,48 @@ const AddSharedResourceComp = ({ </> )} /> - </> + </div> )} </div> - </div> - )} + )} + /> + </Col> + )} + /> + </div> + ) : ( + <div></div> + )} + + <div className="mb-0 form-group row"> + <Col sm={3}> + <label className="form-label pull-right fnt-14"> + Add Condition + </label> + </Col> + <Field + name={`booleanExpression`} + render={({ input, meta }) => ( + <Col sm={9}> + <textarea + {...input} + placeholder="Enter Boolean Expression" + className="form-control gds-placeholder" + id="booleanExpression" + data-cy="booleanExpression" + rows={4} /> </Col> )} /> </div> - ) : ( - <div></div> - )} - - <div className="mb-0 form-group row"> - <Col sm={3}> - <label className="form-label pull-right fnt-14"> - Add Condition - </label> - </Col> - <Field - name={`booleanExpression`} - render={({ input, meta }) => ( - <Col sm={9}> - <textarea - {...input} - placeholder="Enter Boolean Expression" - className="form-control gds-placeholder" - id="booleanExpression" - data-cy="booleanExpression" - rows={4} - /> - </Col> - )} - /> - </div> - </Card.Body> - </Accordion.Collapse> - </Card> - </Accordion> - - <div className="mb-3 form-group row"> - <Col sm={3} /> - <Col sm={9}> + </Card.Body> + </Accordion.Collapse> + </Card> + </Accordion> + </Modal.Body> + <Modal.Footer> + <div className="d-flex gap-half justify-content-end w-100"> <Button variant="secondary" size="sm" @@ -635,21 +670,15 @@ const AddSharedResourceComp = ({ Cancel </Button> <Button - variant={ - loadSharedResource == undefined - ? "secondary" - : "primary" - } + variant="primary" size="sm" onClick={(event) => { handleSubmit(event, true); }} > - {loadSharedResource != undefined - ? "Update" - : "Save & Close"} + {isEdit ? "Update" : "Save & Close"} </Button> - {loadSharedResource == undefined ? ( + {!isEdit ? ( <Button onClick={(event) => { handleSubmit(event, false); @@ -664,53 +693,17 @@ const AddSharedResourceComp = ({ ) : ( <div></div> )} - </Col> - </div> - - <Modal - show={showConditionModal} - onHide={toggleConditionModalClose} - > - <Modal.Header closeButton> - <h3 className="gds-header bold">Conditions</h3> - </Modal.Header> - <Modal.Body> - <div className="p-1"> - <div className="gds-inline-field-grp"> - <div className="wrapper"> - <div - className="gds-left-inline-field" - height="30px" - > - Boolean Expression : - </div> - <div line-height="30px"> - {conditionModalData != undefined && - conditionModalData.conditionExpr != undefined - ? conditionModalData.conditionExpr - : ""} - </div> - </div> - </div> - </div> - </Modal.Body> - <Modal.Footer> - <Button - variant="secondary" - size="sm" - onClick={toggleConditionModalClose} - > - Close - </Button> - </Modal.Footer> - </Modal> + </div> + </Modal.Footer> </form> </div> )} /> </div> - </div> - </div> + {/* </div> */} + {/* </div> */} + </Modal> + </> )} </> ); 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 f0a0beaa4..8a798d923 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 @@ -41,6 +41,7 @@ import { Form } from "react-final-form"; import arrayMutators from "final-form-arrays"; import ReactPaginate from "react-paginate"; import AddSharedResourceComp from "./AddSharedResourceComp"; +import CustomBreadcrumb from "../../CustomBreadcrumb"; const DatashareDetailLayout = () => { let { datashareId } = useParams(); @@ -322,12 +323,6 @@ const DatashareDetailLayout = () => { const handleSubmit = () => {}; - const addResource = () => { - //navigate(`/gds/datashare/resource/${datashareId}`); - setLoadSharedResource(); - setShowAddResourceModal(true); - }; - const back = () => { navigate("/gds/mydatasharelisting"); }; @@ -493,8 +488,15 @@ const DatashareDetailLayout = () => { <i className="fa fa-angle-left fa-lg font-weight-bold" /> </Button> <h3 className="gds-header bold"> - Datashare : {datashareInfo.name} + <span + className="text-truncate" + style={{ maxWidth: "900px", display: "inline-block" }} + > + Datashare : {datashareInfo.name} + </span> </h3> + <CustomBreadcrumb /> + <span className="pipe"></span> {saveCancelButtons ? ( <div className="gds-header-btn-grp"> <Button @@ -517,17 +519,13 @@ const DatashareDetailLayout = () => { </Button> </div> ) : ( - <div className="gds-header-btn-grp"> - <Button - variant="primary" - onClick={addResource} - size="sm" - data-id="save" - data-cy="save" - > - Add a Resource - </Button> - </div> + <AddSharedResourceComp + datashareId={datashareId} + onSharedResourceDataChange={handleSharedResourceChange} + onToggleAddResourceClose={toggleAddResourceModalClose} + isEdit={false} + loadSharedResource={loadSharedResource} + /> )} <div> <DropdownButton @@ -604,7 +602,9 @@ const DatashareDetailLayout = () => { className="gds-left-inline-field pl-1 fnt-14" height="30px" > - Date Updated + <span className="gds-label-color"> + Date Updated + </span> </div> <div className="fnt-14" line-height="30px"> {dateFormat( @@ -619,7 +619,9 @@ const DatashareDetailLayout = () => { className="gds-left-inline-field pl-1 fnt-14" line-height="30px" > - Date Created + <span className="gds-label-color"> + Date Created + </span> </div> <div className="fnt-14" line-height="30px"> {dateFormat( @@ -630,7 +632,11 @@ const DatashareDetailLayout = () => { </div> </div> <div> - <div className="fnt-14 pl-1">Description</div> + <div className="fnt-14 pl-1"> + <span className="gds-label-color"> + Description + </span> + </div> </div> <div> <div> @@ -702,9 +708,9 @@ const DatashareDetailLayout = () => { {resourceAccordionState[ obj.id ] ? ( - <i className="fa fa-angle-down fa-lg font-weight-bold"></i> - ) : ( <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"> @@ -713,7 +719,25 @@ const DatashareDetailLayout = () => { </div> </div> <div className="d-flex gap-half align-items-start"> - <Button + <AddSharedResourceComp + datashareId={ + datashareId + } + onSharedResourceDataChange={ + handleSharedResourceChange + } + onToggleAddResourceClose={ + toggleAddResourceModalClose + } + isEdit={true} + sharedResourceId={ + obj.id + } + loadSharedResource={ + loadSharedResource + } + /> + {/* <Button variant="outline-dark" size="sm" title="Edit" @@ -730,7 +754,7 @@ const DatashareDetailLayout = () => { data-id={obj.id} > <i className="fa-fw fa fa-edit"></i> - </Button> + </Button> */} <Button variant="danger" size="sm" @@ -880,9 +904,9 @@ const DatashareDetailLayout = () => { {requestAccordionState[ obj.id ] ? ( - <i className="fa fa-angle-down fa-lg font-weight-bold"></i> - ) : ( <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{" "} @@ -953,13 +977,58 @@ const DatashareDetailLayout = () => { className="gds-left-inline-field" height="30px" > - Expiry + Validity Period </div> <div line-height="30px"> {obj["service"]} </div> </div> - {obj.validitySchedule !== + {obj.validitySchedule != + undefined ? ( + <div className="gds-inline-field-grp"> + <div className="wrapper"> + <div className="gds-left-inline-field"> + <span className="gds-label-color"> + Start Date{" "} + </span> + </div> + <span> + {dateFormat( + obj + .validitySchedule + .startTime, + "mm/dd/yyyy hh:MM:ss TT" + )} + </span> + <span className="gds-label-color pl-5"> + { + obj + .validitySchedule + .timeZone + } + </span> + </div> + <div className="wrapper"> + <div className="gds-left-inline-field"> + <span className="gds-label-color"> + {" "} + End Date{" "} + </span> + </div> + <span> + {dateFormat( + obj + .validitySchedule + .endTime, + "mm/dd/yyyy hh:MM:ss TT" + )} + </span> + </div> + </div> + ) : ( + <p>--</p> + )} + {/* {obj.validitySchedule !== undefined ? ( <div className="gds-flex"> <div className="gds-right-inline-field"> @@ -996,7 +1065,7 @@ const DatashareDetailLayout = () => { </div> ) : ( <div>--</div> - )} + )} */} </div> <div className="gds-right-inline-field-grp"> <div className="wrapper"> @@ -1023,7 +1092,11 @@ const DatashareDetailLayout = () => { </div> <div className="w-100 text-right"> <div> - View Request + <Link + to={`/gds/request/detail/${obj.id}`} + > + View Request + </Link> </div> </div> </div> @@ -1098,12 +1171,14 @@ const DatashareDetailLayout = () => { </Tabs> </div> - <Modal + {/* <Modal show={showAddResourceModal} onHide={toggleAddResourceModalClose} + //className="mb-7" + size="xl" > <Modal.Header closeButton> - <span className="text-word-break">Add Resources</span> + <h5 className="mb-0">Add Resources</h5> </Modal.Header> <Modal.Body> <AddSharedResourceComp @@ -1113,7 +1188,7 @@ const DatashareDetailLayout = () => { loadSharedResource={loadSharedResource} /> </Modal.Body> - {/* <Modal.Footer> + <Modal.Footer> <Button variant="secondary" size="sm" onClick={toggleClose}> Cancel </Button> @@ -1128,8 +1203,8 @@ const DatashareDetailLayout = () => { > Yes </Button> - </Modal.Footer> */} - </Modal> + </Modal.Footer> + </Modal> */} <Modal show={confirmDeleteModal.showPopup} onHide={toggleClose}> <Modal.Header closeButton> 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 64a84e631..1d47384b2 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 @@ -39,6 +39,7 @@ import { } from "../../../utils/XAUtils"; import moment from "moment-timezone"; import { sortBy } from "lodash"; +import CustomBreadcrumb from "../../CustomBreadcrumb"; const MyDatashareListing = () => { const navigate = useNavigate(); @@ -166,25 +167,49 @@ const MyDatashareListing = () => { Header: "Name", accessor: "name", width: 250, - disableResizing: true, - disableSortBy: true, - getResizerProps: () => {} + Cell: (val) => { + return ( + <span + className="text-truncate" + title={val.value} + style={{ maxWidth: "240px", display: "inline-block" }} + > + {val.value} + </span> + ); + } }, { Header: "Service", accessor: "serviceName", width: 250, - disableResizing: true, - disableSortBy: true, - getResizerProps: () => {} + Cell: (val) => { + return ( + <span + className="text-truncate" + title={val.value} + style={{ maxWidth: "240px", display: "inline-block" }} + > + {val.value} + </span> + ); + } }, { Header: "Zone", accessor: "zoneName", width: 250, - disableResizing: true, - disableSortBy: true, - getResizerProps: () => {} + Cell: (val) => { + return ( + <span + className="text-truncate" + title={val.value} + style={{ maxWidth: "240px", display: "inline-block" }} + > + {val.value} + </span> + ); + } }, { Header: "Created", @@ -260,7 +285,7 @@ const MyDatashareListing = () => { <div className="position-relative text-center"> <Link title="Edit" - to={`/gds/dataset/${row.original.id}/detail`} + to={`/gds/datashare/${row.original.id}/detail`} > {row.original.id} </Link> @@ -279,25 +304,49 @@ const MyDatashareListing = () => { Header: "Name", accessor: "name", width: 250, - disableResizing: true, - disableSortBy: true, - getResizerProps: () => {} + Cell: (val) => { + return ( + <span + className="text-truncate" + title={val.value} + style={{ maxWidth: "240px", display: "inline-block" }} + > + {val.value} + </span> + ); + } }, { Header: "Service", accessor: "serviceName", width: 250, - disableResizing: true, - disableSortBy: true, - getResizerProps: () => {} + Cell: (val) => { + return ( + <span + className="text-truncate" + title={val.value} + style={{ maxWidth: "240px", display: "inline-block" }} + > + {val.value} + </span> + ); + } }, { Header: "Zone", accessor: "zoneName", width: 250, - disableResizing: true, - disableSortBy: true, - getResizerProps: () => {} + Cell: (val) => { + return ( + <span + className="text-truncate" + title={val.value} + style={{ maxWidth: "240px", display: "inline-block" }} + > + {val.value} + </span> + ); + } }, { Header: "Permission", @@ -416,6 +465,7 @@ const MyDatashareListing = () => { <h3 className="gds-header bold"> {isMyDatasharePage ? "My" : ""} Datashares </h3> + <CustomBreadcrumb /> </div> <div className="wrap"> <React.Fragment> 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 c43cffd45..dcf118e6a 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 @@ -30,6 +30,7 @@ import arrayMutators from "final-form-arrays"; import moment from "moment-timezone"; import { isEmpty } from "lodash"; import { toast } from "react-toastify"; +import { getAllTimeZoneList } from "../../../utils/XAUtils"; const RequestDetailView = () => { let { requestId } = useParams(); @@ -39,6 +40,8 @@ const RequestDetailView = () => { const [datasetInfo, setDatasetInfo] = useState({}); const [datashareInfo, setDatashareInfo] = useState({}); const [acceptTerms, setAcceptTerms] = useState(false); + const [formData, setFormData] = useState(); + const [editValidityPeriod, setEditValidityPeriod] = useState(false); useEffect(() => { fetchRequestDetail(requestId); @@ -50,6 +53,26 @@ const RequestDetailView = () => { const resp = await fetchApi({ url: `gds/datashare/dataset/${requestId}` }); + if (resp.data.validitySchedule !== undefined) { + let val = resp.data.validitySchedule; + let data = {}; + data["validitySchedules"] = []; + let obj = {}; + if (val.endTime) { + obj["endTime"] = moment(val.endTime, "YYYY/MM/DD HH:mm:ss"); + } + if (val.startTime) { + obj["startTime"] = moment(val.startTime, "YYYY/MM/DD HH:mm:ss"); + } + if (val.timeZone) { + obj["timeZone"] = getAllTimeZoneList().find((tZoneVal) => { + return tZoneVal.id == val.timeZone; + }); + } + data["validitySchedules"].push(obj); + setFormData(data); + setEditValidityPeriod(true); + } setRequestInfo(resp.data); fetchdatasetInfo(resp.data.datasetId); fetchDatashaerInfo(resp.data.dataShareId); @@ -85,7 +108,7 @@ const RequestDetailView = () => { navigate(`/gds/request/list`); }; - const handleSubmit = async (values) => { + const handleSubmit = async (values, type) => { if ( datasetInfo.termsOfUse != undefined && requestInfo.status === "GRANTED" && @@ -119,7 +142,8 @@ const RequestDetailView = () => { } if (requestInfo.status === "REQUESTED") { - requestInfo["status"] = "GRANTED"; + if (type == "grant") requestInfo["status"] = "GRANTED"; + else requestInfo["status"] = "DENIED"; } else if (requestInfo.status === "GRANTED") { requestInfo["status"] = "ACTIVE"; } @@ -155,6 +179,7 @@ const RequestDetailView = () => { mutators={{ ...arrayMutators }} + initialValues={formData} render={({ form: { mutators: { push: addPolicyItem, pop } @@ -162,7 +187,7 @@ const RequestDetailView = () => { values }) => ( <div> - <div className="gds-header-wrapper gap-half"> + <div className="gds-header-wrapper gap-half py-3"> <Button variant="light" className="border-0 bg-transparent" @@ -178,7 +203,7 @@ const RequestDetailView = () => { <div className="gds-header-btn-grp"> <Button variant="secondary" - //onClick={() => removeChanges()} + onClick={() => handleSubmit(values, "deny")} size="sm" data-id="deny" data-cy="deny" @@ -187,7 +212,7 @@ const RequestDetailView = () => { </Button> <Button variant="primary" - onClick={() => handleSubmit(values)} + onClick={() => handleSubmit(values, "grant")} size="sm" data-id="grant" data-cy="grant" @@ -200,7 +225,7 @@ const RequestDetailView = () => { {requestInfo.status === "GRANTED" ? ( <Button variant="primary" - onClick={() => handleSubmit(values)} + onClick={() => handleSubmit(values, "active")} size="sm" data-id="activate" data-cy="activate" @@ -221,10 +246,9 @@ const RequestDetailView = () => { <div className="gds-inline-field-grp"> <div className="wrapper"> <div className="gds-left-inline-field" height="30px"> - <span>Status</span> + <span className="gds-label-color">Status</span> </div> <span - //className="badge badge-light gds-requested-status" className={ requestInfo.status === "REQUESTED" ? "badge badge-light gds-requested-status" @@ -240,20 +264,20 @@ const RequestDetailView = () => { </div> <div className="wrapper"> <div className="gds-left-inline-field" height="30px"> - <span>Created by</span> + <span className="gds-label-color">Created by</span> </div> <div line-height="30px">{requestInfo.createdBy}</div> </div> <div className="wrapper"> <div className="gds-left-inline-field" height="30px"> - <span>Approver</span> + <span className="gds-label-color">Approver</span> </div> <div line-height="30px">{requestInfo.approvedBy}</div> </div> </div> <div className="gds-right-inline-field-grp"> <div className="wrapper"> - <div>Created</div> + <div className="gds-label-color">Created</div> <div className="gds-right-inline-field"> <span> {dateFormat( @@ -264,7 +288,7 @@ const RequestDetailView = () => { </div> </div> <div className="wrapper"> - <div>Last Updated</div> + <div className="gds-label-color">Last Updated</div> <div className="gds-right-inline-field"> <span> {dateFormat( @@ -274,57 +298,52 @@ const RequestDetailView = () => { </span> </div> </div> - {requestInfo.status == "REQUESTED" ? ( - <Field name="validityPeriod"> - {({ input, meta }) => ( - <PolicyValidityPeriodComp - addPolicyItem={addPolicyItem} - isGdsRequest={ - requestInfo.validitySchedule == undefined - ? true - : false - } - /> - )} - </Field> - ) : ( - <div> - {requestInfo.validitySchedule != undefined ? ( - <div className="wrapper"> - <div> - <span>Validity Period</span> - </div> - <div className="gds-right-inline-field"> - <span> - Start Time:{" "} - {dateFormat( - requestInfo.validitySchedule.startTime, - "mm/dd/yyyy hh:MM:ss TT" - )} - </span> - </div> - <div className="gds-right-inline-field"> - <span> - End Time:{" "} - {dateFormat( - requestInfo.validitySchedule.endTime, - "mm/dd/yyyy hh:MM:ss TT" - )} - </span> - </div> - <div className="gds-right-inline-field"> - <span> - {requestInfo.validitySchedule.timeZone} - </span> - </div> - </div> - ) : ( - <div></div> - )} - </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> + </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> + <span> + {dateFormat( + requestInfo.validitySchedule.endTime, + "mm/dd/yyyy hh:MM:ss TT" + )} + </span> + </div> + </div> + )} + </div> <div className="mb-5"> <Card className="gds-section-card gds-bg-white"> <div className="gds-section-title"> @@ -354,7 +373,7 @@ const RequestDetailView = () => { <div className="w-100 mb-3"> <div className="wrapper"> <div className="gds-left-inline-field" height="30px"> - <span>Name </span> + <span className="gds-label-color">Name </span> </div> <div line-height="30px">{datashareInfo.name}</div> </div> @@ -362,12 +381,12 @@ const RequestDetailView = () => { <div className="w-100 mb-3 d-flex justify-content-between"> <div className="wrapper w-50"> <div className="gds-left-inline-field" height="30px"> - <span>Service </span> + <span className="gds-label-color">Service </span> </div> <div line-height="30px">{datashareInfo.service}</div> </div> <div className="wrapper w-50"> - <div>Security Zone</div> + <div className="gds-label-color">Security Zone</div> <div className="gds-right-inline-field"> <span>{datashareInfo.zone}</span> </div> @@ -376,7 +395,7 @@ const RequestDetailView = () => { <div className="w-100 mb-3"> <div className="wrapper"> <div className="gds-left-inline-field" height="30px"> - <span>Conditions</span> + <span className="gds-label-color">Conditions</span> </div> <div line-height="30px"> {datashareInfo.conditionExpr} @@ -385,7 +404,11 @@ const RequestDetailView = () => { </div> <div className="w-100 mb-3"> <div className="wrapper"> - <div>Default Access Type</div> + <div className="gds-left-inline-field" height="30px"> + <span className="gds-label-color"> + Default Access Type + </span> + </div> <div className="gds-left-inline-field"> <span> {datashareInfo.defaultAccessTypes != undefined ? ( @@ -416,7 +439,7 @@ const RequestDetailView = () => { className="gds-left-inline-field flex-shrink-0" height="30px" > - <span>Name </span> + <span className="gds-label-color">Name </span> </div> <div line-height="30px">{datasetInfo.name}</div> </div> @@ -425,7 +448,9 @@ const RequestDetailView = () => { className="gds-left-inline-field flex-shrink-0" height="30px" > - <span>Description </span> + <span className="gds-label-color"> + Description{" "} + </span> </div> <div line-height="30px"> <span>{datasetInfo.description}</span> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestListing.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestListing.jsx index f0cae8c8c..60b96699f 100755 --- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestListing.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Request/RequestListing.jsx @@ -35,6 +35,7 @@ import { BlockUi } from "../../../components/CommonComponents"; import moment from "moment-timezone"; +import CustomBreadcrumb from "../../CustomBreadcrumb"; import { isKeyAdmin, isKMSAuditor, @@ -196,8 +197,9 @@ const RequestListing = () => { <Loader /> ) : ( <> - <div className="gds-header-wrapper"> - <h3 className="gds-header bold">My Requests</h3> + <div className="header-wraper"> + <h3 className="wrap-header bold">My Requests</h3> + <CustomBreadcrumb /> </div> <div className="wrap"> <React.Fragment> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyValidityPeriodComp.jsx b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyValidityPeriodComp.jsx index 02419e61e..e2ef63188 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyValidityPeriodComp.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyValidityPeriodComp.jsx @@ -93,7 +93,8 @@ export default function PolicyValidityPeriodComp(props) { data-js="policyTimeBtn" data-cy="policyTimeBtn" > - <i className="fa fa-clock-o"></i> Add Validity Period + <i className="fa fa-clock-o"></i>{" "} + {props.editValidityPeriod ? "Edit" : "Add"} Validity Period </Button> <Modal show={showModal} size="lg" onHide={toggleModal} backdrop="static"> <Modal.Header closeButton> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/SideBar/TopNavBar.jsx b/security-admin/src/main/webapp/react-webapp/src/views/SideBar/TopNavBar.jsx index d4dbc57d1..e77cdd5e6 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/SideBar/TopNavBar.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/SideBar/TopNavBar.jsx @@ -240,9 +240,15 @@ export const TopNavBar = (props) => { )} </div> <div - className="collapse navbar-collapse justify-content-end" + className="collapse navbar-collapse justify-content-end gap-half" id="navbarText" > + <span className="navbar-text last-response-time"> + <strong>Last Response Time</strong> + <br /> + {moment(moment()).format("MM/DD/YYYY hh:mm:ss A")} + </span> + {(!isUserRole || isAdminRole) && <span className="pipe"></span>} {(!isUserRole || isAdminRole) && ( <DropdownButton id="dropdown-item-button" @@ -302,13 +308,6 @@ export const TopNavBar = (props) => { )} </DropdownButton> )} - - {(!isUserRole || isAdminRole) && <span className="pipe"></span>} - <span className="navbar-text last-response-time"> - <strong>Last Response Time</strong> - <br /> - {moment(moment()).format("MM/DD/YYYY hh:mm:ss A")} - </span> </div> <Modal show={showView === serviceData?.id}