[SECIOTSRK-676] AJAX request for device state update was implemented
authorArtem Motchanyi <a.motchanyi@samsung.com>
Mon, 6 Nov 2017 09:52:48 +0000 (11:52 +0200)
committerArtem Motchanyi <a.motchanyi@samsung.com>
Mon, 6 Nov 2017 09:53:11 +0000 (11:53 +0200)
12 files changed:
servers/dsm/configuration/develop/jdbc.properties
servers/dsm/src/main/java/com/samsung/dsm/controller/DashboardDevicesController.java
servers/dsm/src/main/java/com/samsung/dsm/model/view/ViewDevice.java
servers/dsm/src/main/resources/ldap.cfg [deleted file]
servers/dsm/src/main/webapp/WEB-INF/tiles/templates/device/devices.jsp
servers/dsm/src/main/webapp/WEB-INF/tiles/templates/template.jsp
servers/dsm/src/main/webapp/resources/css/main.scss
servers/dsm/src/main/webapp/resources/images/device/status/loader.gif [new file with mode: 0644]
servers/dsm/src/main/webapp/resources/js/controls.js
servers/dsm/src/main/webapp/resources/js/devices/devices.js [new file with mode: 0644]
servers/dsm/src/test/java/com/samsung/dsm/controller/DashboardControllerTest.java
servers/dsm/src/test/java/com/samsung/dsm/controller/DashboardDevicesControllerTest.java

index 881658e..1547bc3 100644 (file)
@@ -5,7 +5,7 @@ jdbc.password=postgres
 
 hibernate.dialect=org.hibernate.dialect.PostgreSQL82Dialect
 hibernate.show_sql=true
-hibernate.hbm2ddl.auto=create
+hibernate.hbm2ddl.auto=update
 hibernate.hbm2ddl.import_files=sql/init.sql
 hibernate.temp.use_jdbc_metadata_defaults=false
 
index 8f84761..e9d6acb 100644 (file)
@@ -5,13 +5,42 @@
  */
 package com.samsung.dsm.controller;
 
+import static com.samsung.dsm.policy.parser.PolicyParserFactory.Type.JSON;
+import static org.springframework.http.HttpStatus.BAD_REQUEST;
+import static org.springframework.http.HttpStatus.OK;
+import static org.springframework.web.bind.annotation.RequestMethod.POST;
+
+import java.security.Principal;
+import java.util.List;
+
+import javax.validation.Valid;
+
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.google.gson.Gson;
 import com.google.gson.JsonSyntaxException;
 import com.samsung.commons.domain.Device;
 import com.samsung.commons.domain.Report;
 import com.samsung.commons.domain.ReportType;
 import com.samsung.commons.domain.User;
 import com.samsung.commons.model.MQPolicy;
-import com.samsung.commons.service.*;
+import com.samsung.commons.service.AgentService;
+import com.samsung.commons.service.DeviceService;
+import com.samsung.commons.service.PolicyService;
+import com.samsung.commons.service.ReportService;
+import com.samsung.commons.service.ReportTypeService;
+import com.samsung.commons.service.UserService;
 import com.samsung.dsm.model.request.ApplyPolicy;
 import com.samsung.dsm.model.view.DeviceOverview;
 import com.samsung.dsm.model.view.ViewDevice;
