Merge pull request #790 from dunithd/master

Adding an API method to retrieve an activity by it's ID and a device ID
revert-70aa11f8
Geeth 8 years ago committed by GitHub
commit 3deffa99dd

@ -140,6 +140,93 @@ public interface ActivityInfoProviderService {
@HeaderParam("If-Modified-Since") String ifModifiedSince); @HeaderParam("If-Modified-Since") String ifModifiedSince);
@GET
@Path("/{id}/{devicetype}/{deviceid}")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Getting Details of an Activity for a specific device",
notes = "Retrieve the details of a specific activity/operation, such as the meta information of " +
"an operation, including the responses from a given device",
tags = "Activity Info Provider",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:get-activity")
})
}
)
@ApiResponses(value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully fetched the activity details.",
response = Activity.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. \n Empty body because the client already has the latest version of " +
"the requested resource."),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 401,
message = "Unauthorized. \n Unauthorized request."),
@ApiResponse(
code = 404,
message = "Not Found. \n No activity found with the given ID.",
response = ErrorResponse.class),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while fetching the activity data.",
response = ErrorResponse.class)
})
Response getActivityByDevice(
@ApiParam(
name = "id",
value = "Activity id of the operation/activity.",
required = true,
defaultValue = "ACTIVITY_1")
@PathParam("id")
@Size(max = 45)
String id,
@ApiParam(
name = "devicetype",
value = "The device type name, such as ios, android, windows or fire-alarm.",
required = true)
@PathParam("devicetype")
@Size(max = 45)
String type,
@ApiParam(
name = "deviceid",
value = "The device identifier of the device you want ot get details.",
required = true)
@PathParam("deviceid")
@Size(max = 45)
String deviceid,
@ApiParam(
name = "If-Modified-Since",
value = "Checks if the requested variant was modified, since the specified date-time\n." +
"Provide the value in the Java Date Format: EEE, d MMM yyyy HH:mm:ss Z\n." +
"Example: Mon, 05 Jan 2014 15:10:00 +0200",
required = false)
@HeaderParam("If-Modified-Since") String ifModifiedSince);
@GET @GET
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,

