This is an automated email from the ASF dual-hosted git repository.

madhan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git

commit c9a08e68325a94ea34325b88e7f45290f0ee8bda
Author: Brijesh Bhalala <brijeshbhalala2...@gmail.com>
AuthorDate: Thu Oct 5 19:21:33 2023 +0530

    RANGER-4424: UI updates to support security zones without any resource
    
    Signed-off-by: Madhan Neethiraj <mad...@apache.org>
---
 .../main/resources/META-INF/jpa_named_queries.xml  |   2 +-
 .../webapp/react-webapp/src/images/no-service.svg  |   4 +
 .../AuditEvent/AdminLogs/SecurityZonelogs.jsx      | 530 ++++++++++++---------
 .../src/views/AuditEvent/OperationAdminModal.jsx   |  11 +-
 .../src/views/SecurityZone/SecurityZoneForm.jsx    | 126 +++--
 .../src/views/SecurityZone/ZoneDisplay.jsx         | 158 +++---
 .../src/views/SecurityZone/ZoneListing.jsx         |   2 +-
 .../views/ServiceManager/ServiceDefinitions.jsx    |  60 ++-
 8 files changed, 495 insertions(+), 398 deletions(-)

diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml 
b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
index d3246c60c..33172ce85 100755
--- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
+++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
@@ -324,7 +324,7 @@
        </named-query>
 
        <named-query name="XXTrxLog.findByTrxId">
-               <query>SELECT obj FROM XXTrxLog obj WHERE obj.transactionId = 
:transactionId
+               <query>SELECT obj FROM XXTrxLog obj WHERE obj.transactionId = 
:transactionId order by obj.id
                </query>
        </named-query>
 
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/images/no-service.svg 
b/security-admin/src/main/webapp/react-webapp/src/images/no-service.svg
new file mode 100644
index 000000000..a72198016
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/images/no-service.svg
@@ -0,0 +1,4 @@
+<svg width="415" height="419" viewBox="0 0 415 419" fill="none" 
xmlns="http://www.w3.org/2000/svg";>
+<path d="M107.719 251.062C101.463 251.062 96.1439 248.871 91.7615 
244.489C87.379 240.106 85.1878 234.787 85.1878 228.531V81.212C85.1878 74.956 
87.5029 69.513 92.1329 64.8829C96.763 60.2528 102.206 57.9378 108.462 
57.9378H179.15L204.9 83.6878H306.538C312.299 83.6878 317.267 85.5489 321.443 
89.2711C325.619 92.9932 328.038 97.5695 328.698 103H197.002L171.252 
77.25H108.462C107.306 77.25 106.357 77.6214 105.614 78.3643C104.871 79.1072 
104.5 80.0564 104.5 81.212V227.788C104.5 228.696 104.727 2 [...]
+<path d="M48.017 349.636V402H40.7557L14.1392 
363.597H13.6534V402H5.75284V349.636H13.0653L39.7074 
388.091H40.1932V349.636H48.017ZM75.4709 402.793C71.7891 402.793 68.576 401.949 
65.8317 400.261C63.0874 398.574 60.9567 396.213 59.4396 393.179C57.9226 390.145 
57.1641 386.599 57.1641 382.543C57.1641 378.469 57.9226 374.906 59.4396 
371.855C60.9567 368.804 63.0874 366.435 65.8317 364.747C68.576 363.06 71.7891 
362.216 75.4709 362.216C79.1527 362.216 82.3658 363.06 85.1101 364.747C87.8544 
366.435 [...]
+</svg>
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/SecurityZonelogs.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/SecurityZonelogs.jsx
index c6ab380b7..a582cbb8b 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/SecurityZonelogs.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/SecurityZonelogs.jsx
@@ -25,21 +25,57 @@ import { isEmpty } from "lodash";
 
 export const SecurityZonelogs = ({ data, reportdata }) => {
   const { objectName, objectClassType, createDate, owner, action } = data;
-
-  const updateZoneDetails = reportdata.filter(
-    (zone) => zone.action == "update" && zone.attributeName !== "Zone Services"
-  );
-
-  const updateZoneServices = reportdata.filter(
-    (zone) => zone.action == "update" && zone.attributeName == "Zone Services"
-  );
-
   const createZoneDetails = (newvalue) => {
     return !isEmpty(newvalue.replace(/[[\]]/g, ""))
       ? newvalue.replace(/[[\]]/g, "")
       : "--";
   };
 
+  const zoneServiceData = (reportdata, action, attributeName) => {
+    return reportdata.filter(
+      (zone) => zone.action == action && zone.attributeName == attributeName
+    );
+  };
+  const createZoneServices = zoneServiceData(
+    reportdata,
+    "create",
+    "Zone Services"
+  );
+
+  const deleteZoneServices = zoneServiceData(
+    reportdata,
+    "delete",
+    "Zone Services"
+  );
+  const parseAndFilterData = (zones, zoneValues) => {
+    return zones.map(
+      (zone) => !isEmpty(zone[zoneValues]) && JSON.parse(zone[zoneValues])
+    );
+  };
+
+  const newZoneServiceData = parseAndFilterData(createZoneServices, 
"newValue");
+  const oldZoneServiceData = parseAndFilterData(
+    deleteZoneServices,
+    "previousValue"
+  );
+  const updateZoneDetails = reportdata.filter(
+    (zone) => zone.action == "update" && zone.attributeName != "Zone Services"
+  );
+
+  const updateZoneServices = zoneServiceData(
+    reportdata,
+    "update",
+    "Zone Services"
+  );
+
+  const updateZoneOldServices = parseAndFilterData(
+    updateZoneServices,
+    "previousValue"
+  );
+  const updateZoneNewServices = parseAndFilterData(
+    updateZoneServices,
+    "newValue"
+  );
   return (
     <div>
       {/* CREATE  */}
@@ -83,31 +119,31 @@ export const SecurityZonelogs = ({ data, reportdata }) => {
                 })}
             </Table>
             <br />
