| /* |
| * 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, useCallback, useRef, useEffect } from "react"; |
| import { |
| Link, |
| useParams, |
| useNavigate, |
| useLocation, |
| useSearchParams |
| } from "react-router-dom"; |
| import { Badge, Button, Col, Row, Modal, Alert } from "react-bootstrap"; |
| import moment from "moment-timezone"; |
| import { toast } from "react-toastify"; |
| import { |
| pick, |
| indexOf, |
| isUndefined, |
| isEmpty, |
| map, |
| sortBy, |
| find, |
| concat, |
| camelCase, |
| union |
| } from "lodash"; |
| import { fetchApi } from "Utils/fetchAPI"; |
| import XATableLayout from "Components/XATableLayout"; |
| import { |
| showGroupsOrUsersOrRolesForPolicy, |
| QueryParamsName |
| } from "Utils/XAUtils"; |
| import { MoreLess, scrollToNewData } from "Components/CommonComponents"; |
| import {} from "Utils/XAUtils"; |
| import PolicyViewDetails from "../AuditEvent/AdminLogs/PolicyViewDetails"; |
| import StructuredFilter from "../../components/structured-filter/react-typeahead/tokenizer"; |
| import { |
| isAuditor, |
| isKMSAuditor, |
| isPolicyExpired, |
| isSystemAdmin, |
| isKeyAdmin, |
| isUser, |
| parseSearchFilter, |
| getResourcesDefVal |
| } from "../../utils/XAUtils"; |
| import { |
| alertMessage, |
| ResourcesOverrideInfoMsg, |
| ServerAttrName |
| } from "../../utils/XAEnums"; |
| import { |
| BlockUi, |
| CustomPopover, |
| Loader |
| } from "../../components/CommonComponents"; |
| |
| function PolicyListing(props) { |
| const { serviceDef, serviceData, serviceZone } = props; |
| const { state } = useLocation(); |
| const [policyListingData, setPolicyData] = useState([]); |
| const [loader, setLoader] = useState(true); |
| const [pageCount, setPageCount] = useState( |
| state && state.showLastPage ? state.addPageData.totalPage : 0 |
| ); |
| const [currentpageIndex, setCurrentPageIndex] = useState( |
| state && state.showLastPage ? state.addPageData.totalPage - 1 : 0 |
| ); |
| const [currentpageSize, setCurrentPageSize] = useState( |
| state && state.showLastPage ? state.addPageData.pageSize : 25 |
| ); |
| const [totalCount, setTotalCount] = useState(0); |
| const [tblpageData, setTblPageData] = useState({ |
| totalPage: 0, |
| pageRecords: 0, |
| pageSize: 25 |
| }); |
| const fetchIdRef = useRef(0); |
| const [deletePolicyModal, setConfirmModal] = useState({ |
| policyDetails: {}, |
| showSyncDetails: false |
| }); |
| const [policyviewmodal, setPolicyViewModal] = useState(false); |
| const [policyParamsData, setPolicyParamsData] = useState(null); |
| const [updateTable, setUpdateTable] = useState(moment.now()); |
| const [currentPage, setCurrentPage] = useState(1); |
| const [searchFilterParams, setSearchFilterParams] = useState([]); |
| const [searchParams, setSearchParams] = useSearchParams(); |
| const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState( |
| [] |
| ); |
| const [pageLoader, setPageLoader] = useState(true); |
| const [resetPage, setResetpage] = useState({ page: 0 }); |
| const [show, setShow] = useState(true); |
| const [blockUI, setBlockUI] = useState(false); |
| let navigate = useNavigate(); |
| let { serviceId, policyType } = useParams(); |
| |
| useEffect(() => { |
| let searchFilterParam = {}; |
| let searchParam = {}; |
| let defaultSearchFilterParam = []; |
| |
| // Get Search Filter Params from current search params |
| const currentParams = Object.fromEntries([...searchParams]); |
| for (const param in currentParams) { |
| let searchFilterObj = find(getSearchFilterOptions(), { |
| urlLabel: param |
| }); |
| |
| if (!isUndefined(searchFilterObj)) { |
| let category = searchFilterObj.category; |
| let value = currentParams[param]; |
| |
| if (searchFilterObj.type == "textoptions") { |
| let textOptionObj = find(searchFilterObj.options(), { |
| label: value |
| }); |
| value = textOptionObj !== undefined ? textOptionObj.value : value; |
| } |
| |
| searchFilterParam[category] = value; |
| defaultSearchFilterParam.push({ |
| category: category, |
| value: value |
| }); |
| } |
| } |
| |
| // Updating the states for search params, search filter and default search filter |
| setSearchParams({ ...currentParams, ...searchParam }, { replace: true }); |
| if ( |
| JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam) |
| ) { |
| setSearchFilterParams(searchFilterParam); |
| } |
| setDefaultSearchFilterParams(defaultSearchFilterParam); |
| setPageLoader(false); |
| localStorage.setItem("newDataAdded", state && state.showLastPage); |
| }, [searchParams]); |
| useEffect(() => { |
| if (localStorage.getItem("newDataAdded") == "true") { |
| scrollToNewData(policyListingData); |
| } |
| }, [totalCount]); |
| const getTableSortBy = (sortArr = []) => { |
| return sortArr |
| .map(({ id }) => { |
| return QueryParamsName(id); |
| }) |
| .join(","); |
| }; |
| |
| const getTableSortType = (sortArr = []) => { |
| return sortArr.map(({ desc }) => (desc ? "desc" : "asc")).join(","); |
| }; |
| |
| const fetchPolicyInfo = useCallback( |
| async ({ pageSize, pageIndex, sortBy, gotoPage }) => { |
| setLoader(true); |
| let policyData = []; |
| let policyResp = []; |
| let totalCount = 0; |
| let page = |
| state && state.showLastPage |
| ? state.addPageData.totalPage - 1 |
| : pageIndex; |
| let totalPageCount = 0; |
| const fetchId = ++fetchIdRef.current; |
| let params = { ...searchFilterParams }; |
| if (fetchId === fetchIdRef.current) { |
| params["page"] = page; |
| params["startIndex"] = |
| state && state.showLastPage |
| ? (state.addPageData.totalPage - 1) * pageSize |
| : pageIndex * pageSize; |
| params["pageSize"] = pageSize; |
| params["policyType"] = policyType; |
| if (sortBy.length > 0) { |
| params["sortBy"] = getTableSortBy(sortBy); |
| params["sortType"] = getTableSortType(sortBy); |
| } |
| |
| if (serviceZone !== null) { |
| params["zoneName"] = serviceZone.label; |
| } |
| try { |
| policyResp = await fetchApi({ |
| url: `plugins/policies/service/${serviceId}`, |
| params: params |
| }); |
| policyData = policyResp.data.policies; |
| totalCount = policyResp.data.totalCount; |
| totalPageCount = Math.ceil(totalCount / pageSize); |
| } catch (error) { |
| console.error(`Error occurred while fetching Policies ! ${error}`); |
| } |
| if (state) { |
| state["showLastPage"] = false; |
| } |
| setPolicyData(policyData); |
| setTblPageData({ |
| totalPage: totalPageCount, |
| pageRecords: policyResp?.data?.totalCount, |
| pageSize: 25 |
| }); |
| setTotalCount(totalCount); |
| setPageCount(totalPageCount); |
| setCurrentPageIndex(page); |
| setCurrentPageSize(pageSize); |
| setResetpage({ page: gotoPage }); |
| setLoader(false); |
| } |
| }, |
| [updateTable, searchFilterParams] |
| ); |
| |
| const toggleConfirmModalForDelete = (policyID, policyName) => { |
| setConfirmModal({ |
| policyDetails: { policyID: policyID, policyName: policyName }, |
| showPopup: true |
| }); |
| }; |
| |
| const toggleClose = () => { |
| setConfirmModal({ |
| policyDetails: {}, |
| showPopup: false |
| }); |
| }; |
| |
| const handleClosePolicyId = () => setPolicyViewModal(false); |
| |
| const openModal = (policyDetails) => { |
| let policyId = pick(policyDetails, ["id"]); |
| setPolicyViewModal(true); |
| setPolicyParamsData(policyDetails); |
| fetchVersions(policyId.id); |
| }; |
| |
| const fetchVersions = async (policyId) => { |
| let versionsResp = {}; |
| try { |
| versionsResp = await fetchApi({ |
| url: `plugins/policy/${policyId}/versionList` |
| }); |
| } catch (error) { |
| console.error( |
| `Error occurred while fetching Policy Version or CSRF headers! ${error}` |
| ); |
| } |
| setCurrentPage( |
| versionsResp.data.value |
| .split(",") |
| .map(Number) |
| .sort(function (a, b) { |
| return a - b; |
| }) |
| ); |
| setLoader(false); |
| }; |
| |
| const handleDeleteClick = async (policyID) => { |
| toggleClose(); |
| try { |
| setBlockUI(true); |
| await fetchApi({ |
| url: `plugins/policies/${policyID}`, |
| method: "DELETE" |
| }); |
| setBlockUI(false); |
| toast.success(" Success! Policy deleted successfully"); |
| } catch (error) { |
| setBlockUI(false); |
| let errorMsg = "Failed to delete policy : "; |
| if (error?.response?.data?.msgDesc) { |
| errorMsg += error.response.data.msgDesc; |
| } |
| toast.error(errorMsg); |
| console.error("Error occurred during deleting policy : " + error); |
| } |
| if (policyListingData.length == 1 && currentpageIndex > 0) { |
| let page = currentpageIndex - currentpageIndex; |
| if (typeof resetPage?.page === "function") { |
| resetPage.page(page); |
| } |
| } else { |
| setUpdateTable(moment.now()); |
| } |
| }; |
| |
| const previousVersion = (e) => { |
| if (e.currentTarget.classList.contains("active")) { |
| let curr = policyParamsData && policyParamsData.version; |
| let policyVersionList = currentPage; |
| var previousVal = |
| policyVersionList[ |
| (indexOf(policyVersionList, curr) - 1) % policyVersionList.length |
| ]; |
| } |
| let prevVal = {}; |
| prevVal.version = previousVal; |
| prevVal.id = policyParamsData.id; |
| prevVal.isChangeVersion = true; |
| setPolicyParamsData(prevVal); |
| }; |
| |
| const nextVersion = (e) => { |
| if (e.currentTarget.classList.contains("active")) { |
| let curr = policyParamsData && policyParamsData.version; |
| let policyVersionList = currentPage; |
| var nextValue = |
| policyVersionList[ |
| (indexOf(policyVersionList, curr) + 1) % policyVersionList.length |
| ]; |
| } |
| let nextVal = {}; |
| nextVal.version = nextValue; |
| nextVal.id = policyParamsData.id; |
| nextVal.isChangeVersion = true; |
| setPolicyParamsData(nextVal); |
| }; |
| |
| const revert = (e) => { |
| e.preventDefault(); |
| let version = policyParamsData && policyParamsData.version; |
| let revertVal = {}; |
| revertVal.version = version; |
| revertVal.id = policyParamsData.id; |
| revertVal.isRevert = true; |
| setPolicyParamsData(revertVal); |
| setPolicyViewModal(false); |
| }; |
| |
| const updateServices = () => { |
| setUpdateTable(moment.now()); |
| }; |
| |
| const columns = React.useMemo( |
| () => [ |
| { |
| Header: "Policy ID", |
| accessor: "id", |
| Cell: (rawValue) => { |
| if (isAuditor() || isKMSAuditor()) { |
| if ( |
| !isEmpty(rawValue.row.original.validitySchedules) && |
| isPolicyExpired(rawValue.row.original) |
| ) { |
| return ( |
| <div className="position-relative text-center"> |
| <i |
| className="fa-fw fa fa-exclamation-circle policy-expire-icon" |
| title="Policy expired" |
| ></i> |
| {rawValue.value} |
| </div> |
| ); |
| } else { |
| return ( |
| <div className="position-relative text-center"> |
| {rawValue.value} |
| </div> |
| ); |
| } |
| } else { |
| if ( |
| !isEmpty(rawValue.row.original.validitySchedules) && |
| isPolicyExpired(rawValue.row.original) |
| ) { |
| return ( |
| <div className="position-relative text-center"> |
| <i |
| className="fa-fw fa fa-exclamation-circle policy-expire-icon" |
| title="Policy expired" |
| ></i> |
| <Link |
| title="Edit" |
| to={`/service/${serviceId}/policies/${rawValue.value}/edit`} |
| > |
| {rawValue.value} |
| </Link> |
| </div> |
| ); |
| } else { |
| return ( |
| <div className="position-relative text-center"> |
| <Link |
| title="Edit" |
| to={`/service/${serviceId}/policies/${rawValue.value}/edit`} |
| > |
| {rawValue.value} |
| </Link> |
| </div> |
| ); |
| } |
| } |
| }, |
| width: 90 |
| }, |
| { |
| Header: "Policy Name", |
| accessor: "name", |
| Cell: (val) => { |
| return ( |
| <span |
| className="text-truncate" |
| title={val.value} |
| style={{ maxWidth: "240px", display: "inline-block" }} |
| > |
| {val.value} |
| </span> |
| ); |
| }, |
| width: 250 |
| }, |
| { |
| Header: "Policy Label", |
| accessor: "policyLabels", |
| Cell: (rawValue) => { |
| return !isEmpty(rawValue.value) ? ( |
| <MoreLess data={rawValue.value} /> |
| ) : ( |
| <div className="text-center">--</div> |
| ); |
| }, |
| width: 130, |
| disableSortBy: true |
| }, |
| { |
| Header: "Status", |
| accessor: "isEnabled", |
| Cell: (rawValue) => { |
| if (rawValue.value) |
| return ( |
| <h6> |
| <Badge variant="success">Enabled</Badge> |
| </h6> |
| ); |
| else |
| return ( |
| <h6> |
| <Badge variant="danger">Disabled</Badge> |
| </h6> |
| ); |
| }, |
| width: 100, |
| disableSortBy: true |
| }, |
| { |
| Header: "Audit Logging", |
| accessor: "isAuditEnabled", |
| Cell: (rawValue) => { |
| if (rawValue.value) { |
| return ( |
| <h6> |
| <Badge variant="success">Enabled</Badge> |
| </h6> |
| ); |
| } else |
| return ( |
| <h6> |
| <Badge variant="danger">Disabled</Badge> |
| </h6> |
| ); |
| }, |
| width: 110, |
| disableSortBy: true |
| }, |
| { |
| Header: "Roles", |
| accessor: "roles", |
| Cell: (rawValue) => { |
| let rolesData = showGroupsOrUsersOrRolesForPolicy( |
| "roles", |
| rawValue.row.original, |
| policyType |
| ); |
| return !isEmpty(rolesData) ? ( |
| <MoreLess data={rolesData} key={rawValue.row.original.id} /> |
| ) : ( |
| <div className="text-center">--</div> |
| ); |
| }, |
| minWidth: 190, |
| disableSortBy: true |
| }, |
| { |
| Header: "Groups", |
| accessor: "groups", |
| Cell: (rawValue) => { |
| let groupsData = showGroupsOrUsersOrRolesForPolicy( |
| "groups", |
| rawValue.row.original, |
| policyType |
| ); |
| return !isEmpty(groupsData) ? ( |
| <MoreLess data={groupsData} key={rawValue.row.original.id} /> |
| ) : ( |
| <div className="text-center">--</div> |
| ); |
| }, |
| minWidth: 190, |
| disableSortBy: true |
| }, |
| { |
| Header: "Users", |
| accessor: "users", |
| Cell: (rawValue) => { |
| let usersData = showGroupsOrUsersOrRolesForPolicy( |
| "users", |
| rawValue.row.original, |
| policyType |
| ); |
| return !isEmpty(usersData) ? ( |
| <MoreLess data={usersData} key={rawValue.row.original.id} /> |
| ) : ( |
| <div className="text-center">--</div> |
| ); |
| }, |
| minWidth: 190, |
| disableSortBy: true |
| }, |
| { |
| Header: "Actions", |
| accessor: "actions", |
| Cell: ({ row: { original } }) => { |
| return ( |
| <div> |
| <Button |
| variant="outline-dark" |
| size="sm" |
| className="mr-2" |
| title="View" |
| onClick={(e) => { |
| e.stopPropagation(); |
| openModal(original); |
| }} |
| data-name="viewPolicy" |
| data-id={original.id} |
| > |
| <i className="fa-fw fa fa-eye fa-fw fa fa-large"></i> |
| </Button> |
| {(isSystemAdmin() || isKeyAdmin() || isUser()) && ( |
| <> |
| <Link |
| className="btn btn-outline-dark btn-sm mr-2" |
| title="Edit" |
| to={`/service/${serviceId}/policies/${original.id}/edit`} |
| > |
| <i className="fa-fw fa fa-edit"></i> |
| </Link> |
| <Button |
| variant="danger" |
| size="sm" |
| title="Delete" |
| onClick={() => |
| toggleConfirmModalForDelete(original.id, original.name) |
| } |
| data-name="deletePolicy" |
| data-id={original.id} |
| data-cy={original.id} |
| > |
| <i className="fa-fw fa fa-trash fa-fw fa fa-large"></i> |
| </Button> |
| </> |
| )} |
| </div> |
| ); |
| }, |
| disableSortBy: true |
| } |
| ], |
| [] |
| ); |
| |
| const addPolicy = () => { |
| navigate(`/service/${serviceId}/policies/create/${policyType}`, { |
| state: { tblpageData: tblpageData } |
| }); |
| }; |
| |
| const searchFilterOptions = [ |
| { |
| category: "group", |
| label: "Group Name", |
| urlLabel: "groupName", |
| type: "text" |
| }, |
| { |
| category: "policyLabelsPartial", |
| label: "Policy Label", |
| urlLabel: "policyLabel", |
| type: "text" |
| }, |
| { |
| category: "policyNamePartial", |
| label: "Policy Name", |
| urlLabel: "policyName", |
| type: "text" |
| }, |
| { |
| category: "role", |
| label: "Role Name", |
| urlLabel: "roleName", |
| type: "text" |
| }, |
| { |
| category: "isEnabled", |
| label: "Status", |
| urlLabel: "status", |
| type: "textoptions", |
| options: () => { |
| return [ |
| { value: "true", label: "Enabled" }, |
| { value: "false", label: "Disabled" } |
| ]; |
| } |
| }, |
| { |
| category: "user", |
| label: "User Name", |
| urlLabel: "userName", |
| type: "text" |
| } |
| ]; |
| |
| const getSearchFilterOptions = () => { |
| let currentServiceDef = serviceDef; |
| |
| if (currentServiceDef !== undefined) { |
| let serviceDefResource = getResourcesDefVal( |
| currentServiceDef, |
| policyType |
| ); |
| |
| let serviceDefResourceOption = serviceDefResource?.map((obj) => ({ |
| category: "resource:" + obj.name, |
| label: obj.label, |
| urlLabel: camelCase(obj.label), |
| type: "text" |
| })); |
| |
| return sortBy(concat(searchFilterOptions, serviceDefResourceOption), [ |
| "label" |
| ]); |
| } |
| |
| return sortBy(searchFilterOptions, ["label"]); |
| }; |
| |
| const getSearchInfoContent = () => { |
| let resources = []; |
| let resourceSearchOpt = []; |
| let serverRsrcAttrName = []; |
| let policySearchInfoMsg = []; |
| |
| resources = getResourcesDefVal(serviceDef, policyType); |
| |
| resourceSearchOpt = map(resources, function (resource) { |
| return { |
| name: resource.name, |
| label: resource.label, |
| description: resource.description |
| }; |
| }); |
| |
| serverRsrcAttrName = map(resourceSearchOpt, function (opt) { |
| return { |
| text: opt.label, |
| info: !isUndefined(opt?.description) |
| ? opt.description |
| : ResourcesOverrideInfoMsg[opt.name] |
| }; |
| }); |
| |
| policySearchInfoMsg = union(ServerAttrName, serverRsrcAttrName); |
| |
| return ( |
| <div className="policy-search-info"> |
| <p className="m-0"> |
| Wildcard searches ( for example using * or ? ) are not currently |
| supported. |
| </p> |
| {policySearchInfoMsg?.map((m, index) => { |
| return ( |
| <p className="m-0" key={index}> |
| <span className="font-weight-bold">{m.text}: </span> |
| <span>{m.info}</span> |
| </p> |
| ); |
| })} |
| </div> |
| ); |
| }; |
| |
| const updateSearchFilter = (filter) => { |
| let { searchFilterParam, searchParam } = parseSearchFilter( |
| filter, |
| getSearchFilterOptions() |
| ); |
| |
| setSearchFilterParams(searchFilterParam); |
| setSearchParams(searchParam, { replace: true }); |
| |
| if (typeof resetPage?.page === "function") { |
| resetPage.page(0); |
| } |
| }; |
| |
| return ( |
| <div className="wrap"> |
| {(serviceData.type == "hdfs" || serviceData.type == "yarn") && show && ( |
| <Alert variant="warning" onClose={() => setShow(false)} dismissible> |
| <i className="fa-fw fa fa-info-circle d-inline text-dark"></i> |
| <p className="pd-l-10 d-inline"> |
| {`By default, fallback to ${ |
| alertMessage[serviceData.type].label |
| } ACLs are enabled. If access cannot be |
| determined by Ranger policies, authorization will fall back to |
| ${ |
| alertMessage[serviceData.type].label |
| } ACLs. If this behavior needs to be changed, modify ${ |
| alertMessage[serviceData.type].label |
| } |
| plugin config - ${ |
| alertMessage[serviceData.type].configs |
| }-authorization.`} |
| </p> |
| </Alert> |
| )} |
| {pageLoader ? ( |
| <Loader /> |
| ) : ( |
| <React.Fragment> |
| <BlockUi isUiBlock={blockUI} /> |
| <div className="policy-listing"> |
| <Row className="mb-3"> |
| <Col sm={10}> |
| <div className="filter-icon-wrap"> |
| <StructuredFilter |
| key="policy-listing-search-filter" |
| placeholder="Search for your policy..." |
| options={getSearchFilterOptions()} |
| onChange={updateSearchFilter} |
| defaultSelected={defaultSearchFilterParams} |
| /> |
| <CustomPopover |
| icon="fa-fw fa fa-info-circle info-icon" |
| title={ |
| <span style={{ fontSize: "14px" }}> |
| Search Filter Hints |
| </span> |
| } |
| content={getSearchInfoContent()} |
| placement="bottom" |
| trigger={["hover", "focus"]} |
| /> |
| </div> |
| </Col> |
| <Col sm={2}> |
| <div className="pull-right mb-1"> |
| {(isSystemAdmin() || isKeyAdmin() || isUser()) && ( |
| <Button |
| variant="primary" |
| size="sm" |
| onClick={addPolicy} |
| data-js="addNewPolicy" |
| data-cy="addNewPolicy" |
| > |
| Add New Policy |
| </Button> |
| )} |
| </div> |
| </Col> |
| </Row> |
| |
| <XATableLayout |
| data={policyListingData} |
| columns={columns} |
| fetchData={fetchPolicyInfo} |
| totalCount={totalCount} |
| pagination |
| pageCount={pageCount} |
| currentpageIndex={currentpageIndex} |
| currentpageSize={currentpageSize} |
| loading={loader} |
| columnSort={true} |
| /> |
| </div> |
| |
| <Modal show={deletePolicyModal.showPopup} onHide={toggleClose}> |
| <Modal.Header closeButton> |
| <span className="text-word-break"> |
| Are you sure you want to delete policy " |
| <b>{deletePolicyModal?.policyDetails?.policyName}</b>" ? |
| </span> |
| </Modal.Header> |
| <Modal.Footer> |
| <Button variant="secondary" size="sm" onClick={toggleClose}> |
| Close |
| </Button> |
| <Button |
| variant="primary" |
| size="sm" |
| onClick={() => |
| handleDeleteClick(deletePolicyModal.policyDetails.policyID) |
| } |
| > |
| OK |
| </Button> |
| </Modal.Footer> |
| </Modal> |
| |
| <Modal show={policyviewmodal} onHide={handleClosePolicyId} size="xl"> |
| <Modal.Header closeButton> |
| <Modal.Title>Policy Details</Modal.Title> |
| </Modal.Header> |
| <Modal.Body> |
| <PolicyViewDetails |
| paramsData={policyParamsData} |
| policyInfo={fetchPolicyInfo} |
| totalCount={totalCount} |
| policyView={true} |
| updateServices={updateServices} |
| /> |
| </Modal.Body> |
| <Modal.Footer> |
| <div className="policy-version text-left"> |
| <span> |
| <i |
| className={ |
| policyParamsData && policyParamsData.version > 1 |
| ? "fa-fw fa fa-chevron-left active" |
| : "fa-fw fa fa-chevron-left" |
| } |
| onClick={(e) => |
| e.currentTarget.classList.contains("active") && |
| previousVersion(e) |
| } |
| ></i> |
| <span>{`Version ${ |
| policyParamsData && policyParamsData.version |
| }`}</span> |
| <i |
| className={ |
| !isUndefined( |
| currentPage[ |
| indexOf( |
| currentPage, |
| policyParamsData && policyParamsData.version |
| ) + 1 |
| ] |
| ) |
| ? "fa-fw fa fa-chevron-right active" |
| : "fa-fw fa fa-chevron-right" |
| } |
| onClick={(e) => |
| e.currentTarget.classList.contains("active") && |
| nextVersion(e) |
| } |
| ></i> |
| </span> |
| {!isUndefined( |
| currentPage[ |
| indexOf( |
| currentPage, |
| policyParamsData && policyParamsData.version |
| ) + 1 |
| ] |
| ) && ( |
| <Button |
| variant="primary" |
| size="sm" |
| onClick={(e) => revert(e)} |
| > |
| Revert |
| </Button> |
| )} |
| </div> |
| <Button variant="primary" size="sm" onClick={handleClosePolicyId}> |
| OK |
| </Button> |
| </Modal.Footer> |
| </Modal> |
| </React.Fragment> |
| )} |
| </div> |
| ); |
| } |
| |
| export default PolicyListing; |