Merge branch 'master' of https://github.com/wso2/carbon-device-mgt into das-ext

revert-70aa11f8
ayyoob 9 years ago
commit 6d648eccc6

@ -18,27 +18,44 @@
package org.wso2.carbon.apimgt.webapp.publisher;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.api.APIProvider;
import org.wso2.carbon.apimgt.api.model.*;
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.webapp.publisher.config.APIResource;
import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration;
import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.user.api.TenantManager;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.ConfigurationContextService;
import org.wso2.carbon.utils.NetworkUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import javax.servlet.ServletContext;
import java.util.*;
public class APIPublisherUtil {
private static final Log log = LogFactory.getLog(APIPublisherUtil.class);
private static final String DEFAULT_API_VERSION = "1.0.0";
public static final String API_VERSION_PARAM = "{version}";
public static final String API_PUBLISH_ENVIRONEMENT = "Production and Sandbox";
private static final String API_CONFIG_DEFAULT_VERSION = "1.0.0";
private static final String PARAM_MANAGED_API_NAME = "managed-api-name";
private static final String PARAM_MANAGED_API_VERSION = "managed-api-version";
private static final String PARAM_MANAGED_API_CONTEXT = "managed-api-context";
private static final String PARAM_MANAGED_API_ENDPOINT = "managed-api-endpoint";
private static final String PARAM_MANAGED_API_OWNER = "managed-api-owner";
private static final String PARAM_MANAGED_API_TRANSPORTS = "managed-api-transports";
private static final String PARAM_MANAGED_API_IS_SECURED = "managed-api-isSecured";
private static final String PARAM_MANAGED_API_APPLICATION = "managed-api-application";
private static final String PARAM_SHARED_WITH_ALL_TENANTS = "isSharedWithAllTenants";
private static final String PARAM_PROVIDER_TENANT_DOMAIN = "providerTenantDomain";
enum HTTPMethod {
GET, POST, DELETE, PUT, OPTIONS
}
@ -95,7 +112,9 @@ public class APIPublisherUtil {
}
api.setResponseCache(APIConstants.DISABLED);
String endpointConfig = "{\"production_endpoints\":{\"url\":\" " + config.getEndpoint() + "\",\"config\":null},\"implementation_status\":\"managed\",\"endpoint_type\":\"http\"}";
String endpointConfig = "{\"production_endpoints\":{\"url\":\" " + config.getEndpoint() +
"\",\"config\":null},\"implementation_status\":\"managed\",\"endpoint_type\":\"http\"}";
api.setEndpointConfig(endpointConfig);
if ("".equals(id.getVersion()) || (DEFAULT_API_VERSION.equals(id.getVersion()))) {
@ -163,7 +182,9 @@ public class APIPublisherUtil {
}
/**
* When an input is having '@',replace it with '-AT-' [This is required to persist API data in registry,as registry paths don't allow '@' sign.]
* When an input is having '@',replace it with '-AT-'
* [This is required to persist API data in registry,as registry paths don't allow '@' sign.]
*
* @param input inputString
* @return String modifiedString
*/
@ -193,4 +214,120 @@ public class APIPublisherUtil {
return context;
}
/**
* Build the API Configuration to be passed to APIM, from a given list of URL templates
*
* @param servletContext
* @return
*/
public static APIConfig buildApiConfig(ServletContext servletContext, APIResourceConfiguration apidef) {
APIConfig apiConfig = new APIConfig();
String name = apidef.getName();
if (name == null || name.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("API Name not set in @API Annotation");
}
name = servletContext.getServletContextName();
}
apiConfig.setName(name);
String version = apidef.getVersion();
if (version == null || version.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'API Version not set in @API Annotation'");
}
version = API_CONFIG_DEFAULT_VERSION;
}
apiConfig.setVersion(version);
String context = apidef.getContext();
if (context == null || context.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'API Context not set in @API Annotation'");
}
context = servletContext.getContextPath();
}
apiConfig.setContext(context);
String[] tags = apidef.getTags();
if (tags == null || tags.length == 0) {
if (log.isDebugEnabled()) {
log.debug("'API tag not set in @API Annotation'");
}
} else {
apiConfig.setTags(tags);
}
String tenantDomain = servletContext.getInitParameter(PARAM_PROVIDER_TENANT_DOMAIN);
tenantDomain = (tenantDomain != null && !tenantDomain.isEmpty()) ? tenantDomain :
MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
apiConfig.setTenantDomain(tenantDomain);
String contextTemplate = context + "/" + APIConstants.VERSION_PLACEHOLDER;
if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
contextTemplate = context + "/t/" + tenantDomain + "/" + APIConstants.VERSION_PLACEHOLDER;
}
apiConfig.setContextTemplate(contextTemplate);
String endpoint = servletContext.getInitParameter(PARAM_MANAGED_API_ENDPOINT);
if (endpoint == null || endpoint.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'managed-api-endpoint' attribute is not configured");
}
String endpointContext = servletContext.getContextPath();
endpoint = APIPublisherUtil.getApiEndpointUrl(endpointContext);
}
apiConfig.setEndpoint(endpoint);
String owner = servletContext.getInitParameter(PARAM_MANAGED_API_OWNER);
if (owner == null || owner.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'managed-api-owner' attribute is not configured");
}
}
apiConfig.setOwner(owner);
String isSecuredParam = servletContext.getInitParameter(PARAM_MANAGED_API_IS_SECURED);
boolean isSecured;
if (isSecuredParam == null || isSecuredParam.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'managed-api-isSecured' attribute is not configured. Therefore, using the default, " +
"which is 'true'");
}
isSecured = false;
} else {
isSecured = Boolean.parseBoolean(isSecuredParam);
}
apiConfig.setSecured(isSecured);
String transports = servletContext.getInitParameter(PARAM_MANAGED_API_TRANSPORTS);
if (transports == null || transports.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'managed-api-transports' attribute is not configured. Therefore using the default, " +
"which is 'https'");
}
transports = "https";
}
apiConfig.setTransports(transports);
String sharingValueParam = servletContext.getInitParameter(PARAM_SHARED_WITH_ALL_TENANTS);
boolean isSharedWithAllTenants = (sharingValueParam == null || (!sharingValueParam.isEmpty())
&& Boolean.parseBoolean(sharingValueParam));
apiConfig.setSharedWithAllTenants(isSharedWithAllTenants);
Set<URITemplate> uriTemplates = new LinkedHashSet<URITemplate>();
for (APIResource apiResource : apidef.getResources()) {
URITemplate template = new URITemplate();
template.setAuthType(apiResource.getAuthType());
template.setHTTPVerb(apiResource.getHttpVerb());
template.setResourceURI(apiResource.getUri());
template.setUriTemplate(apiResource.getUriTemplate());
uriTemplates.add(template);
}
apiConfig.setUriTemplates(uriTemplates);
return apiConfig;
}
}

@ -25,36 +25,22 @@ import org.apache.catalina.core.StandardContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.api.model.*;
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.webapp.publisher.*;
import org.wso2.carbon.apimgt.webapp.publisher.config.APIResource;
import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration;
import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
import org.wso2.carbon.apimgt.webapp.publisher.lifecycle.util.AnnotationUtil;
import org.wso2.carbon.base.MultitenantConstants;
import javax.servlet.ServletContext;
import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@SuppressWarnings("unused")
public class APIPublisherLifecycleListener implements LifecycleListener {
private static final String API_CONFIG_DEFAULT_VERSION = "1.0.0";
private static final Log log = LogFactory.getLog(APIPublisherLifecycleListener.class);
private static final String PARAM_MANAGED_API_ENABLED = "managed-api-enabled";
private static final String PARAM_MANAGED_API_NAME = "managed-api-name";
private static final String PARAM_MANAGED_API_VERSION = "managed-api-version";
private static final String PARAM_MANAGED_API_CONTEXT = "managed-api-context";
private static final String PARAM_MANAGED_API_ENDPOINT = "managed-api-endpoint";
private static final String PARAM_MANAGED_API_OWNER = "managed-api-owner";
private static final String PARAM_MANAGED_API_TRANSPORTS = "managed-api-transports";
private static final String PARAM_MANAGED_API_IS_SECURED = "managed-api-isSecured";
private static final String PARAM_MANAGED_API_APPLICATION = "managed-api-application";
private static final String PARAM_SHARED_WITH_ALL_TENANTS = "isSharedWithAllTenants";
private static final String PARAM_PROVIDER_TENANT_DOMAIN = "providerTenantDomain";
private static final Log log = LogFactory.getLog(APIPublisherLifecycleListener.class);
@Override
public void lifecycleEvent(LifecycleEvent lifecycleEvent) {
@ -69,13 +55,20 @@ public class APIPublisherLifecycleListener implements LifecycleListener {
AnnotationUtil annotationUtil = new AnnotationUtil(context);
Set<String> annotatedAPIClasses = annotationUtil.
scanStandardContext(org.wso2.carbon.apimgt.annotations.api.API.class.getName());
List<APIResourceConfiguration> apiDefinitions = annotationUtil.extractAPIInfo(servletContext, annotatedAPIClasses);
List<APIResourceConfiguration> apiDefinitions = annotationUtil.extractAPIInfo(servletContext,
annotatedAPIClasses);
for (APIResourceConfiguration apiDefinition : apiDefinitions) {
APIConfig apiConfig = this.buildApiConfig(servletContext, apiDefinition);
APIConfig apiConfig = APIPublisherUtil.buildApiConfig(servletContext, apiDefinition);
try {
int tenantId = APIPublisherDataHolder.getInstance().getTenantManager().getTenantId(apiConfig.getTenantDomain());
boolean isTenantActive = APIPublisherDataHolder.getInstance().getTenantManager().isTenantActive(tenantId);
int tenantId = APIPublisherDataHolder.getInstance().getTenantManager().
getTenantId(apiConfig.getTenantDomain());
boolean isTenantActive = APIPublisherDataHolder.getInstance().
getTenantManager().isTenantActive(tenantId);
if (isTenantActive) {
apiConfig.init();
API api = APIPublisherUtil.getAPI(apiConfig);
@ -87,7 +80,8 @@ public class APIPublisherLifecycleListener implements LifecycleListener {
}
apiPublisherService.publishAPI(api);
} else {
log.error("No tenant [" + apiConfig.getTenantDomain() + "] found when publishing the webapp");
log.error("No tenant [" + apiConfig.getTenantDomain() + "] " +
"found when publishing the Web app");
}
} catch (Throwable e) {
log.error("Error occurred while publishing API '" + apiConfig.getName() +
@ -96,7 +90,7 @@ public class APIPublisherLifecycleListener implements LifecycleListener {
}
}
} catch (IOException e) {
log.error("Error enconterd while discovering annotated classes", e);
log.error("Error encountered while discovering annotated classes", e);
} catch (ClassNotFoundException e) {
log.error("Error while scanning class for annotations", e);
}
@ -104,126 +98,9 @@ public class APIPublisherLifecycleListener implements LifecycleListener {
}
}
//TODO : Need to implemented, to merge API Definitions in cases where implementation of an API Lies in two classes
private List<APIResourceConfiguration> mergeAPIDefinitions(List<APIResourceConfiguration> inputList) {
//TODO : Need to implemented, to merge API Definitions in cases where implementation of an API Lies in two
// classes
return null;
}
/**
* Build the API Configuration to be passed to APIM, from a given list of URL templates
*
* @param servletContext
* @return
*/
private APIConfig buildApiConfig(ServletContext servletContext, APIResourceConfiguration apidef) {
APIConfig apiConfig = new APIConfig();
String name = apidef.getName();
if (name == null || name.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("API Name not set in @API Annotation");
}
name = servletContext.getServletContextName();
}
apiConfig.setName(name);
String version = apidef.getVersion();
if (version == null || version.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'API Version not set in @API Annotation'");
}
version = API_CONFIG_DEFAULT_VERSION;
}
apiConfig.setVersion(version);
String context = apidef.getContext();
if (context == null || context.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'API Context not set in @API Annotation'");
}
context = servletContext.getContextPath();
}
apiConfig.setContext(context);
String[] tags = apidef.getTags();
if (tags == null || tags.length == 0) {
if (log.isDebugEnabled()) {
log.debug("'API tag not set in @API Annotation'");
}
} else {
apiConfig.setTags(tags);
}
String tenantDomain = servletContext.getInitParameter(PARAM_PROVIDER_TENANT_DOMAIN);
tenantDomain = (tenantDomain != null && !tenantDomain.isEmpty()) ? tenantDomain :
MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
apiConfig.setTenantDomain(tenantDomain);
String contextTemplate = context + "/" + APIConstants.VERSION_PLACEHOLDER;
if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
contextTemplate = context + "/t/" + tenantDomain + "/" + APIConstants.VERSION_PLACEHOLDER;
}
apiConfig.setContextTemplate(contextTemplate);
String endpoint = servletContext.getInitParameter(PARAM_MANAGED_API_ENDPOINT);
if (endpoint == null || endpoint.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'managed-api-endpoint' attribute is not configured");
}
String endpointContext = servletContext.getContextPath();
endpoint = APIPublisherUtil.getApiEndpointUrl(endpointContext);
}
apiConfig.setEndpoint(endpoint);
String owner = servletContext.getInitParameter(PARAM_MANAGED_API_OWNER);
if (owner == null || owner.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'managed-api-owner' attribute is not configured");
}
}
apiConfig.setOwner(owner);
String isSecuredParam = servletContext.getInitParameter(PARAM_MANAGED_API_IS_SECURED);
boolean isSecured;
if (isSecuredParam == null || isSecuredParam.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'managed-api-isSecured' attribute is not configured. Therefore, using the default, " +
"which is 'true'");
}
isSecured = false;
} else {
isSecured = Boolean.parseBoolean(isSecuredParam);
}
apiConfig.setSecured(isSecured);
String transports = servletContext.getInitParameter(PARAM_MANAGED_API_TRANSPORTS);
if (transports == null || transports.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("'managed-api-transports' attribute is not configured. Therefore using the default, " +
"which is 'https'");
}
transports = "https";
}
apiConfig.setTransports(transports);
String sharingValueParam = servletContext.getInitParameter(PARAM_SHARED_WITH_ALL_TENANTS);
boolean isSharedWithAllTenants = (sharingValueParam == null || (!sharingValueParam.isEmpty()) && Boolean.parseBoolean(
sharingValueParam));
apiConfig.setSharedWithAllTenants(isSharedWithAllTenants);
Set<URITemplate> uriTemplates = new LinkedHashSet<URITemplate>();
for (APIResource apiResource : apidef.getResources()) {
URITemplate template = new URITemplate();
template.setAuthType(apiResource.getAuthType());
template.setHTTPVerb(apiResource.getHttpVerb());
template.setResourceURI(apiResource.getUri());
template.setUriTemplate(apiResource.getUriTemplate());
uriTemplates.add(template);
}
apiConfig.setUriTemplates(uriTemplates);
return apiConfig;
}
}