@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.jaxrs.service.impl;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
@ -72,6 +73,43 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService
} }
} }
@GET
@Override
@Path("/{id}/{devicetype}/{deviceid}")
public Response getActivityByDevice(@PathParam("id")
@Size(max = 45) String id,
@PathParam("devicetype")
@Size(max = 45) String devicetype,
@PathParam("deviceid")
@Size(max = 45) String deviceid,
@HeaderParam("If-Modified-Since") String ifModifiedSince) {
Activity activity;
DeviceManagementProviderService dmService;
try {
RequestValidationUtil.validateActivityId(id);
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceid);
deviceIdentifier.setType(devicetype);
dmService = DeviceMgtAPIUtils.getDeviceManagementService();
activity = dmService.getOperationByActivityIdAndDevice(id, deviceIdentifier);
if (activity == null) {
return Response.status(404).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage("No activity can be " +
"found upon the provided activity id '" + id + "'").build()).build();
}
return Response.status(Response.Status.OK).entity(activity).build();
} catch (OperationManagementException e) {
String msg = "ErrorResponse occurred while fetching the activity for the supplied id.";
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
}
@GET @GET
@Override @Override
public Response getActivities(@QueryParam("since") String since, @QueryParam("offset") int offset, public Response getActivities(@QueryParam("since") String since, @QueryParam("offset") int offset,

@ -93,6 +93,8 @@ public interface OperationManager {
Activity getOperationByActivityId(String activity) throws OperationManagementException; Activity getOperationByActivityId(String activity) throws OperationManagementException;
Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException;
List<Operation> getOperationUpdatedAfter(long timestamp) throws OperationManagementException; List<Operation> getOperationUpdatedAfter(long timestamp) throws OperationManagementException;
List<Activity> getActivitiesUpdatedAfter(long timestamp) throws OperationManagementException; List<Activity> getActivitiesUpdatedAfter(long timestamp) throws OperationManagementException;

@ -812,6 +812,28 @@ public class OperationManagerImpl implements OperationManager {
} }
} }
public Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException {
// This parses the operation id from activity id (ex : ACTIVITY_23) and converts to the integer.
int operationId = Integer.parseInt(
activity.replace(DeviceManagementConstants.OperationAttributes.ACTIVITY, ""));
if (operationId == 0) {
throw new IllegalArgumentException("Operation ID cannot be null or zero (0).");
}
Device device = this.getDevice(deviceId);
try {
OperationManagementDAOFactory.openConnection();
return operationDAO.getActivityByDevice(operationId, device.getId());
} catch (SQLException e) {
throw new OperationManagementException("Error occurred while opening a connection to the data source.", e);
} catch (OperationManagementDAOException e) {
throw new OperationManagementException("Error occurred while retrieving the operation with activity Id '" +
activity + " and device Id: " + deviceId.getId(), e);
} finally {
OperationManagementDAOFactory.closeConnection();
}
}
@Override @Override
public List<Operation> getOperationUpdatedAfter(long timestamp) throws OperationManagementException { public List<Operation> getOperationUpdatedAfter(long timestamp) throws OperationManagementException {
return null; return null;

@ -70,6 +70,8 @@ public interface OperationDAO {
Activity getActivity(int operationId) throws OperationManagementDAOException; Activity getActivity(int operationId) throws OperationManagementDAOException;
Activity getActivityByDevice(int operationId, int deviceId) throws OperationManagementDAOException;
int getEnrolmentIdFromMappingId(int enrollmentOpMappingId) throws OperationManagementDAOException; int getEnrolmentIdFromMappingId(int enrollmentOpMappingId) throws OperationManagementDAOException;
List<Operation> getOperationsUpdatedAfter(long timestamp) throws OperationManagementDAOException; List<Operation> getOperationsUpdatedAfter(long timestamp) throws OperationManagementDAOException;

@ -384,6 +384,83 @@ public class GenericOperationDAOImpl implements OperationDAO {
return activity; return activity;
} }
public Activity getActivityByDevice(int operationId, int deviceId) throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
Activity activity = null;
List<ActivityStatus> activityStatusList = new ArrayList<>();
try {
Connection conn = OperationManagementDAOFactory.getConnection();
String sql = "SELECT eom.ENROLMENT_ID, eom.OPERATION_ID, eom.ID AS EOM_MAPPING_ID, dor.ID AS OP_RES_ID,\n" +
"de.DEVICE_ID, d.DEVICE_IDENTIFICATION, \n" +
"d.DEVICE_TYPE_ID, dt.NAME AS DEVICE_TYPE_NAME, eom.STATUS, eom.CREATED_TIMESTAMP, \n" +
"eom.UPDATED_TIMESTAMP, op.OPERATION_CODE, op.TYPE AS OPERATION_TYPE, dor.OPERATION_RESPONSE, \n" +
"dor.RECEIVED_TIMESTAMP FROM DM_ENROLMENT_OP_MAPPING AS eom \n" +
"INNER JOIN DM_OPERATION AS op ON op.ID=eom.OPERATION_ID\n" +
"INNER JOIN DM_ENROLMENT AS de ON de.ID=eom.ENROLMENT_ID\n" +
"INNER JOIN DM_DEVICE AS d ON d.ID=de.DEVICE_ID \n" +
"INNER JOIN DM_DEVICE_TYPE AS dt ON dt.ID=d.DEVICE_TYPE_ID\n" +
"LEFT JOIN DM_DEVICE_OPERATION_RESPONSE AS dor ON dor.ENROLMENT_ID=de.id \n" +
"AND dor.OPERATION_ID = eom.OPERATION_ID\n" +
"WHERE eom.OPERATION_ID = ? AND de.device_id = ? AND de.TENANT_ID = ?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, operationId);
stmt.setInt(2, deviceId);
stmt.setInt(3, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
rs = stmt.executeQuery();
int enrolmentId = 0;
ActivityStatus activityStatus = null;
while (rs.next()) {
if (enrolmentId == 0) {
activity = new Activity();
activity.setType(Activity.Type.valueOf(rs.getString("OPERATION_TYPE")));
activity.setCreatedTimeStamp(new java.util.Date(rs.getLong(("CREATED_TIMESTAMP")) * 1000).toString());
activity.setCode(rs.getString("OPERATION_CODE"));
}
if (enrolmentId != rs.getInt("ENROLMENT_ID")) {
activityStatus = new ActivityStatus();
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION"));
deviceIdentifier.setType(rs.getString("DEVICE_TYPE_NAME"));
activityStatus.setDeviceIdentifier(deviceIdentifier);
activityStatus.setStatus(ActivityStatus.Status.valueOf(rs.getString("STATUS")));
List<OperationResponse> operationResponses = new ArrayList<>();
if (rs.getInt("UPDATED_TIMESTAMP") != 0) {
activityStatus.setUpdatedTimestamp(new java.util.Date(rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString());
operationResponses.add(OperationDAOUtil.getOperationResponse(rs));
}
activityStatus.setResponses(operationResponses);
activityStatusList.add(activityStatus);
enrolmentId = rs.getInt("ENROLMENT_ID");
activity.setActivityStatus(activityStatusList);
} else {
if (rs.getInt("UPDATED_TIMESTAMP") != 0) {
activityStatus.getResponses().add(OperationDAOUtil.getOperationResponse(rs));
}
}
}
} catch (SQLException e) {
throw new OperationManagementDAOException("Error occurred while getting the operation details from " +
"the database.", e);
} catch (ClassNotFoundException e) {
throw new OperationManagementDAOException("Error occurred while converting the operation response to string.", e);
} catch (IOException e) {
throw new OperationManagementDAOException("IO exception occurred while converting the operations responses.", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, rs);
}
return activity;
}
@Override @Override
public List<Activity> getActivitiesUpdatedAfter(long timestamp) throws OperationManagementDAOException { public List<Activity> getActivitiesUpdatedAfter(long timestamp) throws OperationManagementDAOException {
return this.getActivitiesUpdatedAfter(timestamp, 0, 0); return this.getActivitiesUpdatedAfter(timestamp, 0, 0);

@ -116,6 +116,11 @@ public class PushNotificationBasedOperationManager implements OperationManager {
return this.operationManager.getOperationByActivityId(activity); return this.operationManager.getOperationByActivityId(activity);
} }
@Override
public Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException {
return this.operationManager.getOperationByActivityIdAndDevice(activity, deviceId);
}
@Override @Override
public List<Operation> getOperationUpdatedAfter(long timestamp) throws OperationManagementException { public List<Operation> getOperationUpdatedAfter(long timestamp) throws OperationManagementException {
return this.operationManager.getOperationUpdatedAfter(timestamp); return this.operationManager.getOperationUpdatedAfter(timestamp);

@ -532,6 +532,8 @@ public interface DeviceManagementProviderService {
Activity getOperationByActivityId(String activity) throws OperationManagementException; Activity getOperationByActivityId(String activity) throws OperationManagementException;
Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException;
List<Activity> getActivitiesUpdatedAfter(long timestamp) throws OperationManagementException; List<Activity> getActivitiesUpdatedAfter(long timestamp) throws OperationManagementException;
List<Activity> getActivitiesUpdatedAfter(long timestamp, int limit, int offset) throws OperationManagementException; List<Activity> getActivitiesUpdatedAfter(long timestamp, int limit, int offset) throws OperationManagementException;

@ -1008,6 +1008,10 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return DeviceManagementDataHolder.getInstance().getOperationManager().getOperationByActivityId(activity); return DeviceManagementDataHolder.getInstance().getOperationManager().getOperationByActivityId(activity);
} }
public Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException {
return DeviceManagementDataHolder.getInstance().getOperationManager().getOperationByActivityIdAndDevice(activity, deviceId);
}
@Override @Override
public List<Activity> getActivitiesUpdatedAfter(long timestamp) throws OperationManagementException { public List<Activity> getActivitiesUpdatedAfter(long timestamp) throws OperationManagementException {
return DeviceManagementDataHolder.getInstance().getOperationManager().getActivitiesUpdatedAfter(timestamp); return DeviceManagementDataHolder.getInstance().getOperationManager().getActivitiesUpdatedAfter(timestamp);

@ -0,0 +1,345 @@
.operation-icon{
width: 88px;
height: 100px;
background-color: #ebebeb;
float: left;
margin: 0px 10px 10px 0px;
cursor: pointer;
position: relative;
}
.operation-icon i{
padding: 15px 0px 0px 0px;
display: block;
min-height: 65px;
font-size: 3em !important;
margin: 0px !important;
}
.operation-icon span{
height: 35px;
line-height: 15px;
vertical-align: middle;
display: table-cell;
width: inherit;
}
.application{
width: 250px;
height: 100px;
background-color: #ebebeb;
float: left;
margin: 0px 10px 10px 0px;
}
.application img{
height: inherit;
padding: 10px;
float: left;
}
.app-info h4{
margin-bottom: 0px;
}
.application i{
float: right;
margin: 0px 10px;
position: relative;
bottom: -20px;
cursor: pointer;
}
.nav-tabs>li>a{
color: #333;
}
.nav-tabs>li.active>a, .nav-tabs>li.active>a:focus, .nav-tabs>li.active>a:hover{
border-bottom: 2px solid #37474f;
border-right: none;
border-top: none;
border-left: none;
font-weight: 400;
}
.nav-tabs-selector{
margin: 0px;
border: 1px solid #37474f;
}
.tab-pane{
padding: 20px 0px;
}
#location{
height: calc(100vh - 400px);
}
.page-loader{
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: calc(100vh - 160px);
z-index: 9999;
background: url(images/page-loader.gif) 50% 50% no-repeat rgb(249,249,249);
}
.page-loader .loader{
left: 43%;
position: absolute;
bottom: 50%;
width: 13%;
}
.page-loader .loader span{
padding: 9px;
position: absolute;
font-size: 18px;
}
.device-info-container{
margin-bottom: 40px;
}
.device-type{
font-size: 9em;
}
.device-info h1, .device-info h4:not(:last-child){
margin: 0px 0px 9px 0px;
position: relative;
}
.device-id a{
font-size: 0.4em;
position: absolute;
margin: 0px 5px;
}
.device-info h4:last-child{
margin: 0px;
}
.tab-actions{
position: relative;
}
.tab-actions .action-btn{
padding: 10px 15px;
background-color: #ebebeb;
float: right;
cursor: pointer;
position: relative;
margin-left: 10px;
ma
}
.tab-actions .action{
float: right;
margin-left: 10px;
}
.tab-actions .action-btn.show a{
margin: 0 0 10px;
}
.tab-actions .action-btn a{
margin: 0px;
}
.tab-actions {
margin: 0px;
}
.tab-actions .action-prop{
padding: 10px;
background: #ebebeb;
width: 100%;
margin-bottom: 10px;
}
.tab-action-active{
padding-bottom: 15px !important;
}
.action-btn-container:after{
content: '';
display: block;
clear:both;
}
.input-group .fw{
position: absolute;
top: 10px;
right: 10px;
z-index: 100;
}
.vital-strip{
display: flex;
flex-direction: row;
background-color: #ebebeb;
padding: 10px;
margin-bottom: 40px;
}
.vital-strip p{
flex-grow: 1;
margin: 0px;
display: inline-flex;
}
.vital-strip p i{
margin: 0px 10px;
}
.vital-strip p span{
padding: 5px 0px;
}
.memory-amt{
font-size: 0.8em;
position: relative;
bottom: -3px;
padding-left: 2px !important;
}
.policy-item{
display: flex;
flex-direction: row;
padding: 10px;
background-color: #ebebeb;
}
.policy-item .policy-status, .policy-item p{
flex-grow: 1;
}
.policy-item .policy-status{
flex-grow: 1;
flex-basis: 0;
margin-right: 10px;
align-self: center;
color: #5cb85c;
}
.policy-name{
font-size: 1.5em;
display: flex;
}
.policy-platform{
display: flex;
}
.policy-item p:nth-child(2){
margin: 0px;
}
.policy-item p:nth-child(3){
flex-grow: 7;
align-self: center;
margin: 0px;
}
.policy-item p:nth-child(3) span{
display: flex;
}
.policy-item .actions{
flex-grow: 1;
display: flex;
}
.policy-item .action-btn{
flex-grow: 1;
margin: 3px 5px;
background-color: #ccc;
display: flex;
cursor: pointer;
position: relative;
}
.policy-item .action-btn p{
align-self: center;
margin: 0px;
display: flex;
justify-content: center;
}
.policy-item .action-btn p i{
padding: 0px 5px;
}
.policy-item .action-btn span{
align-self: center;
}
#operation-log tr td{
border-bottom: 15px solid #fff !important;
}
#operation-log tr.shown td{
border-bottom: none !important;
}
.log-data-row td{
padding: 0px !important;
border-bottom: 15px solid #fff !important;
}
.log-data{
background-color: #f6f6f6;
padding: 0px 20px;
}
.log-data:after{
content: '';
width: 0;
height: 100%;
position: absolute;
border: 1px solid #ced8db;
top: 0;
left: 50px;
}
.log-record-status{
background-color: #4c4c4c !important;
color: #fff;
cursor: pointer;
user-select: none;
}
.log-record-status i:first-child{
float: left;
line-height: 19px;
padding: 0px 10px 0px 0px;
}
.log-record-status span{
float: left;
line-height: 17px;
}
.log-status{
padding-left: 14px;
z-index: 10;
position: relative;
}
.log-status i{
margin: 0px 10px;
background-color: #f6f6f6;
border-radius: 20px;
}
.log-entry{
padding: 15px 0px;
}
.log-entry:not(:first-child){
padding-top: 0px;
}
/*
* custom css fixes
*/
.page-content-wrapper, .page-content-wrapper[data-container-behaviour=static]{
min-height: calc(100vh - 123px);
}
.content{
/*opacity: 0;*/
}
.content-wrapper{
position: relative;
}
.dataTablesTop{
display: none;
}
.table.list-table:not(.grid-view)>tbody>tr>td, .table.list-table:not(.grid-view)>tbody>tr>th{
background-color: #eaeaea;
}
.table.table-hover>tbody>tr:hover td:not(.dataTables_empty){
background-color: inherit !important;
}
.table-hover>tbody>tr:hover,{
background-color:
}
.table.list-table>tbody>tr:nth-of-type(even), .table.list-table>tbody>tr:nth-of-type(odd){
background-color: #eaeaea;
}
.table.table-hover>tbody>tr:hover td:not(.dataTables_empty){
background-color: inherit !important;
}
.table.table-hover>tbody>tr:hover td.log-record-status{
background-color: #4c4c4c !important;
}
.tab-content{
border:none;
}

@ -16,195 +16,322 @@
* under the License. * under the License.
*/ */
var deviceId = $(".device-id"); var deviceId = $(".device-id");
var deviceIdentifier = deviceId.data("deviceid"); var deviceIdentifier = deviceId.data("deviceid");
var deviceType = deviceId.data("type"); var deviceType = deviceId.data("type");
var deviceOwner = deviceId.data("owner"); var deviceOwner = deviceId.data("owner");
$(document).ready(function () { $(document).ready(function() {
$(".panel-body").removeClass("hidden"); $(".panel-body").removeClass("hidden");
$("#loading-content").remove(); $("#loading-content").remove();
if ($('#event_log').length) { if ($('#event_log').length) {
loadOperationsLog(); loadOperationsLog();
} }
if ($('#policy_compliance').length) {
loadPolicyCompliance();
}
if ($('#policy_compliance').length) {
loadPolicyCompliance();
}
$("#refresh-policy").click(function () {
$('#policy-spinner').removeClass('hidden');
loadPolicyCompliance();
});
$("#refresh-operations").click(function () { $("#refresh-policy").click(function() {
$('#operations-spinner').removeClass('hidden'); $('#policy-spinner').removeClass('hidden');
loadOperationsLog(true); loadPolicyCompliance();
}); });
$("#refresh-operations").click(function() {
$('#operations-spinner').removeClass('hidden');
loadOperationsLog(true);
}); });
function loadOperationsLog(update) { });
var operationsLogTable = "#operations-log-table";
if (update) { function loadOperationsLog() {
operationTable = $(operationsLogTable).DataTable(); var table = $('#operation-log').DataTable({
$("#operations-spinner").removeClass("hidden"); serverSide: true,
operationTable.ajax.reload(function ( json ) { processing: false,
searching: false,
ordering: false,
pageLength: 10,
order: [],
autoWidth: false,
ajax: {
url: "/devicemgt/api/operation/paginate",
data: {
deviceId: deviceIdentifier,
deviceType: deviceType,
owner: deviceOwner
},
dataSrc: function(json) {
$("#operations-spinner").addClass("hidden"); $("#operations-spinner").addClass("hidden");
}, false); $("#operations-log-container").empty();
return; return json.data;
} }
operationTable = $(operationsLogTable).datatables_extended({ },
serverSide: true, columnDefs: [{
processing: false, targets: 0,
searching: false, data: "code",
ordering: false, class: "icon-only content-fill"
pageLength : 10, },
order: [], {
ajax: { targets: 1,
data: "createdTimeStamp",
url: "/devicemgt/api/operation/paginate", class: "text-right",
data: {deviceId : deviceIdentifier, deviceType: deviceType, owner: deviceOwner}, render: function(date) {
dataSrc: function (json) { var value = String(date);
$("#operations-spinner").addClass("hidden"); return value.slice(0, 16);
$("#operations-log-container").empty();
return json.data;
} }
}, },
columnDefs: [ {
{targets: 0, data: "code" }, targets: 2,
{targets: 1, data: "status", render: data: "status",
function (status) { class: "text-right extended-log-data log-record-status",
var html; render: function(data, type, full, meta) {
switch (status) { return '<i class="icon fw fw-success"></i><span> ' + data + ' </span><i class="icon fw fw-down"></i>';
case "COMPLETED" :
html = "<span><i class='fw fw-success icon-success'></i> Completed</span>";
break;
case "PENDING" :
html = "<span><i class='fw fw-warning icon-warning'></i> Pending</span>";
break;
case "ERROR" :
html = "<span><i class='fw fw-error icon-danger'></i> Error</span>";
break;
case "IN_PROGRESS" :
html = "<span><i class='fw fw-success icon-warning'></i> In Progress</span>";
break;
case "REPEATED" :
html = "<span><i class='fw fw-success icon-warning'></i> Repeated</span>";
break;
}
return html;
}
}, },
{targets: 2, data: "createdTimeStamp", render: width: "100%"
function (date) { }
var value = String(date); ],
return value.slice(0, 16); fnCreatedRow: function(nRow, aData, iDataIndex) {
$('td:eq(0)', nRow)
.attr('data-search', aData.Device_Type)
.attr('data-display', aData.Device_Type)
.addClass(' icon-only content-fill');
$('td:eq(1), td:eq(2)', nRow).addClass('text-right');
$('td:eq(2)', nRow).addClass('log-record-status')
}
});
$('#operation-log tbody').on('click', 'td.extended-log-data', function() {
var tr = $(this).closest('tr');
var row = table.row(tr);
var rowData = row.data()
var deviceid = $('.device-id').data('deviceid');
var deviceType = $('.device-id').data('type');
var uri = "/api/device-mgt/v1.0/activities/" + rowData.activityId + "/" + deviceType + "/" + deviceid;
var contentType = "application/json";
if (row.child.isShown()) {
row.child.hide();
$(row.child()).removeClass('log-data-row');
tr.removeClass('shown');
} else {
invokerUtil.get(uri,(payload) => {
row.child(renderLogDetails(row.data(),payload)).show();
$(row.child()).addClass('log-data-row');
tr.addClass('shown');
},(error) => {
},contentType);
}
});
function renderLogDetails(obj,data) {
var payload = JSON.parse(data);
var logStream = '<div class="log-data">';
Object.entries(payload.activityStatus).forEach(
([key, entry]) => {
logStream += '<div class="row log-entry">' +
'<div class="col-lg-8">' +
'<div class="log-status"><i class="icon fw ' + getLogStatusIcon(entry.status) + ' "></i>' +
'<span>' + entry.status + '</span></div>' +
'</div>' +
'<div class="col-lg-4">' +
'<div class="log-time text-right"><span>' + entry.updatedTimestamp + '</span></div>' +
'</div>' +
'</div>';
}
);
logStream += '</div></div>';
return logStream;
function getLogStatusIcon(entry) {
switch (entry) {
case 'COMPLETED':
return 'fw-success'
break;
case 'PENDING':
return 'fw-pending'
break;
default:
return 'fw-info'
}
}
}
}
function loadOperationsLog2(update) {
var operationsLogTable = "#operations-log-table";
if (update) {
operationTable = $(operationsLogTable).DataTable();
$("#operations-spinner").removeClass("hidden");
operationTable.ajax.reload(function(json) {
$("#operations-spinner").addClass("hidden");
}, false);
return;
}
operationTable = $(operationsLogTable).datatables_extended({
serverSide: true,
processing: false,
searching: false,
ordering: false,
pageLength: 10,
order: [],
ajax: {
url: "/devicemgt/api/operation/paginate",
data: {
deviceId: deviceIdentifier,
deviceType: deviceType,
owner: deviceOwner
},
dataSrc: function(json) {
$("#operations-spinner").addClass("hidden");
$("#operations-log-container").empty();
return json.data;
}
},
columnDefs: [{
targets: 0,
data: "code"
},
{
targets: 1,
data: "status",
render: function(status) {
var html;
switch (status) {
case "COMPLETED":
html = "<span><i class='fw fw-success icon-success'></i> Completed</span>";
break;
case "PENDING":
html = "<span><i class='fw fw-warning icon-warning'></i> Pending</span>";
break;
case "ERROR":
html = "<span><i class='fw fw-error icon-danger'></i> Error</span>";
break;
case "IN_PROGRESS":
html = "<span><i class='fw fw-success icon-warning'></i> In Progress</span>";
break;
case "REPEATED":
html = "<span><i class='fw fw-success icon-warning'></i> Repeated</span>";
break;
} }
return html;
}
},
{
targets: 2,
data: "createdTimeStamp",
render: function(date) {
var value = String(date);
return value.slice(0, 16);
} }
],
"createdRow": function(row, data) {
$(row).attr("data-type", "selectable");
$(row).attr("data-id", data["id"]);
$.each($("td", row),
function(colIndex) {
switch(colIndex) {
case 1:
$(this).attr("data-grid-label", "Code");
$(this).attr("data-display", data["code"]);
break;
case 2:
$(this).attr("data-grid-label", "Status");
$(this).attr("data-display", data["status"]);
break;
case 3:
$(this).attr("data-grid-label", "Created Timestamp");
$(this).attr("data-display", data["createdTimeStamp"]);
break;
}
}
);
} }
}); ],
} "createdRow": function(row, data) {
$(row).attr("data-type", "selectable");
$(row).attr("data-id", data["id"]);
$.each($("td", row),
function(colIndex) {
switch (colIndex) {
case 1:
$(this).attr("data-grid-label", "Code");
$(this).attr("data-display", data["code"]);
break;
case 2:
$(this).attr("data-grid-label", "Status");
$(this).attr("data-display", data["status"]);
break;
case 3:
$(this).attr("data-grid-label", "Created Timestamp");
$(this).attr("data-display", data["createdTimeStamp"]);
break;
}
}
);
}
});
}
function loadPolicyCompliance() {
var policyCompliance = $("#policy-view");
var policyComplianceTemplate = policyCompliance.attr("src");
var deviceId = policyCompliance.data("device-id");
var deviceType = policyCompliance.data("device-type");
var activePolicy = null;
function loadPolicyCompliance() { $.template(
var policyCompliance = $("#policy-view"); "policy-view",
var policyComplianceTemplate = policyCompliance.attr("src"); policyComplianceTemplate,
var deviceId = policyCompliance.data("device-id"); function(template) {
var deviceType = policyCompliance.data("device-type"); var getEffectivePolicyURL = "/api/device-mgt/v1.0/devices/" + deviceType + "/" + deviceId + "/effective-policy";
var activePolicy = null; var getDeviceComplianceURL = "/api/device-mgt/v1.0/devices/" + deviceType + "/" + deviceId + "/compliance-data";
invokerUtil.get(
$.template( getEffectivePolicyURL,
"policy-view", // success-callback
policyComplianceTemplate, function(data, textStatus, jqXHR) {
function (template) { if (jqXHR.status == 200) {
var getEffectivePolicyURL = "/api/device-mgt/v1.0/devices/" + deviceType + "/" + deviceId + "/effective-policy"; $("#policy-spinner").addClass("hidden");
var getDeviceComplianceURL = "/api/device-mgt/v1.0/devices/" + deviceType + "/" + deviceId + "/compliance-data"; if (data) {
invokerUtil.get( data = JSON.parse(data);
getEffectivePolicyURL, if (data["active"] == true) {
// success-callback activePolicy = data;
function (data, textStatus, jqXHR) { invokerUtil.get(
if (jqXHR.status == 200) { getDeviceComplianceURL,
$("#policy-spinner").addClass("hidden"); // success-callback
if(data){ function(data, textStatus, jqXHR) {
data = JSON.parse(data); if (jqXHR.status == 200 && data) {
if (data["active"] == true) { var viewModel = {};
activePolicy = data; viewModel["policy"] = activePolicy;
invokerUtil.get( viewModel["deviceType"] = deviceType;
getDeviceComplianceURL, viewModel["deviceId"] = deviceId;
// success-callback viewModel["appContext"] = context;
function (data, textStatus, jqXHR) { data = JSON.parse(data);
if (jqXHR.status == 200 && data) { var content;
var viewModel = {}; if (data["complianceData"]) {
viewModel["policy"] = activePolicy; if (data["complianceData"]["complianceFeatures"] &&
viewModel["deviceType"] = deviceType; data["complianceData"]["complianceFeatures"].length > 0) {
viewModel["deviceId"] = deviceId; viewModel["compliance"] = "NON-COMPLIANT";
viewModel["appContext"] = context; viewModel["complianceFeatures"] = data["complianceData"]["complianceFeatures"];
data = JSON.parse(data); content = template(viewModel);
var content; $("#policy-list-container").html(content);
if (data["complianceData"]) {
if (data["complianceData"]["complianceFeatures"] &&
data["complianceData"]["complianceFeatures"].length > 0) {
viewModel["compliance"] = "NON-COMPLIANT";
viewModel["complianceFeatures"] = data["complianceData"]["complianceFeatures"];
content = template(viewModel);
$("#policy-list-container").html(content);
} else {
viewModel["compliance"] = "COMPLIANT";
content = template(viewModel);
$("#policy-list-container").html(content);
$("#policy-compliance-table").addClass("hidden");
}
} else { } else {
$("#policy-list-container"). viewModel["compliance"] = "COMPLIANT";
html("<div class='panel-body'><br><p class='fw-warning'> This device " + content = template(viewModel);
"has no policy applied.<p></div>"); $("#policy-list-container").html(content);
$("#policy-compliance-table").addClass("hidden");
} }
} else {
$("#policy-list-container").
html("<div class='panel-body'><br><p class='fw-warning'> This device " +
"has no policy applied.<p></div>");
} }
},
// error-callback
function () {
$("#policy-list-container").
html("<div class='panel-body'><br><p class='fw-warning'> Loading policy compliance related data " +
"was not successful. please try refreshing data in a while.<p></div>");
} }
); },
} // error-callback
function() {
$("#policy-list-container").
html("<div class='panel-body'><br><p class='fw-warning'> Loading policy compliance related data " +
"was not successful. please try refreshing data in a while.<p></div>");
}
);
} }
} }
},
// error-callback
function () {
$("#policy-list-container").
html("<div class='panel-body'><br><p class='fw-warning'> Loading policy compliance related data " +
"was not successful. please try refreshing data in a while.<p></div>");
} }
); },
} // error-callback
); function() {
} $("#policy-list-container").
html("<div class='panel-body'><br><p class='fw-warning'> Loading policy compliance related data " +
"was not successful. please try refreshing data in a while.<p></div>");
}
);
}
);
}

@ -15,156 +15,114 @@
specific language governing permissions and limitations specific language governing permissions and limitations
under the License. under the License.
}} }}
{{#zone "topCss"}}
{{css "css/main.css"}}
{{/zone}}
{{unit "cdmf.unit.lib.editable"}} {{unit "cdmf.unit.lib.editable"}}
{{#zone "content"}} {{#zone "content"}}
{{#if deviceFound}} {{#if deviceFound}}
{{#if isAuthorized}} {{#if isAuthorized}}
<span id="logged-in-user" class="hidden" data-username="{{@user.username}}" data-domain="{{@user.domain}}" <div class="row">
data-tenant-id="{{@user.tenantId}}" data-iscloud="{{isCloud}}"></span> <div class="col-lg-4">
{{#defineZone "device-details-header"}} <div class="device-info-container">
<h1 class="page-sub-title device-id device-select" data-deviceid="{{device.deviceIdentifier}}" <div class="row">
data-type="{{device.type}}"> <div class="col-lg-3">
Device {{device.name}} {{#defineZone "device-thumbnail"}}
{{#if device.viewModel.model}} <i class="fw fw-mobile device-type fw-2x"></i>
<span class="lbl-device">
( {{device.viewModel.vendor}} {{device.viewModel.model}} )
</span>
{{/if}}
</h1>
{{/defineZone}}
<div class="row no-gutter add-padding-5x add-margin-top-5x" style="border: 1px solid #e4e4e4;">
<div class="media">
<div id="device_overview">
<div class="media-left media-middle asset-image col-xs-2 col-sm-2 col-md-2 col-lg-2">
<div class="thumbnail icon">
{{#defineZone "device-thumbnail"}}
<i class="square-element text fw fw-mobile"></i>
{{/defineZone}}
</div>
</div>
<div class="media-body asset-desc add-padding-left-5x">
{{#defineZone "overview-section"}}
<div style="background: #11375B; color: #fff; padding: 10px; margin-bottom: 5px">
Device Overview - {{label}}</div>
{{unit "cdmf.unit.device.overview-section" device=device}}
{{/defineZone}}
{{#defineZone "operation-status"}}{{/defineZone}}
{{#defineZone "device-opetations"}}
<div style="background: #11375B; color: #fff; padding: 10px; margin-bottom: 5px">
Operations
</div>
<div class="add-margin-top-4x" style="height: 90px;">
{{unit "cdmf.unit.device.operation-bar" device=device}}
</div>
{{/defineZone}} {{/defineZone}}
</div> </div>
</div> <div class="col-lg-9">
</div> <div class="device-info">
{{#defineZone "device-details-header"}}
<div class="media tab-responsive"> <h1 data-deviceid="{{device.deviceIdentifier}}"
<div class="media-left col-xs-1 col-sm-1 col-md-2 col-lg-2 hidden-xs"> data-type="{{device.type}}"
<ul class="list-group nav nav-pills nav-stacked" role="tablist"> data-ownership="{{device.ownership}}"
{{#defineZone "device-view-tabs"}} data-owner="{{device.owner}}">
{{#defineZone "device-details-tab"}} {{#if device.viewModel.model}}
<li role="presentation" class="list-group-item active"> <h4>{{device.viewModel.vendor}} {{device.viewModel.model}}</h4>
<a href="#device_details_tab" role="tab" data-toggle="tab" {{/if}}
aria-controls="device_details_tab"> <h4>Ownership - <strong>{{device.viewModel.ownership}}</strong></h4>
<i class="icon fw fw-mobile"></i><span class="hidden-sm">Device Details</span> <h4>Device is
</a> <strong>
</li> {{#equal device.status "ACTIVE"}}Active{{/equal}}
{{/defineZone}} {{#equal device.status "INACTIVE"}}Inactive{{/equal}}
{{#defineZone "device-details-tab-injected"}} {{#equal device.status "BLOCKED"}}Blocked{{/equal}}
{{/defineZone}} {{#equal device.status "REMOVED"}}Removed{{/equal}}
{{#defineZone "device-details-tab-operations"}} {{#equal device.status "UNREACHABLE"}}Unreachable{{/equal}}
<li role="presentation" class="list-group-item"> </strong>
<a href="#event_log_tab" role="tab" data-toggle="tab" aria-controls="event_log_tab">
<i class="icon fw fw-text"></i><span class="hidden-sm">Operations Log</span>
</a>
</li>
{{/defineZone}}
{{/defineZone}}
</ul>
</div>
<div class="media-body add-padding-left-5x remove-padding-xs">
<div class="panel-group tab-content remove-padding" id="tabs" role="tablist"
data-status="{{device.isNotRemoved}}" aria-multiselectable="true">
<div class="arrow-left hidden-xs"></div>
{{#defineZone "device-view-tab-contents"}}
{{#defineZone "device-details-tab-contents"}}
<div class="message message-info">
<h4 class="remove-margin">
<i class="icon fw fw-info"></i>
No Device details avaialbe yet.
</h4> </h4>
</div>
{{/defineZone}}
{{#defineZone "device-view-tab-injected-conents"}}
{{/defineZone}}
{{#defineZone "device-view-tab-operations-log-conents"}}
<div class="panel panel-default visible-xs-block" role="tabpanel" id="event_log_tab">
<div class="panel-heading visible-xs collapsed" id="event_log">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#tabs"
href="#collapseFive" aria-expanded="true" aria-controls="collapseFive">
<i class="fw fw-text fw-2x"></i>
Operations Log
<i class="caret-updown fw fw-down"></i>
</a>
</h4>
</div>
<div class="panel-heading display-none-xs">
Operations Log
<span>
<a href="javascript:void(0);" id="refresh-operations">
<i class="fw fw-refresh"></i>
</a>
</span>
</div>
<div id="collapseFive" class="panel-collapse collapse in" role="tabpanel"
aria-labelledby="event_log">
<div class="panel-body">
<span class="visible-xs add-padding-2x text-right">
<a href="javascript:void(0);" id="refresh-operations">
<i class="fw fw-refresh"></i>
</a>
</span>
<div id="operations-spinner" class="wr-advance-operations-init hidden">
<i class="fw fw-settings fw-spin fw-2x"></i> Loading Operations Log...
</div>
<div id="operations-log-container">
<div class="message message-info">
<h4 class="remove-margin">
<i class="icon fw fw-info"></i>
There are no operations, performed yet on this device.
</h4>
</div>
</div>
<table class="table table-striped table-hover table-bordered display data-table"
id="operations-log-table">
<thead>
<tr class="sort-row">
<th>Operation Code</th>
<th>Status</th>
<th>Request created at</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
{{/defineZone}} {{/defineZone}}
{{/defineZone}} </div>
</div>
</div>
</div>
<div class="vital-strip">
{{#defineZone "device-details"}}
{{/defineZone}}
</div>
{{#defineZone "device-opetations"}}
<div class="operation-container">
<div class="operation-title">
<h4>Device Operations</h4>
</div>
{{unit "cdmf.unit.device.operation-bar" device=device}}
</div>
{{/defineZone}}
<div class="clearfix"></div>
</div>
<!-- /col-lg-4 -->
<div class="col-lg-8">
<ul class="nav nav-tabs">
{{#defineZone "device-view-tabs"}}
<li class="active"><a data-toggle="tab" href="#event_log">Operations Log</a></li>
{{#defineZone "device-details-tab-injected"}}
{{/defineZone}}
{{/defineZone}}
</ul>
<div class="tab-content">
{{#defineZone "device-view-tab-contents"}}
<div id="event_log" class="tab-pane fade in active">
<div class="clearfix"></div>
<div class="operation-log-container">
<table class="table table-striped table-hover table-responsive list-table display responsive nowrap data-table"
id="operation-log">
<thead class="block">
<tr class="sort-row">
<!-- <th class="content-fill no-sort"></th> -->
<th>Name</th>
<th>Position</th>
<th>Office</th>
<!-- <th>Age</th>
<th>Start date</th>
<th>Salary</th>
<th class="no-sort"></th> -->
</tr>
</thead>
<tbody>
</tbody>
</table>
<!-- <table class="table table-striped table-hover table-bordered display data-table"
id="operations-log-table">
<thead>
<tr class="sort-row">
<th>Operation Code</th>
<th>Status</th>
<th>Request created at</th>
</tr>
</thead>
<tbody>
</tbody>
</table> -->
</div>
</div> </div>
</div> {{#defineZone "device-view-tab-injected-conents"}}
</div> {{/defineZone}}
{{/defineZone}}
</div>
</div>
<!-- /col-lg-08 -->
</div> </div>
<!-- /row -->
{{else}} {{else}}
<h1 class="page-sub-title"> <h1 class="page-sub-title">
Permission Denied Permission Denied

@ -2859,7 +2859,8 @@ a.ast-type-item:hover {
font-size: 12px; font-size: 12px;
text-decoration: none; text-decoration: none;
margin-right: 10px; margin-right: 10px;
color: #526A84; /*color: #526A84;*/
color: #333;
min-width: 70px; min-width: 70px;
background: #fafafa; background: #fafafa;
padding: 2px 10px 10px 10px; padding: 2px 10px 10px 10px;

Loading…
Cancel
Save