@@ -21,25 +50,6 @@ import com.samsung.dsm.policy.parser.PolicyParserFactory;
 import com.samsung.dsm.utils.alive.AliveApi;
 import com.samsung.dsm.utils.alive.AliveApiSenderException;
 import com.samsung.dsm.utils.mq.MQApi;
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import javax.validation.Valid;
-import java.security.Principal;
-import java.util.List;
-
-import static com.samsung.dsm.policy.parser.PolicyParserFactory.Type.JSON;
-import static org.springframework.http.HttpStatus.BAD_REQUEST;
-import static org.springframework.http.HttpStatus.OK;
-import static org.springframework.web.bind.annotation.RequestMethod.POST;
 
 /**
  * <h1>Dashboard Devices controller</h1>
@@ -95,6 +105,21 @@ public class DashboardDevicesController {
     @RequestMapping(value = "")
     public String iotDevices(Principal principal, Model model) {
         User currentUser = userService.getUserByEmail(principal.getName());
+        model.addAttribute("devices", ViewDevice.getViewDevicesList(deviceService.findByUser(currentUser)));
+
+        return "devices";
+    }
+
+    /**
+     * (Async) Get IoT devices status.
+     *
+     * @param principal the principal
+     * @return devices list with updated status
+     */
+    @ResponseBody
+    @RequestMapping(value = "/status", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE })
+    public ResponseEntity<String> getIotDevicesStatus(Principal principal) {
+        User currentUser = userService.getUserByEmail(principal.getName());
 
         try {
             boolean alive = aliveApi.alive(currentUser.getUsername());
@@ -103,14 +128,11 @@ public class DashboardDevicesController {
             LOG.debug(alive ?
                     message + "states updated" :
                     message + "Nothing changed");
-
         } catch (AliveApiSenderException e) {
             LOG.warn("Couldn't  actualize devices states", e);
         }
 
-        model.addAttribute("devices", ViewDevice.getViewDevicesList(deviceService.findByUser(currentUser)));
-
-        return "devices";
+        return new ResponseEntity<>(new Gson().toJson(ViewDevice.getViewDevicesList(deviceService.findByUser(currentUser))), HttpStatus.OK);
     }
 
     /**
index 3d0b06b..63a8eef 100644 (file)
@@ -53,11 +53,11 @@ public class ViewDevice extends BaseView {
 
     /**
      * Instantiates a new View device.
+     * With policies parsing and setting.
      *
      * @param device     the device
      * @param policyType the policy type
      */
-// With policies parsing and setting
     public ViewDevice(Device device, PolicyParserFactory.Type policyType) {
         reports = new ArrayList<>();
         this.id = device.getId();
@@ -72,10 +72,10 @@ public class ViewDevice extends BaseView {
 
     /**
      * Instantiates a new View device.
+     * Without policies parsing and setting
      *
      * @param device the device
      */
-// Without policies parsing and setting
     public ViewDevice(Device device) {
         reports = new ArrayList<>();
         this.id = device.getId();
diff --git a/servers/dsm/src/main/resources/ldap.cfg b/servers/dsm/src/main/resources/ldap.cfg
deleted file mode 100644 (file)
index 22adfc6..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-106.125.46.74:1389
-cn=Directory Manager
-qazqwe123
\ No newline at end of file
index 1565cb4..7d6f15a 100644 (file)
@@ -6,6 +6,8 @@ $(document).ready(function(){
         valueNames: [ "name" ]
     };
     var smackList = new List("devices-tab", options);
+
+    Devices.updateStatus("<c:url value='/dashboard/devices/status'/>");
 });
 </script>
 
@@ -24,7 +26,7 @@ $(document).ready(function(){
             <div class="list">
                 <c:forEach items="${devices}" var="device">
                     <c:if test="${fn:length(device.parentUuid) == 0 }">
-                        <div class="row device ${device.type}" data-id="${device.id}" data-url="<c:url value='/dashboard/devices/overview'/>">
+                        <div class="row device loading ${device.type}" data-id="${device.id}" data-url="<c:url value='/dashboard/devices/overview'/>">
                             <div class="col-sm-5 col-md-5 col-xs-5">
                                 <div class="icon"></div>
                                 <div class="info">
@@ -33,19 +35,19 @@ $(document).ready(function(){
                                 </div>
                             </div>
                             <div class="col-sm-4 col-md-4 col-xs-4">
-                                <div class="status ${device.status}"></div>
-                                <div class="status-name">${device.statusText}</div>
+                                <div class="status"></div>
+                                <div class="status-name"></div>
                             </div>
                             <div class="col-sm-3 col-md-3 col-xs-3 actions">
-                                <button class="btn btn-primary" data-id="${device.id}" data-url="<c:url value='/dashboard/devices/policies'/>">Policies</button>
-                                <button class="btn btn-primary" data-id="${device.id}" data-url="<c:url value='/dashboard/devices/reports'/>">Reports</button>
-                                <button class="btn btn-primary" data-id="${device.id}" data-url="<c:url value='/dashboard/devices/agents'/>">Agents</button>
+                                <button class="btn btn-primary" disabled="disabled" data-id="${device.id}" data-url="<c:url value='/dashboard/devices/policies'/>">Policies</button>
+                                <button class="btn btn-primary" disabled="disabled" data-id="${device.id}" data-url="<c:url value='/dashboard/devices/reports'/>">Reports</button>
+                                <button class="btn btn-primary" disabled="disabled" data-id="${device.id}" data-url="<c:url value='/dashboard/devices/agents'/>">Agents</button>
                             </div>
                         </div>
                         <div class="simple-list simple-${device.uuid}">
                             <c:forEach items="${devices}" var="simpleDevice">
                                 <c:if test="${fn:length(simpleDevice.parentUuid) > 0  && simpleDevice.parentUuid == device.uuid}">
-                                    <div class="row device simple ${simpleDevice.type}" data-id="${simpleDevice.id}" data-url="<c:url value='/dashboard/devices/overview'/>">
+                                    <div class="row device simple loading ${simpleDevice.type}" data-id="${simpleDevice.id}" data-url="<c:url value='/dashboard/devices/overview'/>">
                                         <div class="col-sm-5 col-md-5 col-xs-5">
                                             <div class="tree"></div>
                                             <div class="icon"></div>
@@ -55,13 +57,13 @@ $(document).ready(function(){
                                             </div>
                                         </div>
                                         <div class="col-sm-4 col-md-4 col-xs-4">
-                                            <div class="status ${simpleDevice.status}"></div>
-                                            <div class="status-name">${simpleDevice.statusText}</div>
+                                            <div class="status"></div>
+                                            <div class="status-name"></div>
                                         </div>
                                         <div class="col-sm-3 col-md-3 col-xs-3 actions">
-                                            <button class="btn btn-primary" data-id="${simpleDevice.id}" data-url="<c:url value='/dashboard/devices/policies'/>">Policies</button>
-                                            <button class="btn btn-primary" data-id="${simpleDevice.id}" data-url="<c:url value='/dashboard/devices/reports'/>">Reports</button>
-                                            <button class="btn btn-primary" data-id="${simpleDevice.id}" data-url="<c:url value='/dashboard/devices/agents'/>">Agents</button>
+                                            <button class="btn btn-primary" disabled="disabled" data-id="${simpleDevice.id}" data-url="<c:url value='/dashboard/devices/policies'/>">Policies</button>
+                                            <button class="btn btn-primary" disabled="disabled" data-id="${simpleDevice.id}" data-url="<c:url value='/dashboard/devices/reports'/>">Reports</button>
+                                            <button class="btn btn-primary" disabled="disabled" data-id="${simpleDevice.id}" data-url="<c:url value='/dashboard/devices/agents'/>">Agents</button>
                                         </div>
                                     </div>
                                 </c:if>
index bb21434..f6a83c7 100644 (file)
@@ -28,6 +28,7 @@
         <script type="text/javascript" src="<c:url value="/resources/thirdparty/search/list.min.js" />"></script>
         <script type="text/javascript" src="<c:url value="/resources/js/devices/policies.js" />"></script>
         <script type="text/javascript" src="<c:url value="/resources/js/devices/agents.js" />"></script>
+        <script type="text/javascript" src="<c:url value="/resources/js/devices/devices.js" />"></script>
         <script type="text/javascript" src="<c:url value="/resources/js/tools/tools.js" />"></script>
         <script type="text/javascript" src="<c:url value="/resources/js/controls.js" />"></script>
     </head>
index d9ef648..4da33ff 100644 (file)
@@ -278,7 +278,6 @@ ul.nav.nav-tabs {
     
     >.logo {
         float: left;
-        width: 14%;
         font-size: 16pt;
 
         >div {
@@ -402,6 +401,7 @@ ul.nav.nav-tabs {
     background-size: 2em;
     height: 3em;
     width: 3em;
+    background-image: url("../images/device/status/loader.gif");
 
     &.on {
         background-image: url("../images/device/status/on.png");
@@ -538,6 +538,17 @@ ul.nav.nav-tabs {
                     margin: 0.5em 0;
                 }
                 
+                &.loading {
+                    &:hover {
+                        background-color: $hover-bg-color;
+                        cursor: not-allowed;
+                    }
+                    
+                    .status {
+                        margin-left: 1em;
+                    }
+                }
+                
                 &:hover {
                     background-color: $hover-bg-color;
                     cursor: pointer;
diff --git a/servers/dsm/src/main/webapp/resources/images/device/status/loader.gif b/servers/dsm/src/main/webapp/resources/images/device/status/loader.gif
new file mode 100644 (file)
index 0000000..3a53049
Binary files /dev/null and b/servers/dsm/src/main/webapp/resources/images/device/status/loader.gif differ
index d7e1748..e520183 100644 (file)
@@ -82,7 +82,8 @@ function logoClick() {
  * Device container click handler.
  */
 function deviceClick(e) {
-    if ($(e.target).hasClass("btn")) {
+    if ($(e.target).hasClass("btn") ||
+        $(e.target).closest(".device").hasClass("loading")) {
         return;
     }
 
diff --git a/servers/dsm/src/main/webapp/resources/js/devices/devices.js b/servers/dsm/src/main/webapp/resources/js/devices/devices.js
new file mode 100644 (file)
index 0000000..98bc29a
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+    @file devices.js
+    @brief Script for Devices View.
+    @author Artem Motchanyi (a.motchanyi@samsung.com)
+    @date Created Nov 03, 2017
+    @par In Samsung Ukraine R&D Center (SRK) under a contract between
+    @par LLC "Samsung Electronics Ukraine Company" (Kyiv, Ukraine)
+    @par and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+    @par Copyright: (c) 2017 Samsung Electronics Co, Ltd. All rights reserved.
+**/
+function Devices() {}
+
+/**
+ * Agent list container selector.
+ */
+Devices.list = "#devices>.list";
+
+/**
+ * Asynchronously update devices status.
+ */
+Devices.updateStatus = function(url) {
+    $.get(url).done(
+        function(data) {
+            console.log(data);
+
+            data.forEach(function(item) {
+                console.log(item);
+                $(Devices.list).find(".device[data-id='" + item.id + "']").removeClass("loading").find(".actions .btn").removeAttr("disabled");
+                $(Devices.list).find(".device[data-id='" + item.id + "']").find(".status").addClass(item.status);
+                $(Devices.list).find(".device[data-id='" + item.id + "']").find(".status-name").text(item.statusText);
+            });
+        }
+    );
+};
index 08e5d12..77861a9 100644 (file)
@@ -5,7 +5,17 @@
  */
 package com.samsung.dsm.controller;
 
-import com.samsung.commons.domain.Role;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.springframework.test.annotation.DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
+
+import java.security.Principal;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -22,13 +32,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.context.WebApplicationContext;
 
-import java.security.Principal;
-
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.springframework.test.annotation.DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+import com.samsung.commons.domain.Role;
 
 /**
  * The type Dashboard controller test.
index 5eba9fb..87a4795 100644 (file)
@@ -7,6 +7,7 @@ package com.samsung.dsm.controller;
 
 import static com.samsung.dsm.policy.parser.PolicyParserFactory.Type.JSON;
 import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertEquals;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl;
@@ -28,6 +29,7 @@ import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.ResultMatcher;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import org.springframework.transaction.annotation.Transactional;
@@ -113,6 +115,19 @@ public class DashboardDevicesControllerTest {
     }
 
     /**
+     * IoT devices negative test. Devices don't exist.
+     *
+     * @throws Exception the exception
+     */
+    @Test
+    @SuppressWarnings("PMD.SignatureDeclareThrowsException")
+    public void dashboardDevicesStatus() throws Exception {
+        ResultActions result = mockMvc.perform(get("/dashboard/devices/status/").principal(principalMock)).andExpect(status().isOk());
+        String content = result.andReturn().getResponse().getContentAsString();
+        assertEquals("[]", content);
+    }
+
+    /**
      * Dashboard devices overview.
      *
      * @throws Exception the exception