@ -18,6 +18,9 @@
package org.wso2.carbon.device.mgt.analytics.dashboard;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import java.util.Map;
/**
@ -26,7 +29,7 @@ import java.util.Map;
public interface GadgetDataService {
@SuppressWarnings("unused")
int getTotalDeviceCount(Map<String, Object> filters);
int getTotalDeviceCount();
@SuppressWarnings("unused")
int getActiveDeviceCount();
@ -44,7 +47,10 @@ public interface GadgetDataService {
int getUnmonitoredDeviceCount();
@SuppressWarnings("unused")
Map<String, Integer> getNonCompliantDeviceCountsByFeatures();
PaginationResult getNonCompliantDeviceCountsByFeatures(PaginationRequest paginationRequest);
@SuppressWarnings("unused")
int getDeviceCount(Map<String, Object> filters);
@SuppressWarnings("unused")
Map<String, Integer> getDeviceCountsByPlatforms(Map<String, Object> filters);

@ -18,6 +18,9 @@
package org.wso2.carbon.device.mgt.analytics.dashboard.dao;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import java.util.List;
import java.util.Map;
@ -26,15 +29,9 @@ public interface GadgetDataServiceDAO {
/**
* Method to get total filtered device count from a particular tenant.
*
* @param filters List of filters to be applied in getting
* total filtered device count.
*
* @return Total filtered device count.
*/
int getTotalDeviceCount(Map<String, Object> filters) throws GadgetDataServiceDAOException;
@SuppressWarnings("unused")
int getFeatureNonCompliantDeviceCount(Map<String, Object> filters) throws GadgetDataServiceDAOException;
int getTotalDeviceCount() throws GadgetDataServiceDAOException;
int getActiveDeviceCount() throws GadgetDataServiceDAOException;
@ -50,9 +47,6 @@ public interface GadgetDataServiceDAO {
@SuppressWarnings("unused")
int getNonCompliantDeviceCount() throws GadgetDataServiceDAOException;
@SuppressWarnings("unused")
Map<String, Integer> getNonCompliantDeviceCountsByFeatures() throws GadgetDataServiceDAOException;
/**
* Method to get unmonitored device count.
*
@ -61,22 +55,36 @@ public interface GadgetDataServiceDAO {
@SuppressWarnings("unused")
int getUnmonitoredDeviceCount() throws GadgetDataServiceDAOException;
@SuppressWarnings("unused")
PaginationResult getNonCompliantDeviceCountsByFeatures(PaginationRequest paginationRequest) throws GadgetDataServiceDAOException;
@SuppressWarnings("unused")
int getDeviceCount(Map<String, Object> filters) throws GadgetDataServiceDAOException;
@SuppressWarnings("unused")
int getFeatureNonCompliantDeviceCount(String nonCompliantFeatureCode,
Map<String, Object> filters) throws GadgetDataServiceDAOException;
@SuppressWarnings("unused")
Map<String, Integer> getDeviceCountsByPlatforms(Map<String, Object> filters) throws GadgetDataServiceDAOException;
@SuppressWarnings("unused")
Map<String, Integer> getFeatureNonCompliantDeviceCountsByPlatforms(Map<String, Object> filters) throws GadgetDataServiceDAOException;
Map<String, Integer> getFeatureNonCompliantDeviceCountsByPlatforms(String nonCompliantFeatureCode,
Map<String, Object> filters) throws GadgetDataServiceDAOException;
@SuppressWarnings("unused")
Map<String, Integer> getDeviceCountsByOwnershipTypes(Map<String, Object> filters) throws GadgetDataServiceDAOException;
Map<String, Integer> getDeviceCountsByOwnershipTypes(Map<String, Object> filters)
throws GadgetDataServiceDAOException;
@SuppressWarnings("unused")
Map<String, Integer> getFeatureNonCompliantDeviceCountsByOwnershipTypes(Map<String, Object> filters) throws GadgetDataServiceDAOException;
Map<String, Integer> getFeatureNonCompliantDeviceCountsByOwnershipTypes(String nonCompliantFeatureCode,
Map<String, Object> filters) throws GadgetDataServiceDAOException;
@SuppressWarnings("unused")
List<Map<String, Object>> getDevicesWithDetails(Map<String, Object> filters) throws GadgetDataServiceDAOException;
@SuppressWarnings("unused")
List<Map<String, Object>> getFeatureNonCompliantDevicesWithDetails(Map<String, Object> filters) throws GadgetDataServiceDAOException;
List<Map<String, Object>> getFeatureNonCompliantDevicesWithDetails(String nonCompliantFeatureCode,
Map<String, Object> filters) throws GadgetDataServiceDAOException;
}

@ -21,6 +21,8 @@ package org.wso2.carbon.device.mgt.analytics.dashboard.dao;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil;
import java.sql.Connection;
@ -37,122 +39,141 @@ class GadgetDataServiceDAOImpl implements GadgetDataServiceDAO {
private static final Log log = LogFactory.getLog(GadgetDataServiceDAOImpl.class);
@Override
public int getTotalDeviceCount(Map<String, Object> filters) throws GadgetDataServiceDAOException {
int filteringViewID = 1;
return this.getDeviceCount(filteringViewID, filters);
}
@Override
public int getFeatureNonCompliantDeviceCount(Map<String, Object> filters) throws GadgetDataServiceDAOException {
int filteringViewID = 2;
return this.getDeviceCount(filteringViewID, filters);
public int getTotalDeviceCount() throws GadgetDataServiceDAOException {
return this.getDeviceCount(null);
}
@Override
public int getActiveDeviceCount() throws GadgetDataServiceDAOException {
int filteringViewID = 1;
Map<String, Object> filters = new HashMap<>();
filters.put("CONNECTIVITY_STATUS", "ACTIVE");
return this.getDeviceCount(filteringViewID, filters);
return this.getDeviceCount(filters);
}
@Override
public int getInactiveDeviceCount() throws GadgetDataServiceDAOException {
int filteringViewID = 1;
Map<String, Object> filters = new HashMap<>();
filters.put("CONNECTIVITY_STATUS", "INACTIVE");
return this.getDeviceCount(filteringViewID, filters);
return this.getDeviceCount(filters);
}
@Override
public int getRemovedDeviceCount() throws GadgetDataServiceDAOException {
int filteringViewID = 1;
Map<String, Object> filters = new HashMap<>();
filters.put("CONNECTIVITY_STATUS", "REMOVED");
return this.getDeviceCount(filteringViewID, filters);
return this.getDeviceCount(filters);
}
@Override
public int getNonCompliantDeviceCount() throws GadgetDataServiceDAOException {
int filteringViewID = 1;
Map<String, Object> filters = new HashMap<>();
filters.put("IS_COMPLIANT", 0);
return this.getDeviceCount(filteringViewID, filters);
return this.getDeviceCount(filters);
}
@Override
public Map<String, Integer> getNonCompliantDeviceCountsByFeatures() throws GadgetDataServiceDAOException {
public PaginationResult getNonCompliantDeviceCountsByFeatures(PaginationRequest paginationRequest) throws GadgetDataServiceDAOException {
Connection con;
PreparedStatement stmt = null;
ResultSet rs = null;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
Map<String, Integer> filteredNonCompliantDeviceCountsByFeatures = new HashMap<>();
List<Map<String, Object>> filteredNonCompliantDeviceCountsByFeatures = new ArrayList<>();
int totalRecordsCount = 0;
try {
con = this.getConnection();
String sql = "SELECT FEATURE_CODE, COUNT(DEVICE_ID) AS DEVICE_COUNT FROM DEVICES_VIEW_2 " +
"WHERE TENANT_ID = ? GROUP BY FEATURE_CODE";
"WHERE TENANT_ID = ? GROUP BY FEATURE_CODE ORDER BY DEVICE_COUNT DESC LIMIT ?, ?";
stmt = con.prepareStatement(sql);
stmt.setInt(1, tenantId);
stmt.setInt(2, paginationRequest.getStartIndex());
stmt.setInt(3, paginationRequest.getRowCount());
// executing query
rs = stmt.executeQuery();
// fetching query results
Map<String, Object> filteredNonCompliantDeviceCountByFeature;
while (rs.next()) {
filteredNonCompliantDeviceCountsByFeatures.
put(rs.getString("FEATURE_CODE"), rs.getInt("DEVICE_COUNT"));
filteredNonCompliantDeviceCountByFeature = new HashMap<>();
filteredNonCompliantDeviceCountByFeature.put("FEATURE_CODE", rs.getString("FEATURE_CODE"));
filteredNonCompliantDeviceCountByFeature.put("DEVICE_COUNT", rs.getInt("DEVICE_COUNT"));
filteredNonCompliantDeviceCountsByFeatures.add(filteredNonCompliantDeviceCountByFeature);
}
// fetching total records count
sql = "SELECT COUNT(FEATURE_CODE) AS NON_COMPLIANT_FEATURE_COUNT FROM " +
"(SELECT DISTINCT FEATURE_CODE FROM DEVICES_VIEW_2 WHERE TENANT_ID = ?)";
stmt = con.prepareStatement(sql);
stmt.setInt(1, tenantId);
// executing query
rs = stmt.executeQuery();
// fetching query results
while (rs.next()) {
totalRecordsCount = rs.getInt("NON_COMPLIANT_FEATURE_COUNT");
}
} catch (SQLException e) {
throw new GadgetDataServiceDAOException("Error occurred while executing a selection query to the database", e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
return filteredNonCompliantDeviceCountsByFeatures;
PaginationResult paginationResult = new PaginationResult();
paginationResult.setData(filteredNonCompliantDeviceCountsByFeatures);
paginationResult.setRecordsTotal(totalRecordsCount);
return paginationResult;
}
@Override
public int getUnmonitoredDeviceCount() throws GadgetDataServiceDAOException {
int filteringViewID = 1;
Map<String, Object> filters = new HashMap<>();
filters.put("POLICY_ID", -1);
return this.getDeviceCount(filteringViewID, filters);
return this.getDeviceCount(filters);
}
@Override
public Map<String, Integer> getDeviceCountsByPlatforms(Map<String, Object> filters) throws GadgetDataServiceDAOException {
int filteringViewID = 1;
return this.getDeviceCountsByPlatforms(filteringViewID, filters);
public int getDeviceCount(Map<String, Object> filters) throws GadgetDataServiceDAOException {
Connection con;
PreparedStatement stmt = null;
ResultSet rs = null;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
int filteredDeviceCount = 0;
try {
con = this.getConnection();
String sql = "SELECT COUNT(DEVICE_ID) AS DEVICE_COUNT FROM DEVICES_VIEW_1 WHERE TENANT_ID = ?";
// appending filters to support advanced filtering options
// [1] appending filter columns
if (filters != null && filters.size() > 0) {
for (String column : filters.keySet()) {
sql = sql + " AND " + column + " = ?";
}
@Override
public Map<String, Integer> getFeatureNonCompliantDeviceCountsByPlatforms(Map<String, Object> filters) throws GadgetDataServiceDAOException {
int filteringViewID = 2;
return this.getDeviceCountsByPlatforms(filteringViewID, filters);
}
@Override
public Map<String, Integer> getDeviceCountsByOwnershipTypes(Map<String, Object> filters) throws GadgetDataServiceDAOException {
int filteringViewID = 1;
return this.getDeviceCountsByOwnershipTypes(filteringViewID, filters);
stmt = con.prepareStatement(sql);
// [2] appending filter column values, if exist
stmt.setInt(1, tenantId);
if (filters != null && filters.values().size() > 0) {
int i = 2;
for (Object value : filters.values()) {
if (value instanceof Integer) {
stmt.setInt(i, (Integer) value);
} else if (value instanceof String) {
stmt.setString(i, (String) value);
}
@Override
public Map<String, Integer> getFeatureNonCompliantDeviceCountsByOwnershipTypes(Map<String, Object> filters) throws GadgetDataServiceDAOException {
int filteringViewID = 2;
return this.getDeviceCountsByOwnershipTypes(filteringViewID, filters);
i++;
}
@Override
public List<Map<String, Object>> getDevicesWithDetails(Map<String, Object> filters) throws GadgetDataServiceDAOException {
int filteringViewID = 1;
return this.getDevicesWithDetails(filteringViewID, filters);
}
@Override
public List<Map<String, Object>> getFeatureNonCompliantDevicesWithDetails(Map<String, Object> filters) throws GadgetDataServiceDAOException {
int filteringViewID = 2;
return this.getDevicesWithDetails(filteringViewID, filters);
// executing query
rs = stmt.executeQuery();
// fetching query results
while (rs.next()) {
filteredDeviceCount = rs.getInt("DEVICE_COUNT");
}
} catch (SQLException e) {
throw new GadgetDataServiceDAOException("Error occurred while executing a selection query to the database", e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
return filteredDeviceCount;
}
private int getDeviceCount(int filteringViewID, Map<String, Object> filters) throws GadgetDataServiceDAOException {
public int getFeatureNonCompliantDeviceCount(String nonCompliantFeatureCode, Map<String, Object> filters) throws GadgetDataServiceDAOException {
Connection con;
PreparedStatement stmt = null;
ResultSet rs = null;
@ -160,13 +181,7 @@ class GadgetDataServiceDAOImpl implements GadgetDataServiceDAO {
int filteredDeviceCount = 0;
try {
con = this.getConnection();
String sql;
if (filteringViewID == 1) {
sql = "SELECT COUNT(DEVICE_ID) AS DEVICE_COUNT FROM DEVICES_VIEW_1 WHERE TENANT_ID = ?";
} else {
// if filteringViewID == 2
sql = "SELECT COUNT(DEVICE_ID) AS DEVICE_COUNT FROM DEVICES_VIEW_2 WHERE TENANT_ID = ?";
}
String sql = "SELECT COUNT(DEVICE_ID) AS DEVICE_COUNT FROM DEVICES_VIEW_2 WHERE TENANT_ID = ? AND FEATURE_CODE = ?";
// appending filters to support advanced filtering options
// [1] appending filter columns
if (filters != null && filters.size() > 0) {
@ -177,8 +192,9 @@ class GadgetDataServiceDAOImpl implements GadgetDataServiceDAO {
stmt = con.prepareStatement(sql);
// [2] appending filter column values, if exist
stmt.setInt(1, tenantId);
stmt.setString(2, nonCompliantFeatureCode);
if (filters != null && filters.values().size() > 0) {
int i = 2;
int i = 3;
for (Object value : filters.values()) {
if (value instanceof Integer) {
stmt.setInt(i, (Integer) value);
@ -202,7 +218,7 @@ class GadgetDataServiceDAOImpl implements GadgetDataServiceDAO {
return filteredDeviceCount;
}
private Map<String, Integer> getDeviceCountsByPlatforms(int filteringViewID, Map<String, Object> filters) throws GadgetDataServiceDAOException {
public Map<String, Integer> getDeviceCountsByPlatforms(Map<String, Object> filters) throws GadgetDataServiceDAOException {
Connection con;
PreparedStatement stmt = null;
ResultSet rs = null;
@ -218,14 +234,8 @@ class GadgetDataServiceDAOImpl implements GadgetDataServiceDAO {
advancedSqlFiltering = advancedSqlFiltering + "AND " + column + " = ? ";
}
}
if (filteringViewID == 1) {
sql = "SELECT PLATFORM, COUNT(DEVICE_ID) AS DEVICE_COUNT FROM DEVICES_VIEW_1 WHERE TENANT_ID = ? " +
advancedSqlFiltering + "GROUP BY PLATFORM";
} else {
// if filteringViewID == 2
sql = "SELECT PLATFORM, COUNT(DEVICE_ID) AS DEVICE_COUNT FROM DEVICES_VIEW_2 WHERE TENANT_ID = ? " +
advancedSqlFiltering + "GROUP BY PLATFORM";
}
stmt = con.prepareStatement(sql);
// [2] appending filter column values, if exist
stmt.setInt(1, tenantId);
@ -254,7 +264,54 @@ class GadgetDataServiceDAOImpl implements GadgetDataServiceDAO {
return filteredDeviceCountsByPlatforms;
}
private Map<String, Integer> getDeviceCountsByOwnershipTypes(int filteringViewID, Map<String, Object> filters) throws GadgetDataServiceDAOException {
public Map<String, Integer> getFeatureNonCompliantDeviceCountsByPlatforms(String nonCompliantFeatureCode, Map<String, Object> filters) throws GadgetDataServiceDAOException {
Connection con;
PreparedStatement stmt = null;
ResultSet rs = null;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
Map<String, Integer> filteredDeviceCountsByPlatforms = new HashMap<>();
try {
con = this.getConnection();
String sql, advancedSqlFiltering = "";
// appending filters if exist, to support advanced filtering options
// [1] appending filter columns, if exist
if (filters != null && filters.size() > 0) {
for (String column : filters.keySet()) {
advancedSqlFiltering = advancedSqlFiltering + "AND " + column + " = ? ";
}
}
sql = "SELECT PLATFORM, COUNT(DEVICE_ID) AS DEVICE_COUNT FROM DEVICES_VIEW_2 WHERE TENANT_ID = ? " +
"AND FEATURE_CODE = ? " + advancedSqlFiltering + "GROUP BY PLATFORM";
stmt = con.prepareStatement(sql);
// [2] appending filter column values, if exist
stmt.setInt(1, tenantId);
stmt.setString(2, nonCompliantFeatureCode);
if (filters != null && filters.values().size() > 0) {
int i = 3;
for (Object value : filters.values()) {
if (value instanceof Integer) {
stmt.setInt(i, (Integer) value);
} else if (value instanceof String) {
stmt.setString(i, (String) value);
}
i++;
}
}
// executing query
rs = stmt.executeQuery();
// fetching query results
while (rs.next()) {
filteredDeviceCountsByPlatforms.put(rs.getString("PLATFORM"), rs.getInt("DEVICE_COUNT"));
}
} catch (SQLException e) {
throw new GadgetDataServiceDAOException("Error occurred while executing a selection query to the database", e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
return filteredDeviceCountsByPlatforms;
}
public Map<String, Integer> getDeviceCountsByOwnershipTypes(Map<String, Object> filters) throws GadgetDataServiceDAOException {
Connection con;
PreparedStatement stmt = null;
ResultSet rs = null;
@ -270,14 +327,8 @@ class GadgetDataServiceDAOImpl implements GadgetDataServiceDAO {
advancedSqlFiltering = advancedSqlFiltering + "AND " + column + " = ? ";
}
}
if (filteringViewID == 1) {
sql = "SELECT OWNERSHIP, COUNT(DEVICE_ID) AS DEVICE_COUNT FROM DEVICES_VIEW_1 WHERE TENANT_ID = ? " +
advancedSqlFiltering + "GROUP BY OWNERSHIP";
} else {
// if filteringViewID == 2
sql = "SELECT OWNERSHIP, COUNT(DEVICE_ID) AS DEVICE_COUNT FROM DEVICES_VIEW_2 WHERE TENANT_ID = ? " +
advancedSqlFiltering + "GROUP BY OWNERSHIP";
}
stmt = con.prepareStatement(sql);
// [2] appending filter column values, if exist
stmt.setInt(1, tenantId);
@ -306,7 +357,54 @@ class GadgetDataServiceDAOImpl implements GadgetDataServiceDAO {
return filteredDeviceCountsByOwnershipTypes;
}
private List<Map<String, Object>> getDevicesWithDetails(int filteringViewID, Map<String, Object> filters) throws GadgetDataServiceDAOException {
public Map<String, Integer> getFeatureNonCompliantDeviceCountsByOwnershipTypes(String nonCompliantFeatureCode, Map<String, Object> filters) throws GadgetDataServiceDAOException {
Connection con;
PreparedStatement stmt = null;
ResultSet rs = null;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
Map<String, Integer> filteredDeviceCountsByOwnershipTypes = new HashMap<>();
try {
con = this.getConnection();
String sql, advancedSqlFiltering = "";
// appending filters if exist, to support advanced filtering options
// [1] appending filter columns, if exist
if (filters != null && filters.size() > 0) {
for (String column : filters.keySet()) {
advancedSqlFiltering = advancedSqlFiltering + "AND " + column + " = ? ";
}
}
sql = "SELECT OWNERSHIP, COUNT(DEVICE_ID) AS DEVICE_COUNT FROM DEVICES_VIEW_2 WHERE TENANT_ID = ? " +
"AND FEATURE_CODE = ? " + advancedSqlFiltering + "GROUP BY OWNERSHIP";
stmt = con.prepareStatement(sql);
// [2] appending filter column values, if exist
stmt.setInt(1, tenantId);
stmt.setString(2, nonCompliantFeatureCode);
if (filters != null && filters.values().size() > 0) {
int i = 3;
for (Object value : filters.values()) {
if (value instanceof Integer) {
stmt.setInt(i, (Integer) value);
} else if (value instanceof String) {
stmt.setString(i, (String) value);
}
i++;
}
}
// executing query
rs = stmt.executeQuery();
// fetching query results
while (rs.next()) {
filteredDeviceCountsByOwnershipTypes.put(rs.getString("OWNERSHIP"), rs.getInt("DEVICE_COUNT"));
}
} catch (SQLException e) {
throw new GadgetDataServiceDAOException("Error occurred while executing a selection query to the database", e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
return filteredDeviceCountsByOwnershipTypes;
}
public List<Map<String, Object>> getDevicesWithDetails(Map<String, Object> filters) throws GadgetDataServiceDAOException {
Connection con;
PreparedStatement stmt = null;
ResultSet rs = null;
@ -316,12 +414,7 @@ class GadgetDataServiceDAOImpl implements GadgetDataServiceDAO {
try {
con = this.getConnection();
String sql;
if (filteringViewID == 1) {
sql = "SELECT DEVICE_ID, PLATFORM, OWNERSHIP, CONNECTIVITY_STATUS FROM DEVICES_VIEW_1 WHERE TENANT_ID = ?";
} else {
// if filteringViewID == 2
sql = "SELECT DEVICE_ID, PLATFORM, OWNERSHIP, CONNECTIVITY_STATUS FROM DEVICES_VIEW_2 WHERE TENANT_ID = ?";
}
// appending filters to support advanced filtering options
// [1] appending filter columns, if exist
if (filters != null && filters.size() > 0) {
@ -361,6 +454,58 @@ class GadgetDataServiceDAOImpl implements GadgetDataServiceDAO {
return filteredDevicesWithDetails;
}
public List<Map<String, Object>> getFeatureNonCompliantDevicesWithDetails(String nonCompliantFeatureCode, Map<String, Object> filters) throws GadgetDataServiceDAOException {
Connection con;
PreparedStatement stmt = null;
ResultSet rs = null;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
Map<String, Object> filteredDeviceWithDetails = new HashMap<>();
List<Map<String, Object>> filteredDevicesWithDetails = new ArrayList<>();
try {
con = this.getConnection();
String sql;
sql = "SELECT DEVICE_ID, PLATFORM, OWNERSHIP, CONNECTIVITY_STATUS FROM DEVICES_VIEW_2 " +
"WHERE TENANT_ID = ? AND FEATURE_CODE = ?";
// appending filters to support advanced filtering options
// [1] appending filter columns, if exist
if (filters != null && filters.size() > 0) {
for (String column : filters.keySet()) {
sql = sql + " AND " + column + " = ?";
}
}
stmt = con.prepareStatement(sql);
// [2] appending filter column values, if exist
stmt.setInt(1, tenantId);
stmt.setString(2, nonCompliantFeatureCode);
if (filters != null && filters.values().size() > 0) {
int i = 3;
for (Object value : filters.values()) {
if (value instanceof Integer) {
stmt.setInt(i, (Integer) value);
} else if (value instanceof String) {
stmt.setString(i, (String) value);
}
i++;
}
}
// executing query
rs = stmt.executeQuery();
// fetching query results
while (rs.next()) {
filteredDeviceWithDetails.put("device-id", rs.getInt("DEVICE_ID"));
filteredDeviceWithDetails.put("platform", rs.getString("PLATFORM"));
filteredDeviceWithDetails.put("ownership", rs.getString("OWNERSHIP"));
filteredDeviceWithDetails.put("connectivity-details", rs.getString("CONNECTIVITY_STATUS"));
filteredDevicesWithDetails.add(filteredDeviceWithDetails);
}
} catch (SQLException e) {
throw new GadgetDataServiceDAOException("Error occurred while executing a selection query to the database", e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
return filteredDevicesWithDetails;
}
private Connection getConnection() throws SQLException {
return GadgetDataServiceDAOFactory.getConnection();
}

@ -23,6 +23,8 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.analytics.dashboard.GadgetDataService;
import org.wso2.carbon.device.mgt.analytics.dashboard.dao.GadgetDataServiceDAOException;
import org.wso2.carbon.device.mgt.analytics.dashboard.dao.GadgetDataServiceDAOFactory;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import java.sql.SQLException;
import java.util.Map;
@ -36,12 +38,12 @@ class GadgetDataServiceImpl implements GadgetDataService {
private static final Log log = LogFactory.getLog(GadgetDataServiceImpl.class);
@Override
public int getTotalDeviceCount(Map<String, Object> filters) {
public int getTotalDeviceCount() {
int totalDeviceCount;
try {
GadgetDataServiceDAOFactory.openConnection();
totalDeviceCount = GadgetDataServiceDAOFactory.
getGadgetDataServiceDAO().getTotalDeviceCount(filters);
getGadgetDataServiceDAO().getTotalDeviceCount();
} catch (GadgetDataServiceDAOException | SQLException e) {
totalDeviceCount = -1;
return totalDeviceCount;
@ -132,18 +134,34 @@ class GadgetDataServiceImpl implements GadgetDataService {
}
@Override
public Map<String, Integer> getNonCompliantDeviceCountsByFeatures() {
Map<String, Integer> nonCompliantDeviceCountsByFeatures = null;
public PaginationResult getNonCompliantDeviceCountsByFeatures(PaginationRequest paginationRequest) {
PaginationResult paginationResult = null;
try {
GadgetDataServiceDAOFactory.openConnection();
nonCompliantDeviceCountsByFeatures =
GadgetDataServiceDAOFactory.getGadgetDataServiceDAO().getNonCompliantDeviceCountsByFeatures();
paginationResult = GadgetDataServiceDAOFactory.getGadgetDataServiceDAO().
getNonCompliantDeviceCountsByFeatures(paginationRequest);
} catch (GadgetDataServiceDAOException | SQLException e) {
return null;
} finally {
GadgetDataServiceDAOFactory.closeConnection();
}
return nonCompliantDeviceCountsByFeatures;
return paginationResult;
}
@Override
public int getDeviceCount(Map<String, Object> filters) {
int deviceCount;
try {
GadgetDataServiceDAOFactory.openConnection();
deviceCount = GadgetDataServiceDAOFactory.
getGadgetDataServiceDAO().getDeviceCount(filters);
} catch (GadgetDataServiceDAOException | SQLException e) {
deviceCount = -1;
return deviceCount;
} finally {
GadgetDataServiceDAOFactory.closeConnection();
}
return deviceCount;
}
@Override

@ -258,23 +258,21 @@ deviceModule = function () {
};
// Refactored methods
publicMethods.getOwnDevicesCount = function () {
publicMethods.getDevicesCount = function () {
var carbonUser = session.get(constants.USER_SESSION_KEY);
var url = devicemgtProps["httpsURL"] + constants.ADMIN_SERVICE_CONTEXT + "/devices/user/" + carbonUser.username
if (carbonUser) {
var userModule = require("/app/modules/user.js").userModule;
var uiPermissions = userModule.getUIPermissions();
var url;
if (uiPermissions.LIST_DEVICES) {
url = devicemgtProps["httpsURL"] + constants.ADMIN_SERVICE_CONTEXT + "/devices/count";
} else if (uiPermissions.LIST_OWN_DEVICES) {
url = devicemgtProps["httpsURL"] + constants.ADMIN_SERVICE_CONTEXT + "/devices/user/" + carbonUser.username
+ "/count";
return serviceInvokers.XMLHttp.get(
url, function (responsePayload) {
return responsePayload;
},
function (responsePayload) {
log.error(responsePayload);
} else {
log.error("Access denied for user: " + carbonUser.username);
return -1;
}
);
};
publicMethods.getAllDevicesCount = function () {
var url = devicemgtProps["httpsURL"] + constants.ADMIN_SERVICE_CONTEXT + "/devices/count";
return serviceInvokers.XMLHttp.get(
url, function (responsePayload) {
return responsePayload;
@ -284,6 +282,10 @@ deviceModule = function () {
return -1;
}
);
} else {
log.error("User object was not found in the session");
throw constants["ERRORS"]["USER_NOT_FOUND"];
}
};
publicMethods.getDeviceTypes = function () {

@ -38,12 +38,14 @@ var groupModule = {};
endPoint = groupServiceEndpoint + "/count";
} else if (permissions.LIST_GROUPS) {
endPoint = groupServiceEndpoint + "/user/" + user.username + "/count";
} else {
log.error("Access denied for user: " + carbonUser.username);
return -1;
}
return serviceInvokers.XMLHttp.get(
endPoint, function (responsePayload) {
return responsePayload;
}
,
},
function (responsePayload) {
log.error(responsePayload);
return -1;
@ -56,8 +58,7 @@ var groupModule = {};
return serviceInvokers.XMLHttp.get(
endPoint, function (responsePayload) {
return responsePayload;
}
,
},
function (responsePayload) {
log.error(responsePayload);
return -1;

@ -653,6 +653,9 @@ var userModule = function () {
if (publicMethods.isAuthorized("/permission/admin/device-mgt/user/policies/list")) {
permissions["LIST_POLICIES"] = true;
}
if (publicMethods.isAuthorized("/permission/admin/device-mgt/user/devices/add")) {
permissions["ADD_DEVICE"] = true;
}
if (publicMethods.isAuthorized("/permission/admin/device-mgt/user/groups/add")) {
permissions["ADD_GROUP"] = true;
}

@ -1,42 +0,0 @@
{{unit "cdmf.unit.ui.title" pageTitle="Analytics"}}
{{unit "cdmf.unit.ui.content.title" pageHeader=title}}
{{#zone "breadcrumbs"}}
<li>
<a href="{{@app.context}}/">
<i class="icon fw fw-home"></i>
</a>
</li>
{{#if groupName}}
<li>
<a href="{{@app.context}}/groups">
Groups
</a>
</li>
<li>
<a href="{{@app.context}}/devices?groupId={{groupId}}&groupName={{groupName}}">
{{groupName}}
</a>
</li>
{{else}}
<li>
<a href="{{@app.context}}/devices">
Devices
</a>
</li>
<li>
<a href="{{@app.context}}/device/{{deviceType}}?id={{deviceId}}">
{{deviceName}}
</a>
</li>
{{/if}}
<li>
<a href="#">
Analytics
</a>
</li>
{{/zone}}
{{#zone "content"}}
{{unit "cdmf.unit.analytics"}}
{{/zone}}

@ -1,39 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
function onRequest(context) {
var groupName = request.getParameter("groupName");
var groupId = request.getParameter("groupId");
var deviceName = request.getParameter("deviceName");
var deviceId = request.getParameter("deviceId");
var deviceType = request.getParameter("deviceType");
var title = "Analytics";
if (groupName) {
title = "Group " + title;
} else {
title = "Device " + title;
}
return {
"title": title,
"groupName": groupName,
"groupId": groupId,
"deviceName": deviceName,
"deviceId": deviceId,
"deviceType": deviceType
};
}

@ -35,7 +35,7 @@ function onRequest(context) {
var groupModule = require("/app/modules/group.js").groupModule;
var policyModule = require("/app/modules/policy.js").policyModule;
page.device_count = deviceModule.getAllDevicesCount();
page.device_count = deviceModule.getDevicesCount();
page.group_count = groupModule.getGroupCount();
page.user_count = userModule.getUsers()["content"].length;
page.policy_count = policyModule.getAllPolicies()["content"].length;

@ -50,7 +50,7 @@
<div class=" margin-top-double">
<div class="row padding-top-double padding-bottom-double margin-bottom-double">
<div class="col-lg-3 margin-top-double">
<h1 class="grey ">{{deviceType}} Analytics</h1>
<h1 class="grey ">{{deviceName}} Analytics</h1>
</div>
<div id="rangeSliderWrapper" class="pull-right col-lg-9">
<div id="dateRangePickerContainer">

@ -17,19 +17,35 @@
*/
function onRequest(context) {
var utility = require("/app/modules/utility.js").utility;
context.handlebars.registerHelper('equal', function (lvalue, rvalue, options) {
if (arguments.length < 3)
if (arguments.length < 3) {
throw new Error("Handlebars Helper equal needs 2 parameters");
}
if (lvalue != rvalue) {
return options.inverse(this);
} else {
return options.fn(this);
}
});
var groupName = request.getParameter("groupName");
var groupId = request.getParameter("groupId");
var deviceName = request.getParameter("deviceName");
var deviceId = request.getParameter("deviceId");
var deviceType = context.uriParams.deviceType;
var title = "Analytics";
if (groupName) {
title = "Group " + title;
} else {
title = "Device " + title;
}
return {
"deviceAnalyticsViewUnitName": "cdmf.unit.device.type." + deviceType + ".analytics-view",
"deviceType": deviceType
"deviceAnalyticsViewUnitName": utility.getTenantedDeviceUnitName(deviceType, "analytics-view"),
"deviceType": deviceType,
"title": title,
"groupName": groupName,
"groupId": groupId,
"deviceName": deviceName,
"deviceId": deviceId
};
}

@ -1,5 +1,5 @@
{
"version": "1.0.0",
"uri": "/device/analytics/{deviceType}",
"uri": "/device/{deviceType}/analytics",
"layout": "cdmf.layout.default"
}

@ -34,8 +34,9 @@ function onRequest(context) {
var currentUser = session.get(constants.USER_SESSION_KEY);
if (currentUser) {
page.permissions = {};
page.permissions.list = stringify(userModule.getUIPermissions());
if (userModule.isAuthorized("/permission/admin/device-mgt/user/devices/add")) {
var uiPermissions = userModule.getUIPermissions();
page.permissions.list = stringify(uiPermissions);
if (uiPermissions.ADD_DEVICE) {
page.permissions.enroll = true;
}
page.currentUser = currentUser;
@ -45,7 +46,7 @@ function onRequest(context) {
deviceCount = groupModule.getGroupDeviceCount(groupName, groupOwner);
page.groupOwner = groupOwner;
} else {
deviceCount = deviceModule.getOwnDevicesCount();
deviceCount = deviceModule.getDevicesCount();
}
if (deviceCount > 0) {
page.deviceCount = deviceCount;

@ -300,7 +300,7 @@ function loadDevices(searchType, searchParam){
html = '<a href="device/' + deviceType + '?id=' + deviceIdentifier + '" data-click-event="remove-form"' +
' class="btn padding-reduce-on-grid-view"><span class="fw-stack"><i class="fw fw-ring fw-stack-2x"></i>' +
'<i class="fw fw-view fw-stack-1x"></i></span><span class="hidden-xs hidden-on-grid-view">View</span></a>';
html += '<a href="analytics?deviceId=' + deviceIdentifier + '&deviceType=' + deviceType + '&deviceName=' + row.name + '" ' +
html += '<a href="device/' + deviceType + '/analytics?deviceId=' + deviceIdentifier + '&deviceName=' + row.name + '" ' +
'data-click-event="remove-form" class="btn padding-reduce-on-grid-view"><span class="fw-stack">' +
'<i class="fw fw-ring fw-stack-2x"></i><i class="fw fw-statistics fw-stack-1x"></i></span>' +
'<span class="hidden-xs hidden-on-grid-view">Analytics</span>';
@ -309,6 +309,11 @@ function loadDevices(searchType, searchParam){
'<span class="fw-stack"><i class="fw fw-ring fw-stack-2x"></i>' +
'<i class="fw fw-edit fw-stack-1x"></i></span>' +
'<span class="hidden-xs hidden-on-grid-view">Edit</span></a>';
html += '<a href="#" data-click-event="remove-form" class="btn padding-reduce-on-grid-view remove-device-link" ' +
'data-deviceid="' + deviceIdentifier + '" data-devicetype="' + deviceType + '" data-devicename="' + row.name + '">' +
'<span class="fw-stack"><i class="fw fw-ring fw-stack-2x"></i>' +
'<i class="fw fw-delete fw-stack-1x"></i></span>' +
'<span class="hidden-xs hidden-on-grid-view">Delete</span>';
}
return html;
}}

@ -1,87 +0,0 @@
{{#each devices}}
{{deviceMap this}}
<tr data-type="selectable" data-deviceid="{{deviceIdentifier}}" data-devicetype="{{type}}">
<td class="remove-padding icon-only content-fill">
<div class="thumbnail icon">
<img class="square-element text fw "
src="{{../imageLocation}}{{type}}.type-view/images/thumb.png"/>
</div>
</td>
<td class="fade-edge" data-search="{{properties.DEVICE_MODEL}},{{properties.VENDOR}}"
data-display="{{properties.DEVICE_MODEL}}">
<h4 data-deviceid="{{deviceIdentifier}}">{{name}}</h4>
{{#if properties.VENDOR}}
<div>({{properties.VENDOR}} - {{properties.DEVICE_MODEL}})</div>
{{/if}}
</td>
<td class="fade-edge remove-padding-top" data-search="{{enrolmentInfo.owner}}"
data-display="{{enrolmentInfo.owner}}"
data-grid-label="Owner">{{enrolmentInfo.owner}}</td>
<td class="fade-edge remove-padding-top" data-search="{{enrolmentInfo.status}}"
data-display="{{enrolmentInfo.status}}" data-grid-label="Status">
{{#equal enrolmentInfo.status "ACTIVE"}}<span><i class="fw fw-ok icon-success"></i> Active</span>{{/equal}}
{{#equal enrolmentInfo.status "INACTIVE"}}<span><i
class="fw fw-warning icon-warning"></i> Inactive</span>{{/equal}}
{{#equal enrolmentInfo.status "BLOCKED"}}<span><i class="fw fw-remove icon-danger"></i> Blocked</span>{{/equal}}
{{#equal enrolmentInfo.status "REMOVED"}}<span><i class="fw fw-delete icon-danger"></i> Removed</span>{{/equal}}
</td>
<td class="fade-edge remove-padding-top" data-search="{{type}}" data-display="{{type}}"
data-grid-label="Type">{{type}}</td>
<td class="fade-edge remove-padding-top" data-search="{{enrolmentInfo.ownership}}"
data-display="{{enrolmentInfo.ownership}}"
data-grid-label="Ownership">{{enrolmentInfo.ownership}}</td>
<td class="text-right content-fill text-left-on-grid-view no-wrap">
{{#unequal enrolmentInfo.status "REMOVED"}}
<a href="device/{{type}}?id={{deviceIdentifier}}"
data-click-event="remove-form" class="btn padding-reduce-on-grid-view">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-view fw-stack-1x"></i>
</span>
<span class="hidden-xs hidden-on-grid-view">View</span>
</a>
<a href="analytics?deviceId={{deviceIdentifier}}&deviceType={{type}}&deviceName={{name}}"
data-click-event="remove-form" class="btn padding-reduce-on-grid-view">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-statistics fw-stack-1x"></i>
</span>
<span class="hidden-xs hidden-on-grid-view">Analytics</span>
</a>
{{#unless ../../isGroupView}}
<a href="#" data-click-event="remove-form"
class="btn padding-reduce-on-grid-view group-device-link"
data-deviceid="{{deviceIdentifier}}" data-devicetype="{{type}}"
data-devicename="{{name}}">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-grouping fw-stack-1x"></i>
</span>
<span class="hidden-xs hidden-on-grid-view">Group</span>
</a>
{{/unless}}
<a href="#" data-click-event="remove-form"
class="btn padding-reduce-on-grid-view edit-device-link"
data-deviceid="{{deviceIdentifier}}" data-devicetype="{{type}}"
data-devicename="{{name}}">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-edit fw-stack-1x"></i>
</span>
<span class="hidden-xs hidden-on-grid-view">Edit</span>
</a>
<a href="#" data-click-event="remove-form"
class="btn padding-reduce-on-grid-view remove-device-link"
data-deviceid="{{deviceIdentifier}}" data-devicetype="{{type}}">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-delete fw-stack-1x"></i>
</span>
<span class="hidden-xs hidden-on-grid-view">Delete</span>
</a>
{{/unequal}}
</td>
</tr>
{{/each}}

@ -1,48 +0,0 @@
{{#zone "topCss"}}
{{css "css/analytics.css"}}
{{css "css/daterangepicker.css"}}
{{css "css/graph.css"}}
{{/zone}}
<span id="request-group-id" data-groupid="{{groupId}}"></span>
<div class="container container-bg white-bg">
<div class=" margin-top-double">
<div class="row padding-top-double padding-bottom-double margin-bottom-double">
<div class="col-lg-3 margin-top-double">
<h1 class="grey ">{{title}}</h1>
</div>
<div id="rangeSliderWrapper" class="pull-right col-lg-9">
<div id="dateRangePickerContainer">
<div class="btn-group" role="group">
<button id="hour-btn" type="button"
class="btn btn-default date-range">Hour
</button>
<button id="h12-btn" type="button"
class="btn btn-default date-range">12 Hours
</button>
<button id="h24-btn" type="button"
class="btn btn-default date-range">24 Hours
</button>
<button id="h48-btn" type="button"
class="btn btn-default date-range">48 Hours
</button>
<button id="date-range" type="button"
class="btn btn-default date-range last-child"
data-toggle="popup"
title="Click to set custom date range"></button>
</div>
</div>
</div>
</div>
<hr>
<div class="clear"></div>
<div id="div-chart">
</div>
</div>
</div>
{{#zone "bottomJs"}}
{{js "js/d3.min.js"}}
{{js "js/rickshaw.min.js"}}
{{js "js/moment.min.js"}}
{{js "js/jquery.daterangepicker.js"}}
{{js "js/graph_util.js"}}
{{/zone}}

@ -1,35 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
function onRequest(context) {
var groupId = request.getParameter("groupId");
var title;
if (groupId) {
title = request.getParameter("groupName") + " Group";
} else {
groupId = 0;
var deviceId = request.getParameter("deviceId");
var deviceType = request.getParameter("deviceType");
var deviceName = request.getParameter("deviceName");
//title = deviceModule.getDevice(deviceType, deviceId).name;
title = deviceName;
}
return {"title": title, "groupId": groupId};
}

@ -1,63 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#rangeSliderWrapper {
margin-top: 25px;
}
#chart {
display: inline-block;
}
#legend {
display: inline-block;
position: relative;
left: 8px;
}
#legend_container {
position: absolute;
right: 0;
bottom: 26px;
width: 0;
}
#chart_container {
float: left;
position: relative;
}
.ast-container {
padding-bottom: 30px;
}
.container {
width: auto;
}
.shrink {
margin-right: 20px;
margin-left: 20px;
}
.date-range{
border: 1px solid #ccc;
}
#dateRangePickerContainer button.active{
background-color: #e6e6e6 !important;
}

@ -1,348 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
.date-picker {
width: 170px;
height: 25px;
padding: 0;
border: 0;
line-height: 25px;
padding-left: 10px;
font-size: 12px;
font-family: Arial;
font-weight: bold;
cursor: pointer;
color: #303030;
position: relative;
z-index: 2;
}
.date-picker-wrapper {
position: absolute;
z-index: 1;
border: 1px solid #bfbfbf;
background-color: #efefef;
width: 448px;
padding: 5px 12px;
font-size: 12px;
line-height: 20px;
color: #aaa;
font-family: Arial;
box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.5);
}
.date-picker-wrapper.single-date {
width: auto;
}
.date-picker-wrapper.no-shortcuts {
padding-bottom: 12px;
}
.date-picker-wrapper .footer {
display: none;
font-size: 11px;
padding-top: 3px;
}
.date-picker-wrapper b {
color: #666;
font-weight: 700;
}
.date-picker-wrapper a {
color: rgb(107, 180, 214);
text-decoration: underline;
}
.date-picker-wrapper .month-wrapper {
border: 1px solid #bfbfbf;
border-radius: 3px;
background-color: #fff;
padding: 5px;
cursor: default;
position: relative;
_overflow: hidden;
}
.date-picker-wrapper .month-wrapper table {
width: 190px;
float: left;
}
.date-picker-wrapper .month-wrapper table.month2 {
width: 190px;
float: right;
}
.date-picker-wrapper .month-wrapper table th,
.date-picker-wrapper .month-wrapper table td {
vertical-align: middle;
text-align: center;
line-height: 14px;
margin: 0px;
padding: 0px;
}
.date-picker-wrapper .month-wrapper table .day {
height: 19px;
line-height: 19px;
font-size: 12px;
margin-bottom: 1px;
color: #999;
cursor: default;
}
.date-picker-wrapper .month-wrapper table div.day.lastMonth,
.date-picker-wrapper .month-wrapper table div.day.nextMonth {
color: #999;
cursor: default;
}
.date-picker-wrapper .month-wrapper table .day.checked {
background-color: rgb(156, 219, 247);
}
.date-picker-wrapper .month-wrapper table .week-name {
height: 20px;
line-height: 20px;
font-weight: 100;
}
.date-picker-wrapper .month-wrapper table .day.has-tooltip {
cursor: help !important;
}
.date-picker-wrapper .month-wrapper table .day.toMonth.valid {
color: #333;
cursor: pointer;
}
.date-picker-wrapper .month-wrapper table .day.real-today {
background-color: rgb(255, 230, 132);
}
.date-picker-wrapper .month-wrapper table .day.real-today.checked {
background-color: rgb(112, 204, 213);
}
.date-picker-wrapper table .caption {
height: 40px;
}
.date-picker-wrapper table .caption .next,
.date-picker-wrapper table .caption .prev {
padding: 0 5px;
cursor: pointer;
}
.date-picker-wrapper table .caption .next:hover,
.date-picker-wrapper table .caption .prev:hover {
background-color: #ccc;
color: white;
}
.date-picker-wrapper .gap {
position: absolute;
display: none;
top: 0px;
left: 204px;
z-index: 1;
width: 15px;
height: 100%;
background-color: red;
font-size: 0;
line-height: 0;
}
.date-picker-wrapper .gap .gap-lines {
height: 100%;
overflow: hidden;
}
.date-picker-wrapper .gap .gap-line {
height: 15px;
width: 15px;
position: relative;
}
.date-picker-wrapper .gap .gap-line .gap-1 {
z-index: 1;
height: 0;
border-left: 8px solid white;
border-top: 8px solid #eee;
border-bottom: 8px solid #eee;
}
.date-picker-wrapper .gap .gap-line .gap-2 {
position: absolute;
right: 0;
top: 0px;
z-index: 2;
height: 0;
border-left: 8px solid transparent;
border-top: 8px solid white;
}
.date-picker-wrapper .gap .gap-line .gap-3 {
position: absolute;
right: 0;
top: 8px;
z-index: 2;
height: 0;
border-left: 8px solid transparent;
border-bottom: 8px solid white;
}
.date-picker-wrapper .gap .gap-top-mask {
width: 6px;
height: 1px;
position: absolute;
top: -1px;
left: 1px;
background-color: #eee;
z-index: 3;
}
.date-picker-wrapper .gap .gap-bottom-mask {
width: 6px;
height: 1px;
position: absolute;
bottom: -1px;
left: 7px;
background-color: #eee;
z-index: 3;
}
.date-picker-wrapper .selected-days {
display: none;
}
.date-picker-wrapper .drp_top-bar {
line-height: 40px;
height: 40px;
position: relative;
}
.date-picker-wrapper .drp_top-bar .error-top {
display: none;
}
.date-picker-wrapper .drp_top-bar .normal-top {
display: none;
}
.date-picker-wrapper .drp_top-bar .default-top {
display: block;
}
.date-picker-wrapper .drp_top-bar.error .default-top {
display: none;
}
.date-picker-wrapper .drp_top-bar.error .error-top {
display: block;
color: red;
}
.date-picker-wrapper .drp_top-bar.normal .default-top {
display: none;
}
.date-picker-wrapper .drp_top-bar.normal .normal-top {
display: block;
}
.date-picker-wrapper .drp_top-bar .apply-btn {
position: absolute;
right: 0px;
top: 6px;
padding: 3px 5px;
margin: 0;
font-size: 12px;
border-radius: 4px;
cursor: pointer;
color: #d9eef7;
border: solid 1px #0076a3;
background: #0095cd;
background: -webkit-gradient(linear, left top, left bottom, from(#00adee), to(#0078a5));
background: -moz-linear-gradient(top, #00adee, #0078a5);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee', endColorstr='#0078a5');
color: white;
}
.date-picker-wrapper .drp_top-bar .apply-btn.disabled {
pointer-events: none;
color: #606060;
border: solid 1px #b7b7b7;
background: #fff;
background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#ededed));
background: -moz-linear-gradient(top, #fff, #ededed);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#ededed');
}
/*time styling*/
.time {
position: relative;
}
.time input[type=range] {
vertical-align: middle;
}
.time1, .time2 {
width: 180px;
padding: 0 5px;
text-align: center;
}
.time1 {
float: left;
}
.time2 {
float: right;
}
.hour, .minute {
text-align: left;
}
.hide {
display: none;
}
input.hour-range, input.minute-range {
width: 150px;
}
#dateRangePickerContainer .date-range, #dateRangePickerContainer .input-append {
background: none !important;
}
#date-range {
padding-right: 30px;
width: 300px;
height: 100%;
display: inline-block;
}
#dateRangePickerContainer {
float: right;
}

@ -1,463 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* graph */
.rickshaw_graph {
position: relative;
}
.rickshaw_graph svg {
display: block;
overflow: hidden;
}
/* ticks */
.rickshaw_graph .x_tick {
position: absolute;
top: 0;
bottom: 0;
width: 0;
border-left: 1px dotted rgba(0, 0, 0, 0.2);
pointer-events: none;
}
.rickshaw_graph .x_tick .title {
position: absolute;
font-size: 12px;
font-family: Arial, sans-serif;
opacity: 0.5;
white-space: nowrap;
margin-left: 3px;
bottom: -20px;
height: auto;
border-bottom: none;
}
/* annotations */
.rickshaw_annotation_timeline {
height: 1px;
border-top: 1px solid #e0e0e0;
margin-top: 10px;
position: relative;
}
.rickshaw_annotation_timeline .annotation {
position: absolute;
height: 6px;
width: 6px;
margin-left: -2px;
top: -3px;
border-radius: 5px;
background-color: rgba(0, 0, 0, 0.25);
}
.rickshaw_graph .annotation_line {
position: absolute;
top: 0;
bottom: -6px;
width: 0;
border-left: 2px solid rgba(0, 0, 0, 0.3);
display: none;
}
.rickshaw_graph .annotation_line.active {
display: block;
}
.rickshaw_graph .annotation_range {
background: rgba(0, 0, 0, 0.1);
display: none;
position: absolute;
top: 0;
bottom: -6px;
}
.rickshaw_graph .annotation_range.active {
display: block;
}
.rickshaw_graph .annotation_range.active.offscreen {
display: none;
}
.rickshaw_annotation_timeline .annotation .content {
background: white;
color: black;
opacity: 0.9;
box-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
border-radius: 3px;
position: relative;
z-index: 20;
font-size: 12px;
padding: 6px 8px 8px;
top: 18px;
left: -11px;
width: 160px;
display: none;
cursor: pointer;
}
.rickshaw_annotation_timeline .annotation .content:before {
content: "\25b2";
position: absolute;
top: -11px;
color: white;
text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.8);
}
.rickshaw_annotation_timeline .annotation.active,
.rickshaw_annotation_timeline .annotation:hover {
background-color: rgba(0, 0, 0, 0.8);
cursor: none;
}
.rickshaw_annotation_timeline .annotation .content:hover {
z-index: 50;
}
.rickshaw_annotation_timeline .annotation.active .content {
display: block;
}
.rickshaw_annotation_timeline .annotation:hover .content {
display: block;
z-index: 50;
}
.rickshaw_graph .y_axis,
.rickshaw_graph .x_axis_d3 {
fill: none;
}
.rickshaw_graph .y_ticks .tick line,
.rickshaw_graph .x_ticks_d3 .tick {
stroke: rgba(0, 0, 0, 0.16);
stroke-width: 2px;
shape-rendering: crisp-edges;
pointer-events: none;
}
.rickshaw_graph .y_grid .tick,
.rickshaw_graph .x_grid_d3 .tick {
z-index: -1;
stroke: rgba(0, 0, 0, 0.20);
stroke-width: 1px;
stroke-dasharray: 1 1;
}
.rickshaw_graph .y_grid .tick[data-y-value="0"] {
stroke-dasharray: 1 0;
}
.rickshaw_graph .y_grid path,
.rickshaw_graph .x_grid_d3 path {
fill: none;
stroke: none;
}
.rickshaw_graph .y_ticks path,
.rickshaw_graph .x_ticks_d3 path {
fill: none;
stroke: #808080;
}
.rickshaw_graph .y_ticks text,
.rickshaw_graph .x_ticks_d3 text {
opacity: 0.5;
font-size: 12px;
pointer-events: none;
}
.rickshaw_graph .x_tick.glow .title,
.rickshaw_graph .y_ticks.glow text {
fill: black;
color: black;
text-shadow: -1px 1px 0 rgba(255, 255, 255, 0.1),
1px -1px 0 rgba(255, 255, 255, 0.1),
1px 1px 0 rgba(255, 255, 255, 0.1),
0 1px 0 rgba(255, 255, 255, 0.1),
0 -1px 0 rgba(255, 255, 255, 0.1),
1px 0 0 rgba(255, 255, 255, 0.1),
-1px 0 0 rgba(255, 255, 255, 0.1),
-1px -1px 0 rgba(255, 255, 255, 0.1);
}
.rickshaw_graph .x_tick.inverse .title,
.rickshaw_graph .y_ticks.inverse text {
fill: white;
color: white;
text-shadow: -1px 1px 0 rgba(0, 0, 0, 0.8),
1px -1px 0 rgba(0, 0, 0, 0.8),
1px 1px 0 rgba(0, 0, 0, 0.8),
0 1px 0 rgba(0, 0, 0, 0.8),
0 -1px 0 rgba(0, 0, 0, 0.8),
1px 0 0 rgba(0, 0, 0, 0.8),
-1px 0 0 rgba(0, 0, 0, 0.8),
-1px -1px 0 rgba(0, 0, 0, 0.8);
}
.custom_rickshaw_graph {
position: relative;
left: 40px;
}
.custom_y_axis {
position: absolute;
width: 40px;
}
.custom_slider {
left: 40px;
}
.custom_x_axis {
position: relative;
left: 40px;
height: 30px;
}
/*detail*/
.rickshaw_graph .detail {
pointer-events: none;
position: absolute;
top: 0;
z-index: 2;
background: rgba(0, 0, 0, 0.1);
bottom: 0;
width: 1px;
transition: opacity 0.25s linear;
-moz-transition: opacity 0.25s linear;
-o-transition: opacity 0.25s linear;
-webkit-transition: opacity 0.25s linear;
}
.rickshaw_graph .detail.inactive {
opacity: 0;
}
.rickshaw_graph .detail .item.active {
opacity: 1;
}
.rickshaw_graph .detail .x_label {
font-family: Arial, sans-serif;
border-radius: 3px;
padding: 6px;
opacity: 0.5;
border: 1px solid #e0e0e0;
font-size: 12px;
position: absolute;
background: white;
white-space: nowrap;
}
.rickshaw_graph .detail .x_label.left {
left: 0;
}
.rickshaw_graph .detail .x_label.right {
right: 0;
}
.rickshaw_graph .detail .item {
position: absolute;
z-index: 2;
border-radius: 3px;
padding: 0.25em;
font-size: 12px;
font-family: Arial, sans-serif;
opacity: 0;
background: rgba(0, 0, 0, 0.4);
color: white;
border: 1px solid rgba(0, 0, 0, 0.4);
margin-left: 1em;
margin-right: 1em;
margin-top: -1em;
white-space: nowrap;
}
.rickshaw_graph .detail .item.left {
left: 0;
}
.rickshaw_graph .detail .item.right {
right: 0;
}
.rickshaw_graph .detail .item.active {
opacity: 1;
background: rgba(0, 0, 0, 0.8);
}
.rickshaw_graph .detail .item:after {
position: absolute;
display: block;
width: 0;
height: 0;
content: "";
border: 5px solid transparent;
}
.rickshaw_graph .detail .item.left:after {
top: 1em;
left: -5px;
margin-top: -5px;
border-right-color: rgba(0, 0, 0, 0.8);
border-left-width: 0;
}
.rickshaw_graph .detail .item.right:after {
top: 1em;
right: -5px;
margin-top: -5px;
border-left-color: rgba(0, 0, 0, 0.8);
border-right-width: 0;
}
.rickshaw_graph .detail .dot {
width: 4px;
height: 4px;
margin-left: -3px;
margin-top: -3.5px;
border-radius: 5px;
position: absolute;
box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
box-sizing: content-box;
-moz-box-sizing: content-box;
background: white;
border-width: 2px;
border-style: solid;
display: none;
background-clip: padding-box;
}
.rickshaw_graph .detail .dot.active {
display: block;
}
/*legend*/
.rickshaw_legend {
font-family: Arial;
font-size: 12px;
color: white;
background: #404040;
display: inline-block;
padding: 12px 5px;
border-radius: 2px;
position: relative;
float: right;
}
.rickshaw_legend:hover {
z-index: 10;
}
.rickshaw_legend .swatch {
width: 10px;
height: 10px;
border: 1px solid rgba(0, 0, 0, 0.2);
}
.rickshaw_legend .line {
clear: both;
line-height: 140%;
padding-right: 15px;
}
.rickshaw_legend .line .swatch {
display: inline-block;
margin-right: 3px;
border-radius: 2px;
}
.rickshaw_legend .label {
margin: 0;
white-space: nowrap;
display: inline;
font-size: inherit;
background-color: transparent;
color: inherit;
font-weight: normal;
line-height: normal;
padding: 0;
text-shadow: none;
}
.rickshaw_legend .action:hover {
opacity: 0.6;
}
.rickshaw_legend .action {
margin-right: 0.2em;
opacity: 0.2;
cursor: pointer;
font-size: 14px;
}
.rickshaw_legend .line.disabled {
opacity: 0.4;
}
.rickshaw_legend ul {
list-style-type: none;
padding: 0;
margin: 2px;
cursor: pointer;
}
.rickshaw_legend li {
padding: 0 0 0 2px;
min-width: 80px;
white-space: nowrap;
}
.rickshaw_legend li:hover {
background: rgba(255, 255, 255, 0.08);
border-radius: 3px;
}
.rickshaw_legend li:active {
background: rgba(255, 255, 255, 0.2);
border-radius: 3px;
}
.legend {
display: inline-block;
position: relative;
left: 8px;
}
.legend_container {
float: right;
padding-right: 10px;
width: 0;
z-index: 1;
position: relative;
opacity: 0.7;
}
.spaced {
margin-top: 20px !important;
}

@ -1,588 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var fromDate, toDate, currentDay = new Date();
var startDate = new Date(currentDay.getTime() - (60 * 60 * 24 * 100));
var endDate = new Date(currentDay.getTime());
var palette = new Rickshaw.Color.Palette({scheme: 'classic9'});
var groupId, stats;
// create a custom bar renderer that shift bars
Rickshaw.Graph.Renderer.BinaryBar = Rickshaw.Class.create(Rickshaw.Graph.Renderer.Bar, {
name: 'binary_bar',
render: function (args) {
args = args || {};
var graph = this.graph;
var series = args.series || graph.series;
var vis = args.vis || graph.vis;
vis.selectAll('*').remove();
var barWidth = this.barWidth(series.active()[0]);
var barXOffset = 0;
var activeSeriesCount = series.filter(function (s) {
return !s.disabled;
}).length;
var seriesBarWidth = this.unstack ? barWidth / activeSeriesCount : barWidth;
var transform = function (d) {
// add a matrix transform for negative values
var matrix = [1, 0, 0, (d.y < 0 ? -1 : 1), 0, (d.y < 0 ? graph.y.magnitude(Math.abs(d.y)) * 2 : 0)];
return "matrix(" + matrix.join(',') + ")";
};
var index = 0;
series.forEach(function (series) {
if (series.disabled) {
return;
}
var nodes = vis.selectAll("path")
.data(series.stack.filter(function (d) {
return d.y !== null
}))
.enter().append("svg:rect")
.attr("x", function (d) {
return graph.x(d.x) + barXOffset
})
.attr("y", function (d) {
return ((graph.y(index + Math.abs(d.y))) * (d.y < 0 ? -1 : 1 ))
})
.attr("width", seriesBarWidth)
.attr("height", function (d) {
return graph.y.magnitude(Math.abs(d.y))
})
.attr("transform", transform);
index++;
Array.prototype.forEach.call(nodes[0], function (n) {
n.setAttribute('fill', series.color);
});
if (this.unstack) {
barXOffset += seriesBarWidth;
}
}, this);
}
});
function initDate() {
currentDay = new Date();
}
var configObject = {
startOfWeek: 'monday',
separator: ' to ',
format: 'YYYY-MM-DD HH:mm',
autoClose: false,
time: {
enabled: true
},
shortcuts: 'hide',
endDate: currentDay,
maxDays: 2,
getValue: function () {
return this.value;
},
setValue: function (s) {
this.value = s;
}
};
var DateRange = convertDate(startDate) + " " + configObject.separator + " " + convertDate(endDate);
$(document).ready(function () {
initDate();
groupId = getQueryParams().groupId;
$('#date-range').html(DateRange);
$('#date-range').dateRangePicker(configObject)
.bind('datepicker-apply', function (event, dateRange) {
$(this).addClass('active');
$(this).siblings().removeClass('active');
fromDate = dateRange.date1 != "Invalid Date" ? dateRange.date1.getTime() / 1000 : null;
toDate = dateRange.date2 != "Invalid Date" ? dateRange.date2.getTime() / 1000 : null;
getStats(fromDate, toDate);
}
);
getDateTime(currentDay.getTime() - 3600000, currentDay.getTime());
$('#hour-btn').addClass('active');
});
//hour
$('#hour-btn').on('click', function () {
initDate();
getDateTime(currentDay.getTime() - 3600000, currentDay.getTime());
});
//12 hours
$('#h12-btn').on('click', function () {
initDate();
getDateTime(currentDay.getTime() - (3600000 * 12), currentDay.getTime());
});
//24 hours
$('#h24-btn').on('click', function () {
initDate();
getDateTime(currentDay.getTime() - (3600000 * 24), currentDay.getTime());
});
//48 hours
$('#h48-btn').on('click', function () {
initDate();
getDateTime(currentDay.getTime() - (3600000 * 48), currentDay.getTime());
});
$('body').on('click', '.btn-group button', function (e) {
$(this).addClass('active');
$(this).siblings().removeClass('active');
});
function getDateTime(from, to) {
fromDate = from;
toDate = to;
startDate = new Date(from);
endDate = new Date(to);
DateRange = convertDate(startDate) + " " + configObject.separator + " " + convertDate(endDate);
$('#date-range').html(DateRange);
getStats(from / 1000, to / 1000);
}
function getStats(from, to) {
var tzOffset = new Date().getTimezoneOffset() * 60 / 1000;
from += tzOffset;
to += tzOffset;
$('#div-chart').html('<div style="height:200px" data-state="loading" ' +
'data-loading-text="Loading..." data-loading-style="icon-only" ' +
'data-loading-inverse="true"></div>');
var requestData = {};
var getStatsRequest;
if (from) {
requestData['from'] = parseInt(from);
}
if (to) {
requestData['to'] = parseInt(to);
}
if (groupId && groupId != "0") {
requestData['groupId'] = groupId;
getStatsRequest = $.ajax({
url: "api/stats/group",
method: "GET",
data: requestData
});
} else {
var deviceId = getQueryParams().deviceId;
var deviceType = getQueryParams().deviceType;
requestData['deviceId'] = deviceId;
requestData['deviceType'] = deviceType;
getStatsRequest = $.ajax({
url: "api/stats",
method: "GET",
data: requestData
});
}
getStatsRequest.done(function (data) {
stats = data;
updateGraphs();
});
getStatsRequest.fail(function (jqXHR, textStatus) {
console.log("Request failed: " + jqXHR.statusText);
});
}
$(window).on('resize', function () {
if (stats) {
updateGraphs();
}
});
function updateGraphs() {
console.log(stats);
var graphId = 1;
$('#div-chart').html("");
for (var stats_data in stats) {
switch (stats[stats_data][0]["stream"]["ui_unit"]["name"]) {
case "cdmf.unit.analytics.line-chart":
$('#div-chart').append("<div class='row margin-double shrink'><div>" +
"<h2 class='grey'>" + stats[stats_data][0]["stream"]["name"] +
"</h2><hr><div id='canvas-wrapper" + graphId +
"'></div></div><hr class='spaced'></div>");
drawLineGraph(graphId++, stats[stats_data]);
break;
case "cdmf.unit.analytics.bar-chart":
$('#div-chart').append("<div class='row margin-double shrink'><div><h2 class='grey'>" +
stats[stats_data][0]["stream"]["name"] +
"</h2><hr><div id='canvas-wrapper" + graphId + "'></div></div>" +
"<hr class='spaced'></div>");
drawBarGraph(graphId++, stats[stats_data]);
break;
}
}
scaleGraphs();
}
function drawLineGraph(graphId, chartDataRaw) {
var chartWrapperElmId = "#canvas-wrapper" + graphId;
var graphWidth = $(chartWrapperElmId).width() - 50;
if (chartDataRaw.length == 0) {
$(chartWrapperElmId).html("No data available...");
return;
}
var chartDiv = "chart" + graphId;
var sliderDiv = "slider" + graphId;
var y_axis = "y_axis" + graphId;
$(chartWrapperElmId).html("").html('<div id = "' + y_axis + '" class="custom_y_axis"></div>' +
'<div class="legend_container" id="legend_container' +
graphId + '"><div id="smoother' + graphId +
'" title="Smoothing"></div><div class="legend" id="legend' +
graphId + '"></div></div><div id="' + chartDiv +
'" class="custom_rickshaw_graph"></div>' +
'<div class="custom_x_axis"></div><div id="' + sliderDiv +
'" class="custom_slider"></div>');
var graphConfig = {
element: document.getElementById(chartDiv),
width: graphWidth,
height: 400,
strokeWidth: 2,
renderer: 'line',
interpolation: "linear",
unstack: true,
stack: false,
xScale: d3.time.scale(),
padding: {top: 0.2, left: 0.02, right: 0.02, bottom: 0.2},
series: []
};
var tzOffset = new Date().getTimezoneOffset() * 60;
var min = Number.MAX_VALUE;
var max = Number.MIN_VALUE;
var range_min = 99999, range_max = 0;
for (var i = 0; i < chartDataRaw.length; i++) {
var chartData = [];
if (chartDataRaw[i].stats.length > 0) {
var max_val = parseInt(chartDataRaw[i].stats[0].value);
var min_val = max_val;
for (var j = 0; j < chartDataRaw[i].stats.length; j++) {
var y_val = parseInt(chartDataRaw[i].stats[j].value);
if (y_val > max_val) {
max_val = y_val;
} else if (y_val < min_val) {
min_val = y_val;
}
chartData.push({
x: parseInt(chartDataRaw[i].stats[j].time) - tzOffset,
y: y_val
});
}
if (range_max < max_val) {
range_max = max_val;
}
if (range_min > min_val) {
range_min = min_val;
}
graphConfig['series'].push({
'color': palette.color(),
'data': summerizeLine(chartData),
'name': chartDataRaw[i].device,
'scale': d3.scale.linear().domain(
[Math.min(min, min_val) - 5,
Math.max(max, max_val) + 5]).nice()
});
}
}
if (graphConfig['series'].length == 0) {
$(chartWrapperElmId).html("No data available...");
return;
}
var graph = new Rickshaw.Graph(graphConfig);
graph.render();
var xAxis = new Rickshaw.Graph.Axis.Time({
graph: graph
});
xAxis.render();
var yAxis = new Rickshaw.Graph.Axis.Y.Scaled({
graph: graph,
orientation: 'left',
element: document.getElementById(y_axis),
width: 40,
height: 410,
'scale': d3.scale.linear().domain([Math.min(min, range_min), Math.max(max, range_max)]).nice()
});
yAxis.render();
var slider = new Rickshaw.Graph.RangeSlider.Preview({
graph: graph,
element: document.getElementById(sliderDiv)
});
var legend = new Rickshaw.Graph.Legend({
graph: graph,
element: document.getElementById('legend' + graphId)
});
var hoverDetail = new Rickshaw.Graph.HoverDetail({
graph: graph,
formatter: function (series, x, y) {
var date = '<span class="date">' +
moment((x + tzOffset) * 1000).format('Do MMM YYYY h:mm:ss a') + '</span>';
var swatch = '<span class="detail_swatch" style="background-color: ' +
series.color + '"></span>';
return swatch + series.name + ": " + parseInt(y) + '<br>' + date;
}
});
var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
graph: graph,
legend: legend
});
var order = new Rickshaw.Graph.Behavior.Series.Order({
graph: graph,
legend: legend
});
var highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({
graph: graph,
legend: legend
});
}
function drawBarGraph(graphId, chartDataRaw) {
var chartWrapperElmId = "#canvas-wrapper" + graphId;
var graphWidth = $(chartWrapperElmId).width() - 50;
if (chartDataRaw.length == 0) {
$(chartWrapperElmId).html("No data available...");
return;
}
var chartDiv = "chart" + graphId;
var sliderDiv = "slider" + graphId;
var y_axis = "y_axis" + graphId;
$(chartWrapperElmId).html("").html('<div id = "' + y_axis + '" class="custom_y_axis"></div>' +
'<div class="legend_container" id="legend_container' +
graphId + '"><div id="smoother' + graphId +
'" title="Smoothing"></div><div class="legend" id="legend' +
graphId + '"></div></div><div id="' + chartDiv +
'" class="custom_rickshaw_graph"></div>' +
'<div class="custom_x_axis"></div><div id="' + sliderDiv +
'" class="custom_slider"></div>');
var graphConfig = {
element: document.getElementById(chartDiv),
width: graphWidth,
height: 50 * chartDataRaw.length,
strokeWidth: 0.5,
renderer: 'binary_bar',
offset: 'zero',
xScale: d3.time.scale(),
padding: {top: 0.2, left: 0.0, right: 0.0, bottom: 0.2},
series: []
};
var tzOffset = new Date().getTimezoneOffset() * 60;
for (var i = 0; i < chartDataRaw.length; i++) {
var chartData = [];
if (chartDataRaw[i].stats.length > 0) {
for (var j = 0; j < chartDataRaw[i].stats.length; j++) {
chartData.push({
x: parseInt(chartDataRaw[i].stats[j].time) - tzOffset,
y: parseInt(chartDataRaw[i].stats[j].value > 0 ? 1 : 0)
});
}
graphConfig['series'].push({
'color': palette.color(),
'data': summerizeBar(chartData),
'name': chartDataRaw[i].device
});
}
}
if (graphConfig['series'].length == 0) {
$(chartWrapperElmId).html("No data available...");
return;
}
var graph = new Rickshaw.Graph(graphConfig);
graph.registerRenderer(new Rickshaw.Graph.Renderer.BinaryBar({graph: graph}));
graph.render();
var xAxis = new Rickshaw.Graph.Axis.Time({
graph: graph
});
xAxis.render();
var yAxis = new Rickshaw.Graph.Axis.Y({
graph: graph,
orientation: 'left',
element: document.getElementById(y_axis),
width: 40,
height: 55 * chartDataRaw.length,
tickFormat: function (y) {
return '';
}
});
yAxis.render();
var slider = new Rickshaw.Graph.RangeSlider.Preview({
graph: graph,
element: document.getElementById(sliderDiv)
});
var legend = new Rickshaw.Graph.Legend({
graph: graph,
element: document.getElementById('legend' + graphId)
});
var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
graph: graph,
legend: legend
});
var order = new Rickshaw.Graph.Behavior.Series.Order({
graph: graph,
legend: legend
});
var highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({
graph: graph,
legend: legend
});
}
function scaleGraphs() {
var sliders = $('.right_handle');
if (sliders.length == 0) {
return;
}
var graphWidth = 0;
for (var i = 1; i < 10; i++) {
if ($('#canvas-wrapper' + i).length) {
graphWidth = $('#canvas-wrapper' + i).width() - 50;
break;
}
}
if (graphWidth <= 0) {
return;
}
//Scale graphs
var sliderX = graphWidth * 60 * 60000 / (toDate - fromDate);
if (sliderX < graphWidth) {
// fake handle move
if (sliderX < 50) {
sliderX = 50;
}
var edown = document.createEvent("HTMLEvents");
edown.initEvent("mousedown", true, true);
edown.clientX = graphWidth;
var emove = document.createEvent("HTMLEvents");
emove.initEvent("mousemove", true, true);
emove.clientX = sliderX;
var eup = document.createEvent("HTMLEvents");
eup.initEvent("mouseup", true, true);
for (var slider in sliders) {
sliders[slider].dispatchEvent(edown);
document.dispatchEvent(emove);
document.dispatchEvent(eup);
}
}
}
function convertDate(date) {
var month = date.getMonth() + 1;
var day = date.getDate();
var hour = date.getHours();
var minute = date.getMinutes();
return date.getFullYear() + '-' + (('' + month).length < 2 ? '0' : '') + month + '-' +
(('' + day).length < 2 ? '0' : '') + day + " " + (('' + hour).length < 2 ? '0' : '') +
hour + ":" + (('' + minute).length < 2 ? '0' : '') + minute;
}
function summerizeLine(data) {
if (data.length > 1500) {
var nData = [];
var i = 1;
while (i < data.length) {
var t_avg = (data[i - 1].x + data[i].x) / 2;
var v_avg = (data[i - 1].y + data[i].y) / 2;
nData.push({x: t_avg, y: v_avg});
i += 2;
}
return summerizeLine(nData);
} else {
return data;
}
}
function summerizeBar(data) {
if (data.length > 1500) {
var nData = [];
var i = 1;
while (i < data.length - 1) {
var t_avg = (data[i - 1].x + data[i].x) / 2;
var v_avg = (data[i - 1].y + data[i].y + data[i + 1].y) / 3;
nData.push({x: t_avg, y: Math.round(v_avg)});
i += 2;
}
return summerizeBar(nData);
} else {
return data;
}
}
function getQueryParams() {
var qs = document.location.search.split('+').join(' ');
var params = {},
tokens,
re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params;
}

@ -16,26 +16,6 @@
* under the License.
*/
/* ========================================================================
* methods/mixins
* ======================================================================== */
/* ========================================================================
* default values
* ======================================================================== */
@font-face {
font-family: "Roboto";
font-weight: 400;
font-style: "normal";
src: url("libs/theme-wso2_1.0/fonts/Roboto/Roboto-Regular.eot");
src: url("libs/theme-wso2_1.0/fonts/Roboto/Roboto-Regular.eot?#iefix") format("embedded-opentype"), local("Roboto Regular"), local("Roboto-Regular"), url("libs/theme-wso2_1.0/fonts/Roboto/Roboto-Regular.woff2") format("woff2"), url("libs/theme-wso2_1.0/fonts/Roboto/Roboto-Regular.woff") format("woff"), url("libs/theme-wso2_1.0/fonts/Roboto/Roboto-Regular.ttf") format("truetype"), url("libs/theme-wso2_1.0/fonts/Roboto/Roboto-Regular.svg#Roboto") format("svg");
}
/* ========================================================================
* loading fonts
* ======================================================================== */
/* ========================================================================
* icon styles
* ======================================================================== */
.icon-success {
color: #5cb85c;
}

@ -521,9 +521,9 @@ FROM
(SELECT
DM_DEVICE.ID AS DEVICE_ID,
DM_DEVICE_TYPE.NAME AS PLATFORM,
DM_ENROLMENT.OWNERSHIP AS OWNERSHIP,
DM_ENROLMENT.OWNERSHIP,
DM_ENROLMENT.STATUS AS CONNECTIVITY_STATUS,
DM_DEVICE.TENANT_ID AS TENANT_ID
DM_DEVICE.TENANT_ID
FROM DM_DEVICE, DM_DEVICE_TYPE, DM_ENROLMENT
WHERE DM_DEVICE.DEVICE_TYPE_ID = DM_DEVICE_TYPE.ID AND DM_DEVICE.ID = DM_ENROLMENT.DEVICE_ID) DEVICE_INFO
LEFT JOIN
@ -531,7 +531,30 @@ LEFT JOIN
DEVICE_ID,
POLICY_ID,
STATUS AS IS_COMPLIANT
FROM
DM_POLICY_COMPLIANCE_STATUS) DEVICE_WITH_POLICY_INFO
FROM DM_POLICY_COMPLIANCE_STATUS) DEVICE_WITH_POLICY_INFO
ON DEVICE_INFO.DEVICE_ID = DEVICE_WITH_POLICY_INFO.DEVICE_ID
ORDER BY DEVICE_INFO.DEVICE_ID;
CREATE VIEW DEVICES_VIEW_2 AS
SELECT
DM_DEVICE.ID AS DEVICE_ID,
DM_DEVICE_DETAIL.DEVICE_MODEL,
DM_DEVICE_DETAIL.VENDOR,
DM_DEVICE_DETAIL.OS_VERSION,
DM_ENROLMENT.OWNERSHIP,
DM_ENROLMENT.OWNER,
DM_ENROLMENT.STATUS AS CONNECTIVITY_STATUS,
DM_POLICY_COMPLIANCE_STATUS.POLICY_ID,
DM_DEVICE_TYPE.NAME AS PLATFORM,
DM_POLICY_COMPLIANCE_FEATURES.FEATURE_CODE,
DM_POLICY_COMPLIANCE_FEATURES.STATUS AS IS_COMPLAINT,
DM_DEVICE.TENANT_ID
FROM
DM_POLICY_COMPLIANCE_FEATURES, DM_POLICY_COMPLIANCE_STATUS, DM_ENROLMENT, DM_DEVICE, DM_DEVICE_TYPE, DM_DEVICE_DETAIL
WHERE
DM_POLICY_COMPLIANCE_FEATURES.COMPLIANCE_STATUS_ID = DM_POLICY_COMPLIANCE_STATUS.ID AND
DM_POLICY_COMPLIANCE_STATUS.ENROLMENT_ID = DM_ENROLMENT.ID AND
DM_POLICY_COMPLIANCE_STATUS.DEVICE_ID = DM_DEVICE.ID AND
DM_DEVICE.DEVICE_TYPE_ID = DM_DEVICE_TYPE.ID AND
DM_DEVICE.ID = DM_DEVICE_DETAIL.DEVICE_ID
ORDER BY TENANT_ID, DEVICE_ID;

Loading…
Cancel
Save