-            <h5 className="bold wrap-header m-t-sm">Zone Service Details:</h5>
-            <Table className="table table-striped table-bordered w-75">
-              <thead className="thead-light">
-                <tr>
-                  <th>Service Name</th>
+            {!isEmpty(Object.keys(newZoneServiceData[0] || {})) && (
+              <>
+                <h5 className="bold wrap-header m-t-sm">
+                  Zone Service Details:
+                </h5>
+                <Table className="table table-striped table-bordered w-75">
+                  <thead className="thead-light">
+                    <tr>
+                      <th>Service Name</th>
 
-                  <th>Zone Service Resources</th>
-                </tr>
-              </thead>
+                      <th>Zone Service Resources</th>
+                    </tr>
+                  </thead>
 
-              {reportdata
-                .filter((obj) => obj.attributeName == "Zone Services")
-                .map((key) => {
-                  return (
-                    !isEmpty(key.newValue) &&
-                    Object.keys(JSON.parse(key.newValue)).map((c) => {
-                      return (
-                        <tbody>
-                          <tr>
-                            <td className="table-warning align-middle">
-                              <strong> {c}</strong>
-                            </td>
-                            <td className="table-warning ">
+                  {Object.entries(newZoneServiceData[0])?.map(([key]) => {
+                    return (
+                      <tbody>
+                        <tr>
+                          <td className="table-warning align-middle">
+                            <strong> {key}</strong>
+                          </td>
+                          {!isEmpty(newZoneServiceData[0][key].resources) ? (
+                            <td className="table-warning">
                               {Object.values(
-                                JSON.parse(key.newValue)[c].resources
+                                newZoneServiceData[0][key].resources
                               ).map((resource) => (
                                 <div className="zone-resource">
                                   {Object.keys(resource).map((policy) => {
@@ -122,13 +158,16 @@ export const SecurityZonelogs = ({ data, reportdata }) => 
{
                                 </div>
                               ))}
                             </td>
-                          </tr>
-                        </tbody>
-                      );
-                    })
-                  );
-                })}
-            </Table>
+                          ) : (
+                            <td className="text-center table-warning">--</td>
+                          )}
+                        </tr>
+                      </tbody>
+                    );
+                  })}
+                </Table>
+              </>
+            )}
           </div>
         )}
 
@@ -136,188 +175,220 @@ export const SecurityZonelogs = ({ data, reportdata }) 
=> {
 
       {action == "update" &&
         objectClassType == ClassTypes.CLASS_TYPE_RANGER_SECURITY_ZONE.value && 
(
-          <div>
-            <div className="row">
-              <div className="col-md-6">
-                <div className="font-weight-bolder">Name: {objectName}</div>
-                <div className="font-weight-bolder">
-                  Date: {dateFormat(createDate, "mm/dd/yyyy hh:MM:ss TT ")}
-                  India Standard Time
+          <>
+            <div>
+              <div className="row">
+                <div className="col-md-6">
+                  <div className="font-weight-bolder">Name: {objectName}</div>
+                  <div className="font-weight-bolder">
+                    Date: {dateFormat(createDate, "mm/dd/yyyy hh:MM:ss TT ")}
+                    India Standard Time
+                  </div>
+                  <div className="font-weight-bolder">Updated By: {owner}</div>
+                </div>
+                <div className="col-md-6 text-right">
+                  <div className="bg-success legend"></div> {" Added "}
+                  <div className="bg-danger legend"></div> {" Deleted "}
                 </div>
-                <div className="font-weight-bolder">Updated By: {owner}</div>
-              </div>
-              <div className="col-md-6 text-right">
-                <div className="bg-success legend"></div> {" Added "}
-                <div className="bg-danger legend"></div> {" Deleted "}
               </div>
-            </div>
-            <br />
-            {action == "update" && !isEmpty(updateZoneDetails) && (
-              <>
-                <h5 className="bold wrap-header m-t-sm">Zone Details:</h5>
+              <br />
+              {action == "update" && !isEmpty(updateZoneDetails) && (
+                <>
+                  <h5 className="bold wrap-header m-t-sm">Zone Details:</h5>
 
-                <Table className="table  table-bordered table-striped  w-auto">
-                  <thead className="thead-light">
-                    <tr>
-                      <th>Fields</th>
-                      <th>Old Value</th>
-                      <th>New Value</th>
-                    </tr>
-                  </thead>
-                  {updateZoneDetails.map((obj) => (
-                    <tbody>
-                      <tr key={obj.id}>
-                        <td className="table-warning text-nowrap">
-                          {obj.attributeName}
-                        </td>
+                  <Table className="table  table-bordered table-striped  
w-auto">
+                    <thead className="thead-light">
+                      <tr>
+                        <th>Fields</th>
+                        <th>Old Value</th>
+                        <th>New Value</th>
+                      </tr>
+                    </thead>
+                    {updateZoneDetails.map((obj) => (
+                      <tbody>
+                        <tr key={obj.id}>
+                          <td className="table-warning text-nowrap">
+                            {!isEmpty(obj.attributeName)
+                              ? obj.attributeName
+                              : "--"}
+                          </td>
 
-                        <td className="table-warning text-nowrap">
-                          {!isEmpty(obj.previousValue.replace(/[[\]]/g, "")) ? 
(
-                            isEmpty(obj.newValue.replace(/[[\]]/g, "")) ? (
-                              <h6>
-                                <Badge
-                                  className="d-inline mr-1"
-                                  variant="danger"
-                                >
-                                  {obj.previousValue.replace(/[[\]]/g, "")}
-                                </Badge>
-                              </h6>
-                            ) : (
+                          <td className="table-warning text-nowrap">
+                            {!isEmpty(
                               obj.previousValue.replace(/[[\]]/g, "")
-                            )
-                          ) : (
-                            "--"
-                          )}
-                        </td>
-                        <td className="table-warning text-nowrap">
-                          {!isEmpty(obj.newValue.replace(/[[\]]/g, "")) ? (
-                            isEmpty(obj.previousValue.replace(/[[\]]/g, "")) ? 
(
-                              <h6>
-                                <Badge
-                                  className="d-inline mr-1"
-                                  variant="success"
-                                >
-                                  {obj.newValue.replace(/[[\]]/g, "")}
-                                </Badge>
-                              </h6>
+                            ) ? (
+                              isEmpty(obj.newValue.replace(/[[\]]/g, "")) ? (
+                                <h6>
+                                  <Badge
+                                    className="d-inline mr-1"
+                                    variant="danger"
+                                  >
+                                    {obj.previousValue.replace(/[[\]]/g, "")}
+                                  </Badge>
+                                </h6>
+                              ) : (
+                                obj.previousValue.replace(/[[\]]/g, "")
+                              )
                             ) : (
-                              obj.newValue.replace(/[[\]]/g, "")
-                            )
-                          ) : (
-                            "--"
-                          )}
-                        </td>
-                      </tr>
-                    </tbody>
-                  ))}
-                </Table>
-                <br />
-              </>
-            )}
-          </div>
-        )}
-
-      {action == "update" && !isEmpty(updateZoneServices) && (
-        <div className="row">
-          <div className="col">
-            <h5 className="bold wrap-header m-t-sm">
-              Old Zone Service Details:
-            </h5>
+                              "--"
+                            )}
+                          </td>
+                          <td className="table-warning text-nowrap">
+                            {!isEmpty(obj.newValue.replace(/[[\]]/g, "")) ? (
+                              isEmpty(
+                                obj.previousValue.replace(/[[\]]/g, "")
+                              ) ? (
+                                <h6>
+                                  <Badge
+                                    className="d-inline mr-1"
+                                    variant="success"
+                                  >
+                                    {obj.newValue.replace(/[[\]]/g, "")}
+                                  </Badge>
+                                </h6>
+                              ) : (
+                                obj.newValue.replace(/[[\]]/g, "")
+                              )
+                            ) : (
+                              "--"
+                            )}
+                          </td>
+                        </tr>
+                      </tbody>
+                    ))}
+                  </Table>
+                  <br />
+                </>
+              )}
+            </div>
+            {(!isEmpty(Object.keys(updateZoneOldServices[0] || {})) ||
+              !isEmpty(Object.keys(updateZoneNewServices[0] || {}))) && (
+              <div className="row">
+                <div className="col">
+                  <h5 className="bold wrap-header m-t-sm">
+                    Old Zone Service Details:
+                  </h5>
 
-            <Table className="table  table-bordered table-striped w-100">
-              <thead className="thead-light">
-                <tr>
-                  <th>Service Name</th>
+                  <Table className="table  table-bordered table-striped w-100">
+                    <thead className="thead-light">
+                      <tr>
+                        <th>Service Name</th>
 
-                  <th> Zone Service Resources</th>
-                </tr>
-              </thead>
-              {updateZoneServices.map((key) => {
-                return (
-                  !isEmpty(key.previousValue) &&
-                  Object.keys(JSON.parse(key.previousValue)).map((c) => {
-                    return (
+                        <th> Zone Service Resources</th>
+                      </tr>
+                    </thead>
+                    {!isEmpty(Object.keys(updateZoneOldServices[0] || {})) ? (
+                      Object.entries(updateZoneOldServices[0]).map(([key]) => {
+                        return (
+                          <tbody>
+                            <tr>
+                              <td className="old-value-bg">
+                                <strong> {key}</strong>
+                              </td>
+                              {!isEmpty(
+                                updateZoneOldServices[0][key].resources
+                              ) ? (
+                                <td className="old-value-bg">
+                                  {Object.values(
+                                    updateZoneOldServices[0][key].resources
+                                  ).map((resource) => (
+                                    <div className="zone-resource">
+                                      {Object.keys(resource).map((policy) => {
+                                        return (
+                                          <>
+                                            <strong>{`${policy} : `}</strong>
+                                            {resource[policy].join(", ")}
+                                            <br />
+                                          </>
+                                        );
+                                      })}
+                                    </div>
+                                  ))}
+                                </td>
+                              ) : (
+                                <td className="text-center 
old-value-bg">--</td>
+                              )}
+                            </tr>
+                          </tbody>
+                        );
+                      })
+                    ) : (
                       <tbody>
                         <tr>
-                          <td className="old-value-bg">
-                            <strong> {c}</strong>
-                          </td>
-                          <td className="old-value-bg">
-                            {Object.values(
-                              JSON.parse(key.previousValue)[c].resources
-                            ).map((resource) => (
-                              <div className="zone-resource">
-                                {Object.keys(resource).map((policy) => {
-                                  return (
-                                    <>
-                                      <strong>{`${policy} : `}</strong>
-                                      {resource[policy].join(", ")}
-                                      <br />
-                                    </>
-                                  );
-                                })}
-                              </div>
-                            ))}
+                          <td colSpan={2} className="text-center old-value-bg">
+                            --
                           </td>
                         </tr>
                       </tbody>
-                    );
-                  })
-                );
-              })}
-            </Table>
-          </div>
-          <div className="col">
-            <h5 className="bold wrap-header m-t-sm">
-              New Zone Service Details:
-            </h5>
+                    )}
+                  </Table>
+                </div>
+                <div className="col">
+                  <h5 className="bold wrap-header m-t-sm">
+                    New Zone Service Details:
+                  </h5>
 
-            <Table className="table  table-bordered table-striped w-100">
-              <thead className="thead-light">
-                <tr>
-                  <th>Service Name </th>
+                  <Table className="table  table-bordered table-striped w-100">
+                    <thead className="thead-light">
+                      <tr>
+                        <th>Service Name </th>
 
-                  <th> Zone Service Resources</th>
-                </tr>
-              </thead>
-              {updateZoneServices.map((key) => {
-                return (
-                  !isEmpty(key.newValue) &&
-                  Object.keys(JSON.parse(key.newValue)).map((c) => {
-                    return (
+                        <th> Zone Service Resources</th>
+                      </tr>
+                    </thead>
+                    {!isEmpty(Object.keys(updateZoneNewServices[0] || {})) ? (
+                      Object.entries(updateZoneNewServices[0]).map(([key]) => {
+                        return (
+                          <tbody>
+                            <tr>
+                              <td className="table-warning align-middle">
+                                <strong> {key}</strong>
+                              </td>
+                              {!isEmpty(
+                                updateZoneNewServices[0][key].resources
+                              ) ? (
+                                <td className="table-warning ">
+                                  {Object.values(
+                                    updateZoneNewServices[0][key].resources
+                                  ).map((resource) => (
+                                    <div className="zone-resource">
+                                      {Object.keys(resource).map((policy) => {
+                                        return (
+                                          <>
+                                            <strong>{`${policy} : `}</strong>
+                                            {resource[policy].join(", ")}
+                                            <br />
+                                          </>
+                                        );
+                                      })}
+                                    </div>
+                                  ))}
+                                </td>
+                              ) : (
+                                <td className="text-center table-warning">
+                                  --
+                                </td>
+                              )}
+                            </tr>
+                          </tbody>
+                        );
+                      })
+                    ) : (
                       <tbody>
                         <tr>
-                          <td className="table-warning align-middle">
-                            <strong> {c}</strong>
-                          </td>
-                          <td className="table-warning ">
-                            {Object.values(
-                              JSON.parse(key.newValue)[c].resources
-                            ).map((resource) => (
-                              <div className="zone-resource">
-                                {Object.keys(resource).map((policy) => {
-                                  return (
-                                    <>
-                                      <strong>{`${policy} : `}</strong>
-                                      {resource[policy].join(", ")}
-                                      <br />
-                                    </>
-                                  );
-                                })}
-                              </div>
-                            ))}
+                          <td colSpan={2} className="text-center 
table-warning">
+                            --
                           </td>
                         </tr>
                       </tbody>
-                    );
-                  })
-                );
-              })}
-            </Table>
-            <br />
-          </div>
-        </div>
-      )}
+                    )}
+                  </Table>
+                  <br />
+                </div>
+              </div>
+            )}
+          </>
+        )}
 
       {/* DELETE  */}
 
@@ -360,31 +431,31 @@ export const SecurityZonelogs = ({ data, reportdata }) => 
{
                 })}
             </Table>
             <br />
-            <h5 className="bold wrap-header m-t-sm">Zone Service Details:</h5>
-            <Table className="table table-striped table-bordered w-75">
-              <thead className="thead-light">
-                <tr>
-                  <th>Service Name</th>
+            {!isEmpty(Object.keys(oldZoneServiceData[0] || {})) && (
+              <>
+                <h5 className="bold wrap-header m-t-sm">
+                  Zone Service Details:
+                </h5>
+                <Table className="table table-striped table-bordered w-75">
+                  <thead className="thead-light">
+                    <tr>
+                      <th>Service Name</th>
 
-                  <th>Zone Service Resources</th>
-                </tr>
-              </thead>
+                      <th>Zone Service Resources</th>
+                    </tr>
+                  </thead>
 
-              {reportdata
-                .filter((obj) => obj.attributeName == "Zone Services")
-                .map((key) => {
-                  return (
-                    !isEmpty(key.previousValue) &&
-                    Object.keys(JSON.parse(key.previousValue)).map((c) => {
-                      return (
-                        <tbody>
-                          <tr>
-                            <td className="table-warning align-middle">
-                              <strong> {c}</strong>
-                            </td>
+                  {Object.entries(oldZoneServiceData[0]).map(([key]) => {
+                    return (
+                      <tbody>
+                        <tr>
+                          <td className="table-warning align-middle">
+                            <strong> {key}</strong>
+                          </td>
+                          {!isEmpty(oldZoneServiceData[0][key].resources) ? (
                             <td className="table-warning">
                               {Object.values(
-                                JSON.parse(key.previousValue)[c].resources
+                                oldZoneServiceData[0][key].resources
                               ).map((resource) => (
                                 <div className="zone-resource">
                                   {Object.keys(resource).map((policy) => {
@@ -399,13 +470,16 @@ export const SecurityZonelogs = ({ data, reportdata }) => 
{
                                 </div>
                               ))}
                             </td>
-                          </tr>
-                        </tbody>
-                      );
-                    })
-                  );
-                })}
-            </Table>
+                          ) : (
+                            <td className="text-center table-warning">--</td>
+                          )}
+                        </tr>
+                      </tbody>
+                    );
+                  })}
+                </Table>
+              </>
+            )}
           </div>
         )}
     </div>
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/OperationAdminModal.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/OperationAdminModal.jsx
index 8e17b4301..0d30e3224 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/OperationAdminModal.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/OperationAdminModal.jsx
@@ -43,17 +43,20 @@ export const OperationAdminModal = ({ onHide, show, data = 
{} }) => {
 
   const rowModal = async () => {
     setLoader(true);
+    let authlogs = [];
+
     try {
       const authResp = await fetchApi({
         url: `assets/report/${transactionId}`
       });
-      let authlogs = authResp.data.vXTrxLogs;
-      setShowview(objectId);
-      setReportData(authlogs);
-      setLoader(false);
+      authlogs = authResp?.data?.vXTrxLogs || [];
     } catch (error) {
       console.error(`Error occurred while fetching Admin logs! ${error}`);
     }
+
+    setShowview(objectId);
+    setReportData(authlogs);
+    setLoader(false);
   };
 
   return (
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx
index fc56b661c..3bf0df71c 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx
@@ -124,14 +124,6 @@ const SecurityZoneForm = () => {
         text: ""
       };
     }
-
-    if (isEmpty(values.resourceServices)) {
-      errors.resourceServices = {
-        required: true,
-        text: "Required"
-      };
-    }
-
     return errors;
   };
 
@@ -325,33 +317,29 @@ const SecurityZoneForm = () => {
     }
 
     zoneData.services = {};
-
-    for (let key of Object.keys(values.tableList)) {
-      let serviceName = values.tableList[key].serviceName;
-      let resourcesName = values.tableList[key].resources;
-      zoneData.services[serviceName] = {};
-      zoneData.services[serviceName].resources = [];
-      resourcesName.map((obj) => {
-        let serviceResourceData = {};
-        pickBy(obj, (key, val) => {
-          if (
-            obj[`value-${key.level}`] &&
-            obj[`value-${key.level}`].length > 0
-          ) {
-            if (val.includes("resourceName")) {
-              serviceResourceData[key.name] = obj[`value-${key.level}`].map(
-                (value) => value.value
-              );
+    if (!isEmpty(Object.keys(values.tableList || {}))) {
+      for (let key of Object.keys(values.tableList)) {
+        let serviceName = values.tableList[key].serviceName;
+        let resourcesName = values.tableList[key].resources;
+        zoneData.services[serviceName] = {};
+        zoneData.services[serviceName].resources = [];
+        resourcesName.map((obj) => {
+          let serviceResourceData = {};
+          pickBy(obj, (key, val) => {
+            if (
+              obj[`value-${key.level}`] &&
+              obj[`value-${key.level}`].length > 0
+            ) {
+              if (val.includes("resourceName")) {
+                serviceResourceData[key.name] = obj[`value-${key.level}`].map(
+                  (value) => value.value
+                );
+              }
             }
-          }
-        });
-        return zoneData.services[serviceName].resources.push(
-          serviceResourceData
-        );
-      });
-      if (zoneData.services[serviceName].resources.length === 0) {
-        toast.error("Please add at least one resource for  service", {
-          toastId: "error1"
+          });
+          return zoneData.services[serviceName].resources.push(
+            serviceResourceData
+          );
         });
       }
     }
@@ -431,7 +419,7 @@ const SecurityZoneForm = () => {
     }
 
     zoneData.tableList = [];
-    for (let name of Object.keys(zone.services)) {
+    for (let name of Object.keys(zone.services || {})) {
       let tableValues = {};
 
       tableValues["serviceName"] = name;
@@ -450,33 +438,36 @@ const SecurityZoneForm = () => {
       }
 
       tableValues["resources"] = [];
-      zone.services[name].resources.map((obj) => {
-        let serviceResource = {};
-        let lastResourceLevel = [];
-        Object.entries(obj).map(([key, value]) => {
-          let setResources = find(filterServiceDef.resources, ["name", key]);
-          serviceResource[`resourceName-${setResources.level}`] = setResources;
-          serviceResource[`value-${setResources.level}`] = value.map((m) => {
-            return { label: m, value: m };
-          });
-          lastResourceLevel.push({
-            level: setResources.level,
-            name: setResources.name
+      if (!isEmpty(zone.services[name].resources)) {
+        zone.services[name].resources?.map((obj) => {
+          let serviceResource = {};
+          let lastResourceLevel = [];
+          Object.entries(obj).map(([key, value]) => {
+            let setResources = find(filterServiceDef.resources, ["name", key]);
+            serviceResource[`resourceName-${setResources.level}`] =
+              setResources;
+            serviceResource[`value-${setResources.level}`] = value.map((m) => {
+              return { label: m, value: m };
+            });
+            lastResourceLevel.push({
+              level: setResources.level,
+              name: setResources.name
+            });
           });
+          lastResourceLevel = maxBy(lastResourceLevel, "level");
+          let setLastResources = find(
+            sortBy(filterServiceDef.resources, "itemId"),
+            ["parent", lastResourceLevel.name]
+          );
+          if (setLastResources && setLastResources?.isValidLeaf) {
+            serviceResource[`resourceName-${setLastResources.level}`] = {
+              label: "None",
+              value: "none"
+            };
+          }
+          tableValues["resources"].push(serviceResource);
         });
-        lastResourceLevel = maxBy(lastResourceLevel, "level");
-        let setLastResources = find(
-          sortBy(filterServiceDef.resources, "itemId"),
-          ["parent", lastResourceLevel.name]
-        );
-        if (setLastResources && setLastResources?.isValidLeaf) {
-          serviceResource[`resourceName-${setLastResources.level}`] = {
-            label: "None",
-            value: "none"
-          };
-        }
-        tableValues["resources"].push(serviceResource);
-      });
+      }
 
       zoneData.tableList.push(tableValues);
     }
@@ -930,22 +921,16 @@ const SecurityZoneForm = () => {
                     />
                     <Field
                       name="resourceServices"
-                      render={({ input, meta }) => (
+                      render={({ input }) => (
                         <Row className="form-group">
                           <Col xs={3}>
                             <label className="form-label pull-right">
-                              Select Resource Services *
+                              Select Resource Services
                             </label>
                           </Col>
                           <Col xs={6}>
                             <Select
                               {...input}
-                              styles={
-                                meta.error && meta.touched
-                                  ? selectCustomStyles
-                                  : ""
-                              }
-                              id={meta.error && meta.touched ? "isError" : ""}
                               onChange={(values, e) =>
                                 resourceServicesOnChange(
                                   e,
@@ -965,11 +950,6 @@ const SecurityZoneForm = () => {
                               isSearchable={true}
                               placeholder="Select Service Name"
                             />
-                            {meta.error && meta.touched && (
-                              <span className="invalid-field">
-                                {meta.error.text}
-                              </span>
-                            )}
                           </Col>
                         </Row>
                       )}
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/ZoneDisplay.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/ZoneDisplay.jsx
index db1fa0622..5a8cbe540 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/ZoneDisplay.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/ZoneDisplay.jsx
@@ -30,7 +30,7 @@ import {
   Modal
 } from "react-bootstrap";
 import { Link } from "react-router-dom";
-import { find } from "lodash";
+import { find, isEmpty } from "lodash";
 import { isSystemAdmin, isKeyAdmin } from "Utils/XAUtils";
 
 class ZoneDisplay extends Component {
@@ -104,7 +104,7 @@ class ZoneDisplay extends Component {
             {this.state.isAdminRole && (
               <div className="float-right d-flex align-items-start">
                 <Link
-                  className="btn btn-sm btn-outline-primary m-r-5 "
+                  className="btn btn-sm btn-outline-primary m-r-5"
                   title="Edit"
                   to={`/zones/edit/${this.props.zone.id}`}
                   data-id="editZone"
@@ -181,7 +181,7 @@ class ZoneDisplay extends Component {
                 <Accordion.Collapse eventKey="0">
                   <Card.Body className="p-0">
                     <Form className="border border-white shadow-none p-0">
-                      <Form.Group as={Row} className="mb-3 ">
+                      <Form.Group as={Row} className="mb-3">
                         <Form.Label className="text-right" column sm="3">
                           Admin Users
                         </Form.Label>
@@ -210,20 +210,18 @@ class ZoneDisplay extends Component {
                         </Form.Label>
                         <Col sm="9" className="pt-2">
                           {this.props?.zone?.adminUserGroups?.length > 0 ? (
-                            this.props?.zone?.adminUserGroups?.map(
-                              (obj, index) => {
-                                return (
-                                  <Badge
-                                    variant="secondary"
-                                    className="mr-1 more-less-width 
text-truncate"
-                                    key={obj}
-                                    title={obj}
-                                  >
-                                    {obj}
-                                  </Badge>
-                                );
-                              }
-                            )
+                            this.props?.zone?.adminUserGroups?.map((obj) => {
+                              return (
+                                <Badge
+                                  variant="secondary"
+                                  className="mr-1 more-less-width 
text-truncate"
+                                  key={obj}
+                                  title={obj}
+                                >
+                                  {obj}
+                                </Badge>
+                              );
+                            })
                           ) : (
                             <span className="mt-1">--</span>
                           )}
@@ -258,20 +256,18 @@ class ZoneDisplay extends Component {
                         </Form.Label>
                         <Col sm="9" className="pt-2">
                           {this.props?.zone?.auditUserGroups?.length > 0 ? (
-                            this.props?.zone?.auditUserGroups?.map(
-                              (obj, index) => {
-                                return (
-                                  <Badge
-                                    variant="secondary"
-                                    className="mr-1 more-less-width 
text-truncate"
-                                    key={obj}
-                                    title={obj}
-                                  >
-                                    {obj}
-                                  </Badge>
-                                );
-                              }
-                            )
+                            this.props?.zone?.auditUserGroups?.map((obj) => {
+                              return (
+                                <Badge
+                                  variant="secondary"
+                                  className="mr-1 more-less-width 
text-truncate"
+                                  key={obj}
+                                  title={obj}
+                                >
+                                  {obj}
+                                </Badge>
+                              );
+                            })
                           ) : (
                             <span className="mt-1">--</span>
                           )}
@@ -360,44 +356,70 @@ class ZoneDisplay extends Component {
                         </tr>
                       </thead>
                       <tbody>
-                        {Object.keys(this.props?.zone?.services)?.map(
-                          (key, index) => {
-                            let servicetype = find(this.props.services, {
-                              name: key
-                            });
+                        {!isEmpty(this.props?.zone?.services) ? (
+                          Object.keys(this.props?.zone?.services)?.map(
+                            (key, index) => {
+                              let servicetype = find(this.props.services, {
+                                name: key
+                              });
 
-                            return (
-                              <tr className="bg-white" key={index}>
-                                <td className="align-middle" width="20%">
-                                  {key}
-                                </td>
-                                <td className="align-middle" width="20%">
-                                  {servicetype &&
-                                    servicetype.type.toUpperCase()}
-                                </td>
-                                <td
-                                  className="text-center"
-                                  width="32%"
-                                  height="55px"
-                                >
-                                  {this.props?.zone?.services[
-                                    key
-                                  ]?.resources?.map((resource, index) => (
-                                    <div className="resource-group" 
key={index}>
-                                      {Object.keys(resource)?.map(
-                                        (resourceKey, index) => (
-                                          <p key={index} 
className="text-break">
-                                            <strong>{`${resourceKey} : 
`}</strong>
-                                            {resource[resourceKey].join(", ")}
-                                          </p>
-                                        )
-                                      )}
-                                    </div>
-                                  ))}
-                                </td>
-                              </tr>
-                            );
-                          }
+                              return (
+                                <tr className="bg-white" key={index}>
+                                  <td className="align-middle" width="20%">
+                                    {key}
+                                  </td>
+                                  <td className="align-middle" width="20%">
+                                    {servicetype &&
+                                      servicetype.type.toUpperCase()}
+                                  </td>
+                                  <td
+                                    className="text-center"
+                                    width="32%"
+                                    height="55px"
+                                  >
+                                    {!isEmpty(
+                                      
this.props?.zone?.services[key]?.resources
+                                    )
+                                      ? this.props?.zone?.services[
+                                          key
+                                        ]?.resources?.map((resource, index) => 
(
+                                          <div
+                                            className="resource-group"
+                                            key={index}
+                                          >
+                                            {Object.keys(resource)?.map(
+                                              (resourceKey, index) => (
+                                                <p
+                                                  key={index}
+                                                  className="text-break"
+                                                >
+                                                  <strong>{`${resourceKey} : 
`}</strong>
+                                                  {resource[resourceKey].join(
+                                                    ", "
+                                                  )}
+                                                </p>
+                                              )
+                                            )}
+                                          </div>
+                                        ))
+                                      : "--"}
+                                  </td>
+                                </tr>
+                              );
+                            }
+                          )
+                        ) : (
+                          <tr>
+                            <td
+                              colSpan="3"
+                              className="text-center text-secondary bg-light"
+                            >
+                              <h6 className="text-muted large mt-2">
+                                No resource based services are associated with
+                                this zone
+                              </h6>
+                            </td>
+                          </tr>
                         )}
                       </tbody>
                     </Table>
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/ZoneListing.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/ZoneListing.jsx
index 046a7fd8b..e672611dd 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/ZoneListing.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/ZoneListing.jsx
@@ -258,7 +258,7 @@ class ZoneListing extends Component {
                       <Col md="auto">
                         <div className="pt-5 pr-5">
                           <img
-                            alt="Avatar"
+                            alt="No Zones"
                             className="w-50 p-3 d-block mx-auto"
                             src={noZoneImage}
                           />
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinitions.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinitions.jsx
index 715038f67..0b2f46bec 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinitions.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinitions.jsx
@@ -18,7 +18,7 @@
  */
 
 import React, { Component } from "react";
-import { Button, Row } from "react-bootstrap";
+import { Button, Col, Row } from "react-bootstrap";
 import Select from "react-select";
 import { toast } from "react-toastify";
 import { filter, map, sortBy, uniq, isEmpty } from "lodash";
@@ -37,6 +37,7 @@ import ImportPolicy from "./ImportPolicy";
 import { serverError } from "../../utils/XAUtils";
 import { BlockUi, Loader } from "../../components/CommonComponents";
 import { getServiceDef } from "../../utils/appState";
+import noServiceImage from "Images/no-service.svg";
 
 class ServiceDefinitions extends Component {
   constructor(props) {
@@ -454,28 +455,41 @@ class ServiceDefinitions extends Component {
           <Loader />
         ) : (
           <div className="wrap policy-manager">
-            <Row>
-              {filterServiceDefs?.map((serviceDef) => (
-                <ServiceDefinition
-                  key={serviceDef && serviceDef.id}
-                  serviceDefData={serviceDef}
-                  servicesData={sortBy(
-                    filterServices.filter(
-                      (service) => service.type === serviceDef.name
-                    ),
-                    "name"
-                  )}
-                  deleteService={this.deleteService}
-                  selectedZone={selectedZone}
-                  zones={zones}
-                  isAdminRole={isAdminRole}
-                  isUserRole={isUserRole}
-                  showBlockUI={this.showBlockUI}
-                  allServices={this.state.allServices}
-                ></ServiceDefinition>
-              ))}
-            </Row>
-
+            {!isEmpty(filterServiceDefs) ? (
+              <Row>
+                {filterServiceDefs?.map((serviceDef) => (
+                  <ServiceDefinition
+                    key={serviceDef && serviceDef.id}
+                    serviceDefData={serviceDef}
+                    servicesData={sortBy(
+                      filterServices.filter(
+                        (service) => service.type === serviceDef.name
+                      ),
+                      "name"
+                    )}
+                    deleteService={this.deleteService}
+                    selectedZone={selectedZone}
+                    zones={zones}
+                    isAdminRole={isAdminRole}
+                    isUserRole={isUserRole}
+                    showBlockUI={this.showBlockUI}
+                    allServices={this.state.allServices}
+                  ></ServiceDefinition>
+                ))}
+              </Row>
+            ) : (
+              <Row className="justify-content-md-center">
+                <Col md="auto">
+                  <div className="pt-5 pr-5">
+                    <img
+                      alt="No Services"
+                      className="w-50 p-3 d-block mx-auto"
+                      src={noServiceImage}
+                    />
+                  </div>
+                </Col>
+              </Row>
+            )}
             <BlockUi isUiBlock={this.state.blockUI} />
           </div>
         )}

Reply via email to