mirror of
https://repository.entgra.net/community/device-mgt-core.git
synced 2025-10-06 02:01:45 +00:00
Adding the store user interface. (#1084)
This commit is contained in:
parent
9c364e6631
commit
17bce6fed1
@ -0,0 +1,68 @@
|
||||
<%
|
||||
/*
|
||||
* Copyright (c) 2015, 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 log = new Log("api/data-tables-invoker-api.jag");
|
||||
|
||||
var uri = request.getRequestURI();
|
||||
var uriMatcher = new URIMatcher(String(uri));
|
||||
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
|
||||
function appendQueryParam (url, queryParam , value) {
|
||||
if (url.indexOf("?") > 0) {
|
||||
return url + "&" + queryParam + "=" + value;
|
||||
}
|
||||
return url + "?" + queryParam + "=" + value;
|
||||
}
|
||||
|
||||
if (uriMatcher.match("/{context}/api/data-tables/invoker")) {
|
||||
var url = request.getParameter("url");
|
||||
var targetURL = devicemgtProps["httpsURL"] + request.getParameter("url");
|
||||
//noinspection JSUnresolvedFunction getAllParameters
|
||||
var allParams = request.getAllParameters();
|
||||
|
||||
for (var allParamsKey in allParams) {
|
||||
if (allParams.hasOwnProperty(allParamsKey)) {
|
||||
if (allParamsKey == "limit" || allParamsKey == "offset") {
|
||||
targetURL = appendQueryParam(targetURL, allParamsKey, allParams[allParamsKey]);
|
||||
} else if (allParamsKey == "filter") {
|
||||
if (allParams[allParamsKey]) {
|
||||
var searchPayload = JSON.parse(allParams[allParamsKey]);
|
||||
for (var searchPayloadKey in searchPayload) {
|
||||
if (searchPayload.hasOwnProperty(searchPayloadKey)) {
|
||||
targetURL = appendQueryParam(targetURL, searchPayloadKey, searchPayload[searchPayloadKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serviceInvokers.XMLHttp.get(
|
||||
targetURL,
|
||||
// response callback
|
||||
function (backendResponse) {
|
||||
response["status"] = backendResponse["status"];
|
||||
response["content"] = utility.encodeJson(backendResponse["responseText"]);
|
||||
response["contentType"] = "application/json";
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,201 @@
|
||||
<%
|
||||
/*
|
||||
* 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 uri = request.getRequestURI();
|
||||
var uriMatcher = new URIMatcher(String(uri));
|
||||
|
||||
var log = new Log("api/device-api.jag");
|
||||
var constants = require("/app/modules/constants.js");
|
||||
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
|
||||
var utility = require("/app/modules/utility.js").utility;
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
|
||||
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
|
||||
|
||||
var user = session.get(constants.USER_SESSION_KEY);
|
||||
var result;
|
||||
|
||||
response.contentType = 'application/json';
|
||||
|
||||
if (!user) {
|
||||
response.sendRedirect("/devicemgt/login?#login-required");
|
||||
exit();
|
||||
} else {
|
||||
if (uriMatcher.match("/{context}/api/devices/sketch/download")) {
|
||||
// works as a proxy to pass the relavant query string to back end api.
|
||||
var queryString = request.getQueryString();
|
||||
if (!queryString) {
|
||||
queryString = "";
|
||||
} else {
|
||||
queryString = "?" + queryString;
|
||||
}
|
||||
var deviceType = request.getParameter("deviceType"); // need a better solution here
|
||||
deviceTypeConfig = utility.getDeviceTypeConfig(deviceType);
|
||||
if (deviceTypeConfig && deviceTypeConfig.deviceType.downloadAgentUri) {
|
||||
hearders = [{"name": constants["ACCEPT_IDENTIFIER"], "value": constants["APPLICATION_ZIP"]}];
|
||||
sketchDownloadEndPoint = devicemgtProps["httpsURL"] + "/" + deviceTypeConfig.deviceType.downloadAgentUri;
|
||||
serviceInvokers.HttpClient.get(sketchDownloadEndPoint + queryString, function (responsePayload, responseHeaders) {
|
||||
if (responseHeaders) {
|
||||
for (var i = 0; i < responseHeaders.length; i++) {
|
||||
var header = responseHeaders[i];
|
||||
var headerName = String(header.getName());
|
||||
var headerValue = String(header.getValue());
|
||||
response.addHeader(headerName, headerValue);
|
||||
}
|
||||
var streamObject = new Stream(responsePayload);
|
||||
print(streamObject);
|
||||
} else {
|
||||
return responsePayload;
|
||||
}
|
||||
}, function (responsePayload) {
|
||||
log.error(responsePayload);
|
||||
var response = {};
|
||||
response["status"] = "error";
|
||||
return response;
|
||||
}
|
||||
, hearders);
|
||||
} else {
|
||||
result = 400;
|
||||
}
|
||||
} else if (uriMatcher.match("/{context}/api/devices/all")) {
|
||||
result = deviceModule.getOwnDevices();
|
||||
|
||||
} else if (uriMatcher.match("/{context}/api/devices/count")) {
|
||||
var count = deviceModule.getOwnDevicesCount().data;
|
||||
result = count.toString();
|
||||
|
||||
} else if (uriMatcher.match("/{context}/api/devices/types")) {
|
||||
result = deviceModule.listDeviceTypes();
|
||||
|
||||
} else if (uriMatcher.match("/{context}/api/devices/{deviceType}/{deviceId}/remove")) {
|
||||
var elements = uriMatcher.elements();
|
||||
var deviceId = elements.deviceId;
|
||||
var deviceType = elements.deviceType;
|
||||
result = deviceModule.removeDevice(deviceType, deviceId);
|
||||
|
||||
} else if (uriMatcher.match("/{context}/api/devices/{deviceType}/{deviceId}/update")) {
|
||||
var elements = uriMatcher.elements();
|
||||
var deviceId = elements.deviceId;
|
||||
var deviceType = elements.deviceType;
|
||||
var deviceName = request.getParameter("name");
|
||||
result = deviceModule.updateDevice(deviceType, deviceId, deviceName);
|
||||
} else if (uriMatcher.match("/{context}/api/devices")) {
|
||||
var url = request.getParameter("url");
|
||||
var draw = request.getParameter("draw");
|
||||
var length = request.getParameter("length");
|
||||
var start = request.getParameter("start");
|
||||
var search = request.getParameter("search[value]");
|
||||
var deviceName = request.getParameter("columns[1][search][value]");
|
||||
var owner = request.getParameter("columns[2][search][value]");
|
||||
var status = request.getParameter("columns[3][search][value]");
|
||||
var platform = request.getParameter("columns[4][search][value]");
|
||||
var ownership = request.getParameter("columns[5][search][value]");
|
||||
var targetURL;
|
||||
|
||||
function appendQueryParam (url, queryParam , value) {
|
||||
if (url.indexOf("?") > 0) {
|
||||
return url + "&" + queryParam + "=" + value;
|
||||
}
|
||||
return url + "?" + queryParam + "=" + value;
|
||||
}
|
||||
targetURL = devicemgtProps.httpsURL + request.getParameter("url");
|
||||
targetURL = appendQueryParam(targetURL, "draw", draw);
|
||||
targetURL = appendQueryParam(targetURL, "start", start);
|
||||
targetURL = appendQueryParam(targetURL, "length", length);
|
||||
|
||||
if (search && search !== "") {
|
||||
targetURL = appendQueryParam(targetURL, "search", search);
|
||||
}
|
||||
|
||||
if (deviceName && deviceName !== "") {
|
||||
targetURL = appendQueryParam(targetURL, "device-name", deviceName);
|
||||
}
|
||||
|
||||
if (owner && owner !== "") {
|
||||
targetURL = appendQueryParam(targetURL, "user", owner);
|
||||
}
|
||||
|
||||
if (status && status !== "") {
|
||||
targetURL = appendQueryParam(targetURL, "status", status);
|
||||
}
|
||||
|
||||
if (platform && platform !== "") {
|
||||
targetURL = appendQueryParam(targetURL, "type", platform);
|
||||
}
|
||||
|
||||
if (ownership && ownership !== "") {
|
||||
targetURL = appendQueryParam(targetURL, "ownership", ownership);
|
||||
}
|
||||
|
||||
serviceInvokers.XMLHttp.get(
|
||||
targetURL, function (responsePayload) {
|
||||
response.status = 200;
|
||||
result = responsePayload;
|
||||
},
|
||||
function (responsePayload) {
|
||||
response.status = responsePayload.status;
|
||||
result = responsePayload.responseText;
|
||||
});
|
||||
} else if (uriMatcher.match("/{context}/api/devices/")) {
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/list")) {
|
||||
result = deviceModule.listDevices();
|
||||
} else {
|
||||
response.sendError(403);
|
||||
}
|
||||
} else if (uriMatcher.match("/{context}/api/devices/{type}/{deviceId}")) {
|
||||
elements = uriMatcher.elements();
|
||||
deviceId = elements.deviceId;
|
||||
type = elements.type;
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/list")) {
|
||||
result = deviceModule.viewDevice(type, deviceId);
|
||||
}else {
|
||||
response.sendError(403);
|
||||
}
|
||||
} else if (uriMatcher.match("/{context}/api/devices/agent/{type}/{deviceId}/config")) {
|
||||
elements = uriMatcher.elements();
|
||||
deviceId = elements.deviceId;
|
||||
type = elements.type;
|
||||
operation = elements.operation;
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device")) {
|
||||
result = deviceModule.getDeviceAgentConfig(type, deviceId);
|
||||
if (!result) {
|
||||
response.sendError(500);
|
||||
}
|
||||
} else {
|
||||
response.sendError(403);
|
||||
}
|
||||
} else if (uriMatcher.match("{context}/api/devices/{type}/{deviceId}/{operation}")) {
|
||||
elements = uriMatcher.elements();
|
||||
deviceId = elements.deviceId;
|
||||
type = elements.type;
|
||||
operation = elements.operation;
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/operation")) {
|
||||
result = deviceModule.performOperation(deviceId, operation, [], type);
|
||||
} else {
|
||||
response.sendError(403);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returning the result.
|
||||
if (result) {
|
||||
print(result);
|
||||
}
|
||||
|
||||
%>
|
||||
@ -0,0 +1,87 @@
|
||||
<%
|
||||
/*
|
||||
* 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 uri = request.getRequestURI();
|
||||
var uriMatcher = new URIMatcher(String(uri));
|
||||
|
||||
var log = new Log("api/device-api.jag");
|
||||
var constants = require("/app/modules/constants.js");
|
||||
var utility = require("/app/modules/utility.js").utility;
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
|
||||
|
||||
var user = session.get(constants.USER_SESSION_KEY);
|
||||
var result;
|
||||
|
||||
response.contentType = 'application/json';
|
||||
|
||||
if (!user) {
|
||||
response.sendRedirect("/devicemgt/login?#login-required");
|
||||
exit();
|
||||
} else {
|
||||
if (uriMatcher.match("/{context}/api/groups")) {
|
||||
var url = request.getParameter("url");
|
||||
var draw = request.getParameter("draw");
|
||||
var length = request.getParameter("length");
|
||||
var start = request.getParameter("start");
|
||||
var search = request.getParameter("search[value]");
|
||||
var groupName = request.getParameter("columns[1][search][value]");
|
||||
var owner = request.getParameter("columns[2][search][value]");
|
||||
var targetURL;
|
||||
|
||||
function appendQueryParam(url, queryParam, value) {
|
||||
if (url.indexOf("?") > 0) {
|
||||
return url + "&" + queryParam + "=" + value;
|
||||
}
|
||||
return url + "?" + queryParam + "=" + value;
|
||||
}
|
||||
|
||||
targetURL = devicemgtProps.httpsURL + request.getParameter("url");
|
||||
targetURL = appendQueryParam(targetURL, "start", start);
|
||||
targetURL = appendQueryParam(targetURL, "length", length);
|
||||
|
||||
if (search && search !== "") {
|
||||
targetURL = appendQueryParam(targetURL, "search", search);
|
||||
}
|
||||
|
||||
if (groupName && groupName !== "") {
|
||||
targetURL = appendQueryParam(targetURL, "group-name", groupName);
|
||||
}
|
||||
|
||||
if (owner && owner !== "") {
|
||||
targetURL = appendQueryParam(targetURL, "user", owner);
|
||||
}
|
||||
|
||||
serviceInvokers.XMLHttp.get(
|
||||
targetURL, function (responsePayload) {
|
||||
response.status = 200;
|
||||
result = responsePayload;
|
||||
},
|
||||
function (responsePayload) {
|
||||
response.status = responsePayload.status;
|
||||
result = responsePayload.responseText;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
print(result);
|
||||
}
|
||||
|
||||
%>
|
||||
@ -0,0 +1,119 @@
|
||||
<%
|
||||
/*
|
||||
* Copyright (c) 2015, 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 log = new Log("api/invoker-api.jag");
|
||||
|
||||
var uri = request.getRequestURI();
|
||||
var uriMatcher = new URIMatcher(String(uri));
|
||||
|
||||
var constants = require("/app/modules/constants.js");
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
|
||||
|
||||
if (uriMatcher.match("/{context}/api/invoker/execute/")) {
|
||||
//NOTE: We are only interested in Content-Type headers. Appending all request headers to the back-end call
|
||||
// will cause unforeseen security issues.
|
||||
var contentType = request.getHeader(constants.CONTENT_TYPE_IDENTIFIER);
|
||||
var acceptType = request.getHeader(constants.ACCEPT_IDENTIFIER);
|
||||
var requestHeaders = [];
|
||||
requestHeaders.push({"name": constants.CONTENT_TYPE_IDENTIFIER, "value" : contentType});
|
||||
requestHeaders.push({"name": constants.ACCEPT_IDENTIFIER, "value" : acceptType});
|
||||
|
||||
var restAPIRequestDetails = request.getContent();
|
||||
|
||||
var requestMethod = restAPIRequestDetails["requestMethod"];
|
||||
var requestURL = restAPIRequestDetails["requestURL"];
|
||||
var requestPayload = restAPIRequestDetails["requestPayload"];
|
||||
|
||||
if (!requestMethod) {
|
||||
requestMethod = parse(restAPIRequestDetails)["requestMethod"];
|
||||
}
|
||||
|
||||
if (!requestURL) {
|
||||
requestURL = parse(restAPIRequestDetails)["requestURL"];
|
||||
}
|
||||
|
||||
if (!requestPayload) {
|
||||
requestPayload = parse(restAPIRequestDetails)["requestPayload"];
|
||||
}
|
||||
|
||||
var restAPIEndpoint = devicemgtProps["httpsURL"] + requestURL;
|
||||
|
||||
try {
|
||||
switch (requestMethod) {
|
||||
case constants["HTTP_GET"]:
|
||||
serviceInvokers.XMLHttp.get(
|
||||
restAPIEndpoint,
|
||||
function (restAPIResponse) {
|
||||
response["status"] = restAPIResponse["status"];
|
||||
if (restAPIResponse["responseText"]) {
|
||||
response["content"] = restAPIResponse["responseText"];
|
||||
}
|
||||
},
|
||||
requestHeaders
|
||||
);
|
||||
break;
|
||||
case constants["HTTP_POST"]:
|
||||
serviceInvokers.XMLHttp.post(
|
||||
restAPIEndpoint,
|
||||
requestPayload,
|
||||
function (restAPIResponse) {
|
||||
response["status"] = restAPIResponse["status"];
|
||||
if (restAPIResponse["responseText"]) {
|
||||
response["content"] = restAPIResponse["responseText"];
|
||||
}
|
||||
},
|
||||
requestHeaders
|
||||
);
|
||||
break;
|
||||
case constants["HTTP_PUT"]:
|
||||
serviceInvokers.XMLHttp.put(
|
||||
restAPIEndpoint,
|
||||
requestPayload,
|
||||
function (restAPIResponse) {
|
||||
response["status"] = restAPIResponse["status"];
|
||||
if (restAPIResponse["responseText"]) {
|
||||
response["content"] = restAPIResponse["responseText"];
|
||||
}
|
||||
},
|
||||
requestHeaders
|
||||
);
|
||||
break;
|
||||
case constants["HTTP_DELETE"]:
|
||||
serviceInvokers.XMLHttp.delete(
|
||||
restAPIEndpoint,
|
||||
function (restAPIResponse) {
|
||||
response["status"] = restAPIResponse["status"];
|
||||
if (restAPIResponse["responseText"]) {
|
||||
response["content"] = restAPIResponse["responseText"];
|
||||
}
|
||||
},
|
||||
requestHeaders
|
||||
);
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
//Since this is an API we'll log the error message.
|
||||
log.error(e.message); // JavaScript error message
|
||||
log.error(e.stack); // Executed JavaScript file stack
|
||||
throw new Error("Exception occurred while trying to access " +
|
||||
"backend REST API services from Jaggery API invoker layer", e);
|
||||
}
|
||||
}
|
||||
%>
|
||||
@ -0,0 +1,66 @@
|
||||
<%
|
||||
/*
|
||||
* Copyright (c) 2015, 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 uri = request.getRequestURI();
|
||||
var uriMatcher = new URIMatcher(String(uri));
|
||||
|
||||
var log = new Log("api/operation-api.jag");
|
||||
|
||||
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
|
||||
if (uriMatcher.match("/{context}/api/operation/paginate")) {
|
||||
var deviceType = request.getParameter("deviceType");
|
||||
var deviceId = request.getParameter("deviceId");
|
||||
var owner = request.getParameter("owner");
|
||||
var index = request.getParameter("start");
|
||||
var length = request.getParameter("length");
|
||||
var search = request.getParameter("search[value]");
|
||||
|
||||
var restAPIEndpoint = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] +
|
||||
"/devices/" + deviceType + "/" + deviceId + "/operations?owner=" + owner + "&offset=" + index + "&limit=" + length;
|
||||
|
||||
serviceInvokers.XMLHttp.get(
|
||||
restAPIEndpoint,
|
||||
function (restAPIResponse) {
|
||||
if (restAPIResponse["status"] == 200 && restAPIResponse["responseText"]) {
|
||||
var responsePayload = parse(restAPIResponse["responseText"]);
|
||||
|
||||
var paginatedResult = {};
|
||||
paginatedResult["recordsTotal"] = responsePayload["count"];
|
||||
paginatedResult["recordsFiltered"] = responsePayload["count"];
|
||||
paginatedResult["data"] = responsePayload["operations"];
|
||||
|
||||
response["status"] = restAPIResponse["status"];
|
||||
response["content"] = paginatedResult;
|
||||
} else {
|
||||
response["status"] = restAPIResponse["status"];
|
||||
if (restAPIResponse["responseText"]) {
|
||||
var responseText = "";
|
||||
try {
|
||||
response["content"] = parse(restAPIResponse["responseText"]);
|
||||
} catch (e) {
|
||||
responseText = restAPIResponse["responseText"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
%>
|
||||
@ -0,0 +1,52 @@
|
||||
<%
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
@Deprecated
|
||||
*/
|
||||
|
||||
var uri = request.getRequestURI();
|
||||
var uriMatcher = new URIMatcher(String(uri));
|
||||
|
||||
var log = new Log("api/policy-api.jag");
|
||||
|
||||
var constants = require("/modules/constants.js");
|
||||
var policyModule = require("/app/modules/business-controllers/group.js")["groupModule"];
|
||||
|
||||
var result;
|
||||
if (uriMatcher.match("/{context}/api/policies/update")) {
|
||||
payload = request.getContent();
|
||||
policyModule.updatePolicyPriorities(payload);
|
||||
} else if (uriMatcher.match("/{context}/api/policies/{id}/delete")) {
|
||||
elements = uriMatcher.elements();
|
||||
policyId = elements.id;
|
||||
try {
|
||||
result = policyModule.deletePolicy(policyId);
|
||||
} catch (e) {
|
||||
log.error("Exception occurred while trying to delete policy for id:" + policyId, e);
|
||||
// http status code 500 refers to - Internal Server Error.
|
||||
result = 500;
|
||||
}
|
||||
}
|
||||
|
||||
// returning the result.
|
||||
if (result) {
|
||||
response.content = result;
|
||||
}
|
||||
%>
|
||||
@ -0,0 +1,77 @@
|
||||
<%
|
||||
/*
|
||||
* Copyright (c) 2015, 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 uri = request.getRequestURI();
|
||||
var uriMatcher = new URIMatcher(String(uri));
|
||||
|
||||
var log = new Log("api/stats-api.jag");
|
||||
|
||||
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
|
||||
if (uriMatcher.match("/{context}/api/stats/paginate")) {
|
||||
var deviceType = request.getParameter("deviceType");
|
||||
var deviceId = request.getParameter("deviceId");
|
||||
var from = request.getParameter("from");
|
||||
var to = request.getParameter("to");
|
||||
var index = request.getParameter("start");
|
||||
var length = request.getParameter("length");
|
||||
var keys = request.getParameter("attributes");
|
||||
keys = JSON.parse(keys);
|
||||
var restAPIEndpoint = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/events/"
|
||||
+ deviceType + "/" + deviceId + "?offset=" + index +"&limit=" + length + "&from="+ from + "&to=" + to;
|
||||
serviceInvokers.XMLHttp.get(
|
||||
restAPIEndpoint,
|
||||
function (restAPIResponse) {
|
||||
if (restAPIResponse["status"] == 200 && restAPIResponse["responseText"]) {
|
||||
var responsePayload = parse(restAPIResponse["responseText"]);
|
||||
|
||||
var paginatedResult = {};
|
||||
paginatedResult["recordsTotal"] = responsePayload["count"];
|
||||
paginatedResult["recordsFiltered"] = responsePayload["count"];
|
||||
var records = responsePayload["records"];
|
||||
var dataSet = [];
|
||||
for (var i = 0; i < records.length; i++){
|
||||
var record = records[i];
|
||||
var timestamp = record["timestamp"];
|
||||
var dataRow = [];
|
||||
dataRow.push(timestamp);
|
||||
for (var j = 0; j < keys.length; j++) {
|
||||
var key = keys[j];
|
||||
dataRow.push(record.values[key]);
|
||||
}
|
||||
//dataSet.push(dataRow);
|
||||
dataSet.push(dataRow);
|
||||
}
|
||||
paginatedResult["data"] = dataSet;
|
||||
response["status"] = restAPIResponse["status"];
|
||||
response["content"] = paginatedResult;
|
||||
} else {
|
||||
response["status"] = 204;
|
||||
var paginatedResult = {};
|
||||
var dataSet = [];
|
||||
paginatedResult["recordsTotal"] = 0;
|
||||
paginatedResult["recordsFiltered"] = 0;
|
||||
paginatedResult["data"] = dataSet;
|
||||
response["content"] = paginatedResult;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
%>
|
||||
@ -0,0 +1,206 @@
|
||||
<%
|
||||
/*
|
||||
* Copyright (c) 2015, 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 uri = request.getRequestURI();
|
||||
var uriMatcher = new URIMatcher(String(uri));
|
||||
|
||||
var log = new Log("api/user-api.jag");
|
||||
|
||||
var constants = require("/app/modules/constants.js");
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
|
||||
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
var apiWrapperUtil = require("/app/modules/oauth/token-handlers.js")["handlers"];
|
||||
var util = require("/app/modules/oauth/token-handler-utils.js")["utils"];
|
||||
|
||||
var responseProcessor = require("utils").response;
|
||||
|
||||
var result;
|
||||
|
||||
if (uriMatcher.match("/{context}/api/user/authenticate")) {
|
||||
var username = request.getParameter("username");
|
||||
var password = request.getParameter("password");
|
||||
//Check if a username and password is provided
|
||||
if ((!username) || (!password)) {
|
||||
response = responseProcessor.buildErrorResponse(response, 400, 'Username and Password must be provided');
|
||||
} else {
|
||||
try {
|
||||
userModule.login(username, password, function (user) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("User Logged In : " + user);
|
||||
}
|
||||
apiWrapperUtil.setupTokenPairByPasswordGrantType(username, password);
|
||||
}, function () {
|
||||
response = responseProcessor.buildSuccessResponse(response, 200, {'sessionId': session.getId()});
|
||||
});
|
||||
} catch (e) {
|
||||
log.error("Exception occurred while a user tried to login to MDM", e);
|
||||
response = responseProcessor.buildErrorResponse(response, 401, 'username/password is incorrect');
|
||||
}
|
||||
}
|
||||
} else if (uriMatcher.match("/{context}/api/user/login/")) {
|
||||
username = request.getParameter("username");
|
||||
password = request.getParameter("password");
|
||||
username = util.decode(username);
|
||||
password = util.decode(password);
|
||||
try {
|
||||
userModule.login(username, password, function (user) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("User Logged In : " + user);
|
||||
}
|
||||
|
||||
apiWrapperUtil.setupTokenPairByPasswordGrantType(username, password);
|
||||
var permissions = userModule.getUIPermissions();
|
||||
if (permissions.VIEW_DASHBOARD) {
|
||||
response.sendRedirect(devicemgtProps["appContext"]);
|
||||
} else {
|
||||
response.sendRedirect(devicemgtProps["appContext"] + "devices");
|
||||
}
|
||||
}, function () {
|
||||
response.sendRedirect(devicemgtProps.appContext + "login?#auth-failed");
|
||||
});
|
||||
} catch (e) {
|
||||
log.error("Exception occurred while a user tried to login to MDM", e);
|
||||
response.sendRedirect(devicemgtProps.appContext + "login?#error");
|
||||
}
|
||||
} else if (uriMatcher.match("/{context}/api/user/logout/")) {
|
||||
userModule.logout(function () {
|
||||
response.sendRedirect(devicemgtProps.appContext + "login");
|
||||
});
|
||||
} else if (uriMatcher.match("/{context}/api/user/devices/")) {
|
||||
/*
|
||||
@Deprecated
|
||||
*/
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/user/devices/list")) {
|
||||
carbonUser = session.get(constants.USER_SESSION_KEY);
|
||||
result = deviceModule.listDevicesForUser(carbonUser.username);
|
||||
} else {
|
||||
response.sendError(403);
|
||||
}
|
||||
} else if (uriMatcher.match("/{context}/api/user/{username}/invite")) {
|
||||
/*
|
||||
@Deprecated
|
||||
*/
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/user/invite")) {
|
||||
elements = uriMatcher.elements();
|
||||
username = elements.username;
|
||||
userModule.inviteUser(username);
|
||||
} else {
|
||||
response.sendError(403);
|
||||
}
|
||||
} else if (uriMatcher.match("/{context}/api/user/add")) {
|
||||
/*
|
||||
@Deprecated
|
||||
*/
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/user/add")) {
|
||||
addUserFormData = request.getContent();
|
||||
username = addUserFormData.username;
|
||||
firstname = addUserFormData.firstname;
|
||||
lastname = addUserFormData.lastname;
|
||||
emailAddress = addUserFormData.emailAddress;
|
||||
|
||||
if (!addUserFormData.userRoles) {
|
||||
userRoles = null;
|
||||
} else {
|
||||
userRoles = String(addUserFormData.userRoles).split(",");
|
||||
}
|
||||
if (username.length < devicemgtProps.userValidationConfig.usernameLength) {
|
||||
log.error("Username Must be between 1 and " + devicemgtProps.userValidationConfig.usernameLength + " characters long");
|
||||
result = "Username Must be between 1 and " + devicemgtProps.userValidationConfig.usernameLength + " characters long";
|
||||
} else {
|
||||
try {
|
||||
result = userModule.addUser(username, firstname, lastname, emailAddress, userRoles);
|
||||
} catch (e) {
|
||||
log.error("Exception occurred while trying to add a user to MDM User Store", e);
|
||||
// http status code 400 refers to - Bad request.
|
||||
result = 400;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// http status code 403 refers to - forbidden.
|
||||
result = 403;
|
||||
}
|
||||
} else if (uriMatcher.match("/{context}/api/user/register")) {
|
||||
|
||||
addUserFormData = request.getContent();
|
||||
username = addUserFormData.username;
|
||||
firstname = addUserFormData.firstname;
|
||||
lastname = addUserFormData.lastname;
|
||||
emailAddress = addUserFormData.emailAddress;
|
||||
password = addUserFormData.password;
|
||||
userRoles = ["internal/devicemgt-user"];
|
||||
|
||||
try {
|
||||
result = userModule.registerUser(username, firstname, lastname, emailAddress, password,
|
||||
userRoles);
|
||||
} catch (e) {
|
||||
log.error("Exception occurred while trying to registering a new user to DC User Store", e);
|
||||
// http status code 400 refers to - Bad request.
|
||||
result = 400;
|
||||
}
|
||||
|
||||
} else if (uriMatcher.match("/{context}/api/user/{username}/remove")) {
|
||||
/*
|
||||
@Deprecated
|
||||
*/
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/user/remove")) {
|
||||
elements = uriMatcher.elements();
|
||||
username = elements.username;
|
||||
try {
|
||||
result = userModule.removeUser(username);
|
||||
} catch (e) {
|
||||
log.error("Exception occurred while trying to remove a user from MDM User Store", e);
|
||||
// http status code 400 refers to - Bad request.
|
||||
result = 400;
|
||||
}
|
||||
} else {
|
||||
// http status code 403 refers to - forbidden.
|
||||
result = 403;
|
||||
}
|
||||
} else if (uriMatcher.match("/{context}/api/user/all")) {
|
||||
result = userModule.getUsers();
|
||||
} else if (uriMatcher.match("/{context}/api/user/environment-loaded")) {
|
||||
try {
|
||||
var carbonUser = session.get(constants.USER_SESSION_KEY);
|
||||
if (!carbonUser) {
|
||||
response.sendRedirect("/devicemgt/login?#login-required");
|
||||
exit();
|
||||
}
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var APIManagementProviderService = utility.getAPIManagementProviderService();
|
||||
var isLoaded = APIManagementProviderService.isTierLoaded();
|
||||
result = {"isLoaded": isLoaded};
|
||||
if (isLoaded) {
|
||||
var samlToken = session.get(constants.SAML_TOKEN_KEY);
|
||||
if (samlToken) {
|
||||
apiWrapperUtil.setupTokenPairByJWTGrantType(carbonUser.username + '@' + carbonUser.domain, samlToken);
|
||||
}
|
||||
}
|
||||
response.contentType = 'application/json';
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
}
|
||||
|
||||
// returning the result.
|
||||
if (result) {
|
||||
print(result);
|
||||
}
|
||||
%>
|
||||
@ -0,0 +1,45 @@
|
||||
{
|
||||
"appName": "WSO2 IoT Server",
|
||||
"cachingEnabled": false,
|
||||
"debuggingEnabled": false,
|
||||
"permissionRoot": "/",
|
||||
"portalURL": "https://${server.ip}:9445",
|
||||
"loginPage": "cdmf.page.sign-in",
|
||||
"adminServicesUrl": "https://${server.ip}:${server.https_port}/admin/services/",
|
||||
"authModule": {
|
||||
"enabled": true,
|
||||
"login": {
|
||||
"onSuccess": {
|
||||
"script": "/app/modules/login.js",
|
||||
"page": "cdmf.page.processing"
|
||||
},
|
||||
"onFail": {
|
||||
"script": "/app/modules/login.js",
|
||||
"page": "cdmf.page.sign-in"
|
||||
}
|
||||
},
|
||||
"logout": {
|
||||
"onSuccess": {
|
||||
"page": "cdmf.page.sign-in"
|
||||
},
|
||||
"onFail": {
|
||||
"page": "cdmf.page.dashboard"
|
||||
}
|
||||
},
|
||||
"sso": {
|
||||
"enabled": true,
|
||||
"issuer" : "devicemgt",
|
||||
"appName" : "devicemgt",
|
||||
"identityProviderUrl" : "https://%iot.keymanager.host%:%iot.keymanager.https.port%/samlsso",
|
||||
"acs": "https://%iot.manager.host%:%iot.manager.https.port%/devicemgt/uuf/sso/acs",
|
||||
"identityAlias": "wso2carbon",
|
||||
"responseSigningEnabled" : true,
|
||||
"validateAssertionValidityPeriod": true,
|
||||
"validateAudienceRestriction": true,
|
||||
"assertionSigningEnabled": true
|
||||
}
|
||||
},
|
||||
"errorPages": {
|
||||
"default": "uuf.page.error"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,159 @@
|
||||
{
|
||||
"appContext": "/devicemgt/",
|
||||
"isCloud": false,
|
||||
"isDeviceOwnerEnabled": false,
|
||||
"httpsURL": "https://%iot.gateway.host%:%iot.gateway.https.port%",
|
||||
"httpURL": "http://%iot.gateway.host%:%iot.gateway.http.port%",
|
||||
"wssURL": "https://%iot.analytics.host%:%iot.analytics.https.port%",
|
||||
"portalURL": "https://%iot.analytics.host%:%iot.analytics.https.port%",
|
||||
"dashboardServerURL": "%https.ip%",
|
||||
"androidEnrollmentDir": "/android-web-agent/enrollment",
|
||||
"windowsEnrollmentDir": "/windows-web-agent/enrollment",
|
||||
"iOSEnrollmentDir": "/ios-web-agent/enrollment",
|
||||
"iOSConfigRoot": "%https.ip%/ios-enrollment/",
|
||||
"iOSAPIRoot": "%https.ip%/ios/",
|
||||
"adminService": "%https.ip%",
|
||||
"gatewayEnabled": true,
|
||||
"oauthProvider": {
|
||||
"appRegistration": {
|
||||
"appType": "webapp",
|
||||
"clientName": "iot_ui",
|
||||
"owner": "admin@carbon.super",
|
||||
"dynamicClientAppRegistrationServiceURL": "%https.ip%/dynamic-client-web/register",
|
||||
"apiManagerClientAppRegistrationServiceURL": "https://%iot.gateway.host%:%iot.gateway.https.port%/api-application-registration/register/tenants",
|
||||
"grantType": "password refresh_token urn:ietf:params:oauth:grant-type:saml2-bearer urn:ietf:params:oauth:grant-type:jwt-bearer",
|
||||
"tokenScope": "admin",
|
||||
"callbackUrl": "%https.ip%/api/device-mgt/v1.0",
|
||||
"samlGrantTypeName": "urn:ietf:params:oauth:grant-type:saml2-bearer"
|
||||
},
|
||||
"tokenServiceURL": "https://%iot.gateway.host%:%iot.gateway.https.port%/token"
|
||||
},
|
||||
"adminUser": "admin@carbon.super",
|
||||
"adminUserTenantId": "-1234",
|
||||
"adminRole": "admin",
|
||||
"userValidationConfig": {
|
||||
"usernameLength": 30,
|
||||
"usernameJSRegEx": "^[\\S]{3,30}$",
|
||||
"usernameRegExViolationErrorMsg": "Provided username is invalid.",
|
||||
"usernameHelpMsg": "Should be in minimum 3 characters long and do not include any whitespaces.",
|
||||
"firstnameJSRegEx": "^.{3,30}$",
|
||||
"firstnameRegExViolationErrorMsg": "Provided first name is invalid.",
|
||||
"lastnameJSRegEx": "^.{3,30}$",
|
||||
"lastnameRegExViolationErrorMsg": "Provided last name is invalid.",
|
||||
"emailJSRegEx": "/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/",
|
||||
"emailRegExViolationErrorMsg": "Provided email is invalid."
|
||||
},
|
||||
"groupValidationConfig": {
|
||||
"groupNameJSRegEx": "^[\\S]{3,30}$",
|
||||
"groupNameRegExViolationErrorMsg": "Provided group name is invalid.",
|
||||
"groupNameHelpMsg": "Should be in minimum 3 characters long and should not include any whitespaces."
|
||||
},
|
||||
"roleValidationConfig": {
|
||||
"roleNameJSRegEx": "^[\\S]{3,30}$",
|
||||
"roleNameRegExViolationErrorMsg": "Provided role name is invalid.",
|
||||
"roleNameHelpMsg": "should be in minimum 3 characters long and do not include any whitespaces."
|
||||
},
|
||||
"generalConfig": {
|
||||
"host": "%http.ip%",
|
||||
"companyName": "WSO2 Carbon Device Manager",
|
||||
"browserTitle": "WSO2 Device Manager",
|
||||
"copyrightPrefix": "\u00A9 %date-year%, ",
|
||||
"copyrightOwner": "WSO2 Inc.",
|
||||
"copyrightOwnersSite": "http://www.wso2.org",
|
||||
"copyrightSuffix": " All Rights Reserved."
|
||||
},
|
||||
"scopes": [
|
||||
"perm:sign-csr",
|
||||
"perm:admin:devices:view",
|
||||
"perm:roles:add",
|
||||
"perm:roles:add-users",
|
||||
"perm:roles:update",
|
||||
"perm:roles:permissions",
|
||||
"perm:roles:details",
|
||||
"perm:roles:view",
|
||||
"perm:roles:create-combined-role",
|
||||
"perm:roles:delete",
|
||||
"perm:dashboard:vulnerabilities",
|
||||
"perm:dashboard:non-compliant-count",
|
||||
"perm:dashboard:non-compliant",
|
||||
"perm:dashboard:by-groups",
|
||||
"perm:dashboard:device-counts",
|
||||
"perm:dashboard:feature-non-compliant",
|
||||
"perm:dashboard:count-overview",
|
||||
"perm:dashboard:filtered-count",
|
||||
"perm:dashboard:details",
|
||||
"perm:get-activity",
|
||||
"perm:devices:delete",
|
||||
"perm:devices:applications",
|
||||
"perm:devices:effective-policy",
|
||||
"perm:devices:compliance-data",
|
||||
"perm:devices:features",
|
||||
"perm:devices:operations",
|
||||
"perm:devices:search",
|
||||
"perm:devices:details",
|
||||
"perm:devices:update",
|
||||
"perm:devices:view",
|
||||
"perm:view-configuration",
|
||||
"perm:manage-configuration",
|
||||
"perm:policies:remove",
|
||||
"perm:policies:priorities",
|
||||
"perm:policies:deactivate",
|
||||
"perm:policies:get-policy-details",
|
||||
"perm:policies:manage",
|
||||
"perm:policies:activate",
|
||||
"perm:policies:update",
|
||||
"perm:policies:changes",
|
||||
"perm:policies:get-details",
|
||||
"perm:users:add",
|
||||
"perm:users:details",
|
||||
"perm:users:count",
|
||||
"perm:users:delete",
|
||||
"perm:users:roles",
|
||||
"perm:users:user-details",
|
||||
"perm:users:credentials",
|
||||
"perm:users:search",
|
||||
"perm:users:is-exist",
|
||||
"perm:users:update",
|
||||
"perm:users:send-invitation",
|
||||
"perm:admin-users:view",
|
||||
"perm:groups:devices",
|
||||
"perm:groups:update",
|
||||
"perm:groups:add",
|
||||
"perm:groups:device",
|
||||
"perm:groups:devices-count",
|
||||
"perm:groups:remove",
|
||||
"perm:groups:groups",
|
||||
"perm:groups:groups-view",
|
||||
"perm:groups:share",
|
||||
"perm:groups:count",
|
||||
"perm:groups:roles",
|
||||
"perm:groups:devices-remove",
|
||||
"perm:groups:devices-add",
|
||||
"perm:groups:assign",
|
||||
"perm:device-types:features",
|
||||
"perm:device-types:types",
|
||||
"perm:applications:install",
|
||||
"perm:applications:uninstall",
|
||||
"perm:admin-groups:count",
|
||||
"perm:admin-groups:view",
|
||||
"perm:notifications:mark-checked",
|
||||
"perm:notifications:view",
|
||||
"perm:admin:certificates:delete",
|
||||
"perm:admin:certificates:details",
|
||||
"perm:admin:certificates:view",
|
||||
"perm:admin:certificates:add",
|
||||
"perm:admin:certificates:verify",
|
||||
"perm:admin",
|
||||
"perm:devicetype:deployment",
|
||||
"perm:device-types:events",
|
||||
"perm:device-types:events:view",
|
||||
"perm:admin:device-type",
|
||||
"perm:device:enroll",
|
||||
"perm:geo-service:analytics-view",
|
||||
"perm:geo-service:alerts-manage"
|
||||
],
|
||||
"isOAuthEnabled": true,
|
||||
"backendRestEndpoints": {
|
||||
"deviceMgt": "/api/device-mgt/v1.0"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,138 @@
|
||||
{
|
||||
"Logo": {
|
||||
"name": "Cloud",
|
||||
"url": "https://cloudmgt.cloud.wso2.com/cloudmgt",
|
||||
"target": "_parent"
|
||||
},
|
||||
"Main": {
|
||||
"Domain": {
|
||||
"url": "#",
|
||||
"icon": "fw fw-organization",
|
||||
"isAdminOnly": false,
|
||||
"target": "_parent",
|
||||
"dropDown": {
|
||||
"Organization": {
|
||||
"url": "https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/organization.jag",
|
||||
"icon": "fw fw-organization",
|
||||
"dropDown": "false",
|
||||
"target": "_self"
|
||||
},
|
||||
"Members": {
|
||||
"url": "https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/user.jag",
|
||||
"icon": "fa fa-users",
|
||||
"dropDown": "false",
|
||||
"target": "_self"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Account": {
|
||||
"url": "#",
|
||||
"icon": "fw fw-resource",
|
||||
"isAdminOnly": false,
|
||||
"billingEnabled": true,
|
||||
"billingApi": {
|
||||
"username": "admin",
|
||||
"password": "admin"
|
||||
},
|
||||
"cloudMgtHost" : "https://cloudmgt.cloudstaging.wso2.com",
|
||||
"cloudMgtIndexPage": "https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/index.jag",
|
||||
"dropDown": {
|
||||
"Upgrade Now": {
|
||||
"url": "https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/payment-plans.jag?cloud-type=device_cloud",
|
||||
"icon": "fw fw-export",
|
||||
"dropDown": "true",
|
||||
"target": "_self"
|
||||
},
|
||||
"Request Extension": {
|
||||
"url": "https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/contact-us.jag?cloud-type=device_cloud&request-extension=true",
|
||||
"icon": "fa fa-mail",
|
||||
"dropDown": "true",
|
||||
"target": "_self"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Support": {
|
||||
"url": "https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/contact-us.jag?cloud-type=device_cloud",
|
||||
"icon": "fw fw-mail",
|
||||
"isAdminOnly": false,
|
||||
"target": "_self",
|
||||
"dropDown": "false"
|
||||
},
|
||||
"Documentation": {
|
||||
"url": "#",
|
||||
"icon": "fw fw-document",
|
||||
"isAdminOnly": false,
|
||||
"dropDown": {
|
||||
"Device Cloud": {
|
||||
"id": "device_cloud",
|
||||
"url": "https://docs.wso2.com/display/DeviceCloud/WSO2+Device+Cloud+Documentation",
|
||||
"icon": "fw fw-mobile",
|
||||
"target": "_blank"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"User": {
|
||||
"url": "#",
|
||||
"icon": "fw fw-user",
|
||||
"dropDown": {
|
||||
"Profile": {
|
||||
"url": "https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/user-profile.jag",
|
||||
"icon": "fw fw-user",
|
||||
"dropDown": "true",
|
||||
"target": "_self"
|
||||
},
|
||||
"Change Password": {
|
||||
"url": "https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/change-password.jag",
|
||||
"icon": "fw fw-lock",
|
||||
"dropDown": "true",
|
||||
"target": "_self"
|
||||
},
|
||||
"Logout": {
|
||||
"url": "https://device.cloud.wso2.com/devicemgt/logout",
|
||||
"icon": "fw fw-sign-out",
|
||||
"dropDown": "true",
|
||||
"target": "_self"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Expand": {
|
||||
"Clouds": {
|
||||
"API Cloud": {
|
||||
"id": "api_cloud",
|
||||
"url": "https://api.cloud.wso2.com/publisher",
|
||||
"icon": "fw fw-api fw-3x",
|
||||
"dropDown": "true",
|
||||
"target": "_self"
|
||||
},
|
||||
"Integration Cloud": {
|
||||
"id": "integration_cloud",
|
||||
"url": "https://integration.cloud.wso2.com/appmgt",
|
||||
"icon": "fw fw-service fw-3x",
|
||||
"dropDown": "true",
|
||||
"target": "_self"
|
||||
},
|
||||
"Identity Cloud": {
|
||||
"id": "integration_cloud",
|
||||
"url": "https://identity.cloud.wso2.com/admin",
|
||||
"icon": "fw fw-security fw-3x",
|
||||
"dropDown": "true",
|
||||
"target": "_self"
|
||||
}
|
||||
},
|
||||
"Actions": {
|
||||
"Organization": {
|
||||
"url": "https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/organization.jag",
|
||||
"icon": "fw fw-organization fw-3x",
|
||||
"dropDown": "true",
|
||||
"target": "_self"
|
||||
},
|
||||
"Members": {
|
||||
"url": "https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/user.jag",
|
||||
"icon": "fa fa-users fa-3x",
|
||||
"dropDown": "true",
|
||||
"target": "_self"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"displayName": "UUF Template App",
|
||||
"logLevel": "debug"
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
{{!-- Copyright (c) 2015, 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. --}}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{{defineZone "favicon"}}
|
||||
<title>
|
||||
{{defineZone "title"}}
|
||||
</title>
|
||||
{{defineZone "topLibCss"}}
|
||||
{{defineZone "topCss"}}
|
||||
{{defineZone "topJs"}}
|
||||
</head>
|
||||
<body>
|
||||
<!--modal-->
|
||||
<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="modalDemo">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content clearfix">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fw fw-cancel"></i></button>
|
||||
</div>
|
||||
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--modal-->
|
||||
|
||||
{{defineZone "header"}}
|
||||
|
||||
{{defineZone "sidePanes"}}
|
||||
|
||||
<!-- page-content-wrapper -->
|
||||
<div class="page-content-wrapper">
|
||||
|
||||
<div class="navbar-wrapper">
|
||||
{{defineZone "navbars"}}
|
||||
</div>
|
||||
|
||||
{{!defineZone "contentTitle"}}
|
||||
|
||||
<div class="container-fluid ">
|
||||
<div class="body-wrapper">
|
||||
{{defineZone "content"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /page-content-wrapper -->
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container-fluid">
|
||||
{{defineZone "footer"}}
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{{defineZone "bottomModalContent"}}
|
||||
{{defineZone "bottomLibJs"}}
|
||||
{{defineZone "bottomJs"}}
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,48 @@
|
||||
{{!-- Copyright (c) 2015, 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. --}}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='UTF-8'>
|
||||
<link rel="stylesheet" href="https://error.cloud.wso2.com/style/style.css">
|
||||
<link rel="stylesheet" href="https://error.cloud.wso2.com/style/font-mf.css">
|
||||
<title>
|
||||
{{defineZone "title"}}
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="sky">
|
||||
<section>
|
||||
<div class="error-400">
|
||||
<img src="https://error.cloud.wso2.com/images/400-error.svg">
|
||||
</div>
|
||||
<div class="text-label">
|
||||
<h1>{{#defineZone "messageTitle"}}Oops something went wrong{{/defineZone}}</h1>
|
||||
<h2>{{defineZone "messageDescription"}}</h2>
|
||||
<div style="clear: both"></div>
|
||||
<div class="button-label">
|
||||
<a href="https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/index.jag"><label class="label-back">Back to Cloud </label></a>
|
||||
<a href="https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/contact-us.jag"><label class="label-report"> Report Issue </label></a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="clouds_one"></div>
|
||||
<div class="clouds_two"></div>
|
||||
<div class="clouds_three"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,57 @@
|
||||
{{!-- Copyright (c) 2015, 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. --}}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{{defineZone "favicon"}}
|
||||
<title>
|
||||
{{defineZone "title"}}
|
||||
</title>
|
||||
{{defineZone "topLibCss"}}
|
||||
{{defineZone "topCss"}}
|
||||
{{defineZone "topJs"}}
|
||||
</head>
|
||||
<body>
|
||||
<!--modal-->
|
||||
<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="modalDemo">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content clearfix">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fw fw-cancel"></i></button>
|
||||
</div>
|
||||
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--modal-->
|
||||
|
||||
{{defineZone "content"}}
|
||||
|
||||
{{defineZone "bottomModalContent"}}
|
||||
{{defineZone "bottomLibJs"}}
|
||||
{{defineZone "bottomJs"}}
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,67 @@
|
||||
{{!--
|
||||
* 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.
|
||||
--}}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>{{#defineZone "title"}}WSO2 Template{{/defineZone}}</title>
|
||||
{{defineZone "favicon"}}
|
||||
{{defineZone "topCss"}}
|
||||
{{defineZone "topJs"}}
|
||||
</head>
|
||||
<body>
|
||||
<!-- header -->
|
||||
{{defineZone "header"}}
|
||||
<!-- /header -->
|
||||
|
||||
<!-- navbars -->
|
||||
<div class="navbar-wrapper">
|
||||
{{defineZone "navbars"}}
|
||||
</div>
|
||||
<!-- /navbars -->
|
||||
|
||||
<!-- sidepanes -->
|
||||
{{defineZone "sidePanes"}}
|
||||
<!-- /sidepanes -->
|
||||
|
||||
<!-- page-content-wrapper -->
|
||||
<div class="page-content-wrapper">
|
||||
{{defineZone "contentTitle"}}
|
||||
<div class="container-fluid ">
|
||||
<div class="body-wrapper">
|
||||
{{defineZone "content"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /page-content-wrapper -->
|
||||
|
||||
<!-- footer -->
|
||||
<footer class="footer">
|
||||
<div class="container-fluid">
|
||||
{{defineZone "footer"}}
|
||||
</div>
|
||||
</footer>
|
||||
<!-- /footer -->
|
||||
|
||||
{{defineZone "bottomJs"}}
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,56 @@
|
||||
{{!--
|
||||
* 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.
|
||||
--}}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>{{#defineZone "title"}}WSO2 Template{{/defineZone}}</title>
|
||||
{{defineZone "favicon"}}
|
||||
{{defineZone "topCss"}}
|
||||
{{defineZone "topJs"}}
|
||||
</head>
|
||||
<body>
|
||||
<!-- header -->
|
||||
{{defineZone "header"}}
|
||||
<!-- /header -->
|
||||
|
||||
<!-- page-content-wrapper -->
|
||||
<div class="page-content-wrapper">
|
||||
<div class="container-fluid ">
|
||||
<div class="body-wrapper">
|
||||
{{defineZone "content"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /page-content-wrapper -->
|
||||
|
||||
<!-- footer -->
|
||||
<footer class="footer">
|
||||
<div class="container-fluid">
|
||||
{{defineZone "footer"}}
|
||||
</div>
|
||||
</footer>
|
||||
<!-- /footer -->
|
||||
|
||||
{{defineZone "bottomJs"}}
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* Licensed 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 batchProviders;
|
||||
|
||||
batchProviders = function () {
|
||||
var operations = {};
|
||||
var CONTENT_TYPE_JSON = "application/json";
|
||||
var JS_MAX_VALUE = "9007199254740992";
|
||||
var JS_MIN_VALUE = "-9007199254740992";
|
||||
|
||||
var TABLENAME_ANDROID = "ORG_WSO2_GEO_FUSEDSPATIALEVENT";
|
||||
var TABLENAME_ANDROID_SENSE = "ORG_WSO2_IOT_ANDROID_LOCATION";
|
||||
|
||||
var tableName = function (deviceType) {
|
||||
switch (deviceType) {
|
||||
case "android" :
|
||||
return TABLENAME_ANDROID;
|
||||
break;
|
||||
case "android_sense" :
|
||||
return TABLENAME_ANDROID_SENSE;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
var typeMap = {
|
||||
"bool": "string",
|
||||
"boolean": "string",
|
||||
"string": "string",
|
||||
"int": "number",
|
||||
"integer": "number",
|
||||
"long": "number",
|
||||
"double": "number",
|
||||
"float": "number",
|
||||
"time": "time"
|
||||
};
|
||||
|
||||
var log = new Log();
|
||||
var carbon = require('carbon');
|
||||
var JSUtils = Packages.org.wso2.carbon.analytics.jsservice.Utils;
|
||||
var AnalyticsCachedJSServiceConnector = Packages.org.wso2.carbon.analytics.jsservice.AnalyticsCachedJSServiceConnector;
|
||||
var AnalyticsCache = Packages.org.wso2.carbon.analytics.jsservice.AnalyticsCachedJSServiceConnector.AnalyticsCache;
|
||||
var cacheTimeoutSeconds = 5;
|
||||
|
||||
var cacheSizeBytes = 1024 * 1024 * 1024; // 1GB
|
||||
response.contentType = CONTENT_TYPE_JSON;
|
||||
|
||||
|
||||
var cache = application.get("AnalyticsWebServiceCache");
|
||||
if (cache == null) {
|
||||
cache = new AnalyticsCache(cacheTimeoutSeconds, cacheSizeBytes);
|
||||
application.put("AnalyticsWebServiceCache", cache);
|
||||
}
|
||||
var connector = new AnalyticsCachedJSServiceConnector(cache);
|
||||
|
||||
|
||||
/**
|
||||
* returns an array of column names & types
|
||||
* @param providerConfig
|
||||
*/
|
||||
operations.getSchema = function (loggedInUser) {
|
||||
var tablename = tableName(deviceType);
|
||||
if (tablename == null) {
|
||||
return [];
|
||||
}
|
||||
var schema = [];
|
||||
var result = connector.getTableSchema(loggedInUser, tablename).getMessage();
|
||||
result = JSON.parse(result);
|
||||
|
||||
var columns = result.columns;
|
||||
Object.getOwnPropertyNames(columns).forEach(function (name, idx, array) {
|
||||
var type = "ordinal";
|
||||
if (columns[name]['type']) {
|
||||
type = columns[name]['type'];
|
||||
}
|
||||
schema.push({
|
||||
fieldName: name,
|
||||
fieldType: typeMap[type.toLowerCase()]
|
||||
});
|
||||
});
|
||||
// log.info(schema);
|
||||
return schema;
|
||||
};
|
||||
|
||||
/**
|
||||
* returns the actual data
|
||||
* @param providerConfig
|
||||
* @param limit
|
||||
*/
|
||||
operations.getData = function (loggedInUser, deviceId, deviceType) {
|
||||
var luceneQuery = "";
|
||||
var limit = 100;
|
||||
var result;
|
||||
var tablename = tableName(deviceType);
|
||||
if (tablename == null) {
|
||||
return [];
|
||||
}
|
||||
//if there's a filter present, we should perform a Lucene search instead of reading the table
|
||||
if (luceneQuery) {
|
||||
luceneQuery = 'id:"' + deviceId + '" AND type:"' + deviceType + '"';
|
||||
var filter = {
|
||||
"query": luceneQuery,
|
||||
"start": 0,
|
||||
"count": limit
|
||||
};
|
||||
result = connector.search(loggedInUser, tablename, stringify(filter)).getMessage();
|
||||
} else {
|
||||
var from = JS_MIN_VALUE;
|
||||
var to = JS_MAX_VALUE;
|
||||
result = connector.getRecordsByRange(loggedInUser, tablename, from, to, 0, limit, null).getMessage();
|
||||
|
||||
}
|
||||
|
||||
// error handling ----
|
||||
var resultString = result.toString();
|
||||
if (resultString.contains("Failed to get records from table")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
result = JSON.parse(result);
|
||||
var data = [];
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var values = result[i].values;
|
||||
data.push(values);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
|
||||
|
||||
return operations;
|
||||
}();
|
||||
@ -0,0 +1,748 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module contains user and roles related functionality.
|
||||
*/
|
||||
var userModule = function () {
|
||||
var log = new Log("/app/modules/business-controllers/user.js");
|
||||
|
||||
var constants = require("/app/modules/constants.js");
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
|
||||
|
||||
/* Initializing user manager */
|
||||
var carbon = require("carbon");
|
||||
var url = carbon.server.address("https") + "/admin/services";
|
||||
var server = new carbon.server.Server(url);
|
||||
|
||||
var publicMethods = {};
|
||||
var privateMethods = {};
|
||||
|
||||
/**
|
||||
* Get the carbon user object from the session. If not found - it will throw a user not found error.
|
||||
* @returns {object} carbon user object
|
||||
*/
|
||||
publicMethods.getCarbonUser = function () {
|
||||
var carbon = require("carbon");
|
||||
var carbonUser = session.get(constants["USER_SESSION_KEY"]);
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants["ERRORS"]["USER_NOT_FOUND"];
|
||||
}
|
||||
return carbonUser;
|
||||
};
|
||||
|
||||
/**
|
||||
* Only GET method is implemented for now since there are no other type of methods used this method.
|
||||
* @param url - URL to call the backend without the host
|
||||
* @param method - HTTP Method (GET, POST)
|
||||
* @returns An object with 'status': 'success'|'error', 'content': {}
|
||||
*/
|
||||
privateMethods.callBackend = function (url, method) {
|
||||
if (constants["HTTP_GET"] == method) {
|
||||
return serviceInvokers.XMLHttp.get(url,
|
||||
function (backendResponse) {
|
||||
var response = {};
|
||||
response.content = backendResponse.responseText;
|
||||
if (backendResponse.status == 200) {
|
||||
response.status = "success";
|
||||
} else if (backendResponse.status == 400 || backendResponse.status == 401 ||
|
||||
backendResponse.status == 404 || backendResponse.status == 500) {
|
||||
response.status = "error";
|
||||
}
|
||||
return response;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
log.error("Runtime error : This method only support HTTP GET requests.");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Build default user claims.
|
||||
*
|
||||
* @param firstname First name of the user
|
||||
* @param lastname Last name of the user
|
||||
* @param emailAddress Email address of the user
|
||||
*
|
||||
* @returns {Object} Default user claims to be provided
|
||||
*/
|
||||
privateMethods.buildDefaultUserClaims = function (firstname, lastname, emailAddress) {
|
||||
var defaultUserClaims = {
|
||||
"http://wso2.org/claims/givenname": firstname,
|
||||
"http://wso2.org/claims/lastname": lastname,
|
||||
"http://wso2.org/claims/emailaddress": emailAddress
|
||||
};
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("ClaimMap created for new user : " + stringify(defaultUserClaims));
|
||||
}
|
||||
return defaultUserClaims;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register user to dc-user-store.
|
||||
*
|
||||
* @param username Username of the user
|
||||
* @param firstname First name of the user
|
||||
* @param lastname Last name of the user
|
||||
* @param emailAddress Email address of the user
|
||||
* @param password Password of the user
|
||||
* @param userRoles Roles assigned to the user
|
||||
*
|
||||
* @returns {number} HTTP Status code 201 if succeeded, 409 if user already exists
|
||||
*/
|
||||
publicMethods.registerUser = function (username, firstname, lastname, emailAddress, password, userRoles) {
|
||||
var carbon = require('carbon');
|
||||
var tenantId = carbon.server.tenantId();
|
||||
var url = carbon.server.address('https') + "/admin/services";
|
||||
var server = new carbon.server.Server(url);
|
||||
var userManager = new carbon.user.UserManager(server, tenantId);
|
||||
try {
|
||||
if (userManager.userExists(username)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("A user with name '" + username + "' already exists.");
|
||||
}
|
||||
// http status code 409 refers to - conflict.
|
||||
return constants.HTTP_CONFLICT;
|
||||
} else {
|
||||
var defaultUserClaims = privateMethods.buildDefaultUserClaims(firstname, lastname, emailAddress);
|
||||
userManager.addUser(username, password, userRoles, defaultUserClaims, "default");
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("A new user with name '" + username + "' was created.");
|
||||
}
|
||||
// http status code 201 refers to - created.
|
||||
return constants.HTTP_CREATED;
|
||||
}
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@Updated
|
||||
*/
|
||||
publicMethods.getUsers = function () {
|
||||
var carbonUser = session.get(constants["USER_SESSION_KEY"]);
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants["ERRORS"]["USER_NOT_FOUND"];
|
||||
}
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/users?offset=0&limit=100";
|
||||
var response = privateMethods.callBackend(url, constants["HTTP_GET"]);
|
||||
if (response.status == "success") {
|
||||
response.content = parse(response.content).users;
|
||||
}
|
||||
return response;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Get users count from backend services.
|
||||
*/
|
||||
publicMethods.getUsersCount = function () {
|
||||
var carbonUser = session.get(constants["USER_SESSION_KEY"]);
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants["ERRORS"]["USER_NOT_FOUND"];
|
||||
}
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/users/count";
|
||||
return serviceInvokers.XMLHttp.get(
|
||||
url, function (responsePayload) {
|
||||
return parse(responsePayload["responseText"])["count"];
|
||||
},
|
||||
function (responsePayload) {
|
||||
log.error(responsePayload["responseText"]);
|
||||
return -1;
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a User object from the backend by calling the JAX-RS
|
||||
* @param username
|
||||
* @returns {object} a response object with status and content on success.
|
||||
*/
|
||||
publicMethods.getUser = function (username) {
|
||||
var carbonUser = publicMethods.getCarbonUser();
|
||||
var domain;
|
||||
if (username.indexOf('/') > 0) {
|
||||
domain = username.substr(0, username.indexOf('/'));
|
||||
username = username.substr(username.indexOf('/') + 1);
|
||||
}
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/users/" +
|
||||
encodeURIComponent(username);
|
||||
if (domain) {
|
||||
url += '?domain=' + encodeURIComponent(domain);
|
||||
}
|
||||
var response = privateMethods.callBackend(url, constants["HTTP_GET"]);
|
||||
response["content"] = parse(response.content);
|
||||
response["userDomain"] = carbonUser.domain;
|
||||
return response;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a set of roles assigned to a particular user
|
||||
* @param username
|
||||
* @returns {object} a response object with status and content on success.
|
||||
*/
|
||||
publicMethods.getRolesByUsername = function (username) {
|
||||
var carbonUser = publicMethods.getCarbonUser();
|
||||
var domain;
|
||||
if (username.indexOf('/') > 0) {
|
||||
domain = username.substr(0, username.indexOf('/'));
|
||||
username = username.substr(username.indexOf('/') + 1);
|
||||
}
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/users/" +
|
||||
encodeURIComponent(username) + "/roles";
|
||||
if (domain) {
|
||||
url += '?domain=' + encodeURIComponent(domain);
|
||||
}
|
||||
var response = privateMethods.callBackend(url, constants["HTTP_GET"]);
|
||||
if (response.status == "success") {
|
||||
response.content = parse(response.content).roles;
|
||||
}
|
||||
return response;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@NewlyAdded
|
||||
*/
|
||||
publicMethods.getUsersByUsername = function () {
|
||||
var carbonUser = session.get(constants["USER_SESSION_KEY"]);
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants["ERRORS"]["USER_NOT_FOUND"];
|
||||
}
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var url = devicemgtProps["httpsURL"] + "/mdm-admin/users/users-by-username";
|
||||
return privateMethods.callBackend(url, constants["HTTP_GET"]);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@Updated
|
||||
*/
|
||||
/**
|
||||
* Get User Roles from user store (Internal roles not included).
|
||||
*/
|
||||
publicMethods.getRoles = function () {
|
||||
var carbonUser = session.get(constants["USER_SESSION_KEY"]);
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants["ERRORS"]["USER_NOT_FOUND"];
|
||||
}
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] +
|
||||
"/roles?offset=0&limit=100&user-store=all";
|
||||
var response = privateMethods.callBackend(url, constants["HTTP_GET"]);
|
||||
if (response.status == "success") {
|
||||
response.content = parse(response.content).roles;
|
||||
}
|
||||
return response;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get User Roles from user store (Internal roles not included).
|
||||
*/
|
||||
publicMethods.getFilteredRoles = function (prefix) {
|
||||
var carbonUser = session.get(constants["USER_SESSION_KEY"]);
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants["ERRORS"]["USER_NOT_FOUND"];
|
||||
}
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] +
|
||||
"/roles/filter/" + prefix + "?offset=0&limit=100&user-store=all";
|
||||
var response = privateMethods.callBackend(url, constants["HTTP_GET"]);
|
||||
if (response.status == "success") {
|
||||
response.content = parse(response.content);
|
||||
}
|
||||
return response;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get User Roles count from user store (Internal roles not included).
|
||||
*/
|
||||
publicMethods.getRolesCount = function () {
|
||||
var carbonUser = session.get(constants["USER_SESSION_KEY"]);
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants["ERRORS"]["USER_NOT_FOUND"];
|
||||
}
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] +
|
||||
"/roles?offset=0&limit=1&user-store=all";
|
||||
return serviceInvokers.XMLHttp.get(
|
||||
url, function (responsePayload) {
|
||||
return parse(responsePayload["responseText"])["count"];
|
||||
},
|
||||
function (responsePayload) {
|
||||
log.error(responsePayload["responseText"]);
|
||||
return -1;
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@Updated
|
||||
*/
|
||||
/**
|
||||
* Get User Roles from user store (Internal roles not included).
|
||||
* @returns {object} a response object with status and content on success.
|
||||
*/
|
||||
publicMethods.getRolesByUserStore = function (userStore) {
|
||||
userStore = userStore ? userStore : "all";
|
||||
var carbonUser = session.get(constants["USER_SESSION_KEY"]);
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants["ERRORS"]["USER_NOT_FOUND"];
|
||||
}
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] +
|
||||
"/roles?user-store=" + encodeURIComponent(userStore) + "&limit=100";
|
||||
var response = privateMethods.callBackend(url, constants["HTTP_GET"]);
|
||||
if (response.status == "success") {
|
||||
response.content = parse(response.content).roles;
|
||||
}
|
||||
return response;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get Platforms.
|
||||
* @deprecated moved this device module under getDeviceTypes.
|
||||
*/
|
||||
//TODO Move this piece of logic out of user.js to somewhere else appropriate.
|
||||
publicMethods.getPlatforms = function () {
|
||||
var carbonUser = session.get(constants["USER_SESSION_KEY"]);
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants["ERRORS"]["USER_NOT_FOUND"];
|
||||
}
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/device-types";
|
||||
var response = privateMethods.callBackend(url, constants["HTTP_GET"]);
|
||||
if (response.status == "success") {
|
||||
response.content = parse(response.content);
|
||||
}
|
||||
return response;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get role
|
||||
*/
|
||||
publicMethods.getRole = function (roleName) {
|
||||
var carbonUser = session.get(constants["USER_SESSION_KEY"]);
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
var userStore;
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants["ERRORS"]["USER_NOT_FOUND"];
|
||||
}
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
if (roleName.indexOf('/') > 0) {
|
||||
userStore = roleName.substr(0, roleName.indexOf('/'));
|
||||
roleName = roleName.substr(roleName.indexOf('/') + 1);
|
||||
}
|
||||
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] +
|
||||
"/roles/" + encodeURIComponent(roleName);
|
||||
if (userStore) {
|
||||
url += "?user-store=" + encodeURIComponent(userStore);
|
||||
}
|
||||
var response = privateMethods.callBackend(url, constants["HTTP_GET"]);
|
||||
if (response.status == "success") {
|
||||
response.content = parse(response.content);
|
||||
}
|
||||
return response;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Authenticate a user when he or she attempts to login to MDM.
|
||||
*
|
||||
* @param username Username of the user
|
||||
* @param password Password of the user
|
||||
* @param successCallback Function to be called at the event of successful authentication
|
||||
* @param failureCallback Function to be called at the event of failed authentication
|
||||
*/
|
||||
publicMethods.login = function (username, password, successCallback, failureCallback) {
|
||||
var carbonModule = require("carbon");
|
||||
var carbonServer = application.get("carbonServer");
|
||||
try {
|
||||
// check if the user is an authenticated user.
|
||||
var isAuthenticated = carbonServer.authenticate(username, password);
|
||||
if (!isAuthenticated) {
|
||||
failureCallback("authentication");
|
||||
return;
|
||||
}
|
||||
var tenantUser = carbonModule.server.tenantUser(username);
|
||||
var isAuthorizedToLogin = privateMethods.isAuthorizedToLogin(tenantUser);
|
||||
if (!isAuthorizedToLogin) {
|
||||
failureCallback("authorization");
|
||||
return;
|
||||
}
|
||||
session.put(constants.USER_SESSION_KEY, tenantUser);
|
||||
successCallback(tenantUser);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods.logout = function (successCallback) {
|
||||
session.invalidate();
|
||||
successCallback();
|
||||
};
|
||||
|
||||
publicMethods.isAuthorized = function (permission) {
|
||||
var carbon = require("carbon");
|
||||
var carbonServer = application.get("carbonServer");
|
||||
var carbonUser;
|
||||
try {
|
||||
carbonUser = session.get(constants.USER_SESSION_KEY);
|
||||
} catch (e) {
|
||||
log.error("User object was not found in the session");
|
||||
carbonUser = null;
|
||||
}
|
||||
var utility = require('/app/modules/utility.js').utility;
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
response.sendError(401, constants.ERRORS.USER_NOT_FOUND);
|
||||
exit();
|
||||
}
|
||||
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var tenantId = carbon.server.tenantId();
|
||||
var userManager = new carbon.user.UserManager(server, tenantId);
|
||||
var user = new carbon.user.User(userManager, carbonUser.username);
|
||||
return user.isAuthorized(permission, "ui.execute");
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
privateMethods.isAuthorizedToLogin = function(carbonUser) {
|
||||
var utility = require('/app/modules/utility.js').utility;
|
||||
try {
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var tenantId = carbon.server.tenantId();
|
||||
var userManager = new carbon.user.UserManager(server, tenantId);
|
||||
var user = new carbon.user.User(userManager, carbonUser.username);
|
||||
return user.isAuthorized("/permission/admin/login", "ui.execute");
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods.getUIPermissions = function () {
|
||||
var permissions = {};
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/devices/any-device")) {
|
||||
permissions["LIST_DEVICES"] = true;
|
||||
permissions["LIST_OWN_DEVICES"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/devices/owning-device/view")) {
|
||||
permissions["LIST_OWN_DEVICES"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/admin/groups/view")) {
|
||||
permissions["LIST_ALL_GROUPS"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/groups/view")) {
|
||||
permissions["LIST_GROUPS"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/users/list")) {
|
||||
permissions["LIST_USERS"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/roles/list")) {
|
||||
permissions["LIST_ROLES"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/policies/list")) {
|
||||
permissions["LIST_ALL_POLICIES"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/user/policies/list")) {
|
||||
permissions["LIST_POLICIES"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/devices/enroll")) {
|
||||
permissions["ADD_DEVICE"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/groups/add")) {
|
||||
permissions["ADD_GROUP"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/users/add")) {
|
||||
permissions["ADD_USER"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/groups/devices/add")) {
|
||||
permissions["ADD_GROUP_DEVICES"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/groups/devices/remove")) {
|
||||
permissions["REMOVE_GROUP_DEVICES"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/groups/devices/view")) {
|
||||
permissions["VIEW_GROUP_DEVICES"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/groups/roles/view")) {
|
||||
permissions["VIEW_GROUP_ROLES"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/groups/update")) {
|
||||
permissions["UPDATE_GROUP"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/groups/share")) {
|
||||
permissions["SHARE_GROUP"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/users/remove")) {
|
||||
permissions["REMOVE_USER"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/groups/remove")) {
|
||||
permissions["REMOVE_GROUP"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/roles/add")) {
|
||||
permissions["ADD_ROLE"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/policies/add")) {
|
||||
permissions["ADD_ADMIN_POLICY"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/user/policies/add")) {
|
||||
permissions["ADD_POLICY"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/policies/priority")) {
|
||||
permissions["CHANGE_POLICY_PRIORITY"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/dashboard/view")) {
|
||||
permissions["VIEW_DASHBOARD"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/platform-configs/view")) {
|
||||
permissions["TENANT_CONFIGURATION"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt/devices/change-status")) {
|
||||
permissions["CHANGE_DEVICE_STATUS"] = true;
|
||||
}
|
||||
if (publicMethods.isAuthorized("/permission/admin/device-mgt")) {
|
||||
permissions["IS_ADMIN"] = true;
|
||||
}
|
||||
|
||||
return permissions;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add new role with permissions.
|
||||
*
|
||||
* @param roleName Name of the role
|
||||
* @param users List of users to assign the role
|
||||
* @param permissions List of permissions
|
||||
*/
|
||||
publicMethods.addRole = function (roleName, users, permissions) {
|
||||
var carbon = require('carbon');
|
||||
var tenantId = carbon.server.tenantId();
|
||||
var url = carbon.server.address('https') + "/admin/services";
|
||||
var server = new carbon.server.Server(url);
|
||||
var userManager = new carbon.user.UserManager(server, tenantId);
|
||||
|
||||
try {
|
||||
if (!userManager.roleExists(roleName)) {
|
||||
userManager.addRole(roleName, users, permissions);
|
||||
} else {
|
||||
var array = Object.keys(permissions);
|
||||
var i, permission;
|
||||
for (i = 0; i < array.length; i++) {
|
||||
permission = array[i];
|
||||
userManager.authorizeRole(roleName, permission, "ui.execute");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods.addPermissions = function (permissionList, path, init) {
|
||||
var registry, carbon = require("carbon");
|
||||
var carbonServer = application.get("carbonServer");
|
||||
var utility = require('/app/modules/utility.js').utility;
|
||||
var options = {system: true};
|
||||
if (init == "login") {
|
||||
try {
|
||||
var carbonUser = session.get(constants.USER_SESSION_KEY);
|
||||
if (!carbonUser) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants.ERRORS.USER_NOT_FOUND;
|
||||
}
|
||||
utility.startTenantFlow(carbonUser);
|
||||
var tenantId = carbon.server.tenantId();
|
||||
if (carbonUser) {
|
||||
options.tenantId = tenantId;
|
||||
}
|
||||
registry = new carbon.registry.Registry(carbonServer, options);
|
||||
var i, permission, resource;
|
||||
for (i = 0; i < permissionList.length; i++) {
|
||||
permission = permissionList[i];
|
||||
resource = {
|
||||
collection: true,
|
||||
name: permission.name,
|
||||
properties: {
|
||||
name: permission.name
|
||||
}
|
||||
};
|
||||
if (path != "") {
|
||||
registry.put("/_system/governance/permission/admin/" + path + "/" + permission.key, resource);
|
||||
} else {
|
||||
registry.put("/_system/governance/permission/admin/" + permission.key, resource);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
} else {
|
||||
registry = new carbon.registry.Registry(carbonServer, options);
|
||||
var i, permission, resource;
|
||||
for (i = 0; i < permissionList.length; i++) {
|
||||
permission = permissionList[i];
|
||||
resource = {
|
||||
collection: true,
|
||||
name: permission.name,
|
||||
properties: {
|
||||
name: permission.name
|
||||
}
|
||||
};
|
||||
if (path != "") {
|
||||
registry.put("/_system/governance/permission/admin/" + path + "/" + permission.key, resource);
|
||||
} else {
|
||||
registry.put("/_system/governance/permission/admin/" + permission.key, resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Private method to be used by addUser() to
|
||||
* retrieve secondary user stores.
|
||||
* This needs Authentication since the method access admin services.
|
||||
*
|
||||
* @returns Array of secondary user stores.
|
||||
*/
|
||||
publicMethods.getSecondaryUserStores = function () {
|
||||
var returnVal = [];
|
||||
// To call the userstore admin service, user needs to have admin permission
|
||||
if (publicMethods.isAuthorized("/permission/admin")) {
|
||||
var endpoint = devicemgtProps["adminService"] + constants["USER_STORE_CONFIG_ADMIN_SERVICE_END_POINT"];
|
||||
var wsPayload = "<xsd:getSecondaryRealmConfigurations xmlns:xsd='http://org.apache.axis2/xsd'/>";
|
||||
serviceInvokers.WS.soapRequest(
|
||||
"urn:getSecondaryRealmConfigurations",
|
||||
wsPayload,
|
||||
endpoint,
|
||||
function (wsResponse) {
|
||||
var domainIDs = stringify(wsResponse. * ::['return']. * ::domainId.text());
|
||||
if (domainIDs != "\"\"") {
|
||||
var regExpForSearch = new RegExp(constants["USER_STORES_NOISY_CHAR"], "g");
|
||||
domainIDs = domainIDs.replace(regExpForSearch, "");
|
||||
returnVal = domainIDs.split(constants["USER_STORES_SPLITTING_CHAR"]);
|
||||
}
|
||||
}, function (e) {
|
||||
log.error("Error retrieving secondary user stores", e);
|
||||
},
|
||||
constants["SOAP_VERSION"]);
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("User does not have admin permission to get the secondary user store details.");
|
||||
}
|
||||
}
|
||||
return returnVal;
|
||||
};
|
||||
|
||||
return publicMethods;
|
||||
}();
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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 conf = function () {
|
||||
var cloudConf = application.get("CLOUD_CONF");
|
||||
if (!cloudConf) {
|
||||
cloudConf = require("/app/conf/toplink-menu.json");
|
||||
var pinch = require("/app/modules/conf-reader/pinch.min.js")["pinch"];
|
||||
var server = require("carbon")["server"];
|
||||
var process = require("process");
|
||||
pinch(cloudConf, /^/,
|
||||
function (path, key, value) {
|
||||
if ((typeof value === "string") && value.indexOf("%https.ip%") > -1) {
|
||||
//noinspection JSUnresolvedFunction
|
||||
return value.replace("%https.ip%", server.address("https"));
|
||||
} else if ((typeof value === "string") && value.indexOf("%http.ip%") > -1) {
|
||||
//noinspection JSUnresolvedFunction
|
||||
return value.replace("%http.ip%", server.address("http"));
|
||||
} else if ((typeof value === "string") && value.indexOf("%date-year%") > -1) {
|
||||
var year = new Date().getFullYear();
|
||||
return value.replace("%date-year%", year);
|
||||
} else if ((typeof value === "string") && value.indexOf("%server.ip%") > -1) {
|
||||
var getProperty = require("process").getProperty;
|
||||
return value.replace("%server.ip%", getProperty("carbon.local.ip"));
|
||||
} else {
|
||||
var paramPattern = new RegExp("%(.*?)%", "g");
|
||||
var out = value;
|
||||
while ((matches = paramPattern.exec(value)) !== null) {
|
||||
// This is necessary to avoid infinite loops with zero-width matches
|
||||
if (matches.index === paramPattern.lastIndex) {
|
||||
paramPattern.lastIndex++;
|
||||
}
|
||||
if (matches.length == 2) {
|
||||
var property = process.getProperty(matches[1]);
|
||||
if (property) {
|
||||
out = out.replace(new RegExp("%" + matches[1] + "%", "g"), property);
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
);
|
||||
application.put("CLOUD_CONF", cloudConf);
|
||||
}
|
||||
return cloudConf;
|
||||
}();
|
||||
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 conf = function () {
|
||||
var conf = application.get("CONF");
|
||||
if (!conf) {
|
||||
conf = require("/app/conf/config.json");
|
||||
var pinch = require("/app/modules/conf-reader/pinch.min.js")["pinch"];
|
||||
var server = require("carbon")["server"];
|
||||
var process = require("process");
|
||||
pinch(conf, /^/,
|
||||
function (path, key, value) {
|
||||
if ((typeof value === "string") && value.indexOf("%https.ip%") > -1) {
|
||||
//noinspection JSUnresolvedFunction
|
||||
return value.replace("%https.ip%", server.address("https"));
|
||||
} else if ((typeof value === "string") && value.indexOf("%http.ip%") > -1) {
|
||||
//noinspection JSUnresolvedFunction
|
||||
return value.replace("%http.ip%", server.address("http"));
|
||||
} else if ((typeof value === "string") && value.indexOf("%date-year%") > -1) {
|
||||
var year = new Date().getFullYear();
|
||||
return value.replace("%date-year%", year);
|
||||
} else if ((typeof value === "string") && value.indexOf("%server.ip%") > -1) {
|
||||
var getProperty = require("process").getProperty;
|
||||
return value.replace("%server.ip%", getProperty("carbon.local.ip"));
|
||||
} else {
|
||||
var paramPattern = new RegExp("%(.*?)%", "g");
|
||||
var out = value;
|
||||
while ((matches = paramPattern.exec(value)) !== null) {
|
||||
// This is necessary to avoid infinite loops with zero-width matches
|
||||
if (matches.index === paramPattern.lastIndex) {
|
||||
paramPattern.lastIndex++;
|
||||
}
|
||||
if (matches.length == 2) {
|
||||
var property = process.getProperty(matches[1]);
|
||||
if (property) {
|
||||
out = out.replace(new RegExp("%" + matches[1] + "%", "g"), property);
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
);
|
||||
var DeviceConfigurationManager = Packages.org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
|
||||
conf["serverConfig"] = DeviceConfigurationManager.getInstance().getDeviceManagementConfig();
|
||||
application.put("CONF", conf);
|
||||
}
|
||||
return conf;
|
||||
}();
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2011 František Hába <hello@frantisekhaba.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the 'Software'), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Reference:- https://github.com/Baggz/Pinch
|
||||
* */
|
||||
(function(){var k=function(a,c){return a.length!==c.length?!1:a.every(function(a,b){return c[b]===a})},j=function(a,c,d){var b,e;if("[object Array]"===Object.prototype.toString.call(a)){b=0;for(e=a.length;b<e;b++)c.apply(d,[b,a[b],a])}else for(b in a)a.hasOwnProperty(b)&&c.apply(d,[b,a[b],a])},h=function(a){for(var c=[],d=!1,b=0,e=a.length,f="",g=function(){f&&(c.push(f),f="")};b<e;b++)a[b].match(/\[|\]/)?(g(),d="]"===a[b]?!1:!0):'"'!==a[b]&&"'"!==a[b]&&("."===a[b]&&!d?g():f+=a[b]),b===e-1&&g();return c},
|
||||
g=function(a,c,d){var b=-1!==["string","object"].indexOf(typeof a),e="string"===typeof c||c&&c.test&&c.exec,f=-1!==["string","object","function"].indexOf(typeof d);b&&e&&f&&("string"===typeof a?(this.instance=JSON.parse(a),this.json=!0):this.instance=a,this.pattern="string"===typeof c?c.replace(/'/g,'"'):c,this.replacement=d,this.createIndex(this.instance))};g.prototype.createIndex=function(a,c){var d=this;this.index=this.index||[];c=c||"";j(a,function(a,e){var f,a=a+"";f=a.match(/^[a-zA-Z]+$/)?c?
|
||||
c+"."+a:a:a.match(/\d+/)?c+"["+a+"]":c+'["'+a+'"]';d.index.push(f);"object"===typeof e&&d.createIndex(e,f)})};g.prototype.replace=function(){var a=this;j(this.index,function(c,d){if(a.pattern&&a.pattern.test&&a.pattern.exec&&d.match(a.pattern))return a.replaceValue(d);if("string"===typeof a.pattern){var b=h(d),e=h(a.pattern);if(k(b,e))return a.replaceValue(d)}});return this.json?JSON.stringify(this.instance):this.instance};g.prototype.replaceValue=function(a){var c=this,d=h(a);d.reduce(function(b,
|
||||
e,f){if(f===d.length-1)f="function"===typeof c.replacement?c.replacement(a,e,b[e]):c.replacement,b[e]=f;else return b[e]},this.instance)};var i=function(a,c,d,b){a=(new g(a,c,d)).replace();return"function"===typeof b?b(null,a):a};"undefined"!==typeof module&&module.exports?module.exports=i:"undefined"!==typeof define?define(function(){return i}):this.pinch=i})();
|
||||
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 USER_SESSION_KEY = "_UUF_USER";
|
||||
var UNSPECIFIED = "Unspecified";
|
||||
var httpURL = "httpURL";
|
||||
var httpsURL = "httpsURL";
|
||||
|
||||
var DEVICE_IDENTIFIER = "deviceIdentifier";
|
||||
var DEVICE_NAME = "name";
|
||||
var DEVICE_OWNERSHIP = "ownership";
|
||||
var DEVICE_OWNER = "owner";
|
||||
var DEVICE_TYPE = "type";
|
||||
var DEVICE_VENDOR = "vendor";
|
||||
var DEVICE_MODEL = "model";
|
||||
var DEVICE_PRODUCT = "PRODUCT";
|
||||
var DEVICE_OS_VERSION = "osVersion";
|
||||
var DEVICE_OS_BUILD_DATE = "osBuildDate";
|
||||
var DEVICE_PROPERTIES = "properties";
|
||||
var DEVICE_ENROLLMENT_INFO = "enrolmentInfo";
|
||||
var DEVICE_STATUS = "status";
|
||||
var DEVICE_INFO = "deviceInfo";
|
||||
|
||||
var FEATURE_NAME = "featureName";
|
||||
var FEATURE_DESCRIPTION = "featureDescription";
|
||||
|
||||
var PLATFORM_ANDROID = "android";
|
||||
var PLATFORM_WINDOWS = "windows";
|
||||
var PLATFORM_IOS = "ios";
|
||||
|
||||
var LANGUAGE_US = "en_US";
|
||||
|
||||
var VENDOR_APPLE = "Apple";
|
||||
var ERRORS = {
|
||||
"USER_NOT_FOUND": "USER_NOT_FOUND",
|
||||
"UNKNOWN_ERROR": "Unknown Error"
|
||||
};
|
||||
|
||||
var USER_STORES_NOISY_CHAR = "\"";
|
||||
var USER_STORES_SPLITTING_CHAR = "\\n";
|
||||
var USER_STORE_CONFIG_ADMIN_SERVICE_END_POINT =
|
||||
"/services/UserStoreConfigAdminService.UserStoreConfigAdminServiceHttpsSoap12Endpoint/";
|
||||
|
||||
var SOAP_VERSION = 1.2;
|
||||
var WEB_SERVICE_ADDRESSING_VERSION = 1.0;
|
||||
var TOKEN_PAIR = "tokenPair";
|
||||
var ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS = "encodedTenantBasedClientAppCredentials";
|
||||
var CONTENT_TYPE_IDENTIFIER = "Content-Type";
|
||||
var ENCODED_TENANT_BASED_WEB_SOCKET_CLIENT_CREDENTIALS = "encodedTenantBasedWebSocketClientCredentials";
|
||||
|
||||
var CONTENT_DISPOSITION_IDENTIFIER = "Content-Disposition";
|
||||
var APPLICATION_JSON = "application/json";
|
||||
var APPLICATION_ZIP = "application/zip";
|
||||
var STREAMING_FILES_ACCEPT_HEADERS = ["application/zip", "application/pdf", "application/octet-stream"];
|
||||
var ACCEPT_IDENTIFIER = "Accept";
|
||||
var AUTHORIZATION_HEADER= "Authorization";
|
||||
var BEARER_PREFIX = "Bearer ";
|
||||
var HTTP_GET = "GET";
|
||||
var HTTP_POST = "POST";
|
||||
var HTTP_PUT = "PUT";
|
||||
var HTTP_DELETE = "DELETE";
|
||||
|
||||
var HTTP_CONFLICT = 409;
|
||||
var HTTP_CREATED = 201;
|
||||
|
||||
var CACHED_CREDENTIALS = "tenantBasedCredentials";
|
||||
var CACHED_CREDENTIALS_FOR_WEBSOCKET_APP = "tenantBasedWebSocketClientCredentials";
|
||||
|
||||
var ALLOWED_SCOPES = "scopes";
|
||||
|
||||
var SAML_TOKEN_KEY = "samlToken";
|
||||
var SKIP_WELCOME_SCREEN ="skipWelcomeScreen";
|
||||
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 carbonModule = require("carbon");
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
|
||||
|
||||
//noinspection JSUnresolvedFunction Server
|
||||
var carbonServer = new carbonModule.server.Server({
|
||||
tenanted: true,
|
||||
url: devicemgtProps["httpsURL"] + "/admin"
|
||||
});
|
||||
|
||||
application.put("carbonServer", carbonServer);
|
||||
|
||||
var permissions = {
|
||||
"/permission/admin/Login": ["ui.execute"],
|
||||
"/permission/admin/manage/api/subscribe": ["ui.execute"],
|
||||
"/permission/admin/device-mgt/device/api/subscribe": ["ui.execute"],
|
||||
"/permission/admin/device-mgt/devices/enroll": ["ui.execute"],
|
||||
"/permission/admin/device-mgt/devices/disenroll": ["ui.execute"],
|
||||
"/permission/admin/device-mgt/devices/owning-device/view": ["ui.execute"],
|
||||
"/permission/admin/manage/portal": ["ui.execute"]
|
||||
};
|
||||
|
||||
var adminPermissions = {
|
||||
"/permission/admin/device-mgt": ["ui.execute"],
|
||||
"/permission/admin/manage/api": ["ui.execute"],
|
||||
"/permission/admin/manage/portal": ["ui.execute"]
|
||||
};
|
||||
|
||||
//On Startup, admin user will get both roles: devicemgt-admin and devicemgt-user
|
||||
//Average user through sign-up will only receive the role: devicemgt-user.
|
||||
//Admin can setup necessary permissions for the role: devicemgt-user
|
||||
userModule.addRole("internal/devicemgt-user", ["admin"], permissions);
|
||||
userModule.addRole("internal/devicemgt-admin", ["admin"], adminPermissions);
|
||||
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 onSuccess;
|
||||
var onFail;
|
||||
|
||||
(function () {
|
||||
var log = new Log("/app/modules/login.js");
|
||||
var constants = require("/app/modules/constants.js");
|
||||
onSuccess = function (context) {
|
||||
var utility = require("/app/modules/utility.js").utility;
|
||||
var apiWrapperUtil = require("/app/modules/oauth/token-handlers.js")["handlers"];
|
||||
try {
|
||||
utility.startTenantFlow(context.user);
|
||||
var APIManagementProviderService = utility.getAPIManagementProviderService();
|
||||
var isLoaded = APIManagementProviderService.isTierLoaded();
|
||||
if(!isLoaded && context.input.samlToken) {
|
||||
session.put(constants.SKIP_WELCOME_SCREEN, false);
|
||||
session.put(constants.SAML_TOKEN_KEY, context.input.samlToken);
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
utility.endTenantFlow();
|
||||
}
|
||||
session.put(constants.SKIP_WELCOME_SCREEN, true);
|
||||
if (context.input.samlToken) {
|
||||
//apiWrapperUtil.setupTokenPairBySamlGrantType(context.user.username + '@' + context.user.domain, context.input.samlToken);
|
||||
/**
|
||||
* Since the user can be verified using the sso.client.js we can use JWT grant type to issue the token for the user.
|
||||
*/
|
||||
apiWrapperUtil.setupTokenPairByJWTGrantType(context.user.username + '@' + context.user.domain, context.input.samlToken);
|
||||
} else {
|
||||
apiWrapperUtil.setupTokenPairByPasswordGrantType(context.input.username, context.input.password);
|
||||
}
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var carbonServer = require("carbon").server;
|
||||
if (!context.input.samlToken) {
|
||||
(new carbonServer.Server({url: devicemgtProps["adminService"]}))
|
||||
.login(context.input.username, context.input.password);
|
||||
}
|
||||
};
|
||||
|
||||
onFail = function (error) {
|
||||
log.error(error.message);
|
||||
}
|
||||
})();
|
||||
@ -0,0 +1,406 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 utils = function () {
|
||||
var log = new Log("/app/modules/oauth/token-handler-utils.js");
|
||||
|
||||
var deviceMgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var constants = require("/app/modules/constants.js");
|
||||
var carbon = require("carbon");
|
||||
var authModule = require("/lib/modules/auth/auth.js").module;
|
||||
var utility = require('/app/modules/utility.js').utility;
|
||||
|
||||
//noinspection JSUnresolvedVariable
|
||||
var Base64 = Packages.org.apache.commons.codec.binary.Base64;
|
||||
//noinspection JSUnresolvedVariable
|
||||
var String = Packages.java.lang.String;
|
||||
|
||||
var publicMethods = {};
|
||||
var privateMethods = {};
|
||||
|
||||
publicMethods["encode"] = function (payload) {
|
||||
//noinspection JSUnresolvedFunction
|
||||
return String(Base64.encodeBase64(String(payload).getBytes()));
|
||||
};
|
||||
|
||||
publicMethods["decode"] = function (payload) {
|
||||
//noinspection JSUnresolvedFunction
|
||||
return String(Base64.decodeBase64(String(payload).getBytes()));
|
||||
};
|
||||
|
||||
publicMethods["getDynamicClientAppCredentials"] = function () {
|
||||
// setting up dynamic client application properties
|
||||
var dcAppProperties = {
|
||||
"applicationType": deviceMgtProps["oauthProvider"]["appRegistration"]["appType"],
|
||||
"clientName": deviceMgtProps["oauthProvider"]["appRegistration"]["clientName"],
|
||||
"owner": deviceMgtProps["oauthProvider"]["appRegistration"]["owner"],
|
||||
"tokenScope": deviceMgtProps["oauthProvider"]["appRegistration"]["tokenScope"],
|
||||
"grantType": deviceMgtProps["oauthProvider"]["appRegistration"]["grantType"],
|
||||
"callbackUrl": deviceMgtProps["oauthProvider"]["appRegistration"]["callbackUrl"],
|
||||
"saasApp" : true
|
||||
};
|
||||
// calling dynamic client app registration service endpoint
|
||||
var requestURL = deviceMgtProps["oauthProvider"]["appRegistration"]
|
||||
["dynamicClientAppRegistrationServiceURL"];
|
||||
var requestPayload = dcAppProperties;
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", requestURL, false);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.send(stringify(requestPayload));
|
||||
|
||||
var dynamicClientAppCredentials = {};
|
||||
if (xhr["status"] == 201 && xhr["responseText"]) {
|
||||
var responsePayload = parse(xhr["responseText"]);
|
||||
dynamicClientAppCredentials["clientId"] = responsePayload["client_id"];
|
||||
dynamicClientAppCredentials["clientSecret"] = responsePayload["client_secret"];
|
||||
} else if (xhr["status"] == 400) {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js - getDynamicClientAppCredentials()} " +
|
||||
"Bad request. Invalid data provided as dynamic client application properties.");
|
||||
dynamicClientAppCredentials = null;
|
||||
} else {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js - getDynamicClientAppCredentials()} " +
|
||||
"Error in retrieving dynamic client credentials.");
|
||||
dynamicClientAppCredentials = null;
|
||||
}
|
||||
// returning dynamic client credentials
|
||||
return dynamicClientAppCredentials;
|
||||
};
|
||||
|
||||
publicMethods["getTenantBasedClientAppCredentials"] = function (username) {
|
||||
if (!username) {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving tenant " +
|
||||
"based client app credentials. No username " +
|
||||
"as input - getTenantBasedClientAppCredentials(x)");
|
||||
return null;
|
||||
} else {
|
||||
//noinspection JSUnresolvedFunction, JSUnresolvedVariable
|
||||
var tenantDomain = carbon.server.tenantDomain({username: username});
|
||||
if (!tenantDomain) {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving tenant " +
|
||||
"based client application credentials. Unable to obtain a valid tenant domain for provided " +
|
||||
"username - getTenantBasedClientAppCredentials(x, y)");
|
||||
return null;
|
||||
} else {
|
||||
var cachedTenantBasedClientAppCredentials = privateMethods.
|
||||
getCachedTenantBasedClientAppCredentials(tenantDomain);
|
||||
if (cachedTenantBasedClientAppCredentials) {
|
||||
return cachedTenantBasedClientAppCredentials;
|
||||
} else {
|
||||
var adminUsername = deviceMgtProps["adminUser"];
|
||||
var adminUserTenantId = deviceMgtProps["adminUserTenantId"];
|
||||
//claims required for jwtAuthenticator.
|
||||
var claims = {"http://wso2.org/claims/enduserTenantId": adminUserTenantId,
|
||||
"http://wso2.org/claims/enduser": adminUsername};
|
||||
var jwtToken = publicMethods.getJwtToken(adminUsername, claims);
|
||||
|
||||
// register a tenant based client app at API Manager
|
||||
var applicationName = deviceMgtProps["oauthProvider"]["appRegistration"]
|
||||
["clientName"] + "_" + tenantDomain;
|
||||
var requestURL = deviceMgtProps["oauthProvider"]["appRegistration"]
|
||||
["apiManagerClientAppRegistrationServiceURL"] +
|
||||
"?tenantDomain=" + tenantDomain + "&applicationName=" + applicationName;
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", requestURL, false);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.setRequestHeader("X-JWT-Assertion", "" + jwtToken);
|
||||
xhr.send();
|
||||
|
||||
if (xhr["status"] == 201 && xhr["responseText"]) {
|
||||
var responsePayload = parse(xhr["responseText"]);
|
||||
var tenantBasedClientAppCredentials = {};
|
||||
tenantBasedClientAppCredentials["clientId"] = responsePayload["client_id"];
|
||||
tenantBasedClientAppCredentials["clientSecret"] = responsePayload["client_secret"];
|
||||
privateMethods.
|
||||
setCachedTenantBasedClientAppCredentials(tenantDomain, tenantBasedClientAppCredentials);
|
||||
return tenantBasedClientAppCredentials;
|
||||
} else {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving tenant " +
|
||||
"based client application credentials from API " +
|
||||
"Manager - getTenantBasedClientAppCredentials(x, y)");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["getTenantBasedWebSocketClientAppCredentials"] = function (username) {
|
||||
if (!username) {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving tenant " +
|
||||
"based client app credentials. No username " +
|
||||
"as input - getTenantBasedWebSocketClientAppCredentials(x)");
|
||||
return null;
|
||||
} else {
|
||||
//noinspection JSUnresolvedFunction, JSUnresolvedVariable
|
||||
var tenantDomain = carbon.server.tenantDomain({username: username});
|
||||
if (!tenantDomain) {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving tenant " +
|
||||
"based client application credentials. Unable to obtain a valid tenant domain for provided " +
|
||||
"username - getTenantBasedWebSocketClientAppCredentials(x, y)");
|
||||
return null;
|
||||
} else {
|
||||
var cachedBasedWebsocketClientAppCredentials = privateMethods.
|
||||
getCachedBasedWebSocketClientAppCredentials(tenantDomain);
|
||||
if (cachedBasedWebsocketClientAppCredentials) {
|
||||
return cachedBasedWebsocketClientAppCredentials;
|
||||
} else {
|
||||
var adminUsername = deviceMgtProps["adminUser"];
|
||||
var adminUserTenantId = deviceMgtProps["adminUserTenantId"];
|
||||
//claims required for jwtAuthenticator.
|
||||
var claims = {"http://wso2.org/claims/enduserTenantId": adminUserTenantId,
|
||||
"http://wso2.org/claims/enduser": adminUsername};
|
||||
var jwtToken = publicMethods.getJwtToken(adminUsername, claims);
|
||||
|
||||
// register a tenant based app at API Manager
|
||||
var applicationName = "websocket_webapp_" + tenantDomain;
|
||||
var requestURL = (deviceMgtProps["oauthProvider"]["appRegistration"]
|
||||
["apiManagerClientAppRegistrationServiceURL"]).replace("/tenants","");
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", requestURL, false);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.setRequestHeader("X-JWT-Assertion", "" + jwtToken);
|
||||
xhr.send(stringify({applicationName:applicationName, tags:["device_management"],
|
||||
isAllowedToAllDomains:false, isMappingAnExistingOAuthApp:false, validityPeriod: 3600}));
|
||||
if (xhr["status"] == 201 && xhr["responseText"]) {
|
||||
var responsePayload = parse(xhr["responseText"]);
|
||||
var tenantTenantBasedWebsocketClientAppCredentials = {};
|
||||
tenantTenantBasedWebsocketClientAppCredentials["clientId"] = responsePayload["client_id"];
|
||||
tenantTenantBasedWebsocketClientAppCredentials["clientSecret"] =
|
||||
responsePayload["client_secret"];
|
||||
privateMethods.setCachedBasedWebSocketClientAppCredentials(tenantDomain,
|
||||
tenantTenantBasedWebsocketClientAppCredentials);
|
||||
return tenantTenantBasedWebsocketClientAppCredentials;
|
||||
} else {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving tenant " +
|
||||
"based client application credentials from API " +
|
||||
"Manager - getTenantBasedWebSocketClientAppCredentials(x, y)");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
privateMethods["setCachedTenantBasedClientAppCredentials"] = function (tenantDomain, clientAppCredentials) {
|
||||
var cachedTenantBasedClientAppCredentialsMap = application.get(constants["CACHED_CREDENTIALS"]);
|
||||
if (!cachedTenantBasedClientAppCredentialsMap) {
|
||||
cachedTenantBasedClientAppCredentialsMap = {};
|
||||
cachedTenantBasedClientAppCredentialsMap[tenantDomain] = clientAppCredentials;
|
||||
application.put(constants["CACHED_CREDENTIALS"], cachedTenantBasedClientAppCredentialsMap);
|
||||
} else if (!cachedTenantBasedClientAppCredentialsMap[tenantDomain]) {
|
||||
cachedTenantBasedClientAppCredentialsMap[tenantDomain] = clientAppCredentials;
|
||||
}
|
||||
};
|
||||
|
||||
privateMethods["getCachedTenantBasedClientAppCredentials"] = function (tenantDomain) {
|
||||
var cachedTenantBasedClientAppCredentialsMap = application.get(constants["CACHED_CREDENTIALS"]);
|
||||
if (!cachedTenantBasedClientAppCredentialsMap ||
|
||||
!cachedTenantBasedClientAppCredentialsMap[tenantDomain]) {
|
||||
return null;
|
||||
} else {
|
||||
return cachedTenantBasedClientAppCredentialsMap[tenantDomain];
|
||||
}
|
||||
};
|
||||
|
||||
privateMethods["getCachedBasedWebSocketClientAppCredentials"] = function (tenantDomain) {
|
||||
var cachedBasedWebSocketClientAppCredentialsMap
|
||||
= application.get(constants["CACHED_CREDENTIALS_FOR_WEBSOCKET_APP"]);
|
||||
if (!cachedBasedWebSocketClientAppCredentialsMap ||
|
||||
!cachedBasedWebSocketClientAppCredentialsMap[tenantDomain]) {
|
||||
return null;
|
||||
} else {
|
||||
return cachedBasedWebSocketClientAppCredentialsMap[tenantDomain];
|
||||
}
|
||||
};
|
||||
|
||||
privateMethods["setCachedBasedWebSocketClientAppCredentials"] = function (tenantDomain, clientAppCredentials) {
|
||||
var cachedBasedWebSocketClientAppCredentialsMap
|
||||
= application.get(constants["CACHED_CREDENTIALS_FOR_WEBSOCKET_APP"]);
|
||||
if (!cachedBasedWebSocketClientAppCredentialsMap) {
|
||||
cachedBasedWebSocketClientAppCredentialsMap = {};
|
||||
cachedBasedWebSocketClientAppCredentialsMap[tenantDomain] = clientAppCredentials;
|
||||
application.put(constants["CACHED_CREDENTIALS_FOR_WEBSOCKET_APP"]
|
||||
, cachedBasedWebSocketClientAppCredentialsMap);
|
||||
} else if (!cachedBasedWebSocketClientAppCredentialsMap[tenantDomain]) {
|
||||
cachedBasedWebSocketClientAppCredentialsMap[tenantDomain] = clientAppCredentials;
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["getTokenPairAndScopesByPasswordGrantType"] = function (username, password
|
||||
, encodedClientAppCredentials, scopes) {
|
||||
if (!username || !password || !encodedClientAppCredentials || !scopes) {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving access token by password " +
|
||||
"grant type. No username, password, encoded client app credentials or scopes are " +
|
||||
"found - getTokenPairAndScopesByPasswordGrantType(a, b, c, d)");
|
||||
return null;
|
||||
} else {
|
||||
// calling oauth provider token service endpoint
|
||||
var requestURL = deviceMgtProps["oauthProvider"]["tokenServiceURL"];
|
||||
var requestPayload = "grant_type=password&username=" +
|
||||
username + "&password=" + password + "&scope=" + scopes;
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", requestURL, false);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.setRequestHeader("Authorization", "Basic " + encodedClientAppCredentials);
|
||||
xhr.send(requestPayload);
|
||||
|
||||
if (xhr["status"] == 200 && xhr["responseText"]) {
|
||||
var responsePayload = parse(xhr["responseText"]);
|
||||
var tokenData = {};
|
||||
tokenData["accessToken"] = responsePayload["access_token"];
|
||||
tokenData["refreshToken"] = responsePayload["refresh_token"];
|
||||
tokenData["scopes"] = responsePayload["scope"];
|
||||
return tokenData;
|
||||
} else {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving access token " +
|
||||
"by password grant type - getTokenPairAndScopesByPasswordGrantType(a, b, c, d)");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["getTokenPairAndScopesByJWTGrantType"] = function (assertion, encodedClientAppCredentials, scopes) {
|
||||
if (!assertion || !encodedClientAppCredentials || !scopes) {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving access token by jwt " +
|
||||
"grant type. No assertion, encoded client app credentials or scopes are " +
|
||||
"found - getTokenPairAndScopesByJWTGrantType(x, y, z)");
|
||||
return null;
|
||||
} else {
|
||||
var ssoLoginUser = authModule.ssoLogin(assertion);
|
||||
if (!ssoLoginUser.user.username) {
|
||||
return null;
|
||||
}
|
||||
var endUsername = ssoLoginUser.user.username + "@" + ssoLoginUser.user.domain;
|
||||
var JWTClientManagerServicePackagePath =
|
||||
"org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService";
|
||||
//noinspection JSUnresolvedFunction, JSUnresolvedVariable
|
||||
var JWTClientManagerService = carbon.server.osgiService(JWTClientManagerServicePackagePath);
|
||||
//noinspection JSUnresolvedFunction
|
||||
var jwtClient = JWTClientManagerService.getJWTClient();
|
||||
// returning access token by JWT grant type
|
||||
var tokenInfo = jwtClient.getAccessToken(encodedClientAppCredentials,
|
||||
endUsername, scopes);
|
||||
if (tokenInfo) {
|
||||
var tokenData = {};
|
||||
tokenData["accessToken"] = tokenInfo.getAccessToken();
|
||||
tokenData["refreshToken"] = tokenInfo.getRefreshToken();
|
||||
tokenData["scopes"] = tokenInfo.getScopes();
|
||||
return tokenData;
|
||||
} else {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving access token " +
|
||||
"by jwt grant type - getTokenPairAndScopesByJWTGrantType()");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["getNewTokenPairByRefreshToken"] = function (refreshToken, encodedClientAppCredentials, scopes) {
|
||||
if (!refreshToken || !encodedClientAppCredentials) {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving new access token " +
|
||||
"by current refresh token. No refresh token or encoded client app credentials are " +
|
||||
"found - getNewTokenPairByRefreshToken(x, y, z)");
|
||||
return null;
|
||||
} else {
|
||||
var requestURL = deviceMgtProps["oauthProvider"]["tokenServiceURL"];
|
||||
var requestPayload = "grant_type=refresh_token&refresh_token=" + refreshToken;
|
||||
if (scopes) {
|
||||
requestPayload = requestPayload + "&scope=" + scopes;
|
||||
}
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", requestURL, false);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.setRequestHeader("Authorization", "Basic " + encodedClientAppCredentials);
|
||||
xhr.send(requestPayload);
|
||||
|
||||
if (xhr["status"] == 200 && xhr["responseText"]) {
|
||||
var responsePayload = parse(xhr["responseText"]);
|
||||
var tokenPair = {};
|
||||
tokenPair["accessToken"] = responsePayload["access_token"];
|
||||
tokenPair["refreshToken"] = responsePayload["refresh_token"];
|
||||
return tokenPair;
|
||||
} else {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving new access token by " +
|
||||
"current refresh token - getNewTokenPairByRefreshToken(x, y, z)");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["getAccessTokenByJWTGrantType"] = function (clientAppCredentials) {
|
||||
if (!clientAppCredentials) {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving new access token " +
|
||||
"by current refresh token. No client app credentials are found " +
|
||||
"as input - getAccessTokenByJWTGrantType(x)");
|
||||
return null;
|
||||
} else {
|
||||
var JWTClientManagerServicePackagePath =
|
||||
"org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService";
|
||||
//noinspection JSUnresolvedFunction, JSUnresolvedVariable
|
||||
var JWTClientManagerService = carbon.server.osgiService(JWTClientManagerServicePackagePath);
|
||||
//noinspection JSUnresolvedFunction
|
||||
var jwtClient = JWTClientManagerService.getJWTClient();
|
||||
// returning access token by JWT grant type
|
||||
return jwtClient.getAccessToken(clientAppCredentials["clientId"], clientAppCredentials["clientSecret"],
|
||||
deviceMgtProps["oauthProvider"]["appRegistration"]["owner"], null)["accessToken"];
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["getJwtToken"] = function (username, claims) {
|
||||
if (!username) {
|
||||
log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving new jwt token");
|
||||
return null;
|
||||
} else {
|
||||
var JWTClientManagerServicePackagePath =
|
||||
"org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService";
|
||||
//noinspection JSUnresolvedFunction, JSUnresolvedVariable
|
||||
var JWTClientManagerService = carbon.server.osgiService(JWTClientManagerServicePackagePath);
|
||||
//noinspection JSUnresolvedFunction
|
||||
var jwtClient = JWTClientManagerService.getJWTClient();
|
||||
// returning access token by JWT grant type
|
||||
if (claims) {
|
||||
return jwtClient.getJwtToken(username, claims);
|
||||
} else {
|
||||
return jwtClient.getJwtToken(username);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["removeClientAppCredentials"] = function (tenantDomain) {
|
||||
var cachedTenantBasedClientAppCredentialsMap = application.get(constants["CACHED_CREDENTIALS"]);
|
||||
if (cachedTenantBasedClientAppCredentialsMap) {
|
||||
if (cachedTenantBasedClientAppCredentialsMap[tenantDomain]) {
|
||||
delete cachedTenantBasedClientAppCredentialsMap[tenantDomain];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["getUniqueBrowserScope"] = function () {
|
||||
var deviceScope = "device_" + utility.md5(request.getHeader("User-Agent") + "::" + request.getRemoteAddr());
|
||||
deviceScope = deviceScope + " ";
|
||||
return deviceScope;
|
||||
};
|
||||
|
||||
|
||||
|
||||
return publicMethods;
|
||||
}();
|
||||
@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* -----------------------------------------------------
|
||||
* Following module includes handlers
|
||||
* at Jaggery Layer for handling OAuth tokens.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
var handlers = function () {
|
||||
var log = new Log("/app/modules/oauth/token-handlers.js");
|
||||
|
||||
var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"];
|
||||
var constants = require("/app/modules/constants.js");
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var utility = require("/app/modules/utility.js")["utility"];
|
||||
|
||||
var publicMethods = {};
|
||||
var privateMethods = {};
|
||||
|
||||
publicMethods["setupTokenPairByPasswordGrantType"] = function (username, password) {
|
||||
if (!username || !password) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up access token pair by " +
|
||||
"password grant type. Either username of logged in user, password or both are missing " +
|
||||
"as input - setupTokenPairByPasswordGrantType(x, y)");
|
||||
} else {
|
||||
privateMethods.setUpEncodedTenantBasedClientAppCredentials(username);
|
||||
privateMethods.setUpEncodedTenantBasedWebSocketClientAppCredentials(username);
|
||||
var encodedClientAppCredentials = session.get(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"]);
|
||||
if (!encodedClientAppCredentials) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up access token pair by " +
|
||||
"password grant type. Encoded client credentials are " +
|
||||
"missing - setupTokenPairByPasswordGrantType(x, y)");
|
||||
} else {
|
||||
var tokenData;
|
||||
// tokenPair will include current access token as well as current refresh token
|
||||
var arrayOfScopes = devicemgtProps["scopes"];
|
||||
arrayOfScopes = arrayOfScopes.concat(utility.getDeviceTypesScopesList());
|
||||
var stringOfScopes = tokenUtil.getUniqueBrowserScope();
|
||||
arrayOfScopes.forEach(function (entry) {
|
||||
stringOfScopes += entry + " ";
|
||||
});
|
||||
tokenData = tokenUtil.
|
||||
getTokenPairAndScopesByPasswordGrantType(username,
|
||||
encodeURIComponent(password), encodedClientAppCredentials, stringOfScopes);
|
||||
if (!tokenData) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up " +
|
||||
"token pair by password grant type. Error in token " +
|
||||
"retrieval - setupTokenPairByPasswordGrantType(x, y)");
|
||||
} else {
|
||||
var tokenPair = {};
|
||||
tokenPair["accessToken"] = tokenData["accessToken"];
|
||||
tokenPair["refreshToken"] = tokenData["refreshToken"];
|
||||
// setting up token pair into session context as a string
|
||||
session.put(constants["TOKEN_PAIR"], stringify(tokenPair));
|
||||
|
||||
var scopes = tokenData.scopes.split(" ");
|
||||
// adding allowed scopes to the session
|
||||
session.put(constants["ALLOWED_SCOPES"], scopes);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["setupTokenPairBySamlGrantType"] = function (username, samlToken) {
|
||||
if (!username || !samlToken) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up access token pair by " +
|
||||
"saml grant type. Either username of logged in user, samlToken or both are missing " +
|
||||
"as input - setupTokenPairBySamlGrantType(x, y)");
|
||||
} else {
|
||||
privateMethods.setUpEncodedTenantBasedClientAppCredentials(username);
|
||||
privateMethods.setUpEncodedTenantBasedWebSocketClientAppCredentials(username);
|
||||
var encodedClientAppCredentials = session.get(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"]);
|
||||
if (!encodedClientAppCredentials) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up access token pair " +
|
||||
"by saml grant type. Encoded client credentials are " +
|
||||
"missing - setupTokenPairBySamlGrantType(x, y)");
|
||||
} else {
|
||||
var tokenData;
|
||||
var arrayOfScopes = devicemgtProps["scopes"];
|
||||
arrayOfScopes = arrayOfScopes.concat(utility.getDeviceTypesScopesList());
|
||||
var stringOfScopes = tokenUtil.getUniqueBrowserScope();
|
||||
arrayOfScopes.forEach(function (entry) {
|
||||
stringOfScopes += entry + " ";
|
||||
});
|
||||
|
||||
// accessTokenPair will include current access token as well as current refresh token
|
||||
tokenData = tokenUtil.
|
||||
getTokenPairAndScopesBySAMLGrantType(samlToken, encodedClientAppCredentials, stringOfScopes);
|
||||
if (!tokenData) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up token " +
|
||||
"pair by password grant type. Error in token " +
|
||||
"retrieval - setupTokenPairBySamlGrantType(x, y)");
|
||||
} else {
|
||||
var tokenPair = {};
|
||||
tokenPair["accessToken"] = tokenData["accessToken"];
|
||||
tokenPair["refreshToken"] = tokenData["refreshToken"];
|
||||
// setting up access token pair into session context as a string
|
||||
session.put(constants["TOKEN_PAIR"], stringify(tokenPair));
|
||||
|
||||
var scopes = tokenData.scopes.split(" ");
|
||||
// adding allowed scopes to the session
|
||||
session.put(constants["ALLOWED_SCOPES"], scopes);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["setupTokenPairByJWTGrantType"] = function (username, samlToken) {
|
||||
//samlToken is used to validate then if the user is a valid user then token is issued with JWT Grant Type.
|
||||
if (!username || !samlToken) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up access token pair by " +
|
||||
"saml grant type. Either username of logged in user, samlToken or both are missing " +
|
||||
"as input - setupTokenPairBySamlGrantType(x, y)");
|
||||
} else {
|
||||
privateMethods.setUpEncodedTenantBasedClientAppCredentials(username);
|
||||
privateMethods.setUpEncodedTenantBasedWebSocketClientAppCredentials(username);
|
||||
var encodedClientAppCredentials = session.get(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"]);
|
||||
if (!encodedClientAppCredentials) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up access token pair " +
|
||||
"by saml grant type. Encoded client credentials are " +
|
||||
"missing - setupTokenPairBySamlGrantType(x, y)");
|
||||
} else {
|
||||
var tokenData;
|
||||
var arrayOfScopes = devicemgtProps["scopes"];
|
||||
arrayOfScopes = arrayOfScopes.concat(utility.getDeviceTypesScopesList());
|
||||
var stringOfScopes = tokenUtil.getUniqueBrowserScope();
|
||||
arrayOfScopes.forEach(function (entry) {
|
||||
stringOfScopes += entry + " ";
|
||||
});
|
||||
|
||||
// accessTokenPair will include current access token as well as current refresh token
|
||||
tokenData = tokenUtil.
|
||||
getTokenPairAndScopesByJWTGrantType(samlToken, encodedClientAppCredentials, stringOfScopes);
|
||||
if (!tokenData) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up token. Error in token " +
|
||||
"retrieval - setupTokenPairBySamlGrantType(x, y)");
|
||||
} else {
|
||||
var tokenPair = {};
|
||||
tokenPair["accessToken"] = tokenData["accessToken"];
|
||||
tokenPair["refreshToken"] = tokenData["refreshToken"];
|
||||
// setting up access token pair into session context as a string
|
||||
session.put(constants["TOKEN_PAIR"], stringify(tokenPair));
|
||||
|
||||
var scopes = tokenData.scopes.split(" ");
|
||||
// adding allowed scopes to the session
|
||||
session.put(constants["ALLOWED_SCOPES"], scopes);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["refreshTokenPair"] = function () {
|
||||
var currentTokenPair = parse(session.get(constants["TOKEN_PAIR"]));
|
||||
// currentTokenPair includes current access token as well as current refresh token
|
||||
var encodedClientAppCredentials = session.get(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"]);
|
||||
if (!currentTokenPair || !encodedClientAppCredentials) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Error in refreshing tokens. Either the " +
|
||||
"token pair, encoded client app credentials or both input are not found under " +
|
||||
"session context - refreshTokenPair()");
|
||||
} else {
|
||||
var newTokenPair = tokenUtil.
|
||||
getNewTokenPairByRefreshToken(currentTokenPair["refreshToken"], encodedClientAppCredentials);
|
||||
if (!newTokenPair) {
|
||||
log.error("{/app/modules/oauth/token-handlers.js} Error in refreshing token pair. " +
|
||||
"Unable to update session context with new access token pair - refreshTokenPair()");
|
||||
userModule.logout(function () {
|
||||
response.sendRedirect(devicemgtProps["appContext"] + "login");
|
||||
});
|
||||
} else {
|
||||
session.put(constants["TOKEN_PAIR"], stringify(newTokenPair));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
privateMethods["setUpEncodedTenantBasedClientAppCredentials"] = function (username) {
|
||||
if (!username) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up encoded tenant based " +
|
||||
"client credentials to session context. No username of logged in user is found as " +
|
||||
"input - setUpEncodedTenantBasedClientAppCredentials(x)");
|
||||
} else {
|
||||
if (devicemgtProps["gatewayEnabled"]) {
|
||||
var tenantBasedClientAppCredentials = tokenUtil.getTenantBasedClientAppCredentials(username);
|
||||
if (!tenantBasedClientAppCredentials) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up encoded tenant " +
|
||||
"based client credentials to session context as the server is unable " +
|
||||
"to obtain such credentials - setUpEncodedTenantBasedClientAppCredentials(x)");
|
||||
} else {
|
||||
var encodedTenantBasedClientAppCredentials =
|
||||
tokenUtil.encode(tenantBasedClientAppCredentials["clientId"] + ":" +
|
||||
tenantBasedClientAppCredentials["clientSecret"]);
|
||||
// setting up encoded tenant based client credentials to session context.
|
||||
session.put(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"],
|
||||
encodedTenantBasedClientAppCredentials);
|
||||
}
|
||||
} else {
|
||||
var dynamicClientAppCredentials = tokenUtil.getDynamicClientAppCredentials();
|
||||
if (!dynamicClientAppCredentials) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up encoded tenant based " +
|
||||
"client credentials to session context as the server is unable to obtain " +
|
||||
"dynamic client credentials - setUpEncodedTenantBasedClientAppCredentials(x)");
|
||||
}
|
||||
var encodedTenantBasedClientAppCredentials =
|
||||
tokenUtil.encode(dynamicClientAppCredentials["clientId"] + ":" +
|
||||
dynamicClientAppCredentials["clientSecret"]);
|
||||
// setting up encoded tenant based client credentials to session context.
|
||||
session.put(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"],
|
||||
encodedTenantBasedClientAppCredentials);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
privateMethods["setUpEncodedTenantBasedWebSocketClientAppCredentials"] = function (username) {
|
||||
if (!username) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up encoded tenant based " +
|
||||
"client credentials to session context. No username of logged in user is found as " +
|
||||
"input - setUpEncodedTenantBasedWebSocketClientAppCredentials(x)");
|
||||
} else {
|
||||
if (devicemgtProps["gatewayEnabled"]) {
|
||||
var tenantBasedWebSocketClientAppCredentials
|
||||
= tokenUtil.getTenantBasedWebSocketClientAppCredentials(username);
|
||||
if (!tenantBasedWebSocketClientAppCredentials) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up encoded tenant " +
|
||||
"based client credentials to session context as the server is unable " +
|
||||
"to obtain such credentials - setUpEncodedTenantBasedWebSocketClientAppCredentials(x)");
|
||||
} else {
|
||||
var encodedTenantBasedWebSocketClientAppCredentials =
|
||||
tokenUtil.encode(tenantBasedWebSocketClientAppCredentials["clientId"] + ":" +
|
||||
tenantBasedWebSocketClientAppCredentials["clientSecret"]);
|
||||
// setting up encoded tenant based client credentials to session context.
|
||||
session.put(constants["ENCODED_TENANT_BASED_WEB_SOCKET_CLIENT_CREDENTIALS"],
|
||||
encodedTenantBasedWebSocketClientAppCredentials);
|
||||
}
|
||||
} else {
|
||||
var dynamicClientAppCredentials = tokenUtil.getDynamicClientAppCredentials();
|
||||
if (!dynamicClientAppCredentials) {
|
||||
throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up encoded tenant based " +
|
||||
"client credentials to session context as the server is unable to obtain " +
|
||||
"dynamic client credentials - setUpEncodedTenantBasedWebSocketClientAppCredentials(x)");
|
||||
}
|
||||
var encodedTenantBasedWebSocketClientAppCredentials =
|
||||
tokenUtil.encode(dynamicClientAppCredentials["clientId"] + ":" +
|
||||
dynamicClientAppCredentials["clientSecret"]);
|
||||
// setting up encoded tenant based client credentials to session context.
|
||||
session.put(constants["ENCODED_TENANT_BASED_WEB_SOCKET_CLIENT_CREDENTIALS"],
|
||||
encodedTenantBasedWebSocketClientAppCredentials);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods["removeClientDetails"] = function () {
|
||||
var user = session.get(constants.USER_SESSION_KEY);
|
||||
if (!user) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants.ERRORS.USER_NOT_FOUND;
|
||||
}
|
||||
tokenUtil.removeClientAppCredentials(user.domain);
|
||||
session.remove(constants["ENCODED_TENANT_BASED_WEB_SOCKET_CLIENT_CREDENTIALS"]);
|
||||
session.remove(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"]);
|
||||
session.remove(constants["TOKEN_PAIR"]);
|
||||
session.remove(constants["ALLOWED_SCOPES"]);
|
||||
};
|
||||
|
||||
return publicMethods;
|
||||
}();
|
||||
@ -0,0 +1,496 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ----------------------------------------------------------------------------
|
||||
* Following module includes invokers
|
||||
* at Jaggery Layer for calling Backend Services, protected by OAuth Tokens.
|
||||
* These Services include both REST and SOAP Services.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
var invokers = function () {
|
||||
var log = new Log("/app/modules/oauth/token-protected-service-invokers.js");
|
||||
|
||||
var publicXMLHTTPInvokers = {};
|
||||
var publicHTTPClientInvokers = {};
|
||||
|
||||
var privateMethods = {};
|
||||
var publicWSInvokers = {};
|
||||
|
||||
var TOKEN_EXPIRED = "Access token expired";
|
||||
var TOKEN_INVALID = "Invalid input. Access token validation failed";
|
||||
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var constants = require("/app/modules/constants.js");
|
||||
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
|
||||
var tokenUtil = require("/app/modules/oauth/token-handlers.js")["handlers"];
|
||||
|
||||
/**
|
||||
* This method reads the token pair from the session and return the access token.
|
||||
* If the token pair is not set in the session, this will return null.
|
||||
*/
|
||||
privateMethods.getAccessToken = function () {
|
||||
if (session) {
|
||||
var tokenPair = session.get(constants["TOKEN_PAIR"]);
|
||||
if (tokenPair) {
|
||||
return parse(tokenPair)["accessToken"];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------
|
||||
* Start of XML-HTTP-REQUEST based Interceptor implementations
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method add Oauth authentication header to outgoing XML-HTTP Requests if Oauth authentication is enabled.
|
||||
* @param httpMethod HTTP request type.
|
||||
* @param requestPayload payload/data if exists which is needed to be send.
|
||||
* @param endpoint Backend REST API url.
|
||||
* @param responseCallback a function to be called with response retrieved.
|
||||
* @param count a counter which hold the number of recursive execution
|
||||
* @param headers a list of name value pairs for additional http headers
|
||||
*/
|
||||
privateMethods["execute"] = function (httpMethod, requestPayload, endpoint, responseCallback, count, headers) {
|
||||
var xmlHttpRequest = new XMLHttpRequest();
|
||||
|
||||
xmlHttpRequest.open(httpMethod, endpoint);
|
||||
|
||||
var contentTypeFound = false;
|
||||
var acceptTypeFound = false;
|
||||
for (var i in headers) {
|
||||
xmlHttpRequest.setRequestHeader(headers[i].name, headers[i].value);
|
||||
if(constants["CONTENT_TYPE_IDENTIFIER"] == headers[i].name){
|
||||
contentTypeFound = true;
|
||||
}
|
||||
if(constants["ACCEPT_IDENTIFIER"] == headers[i].name){
|
||||
acceptTypeFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!contentTypeFound) {
|
||||
xmlHttpRequest.setRequestHeader(constants["CONTENT_TYPE_IDENTIFIER"], constants["APPLICATION_JSON"]);
|
||||
}
|
||||
|
||||
if (!acceptTypeFound) {
|
||||
xmlHttpRequest.setRequestHeader(constants["ACCEPT_IDENTIFIER"], constants["APPLICATION_JSON"]);
|
||||
}
|
||||
|
||||
if (devicemgtProps["isOAuthEnabled"]) {
|
||||
var accessToken = privateMethods.getAccessToken();
|
||||
if (accessToken == null) {
|
||||
userModule.logout(function () {
|
||||
response.sendRedirect(devicemgtProps["appContext"] + "login");
|
||||
});
|
||||
} else {
|
||||
xmlHttpRequest.setRequestHeader(constants["AUTHORIZATION_HEADER"],
|
||||
constants["BEARER_PREFIX"] + accessToken);
|
||||
}
|
||||
}
|
||||
|
||||
if (requestPayload) {
|
||||
xmlHttpRequest.send(requestPayload);
|
||||
} else {
|
||||
xmlHttpRequest.send();
|
||||
}
|
||||
|
||||
log.debug("Request : " + httpMethod + " " + endpoint);
|
||||
log.debug("Request payload if any : " + stringify(requestPayload));
|
||||
log.debug("Response status : " + xmlHttpRequest.status);
|
||||
log.debug("Response payload if any : " + xmlHttpRequest.responseText);
|
||||
|
||||
if (xmlHttpRequest.status == 401) {
|
||||
if ((xmlHttpRequest.responseText == TOKEN_EXPIRED ||
|
||||
xmlHttpRequest.responseText == TOKEN_INVALID ) && count < 5) {
|
||||
tokenUtil.refreshTokenPair();
|
||||
return privateMethods.execute(httpMethod, requestPayload, endpoint, responseCallback, ++count, headers);
|
||||
} else if (privateMethods.isInvalidClientCredential(xmlHttpRequest.responseText)) {
|
||||
log.error("API application has been removed.");
|
||||
tokenUtil.removeClientDetails();
|
||||
session.invalidate();
|
||||
response.sendRedirect(devicemgtProps["appContext"] + "login");
|
||||
} else if (privateMethods.isInvalidCredential(xmlHttpRequest.responseText)) {
|
||||
tokenUtil.refreshTokenPair();
|
||||
return privateMethods.execute(httpMethod, requestPayload, endpoint, responseCallback, ++count, headers);
|
||||
}
|
||||
} else {
|
||||
return responseCallback(xmlHttpRequest);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This method verify whether the access token is expired using response payload.
|
||||
* This is required when using API gateway.
|
||||
* @param responsePayload response payload.
|
||||
* return true if it is invalid otherwise false.
|
||||
*/
|
||||
privateMethods["isInvalidCredential"] =
|
||||
function (responsePayload) {
|
||||
if (responsePayload) {
|
||||
try {
|
||||
payload = parse(responsePayload);
|
||||
if (payload["fault"]["code"] == 900901) {
|
||||
log.debug("Access token is invalid: " + payload["fault"]["code"]);
|
||||
log.debug(payload["fault"]["description"]);
|
||||
return true;
|
||||
}
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method verify whether the client credential is removed/blocked using response payload.
|
||||
* This is required when using API gateway.
|
||||
* @param responsePayload response payload.
|
||||
* return true if it is invalid otherwise false.
|
||||
*/
|
||||
privateMethods["isInvalidClientCredential"] =
|
||||
function (responsePayload) {
|
||||
if (responsePayload) {
|
||||
try {
|
||||
payload = parse(responsePayload);
|
||||
if (payload["fault"]["message"] == "Invalid Credentials") {
|
||||
return true;
|
||||
}
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method add Oauth authentication header to outgoing XML-HTTP Requests if Oauth authentication is enabled.
|
||||
* @param httpMethod HTTP request type.
|
||||
* @param requestPayload payload/data if exists which is needed to be send.
|
||||
* @param endpoint Backend REST API url.
|
||||
* @param responseCallback a function to be called with response retrieved.
|
||||
*/
|
||||
privateMethods["initiateXMLHTTPRequest"] =
|
||||
function (httpMethod, requestPayload, endpoint, responseCallback, headers) {
|
||||
return privateMethods.execute(httpMethod, requestPayload, endpoint, responseCallback, 0, headers);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method invokes return initiateXMLHttpRequest for get calls.
|
||||
* @param endpoint Backend REST API url.
|
||||
* @param responseCallback a function to be called with response retrieved.
|
||||
*/
|
||||
publicXMLHTTPInvokers["get"] = function (endpoint, responseCallback, headers) {
|
||||
var requestPayload = null;
|
||||
return privateMethods.initiateXMLHTTPRequest(constants["HTTP_GET"], requestPayload, endpoint, responseCallback,
|
||||
headers);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method invokes return initiateXMLHttpRequest for post calls.
|
||||
* @param endpoint Backend REST API url.
|
||||
* @param requestPayload payload/data if exists which is needed to be send.
|
||||
* @param responseCallback a function to be called with response retrieved.
|
||||
*/
|
||||
publicXMLHTTPInvokers["post"] = function (endpoint, requestPayload, responseCallback, headers) {
|
||||
return privateMethods.initiateXMLHTTPRequest(constants["HTTP_POST"], requestPayload, endpoint, responseCallback,
|
||||
headers);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method invokes return initiateXMLHttpRequest for put calls.
|
||||
* @param endpoint Backend REST API url.
|
||||
* @param requestPayload payload/data if exists which is needed to be send.
|
||||
* @param responseCallback a function to be called with response retrieved.
|
||||
*/
|
||||
publicXMLHTTPInvokers["put"] = function (endpoint, requestPayload, responseCallback, headers) {
|
||||
return privateMethods.initiateXMLHTTPRequest(constants["HTTP_PUT"], requestPayload, endpoint, responseCallback,
|
||||
headers);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method invokes return initiateXMLHttpRequest for delete calls.
|
||||
* @param endpoint Backend REST API url.
|
||||
* @param responseCallback a function to be called with response retrieved.
|
||||
*/
|
||||
publicXMLHTTPInvokers["delete"] = function (endpoint, responseCallback, headers) {
|
||||
var requestPayload = null;
|
||||
return privateMethods.initiateXMLHTTPRequest(constants["HTTP_DELETE"], requestPayload, endpoint,
|
||||
responseCallback, headers);
|
||||
};
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------
|
||||
* Start of WS-REQUEST based Interceptor implementations
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method add Oauth authentication header to outgoing WS Requests if Oauth authentication is enabled.
|
||||
* @param action
|
||||
* @param endpoint service end point to be triggered.
|
||||
* @param payload soap payload which need to be send.
|
||||
* @param successCallback a function to be called if the respond if successful.
|
||||
* @param errorCallback a function to be called if en error is reserved.
|
||||
* @param soapVersion soapVersion which need to used.
|
||||
*/
|
||||
privateMethods["initiateWSRequest"] = function (action, endpoint, successCallback,
|
||||
errorCallback, soapVersion, payload) {
|
||||
var ws = require("ws");
|
||||
//noinspection JSUnresolvedFunction
|
||||
var wsRequest = new ws.WSRequest();
|
||||
var options = [];
|
||||
if (devicemgtProps["isOAuthEnabled"]) {
|
||||
var accessToken = privateMethods.getAccessToken();
|
||||
if (accessToken) {
|
||||
var authenticationHeaderName = String(constants["AUTHORIZATION_HEADER"]);
|
||||
var authenticationHeaderValue = String(constants["BEARER_PREFIX"] + accessToken);
|
||||
var headers = [];
|
||||
var oAuthAuthenticationData = {};
|
||||
oAuthAuthenticationData.name = authenticationHeaderName;
|
||||
oAuthAuthenticationData.value = authenticationHeaderValue;
|
||||
headers.push(oAuthAuthenticationData);
|
||||
options.HTTPHeaders = headers;
|
||||
} else {
|
||||
response.sendRedirect(devicemgtProps["appContext"] + "login");
|
||||
}
|
||||
}
|
||||
options.useSOAP = soapVersion;
|
||||
options.useWSA = constants["WEB_SERVICE_ADDRESSING_VERSION"];
|
||||
options.action = action;
|
||||
var wsResponse;
|
||||
try {
|
||||
wsRequest.open(options, endpoint, false);
|
||||
if (payload) {
|
||||
wsRequest.send(payload);
|
||||
} else {
|
||||
wsRequest.send();
|
||||
}
|
||||
wsResponse = wsRequest.responseE4X;
|
||||
} catch (e) {
|
||||
return errorCallback(e);
|
||||
}
|
||||
return successCallback(wsResponse);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method invokes return initiateWSRequest for soap calls.
|
||||
* @param action describes particular soap action.
|
||||
* @param requestPayload SOAP request payload which is needed to be send.
|
||||
* @param endpoint service end point to be triggered.
|
||||
* @param successCallback a function to be called if the respond if successful.
|
||||
* @param errorCallback a function to be called if en error is reserved.
|
||||
* @param soapVersion soapVersion which need to used.
|
||||
*/
|
||||
publicWSInvokers["soapRequest"] = function (action, requestPayload, endpoint,
|
||||
successCallback, errorCallback, soapVersion) {
|
||||
return privateMethods.initiateWSRequest(action, endpoint, successCallback,
|
||||
errorCallback, soapVersion, requestPayload);
|
||||
};
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------
|
||||
* Start of HTTP-CLIENT-REQUEST based Interceptor implementations
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method add Oauth authentication header to outgoing HTTPClient Requests if Oauth authentication is enabled.
|
||||
* @param method HTTP request type.
|
||||
* @param url target url.
|
||||
* @param payload payload/data which need to be send.
|
||||
* @param successCallback a function to be called if the respond if successful.
|
||||
* @param errorCallback a function to be called if en error is reserved.
|
||||
* @param headers a list of name value pairs for additional http headers.
|
||||
*/
|
||||
privateMethods["initiateHTTPClientRequest"] =
|
||||
function (method, url, successCallback, errorCallback, payload, headers) {
|
||||
//noinspection JSUnresolvedVariable
|
||||
var HttpClient = Packages.org.apache.commons.httpclient.HttpClient;
|
||||
var httpMethodObject;
|
||||
switch (method) {
|
||||
case constants["HTTP_GET"]:
|
||||
//noinspection JSUnresolvedVariable
|
||||
var GetMethod = Packages.org.apache.commons.httpclient.methods.GetMethod;
|
||||
httpMethodObject = new GetMethod(url);
|
||||
break;
|
||||
case constants["HTTP_POST"]:
|
||||
//noinspection JSUnresolvedVariable
|
||||
var PostMethod = Packages.org.apache.commons.httpclient.methods.PostMethod;
|
||||
httpMethodObject = new PostMethod(url);
|
||||
break;
|
||||
case constants["HTTP_PUT"]:
|
||||
//noinspection JSUnresolvedVariable
|
||||
var PutMethod = Packages.org.apache.commons.httpclient.methods.PutMethod;
|
||||
httpMethodObject = new PutMethod(url);
|
||||
break;
|
||||
case constants["HTTP_DELETE"]:
|
||||
//noinspection JSUnresolvedVariable
|
||||
var DeleteMethod = Packages.org.apache.commons.httpclient.methods.DeleteMethod;
|
||||
httpMethodObject = new DeleteMethod(url);
|
||||
break;
|
||||
default:
|
||||
//noinspection JSUnresolvedFunction
|
||||
throw new IllegalArgumentException("Invalid HTTP request method: " + method);
|
||||
}
|
||||
|
||||
//noinspection JSUnresolvedVariable
|
||||
var Header = Packages.org.apache.commons.httpclient.Header;
|
||||
var contentTypeFound = false;
|
||||
var acceptTypeFound = false;
|
||||
var acceptTypeValue = constants["APPLICATION_JSON"];
|
||||
for (var i in headers) {
|
||||
var header = new Header();
|
||||
header.setName(headers[i].name);
|
||||
header.setValue(headers[i].value);
|
||||
httpMethodObject.addRequestHeader(header);
|
||||
|
||||
if(constants["CONTENT_TYPE_IDENTIFIER"] == headers[i].name){
|
||||
contentTypeFound = true;
|
||||
}
|
||||
if(constants["ACCEPT_IDENTIFIER"] == headers[i].name){
|
||||
acceptTypeFound = true;
|
||||
acceptTypeValue = headers[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
var header = new Header();
|
||||
if(!contentTypeFound){
|
||||
header.setName(constants["CONTENT_TYPE_IDENTIFIER"]);
|
||||
header.setValue(constants["APPLICATION_JSON"]);
|
||||
//noinspection JSUnresolvedFunction
|
||||
httpMethodObject.addRequestHeader(header);
|
||||
}
|
||||
|
||||
if(!acceptTypeFound) {
|
||||
header = new Header();
|
||||
header.setName(constants["ACCEPT_IDENTIFIER"]);
|
||||
header.setValue(constants["APPLICATION_JSON"]);
|
||||
//noinspection JSUnresolvedFunction
|
||||
httpMethodObject.addRequestHeader(header);
|
||||
}
|
||||
|
||||
if (devicemgtProps["isOAuthEnabled"]) {
|
||||
var accessToken = privateMethods.getAccessToken();
|
||||
if (accessToken) {
|
||||
header = new Header();
|
||||
header.setName(constants["AUTHORIZATION_HEADER"]);
|
||||
header.setValue(constants["BEARER_PREFIX"] + accessToken);
|
||||
//noinspection JSUnresolvedFunction
|
||||
httpMethodObject.addRequestHeader(header);
|
||||
} else {
|
||||
response.sendRedirect(devicemgtProps["appContext"] + "login");
|
||||
}
|
||||
}
|
||||
//noinspection JSUnresolvedFunction
|
||||
if (payload != null) {
|
||||
var StringRequestEntity = Packages.org.apache.commons.httpclient.methods.StringRequestEntity;
|
||||
var stringRequestEntity = new StringRequestEntity(stringify(payload));
|
||||
//noinspection JSUnresolvedFunction
|
||||
httpMethodObject.setRequestEntity(stringRequestEntity);
|
||||
}
|
||||
var client = new HttpClient();
|
||||
try {
|
||||
//noinspection JSUnresolvedFunction
|
||||
client.executeMethod(httpMethodObject);
|
||||
//noinspection JSUnresolvedFunction
|
||||
var status = httpMethodObject.getStatusCode();
|
||||
if (status >= 200 && status < 300) {
|
||||
if (constants["STREAMING_FILES_ACCEPT_HEADERS"].indexOf(acceptTypeValue) > -1) {
|
||||
return successCallback(httpMethodObject.getResponseBodyAsStream(),
|
||||
httpMethodObject.getResponseHeaders());
|
||||
} else {
|
||||
return successCallback(httpMethodObject.getResponseBodyAsString(),
|
||||
httpMethodObject.getResponseHeaders());
|
||||
}
|
||||
} else {
|
||||
return errorCallback(httpMethodObject.getResponseBodyAsString(),
|
||||
httpMethodObject.getResponseHeaders());
|
||||
}
|
||||
} catch (e) {
|
||||
return errorCallback(response);
|
||||
} finally {
|
||||
//noinspection JSUnresolvedFunction
|
||||
if (method != constants["HTTP_GET"]) {
|
||||
method.releaseConnection();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This method invokes return initiateHTTPClientRequest for get calls.
|
||||
* @param url target url.
|
||||
* @param successCallback a function to be called if the respond if successful.
|
||||
* @param errorCallback a function to be called if en error is reserved.
|
||||
* @param headers a list of name value pairs for additional http headers.
|
||||
*/
|
||||
publicHTTPClientInvokers["get"] = function (url, successCallback, errorCallback, headers) {
|
||||
var requestPayload = null;
|
||||
return privateMethods.initiateHTTPClientRequest(constants["HTTP_GET"], url, successCallback, errorCallback,
|
||||
requestPayload, headers);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method invokes return initiateHTTPClientRequest for post calls.
|
||||
* @param url target url.
|
||||
* @param payload payload/data which need to be send.
|
||||
* @param successCallback a function to be called if the respond if successful.
|
||||
* @param errorCallback a function to be called if en error is reserved.
|
||||
* @param headers a list of name value pairs for additional http headers.
|
||||
*/
|
||||
publicHTTPClientInvokers["post"] = function (url, payload, successCallback, errorCallback, headers) {
|
||||
return privateMethods.initiateHTTPClientRequest(constants["HTTP_POST"], url, successCallback, errorCallback,
|
||||
payload, headers);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method invokes return initiateHTTPClientRequest for put calls.
|
||||
* @param url target url.
|
||||
* @param payload payload/data which need to be send.
|
||||
* @param successCallback a function to be called if the respond if successful.
|
||||
* @param errorCallback a function to be called if en error is reserved.
|
||||
* @param headers a list of name value pairs for additional http headers.
|
||||
*/
|
||||
publicHTTPClientInvokers["put"] = function (url, payload, successCallback, errorCallback, headers) {
|
||||
return privateMethods.initiateHTTPClientRequest(constants["HTTP_PUT"], url, successCallback, errorCallback,
|
||||
payload, headers);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method invokes return initiateHTTPClientRequest for delete calls.
|
||||
* @param url target url.
|
||||
* @param successCallback a function to be called if the respond if successful.
|
||||
* @param errorCallback a function to be called if en error is reserved.
|
||||
* @param headers a list of name value pairs for additional http headers.
|
||||
*/
|
||||
publicHTTPClientInvokers["delete"] = function (url, successCallback, errorCallback, headers) {
|
||||
var requestPayload = null;
|
||||
return privateMethods.initiateHTTPClientRequest(constants["HTTP_DELETE"], url, successCallback, errorCallback,
|
||||
requestPayload, headers);
|
||||
};
|
||||
|
||||
var publicMethods = {};
|
||||
publicMethods.XMLHttp = publicXMLHTTPInvokers;
|
||||
publicMethods.WS = publicWSInvokers;
|
||||
publicMethods.HttpClient = publicHTTPClientInvokers;
|
||||
|
||||
return publicMethods;
|
||||
}();
|
||||
@ -0,0 +1,396 @@
|
||||
/*
|
||||
* 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 utility;
|
||||
utility = function () {
|
||||
|
||||
var constants = require('/app/modules/constants.js');
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var log = new Log("/app/modules/utility.js");
|
||||
var JavaClass = Packages.java.lang.Class;
|
||||
var PrivilegedCarbonContext = Packages.org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||
var server = require("carbon")["server"];
|
||||
|
||||
var getOsgiService = function (className) {
|
||||
return PrivilegedCarbonContext.getThreadLocalCarbonContext().getOSGiService(JavaClass.forName(className));
|
||||
};
|
||||
|
||||
var deviceTypeConfigMap = {};
|
||||
|
||||
var publicMethods = {};
|
||||
|
||||
publicMethods.startTenantFlow = function (userInfo) {
|
||||
var context, carbon = require('carbon');
|
||||
PrivilegedCarbonContext.startTenantFlow();
|
||||
context = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||
context.setTenantDomain(carbon.server.tenantDomain({
|
||||
tenantId: userInfo.tenantId
|
||||
}));
|
||||
context.setTenantId(userInfo.tenantId);
|
||||
context.setUsername(userInfo.username || null);
|
||||
};
|
||||
|
||||
publicMethods.endTenantFlow = function () {
|
||||
PrivilegedCarbonContext.endTenantFlow();
|
||||
};
|
||||
|
||||
publicMethods.getDeviceManagementService = function () {
|
||||
return getOsgiService('org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService');
|
||||
};
|
||||
|
||||
publicMethods.getAPIManagementProviderService = function () {
|
||||
return getOsgiService('org.wso2.carbon.apimgt.application.extension.APIManagementProviderService');
|
||||
};
|
||||
|
||||
publicMethods.getUserManagementService = function () {
|
||||
return getOsgiService("org.wso2.carbon.device.mgt.user.core.UserManager");
|
||||
};
|
||||
|
||||
publicMethods.getPolicyManagementService = function () {
|
||||
return getOsgiService("org.wso2.carbon.policy.mgt.core.PolicyManagerService");
|
||||
};
|
||||
|
||||
publicMethods.getDeviceTypeConfig = function (deviceType) {
|
||||
var unitName = publicMethods.getTenantedDeviceUnitName(deviceType, "type-view");
|
||||
if (!unitName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (deviceType in deviceTypeConfigMap) {
|
||||
return deviceTypeConfigMap[deviceType];
|
||||
}
|
||||
var deviceTypeConfig;
|
||||
var deviceTypeConfigFile = new File("/app/units/" + unitName + "/private/config.json");
|
||||
if (deviceTypeConfigFile.isExists()) {
|
||||
try {
|
||||
deviceTypeConfigFile.open("r");
|
||||
var config = deviceTypeConfigFile.readAll();
|
||||
config = config.replace("%https.ip%", server.address("https"));
|
||||
config = config.replace("%http.ip%", server.address("http"));
|
||||
deviceTypeConfig = parse(config);
|
||||
} catch (err) {
|
||||
log.error("Error while reading device config file for `" + deviceType + "`: " + err);
|
||||
} finally {
|
||||
deviceTypeConfigFile.close();
|
||||
}
|
||||
}
|
||||
deviceTypeConfigMap[deviceType] = deviceTypeConfig;
|
||||
return deviceTypeConfig;
|
||||
};
|
||||
|
||||
publicMethods.getOperationIcon = function (deviceType, operation) {
|
||||
var unitName = publicMethods.getTenantedDeviceUnitName(deviceType, "type-view");
|
||||
var iconPath = "/app/units/" + unitName + "/public/images/operations/" + operation + ".png";
|
||||
var icon = new File(iconPath);
|
||||
if (icon.isExists()) {
|
||||
return devicemgtProps["appContext"] + "public/" + unitName + "/images/operations/" + operation + ".png";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods.getDeviceThumb = function (deviceType) {
|
||||
var unitName = publicMethods.getTenantedDeviceUnitName(deviceType, "type-view");
|
||||
if (!unitName) {
|
||||
unitName = "cdmf.unit.default.device.type.type-view";
|
||||
}
|
||||
var iconPath = "/app/units/" + unitName + "/public/images/thumb.png";
|
||||
var icon = new File(iconPath);
|
||||
if (icon.isExists()) {
|
||||
return devicemgtProps["appContext"] + "public/" + unitName + "/images/thumb.png";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods.getTenantedDeviceUnitName = function (deviceType, unitPostfix) {
|
||||
var user = session.get(constants.USER_SESSION_KEY);
|
||||
if (!user) {
|
||||
log.error("User object was not found in the session");
|
||||
throw constants.ERRORS.USER_NOT_FOUND;
|
||||
}
|
||||
var unitName = user.domain + ".cdmf.unit.device.type." + deviceType + "." + unitPostfix;
|
||||
if (new File("/app/units/" + unitName).isExists()) {
|
||||
return unitName;
|
||||
}
|
||||
unitName = "cdmf.unit.device.type." + deviceType + "." + unitPostfix;
|
||||
if (new File("/app/units/" + unitName).isExists()) {
|
||||
return unitName;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
publicMethods.getDeviceTypesScopesList = function () {
|
||||
var dirs = new File("/app/units/").listFiles();
|
||||
var scopesList = [];
|
||||
for (var i = 0; i < dirs.length; i++) {
|
||||
var unitName = dirs[i].getName();
|
||||
if (unitName.match(/^cdmf\.unit\.device\.type\..*\.type-view$/g)) {
|
||||
var deviceTypeConfigFile = new File("/app/units/" + unitName + "/private/config.json");
|
||||
if (deviceTypeConfigFile.isExists()) {
|
||||
try {
|
||||
deviceTypeConfigFile.open("r");
|
||||
var config = deviceTypeConfigFile.readAll();
|
||||
config = config.replace("%https.ip%", server.address("https"));
|
||||
config = config.replace("%http.ip%", server.address("http"));
|
||||
var deviceTypeConfig = parse(config);
|
||||
if (deviceTypeConfig.deviceType && deviceTypeConfig.deviceType.scopes) {
|
||||
scopesList = scopesList.concat(deviceTypeConfig.deviceType.scopes);
|
||||
}
|
||||
} catch (err) {
|
||||
log.error("Error while reading device config file for `" + deviceType + "`: " + err);
|
||||
} finally {
|
||||
deviceTypeConfigFile.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return scopesList;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Escapes special characters such as <,>,',",...etc
|
||||
* This will prevent XSS attacks upon JSON.
|
||||
* @param text
|
||||
* @returns {*}
|
||||
*/
|
||||
publicMethods.encodeJson = function (text) {
|
||||
if (text) {
|
||||
return text
|
||||
.replace(/\\u003c/g, "<")
|
||||
.replace(/</g, "<")
|
||||
.replace(/\\u003e/g, ">")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/\\u0027/g, "'")
|
||||
.replace(/'/g, "'")
|
||||
.replace(/\\"/g, """)
|
||||
.replace(/\\u0022/g, """);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
publicMethods.md5 = function (s) {
|
||||
function L(k, d) {
|
||||
return (k << d) | (k >>> (32 - d))
|
||||
}
|
||||
|
||||
function K(G, k) {
|
||||
var I, d, F, H, x;
|
||||
F = (G & 2147483648);
|
||||
H = (k & 2147483648);
|
||||
I = (G & 1073741824);
|
||||
d = (k & 1073741824);
|
||||
x = (G & 1073741823) + (k & 1073741823);
|
||||
if (I & d) {
|
||||
return (x ^ 2147483648 ^ F ^ H)
|
||||
}
|
||||
if (I | d) {
|
||||
if (x & 1073741824) {
|
||||
return (x ^ 3221225472 ^ F ^ H)
|
||||
} else {
|
||||
return (x ^ 1073741824 ^ F ^ H)
|
||||
}
|
||||
} else {
|
||||
return (x ^ F ^ H)
|
||||
}
|
||||
}
|
||||
|
||||
function r(d, F, k) {
|
||||
return (d & F) | ((~d) & k)
|
||||
}
|
||||
|
||||
function q(d, F, k) {
|
||||
return (d & k) | (F & (~k))
|
||||
}
|
||||
|
||||
function p(d, F, k) {
|
||||
return (d ^ F ^ k)
|
||||
}
|
||||
|
||||
function n(d, F, k) {
|
||||
return (F ^ (d | (~k)))
|
||||
}
|
||||
|
||||
function u(G, F, aa, Z, k, H, I) {
|
||||
G = K(G, K(K(r(F, aa, Z), k), I));
|
||||
return K(L(G, H), F)
|
||||
}
|
||||
|
||||
function f(G, F, aa, Z, k, H, I) {
|
||||
G = K(G, K(K(q(F, aa, Z), k), I));
|
||||
return K(L(G, H), F)
|
||||
}
|
||||
|
||||
function D(G, F, aa, Z, k, H, I) {
|
||||
G = K(G, K(K(p(F, aa, Z), k), I));
|
||||
return K(L(G, H), F)
|
||||
}
|
||||
|
||||
function t(G, F, aa, Z, k, H, I) {
|
||||
G = K(G, K(K(n(F, aa, Z), k), I));
|
||||
return K(L(G, H), F)
|
||||
}
|
||||
|
||||
function e(G) {
|
||||
var Z;
|
||||
var F = G.length;
|
||||
var x = F + 8;
|
||||
var k = (x - (x % 64)) / 64;
|
||||
var I = (k + 1) * 16;
|
||||
var aa = Array(I - 1);
|
||||
var d = 0;
|
||||
var H = 0;
|
||||
while (H < F) {
|
||||
Z = (H - (H % 4)) / 4;
|
||||
d = (H % 4) * 8;
|
||||
aa[Z] = (aa[Z] | (G.charCodeAt(H) << d));
|
||||
H++
|
||||
}
|
||||
Z = (H - (H % 4)) / 4;
|
||||
d = (H % 4) * 8;
|
||||
aa[Z] = aa[Z] | (128 << d);
|
||||
aa[I - 2] = F << 3;
|
||||
aa[I - 1] = F >>> 29;
|
||||
return aa
|
||||
}
|
||||
|
||||
function B(x) {
|
||||
var k = "", F = "", G, d;
|
||||
for (d = 0; d <= 3; d++) {
|
||||
G = (x >>> (d * 8)) & 255;
|
||||
F = "0" + G.toString(16);
|
||||
k = k + F.substr(F.length - 2, 2)
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
function J(k) {
|
||||
k = k.replace(/rn/g, "n");
|
||||
var d = "";
|
||||
for (var F = 0; F < k.length; F++) {
|
||||
var x = k.charCodeAt(F);
|
||||
if (x < 128) {
|
||||
d += String.fromCharCode(x)
|
||||
} else {
|
||||
if ((x > 127) && (x < 2048)) {
|
||||
d += String.fromCharCode((x >> 6) | 192);
|
||||
d += String.fromCharCode((x & 63) | 128)
|
||||
} else {
|
||||
d += String.fromCharCode((x >> 12) | 224);
|
||||
d += String.fromCharCode(((x >> 6) & 63) | 128);
|
||||
d += String.fromCharCode((x & 63) | 128)
|
||||
}
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
var C = Array();
|
||||
var P, h, E, v, g, Y, X, W, V;
|
||||
var S = 7, Q = 12, N = 17, M = 22;
|
||||
var A = 5, z = 9, y = 14, w = 20;
|
||||
var o = 4, m = 11, l = 16, j = 23;
|
||||
var U = 6, T = 10, R = 15, O = 21;
|
||||
s = J(s);
|
||||
C = e(s);
|
||||
Y = 1732584193;
|
||||
X = 4023233417;
|
||||
W = 2562383102;
|
||||
V = 271733878;
|
||||
for (P = 0; P < C.length; P += 16) {
|
||||
h = Y;
|
||||
E = X;
|
||||
v = W;
|
||||
g = V;
|
||||
Y = u(Y, X, W, V, C[P + 0], S, 3614090360);
|
||||
V = u(V, Y, X, W, C[P + 1], Q, 3905402710);
|
||||
W = u(W, V, Y, X, C[P + 2], N, 606105819);
|
||||
X = u(X, W, V, Y, C[P + 3], M, 3250441966);
|
||||
Y = u(Y, X, W, V, C[P + 4], S, 4118548399);
|
||||
V = u(V, Y, X, W, C[P + 5], Q, 1200080426);
|
||||
W = u(W, V, Y, X, C[P + 6], N, 2821735955);
|
||||
X = u(X, W, V, Y, C[P + 7], M, 4249261313);
|
||||
Y = u(Y, X, W, V, C[P + 8], S, 1770035416);
|
||||
V = u(V, Y, X, W, C[P + 9], Q, 2336552879);
|
||||
W = u(W, V, Y, X, C[P + 10], N, 4294925233);
|
||||
X = u(X, W, V, Y, C[P + 11], M, 2304563134);
|
||||
Y = u(Y, X, W, V, C[P + 12], S, 1804603682);
|
||||
V = u(V, Y, X, W, C[P + 13], Q, 4254626195);
|
||||
W = u(W, V, Y, X, C[P + 14], N, 2792965006);
|
||||
X = u(X, W, V, Y, C[P + 15], M, 1236535329);
|
||||
Y = f(Y, X, W, V, C[P + 1], A, 4129170786);
|
||||
V = f(V, Y, X, W, C[P + 6], z, 3225465664);
|
||||
W = f(W, V, Y, X, C[P + 11], y, 643717713);
|
||||
X = f(X, W, V, Y, C[P + 0], w, 3921069994);
|
||||
Y = f(Y, X, W, V, C[P + 5], A, 3593408605);
|
||||
V = f(V, Y, X, W, C[P + 10], z, 38016083);
|
||||
W = f(W, V, Y, X, C[P + 15], y, 3634488961);
|
||||
X = f(X, W, V, Y, C[P + 4], w, 3889429448);
|
||||
Y = f(Y, X, W, V, C[P + 9], A, 568446438);
|
||||
V = f(V, Y, X, W, C[P + 14], z, 3275163606);
|
||||
W = f(W, V, Y, X, C[P + 3], y, 4107603335);
|
||||
X = f(X, W, V, Y, C[P + 8], w, 1163531501);
|
||||
Y = f(Y, X, W, V, C[P + 13], A, 2850285829);
|
||||
V = f(V, Y, X, W, C[P + 2], z, 4243563512);
|
||||
W = f(W, V, Y, X, C[P + 7], y, 1735328473);
|
||||
X = f(X, W, V, Y, C[P + 12], w, 2368359562);
|
||||
Y = D(Y, X, W, V, C[P + 5], o, 4294588738);
|
||||
V = D(V, Y, X, W, C[P + 8], m, 2272392833);
|
||||
W = D(W, V, Y, X, C[P + 11], l, 1839030562);
|
||||
X = D(X, W, V, Y, C[P + 14], j, 4259657740);
|
||||
Y = D(Y, X, W, V, C[P + 1], o, 2763975236);
|
||||
V = D(V, Y, X, W, C[P + 4], m, 1272893353);
|
||||
W = D(W, V, Y, X, C[P + 7], l, 4139469664);
|
||||
X = D(X, W, V, Y, C[P + 10], j, 3200236656);
|
||||
Y = D(Y, X, W, V, C[P + 13], o, 681279174);
|
||||
V = D(V, Y, X, W, C[P + 0], m, 3936430074);
|
||||
W = D(W, V, Y, X, C[P + 3], l, 3572445317);
|
||||
X = D(X, W, V, Y, C[P + 6], j, 76029189);
|
||||
Y = D(Y, X, W, V, C[P + 9], o, 3654602809);
|
||||
V = D(V, Y, X, W, C[P + 12], m, 3873151461);
|
||||
W = D(W, V, Y, X, C[P + 15], l, 530742520);
|
||||
X = D(X, W, V, Y, C[P + 2], j, 3299628645);
|
||||
Y = t(Y, X, W, V, C[P + 0], U, 4096336452);
|
||||
V = t(V, Y, X, W, C[P + 7], T, 1126891415);
|
||||
W = t(W, V, Y, X, C[P + 14], R, 2878612391);
|
||||
X = t(X, W, V, Y, C[P + 5], O, 4237533241);
|
||||
Y = t(Y, X, W, V, C[P + 12], U, 1700485571);
|
||||
V = t(V, Y, X, W, C[P + 3], T, 2399980690);
|
||||
W = t(W, V, Y, X, C[P + 10], R, 4293915773);
|
||||
X = t(X, W, V, Y, C[P + 1], O, 2240044497);
|
||||
Y = t(Y, X, W, V, C[P + 8], U, 1873313359);
|
||||
V = t(V, Y, X, W, C[P + 15], T, 4264355552);
|
||||
W = t(W, V, Y, X, C[P + 6], R, 2734768916);
|
||||
X = t(X, W, V, Y, C[P + 13], O, 1309151649);
|
||||
Y = t(Y, X, W, V, C[P + 4], U, 4149444226);
|
||||
V = t(V, Y, X, W, C[P + 11], T, 3174756917);
|
||||
W = t(W, V, Y, X, C[P + 2], R, 718787259);
|
||||
X = t(X, W, V, Y, C[P + 9], O, 3951481745);
|
||||
Y = K(Y, h);
|
||||
X = K(X, E);
|
||||
W = K(W, v);
|
||||
V = K(V, g)
|
||||
}
|
||||
var i = B(Y) + B(X) + B(W) + B(V);
|
||||
return i.toLowerCase()
|
||||
};
|
||||
|
||||
return publicMethods;
|
||||
}();
|
||||
@ -0,0 +1,234 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{unit "cdmf.unit.ui.title" pageTitle="Home"}}
|
||||
|
||||
{{#zone "breadcrumbs"}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/">
|
||||
<i class="icon fw fw-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "content"}}
|
||||
<div class="row">
|
||||
{{#if permissions.VIEW_DASHBOARD}}
|
||||
<div class="col-md-3 wr-stats-board">
|
||||
<div class="wr-stats-board-tile">
|
||||
<div class="tile-name">Devices</div>
|
||||
<div>
|
||||
<div class="tile-icon"><i class="fw fw-mobile"></i></div>
|
||||
<div class="tile-stats">
|
||||
<span id="device-count">{{deviceCount}}</span>
|
||||
<span class="tile-stats-free">
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
{{#if deviceCount}}
|
||||
<a href="{{@app.context}}/devices">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-view fw-stack-1x"></i>
|
||||
</span>
|
||||
View
|
||||
</a>
|
||||
{{/if}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/device/enroll">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
</span>
|
||||
Add
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 wr-stats-board">
|
||||
<div class="wr-stats-board-tile">
|
||||
<div class="tile-name">Groups</div>
|
||||
<div>
|
||||
<div class="tile-icon"><i class="fw fw-group"></i></div>
|
||||
<div class="tile-stats">
|
||||
<span id="group-count">{{groupCount}}</span>
|
||||
<span class="tile-stats-free">
|
||||
{{#if groupCount}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/groups">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-view fw-stack-1x"></i>
|
||||
</span>
|
||||
View
|
||||
</a>
|
||||
{{/if}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
|
||||
<a href="{{@app.context}}/group/add">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
</span>
|
||||
Add
|
||||
</a>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 wr-stats-board">
|
||||
<div class="wr-stats-board-tile">
|
||||
<div class="tile-name">Users</div>
|
||||
<div>
|
||||
<div class="tile-icon"><i class="fw fw-user"></i></div>
|
||||
<div class="tile-stats">
|
||||
<span id="user-count">{{userCount}}</span>
|
||||
<span class="tile-stats-free">
|
||||
{{#if userCount}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/users">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-view fw-stack-1x"></i>
|
||||
</span>
|
||||
View
|
||||
</a>
|
||||
{{/if}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
{{#unless isCloud}}
|
||||
<a href="{{@app.context}}/user/add">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
</span>
|
||||
Add
|
||||
</a>
|
||||
{{/unless}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 wr-stats-board">
|
||||
<div class="wr-stats-board-tile">
|
||||
<div class="tile-name">Policies</div>
|
||||
<div>
|
||||
<div class="tile-icon"><i class="fw fw-policy"></i></div>
|
||||
<div class="tile-stats">
|
||||
<span id="policy-count">{{policyCount}}</span>
|
||||
<span class="tile-stats-free">
|
||||
{{#if policyCount}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/policies">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-view fw-stack-1x"></i>
|
||||
</span>
|
||||
View
|
||||
</a>
|
||||
{{/if}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
|
||||
<a href="{{@app.context}}/policy/add">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
</span>
|
||||
Add
|
||||
</a>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 wr-stats-board">
|
||||
<div class="wr-stats-board-tile">
|
||||
<div class="tile-name">Roles</div>
|
||||
<div>
|
||||
<div class="tile-icon"><i class="fw fw-bookmark"></i></div>
|
||||
<div class="tile-stats">
|
||||
<span id="role-count">{{roleCount}}</span>
|
||||
<span class="tile-stats-free">
|
||||
{{#if roleCount}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a id="device-count-view-btn" href="{{@app.context}}/roles">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-view fw-stack-1x"></i>
|
||||
</span>
|
||||
View
|
||||
</a>
|
||||
{{/if}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
{{#unless isCloud}}
|
||||
<a href="{{@app.context}}/role/add">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
</span>
|
||||
Add
|
||||
</a>
|
||||
{{/unless}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#if permissions.IS_ADMIN}}
|
||||
<div class="col-md-3 wr-stats-board">
|
||||
<div class="wr-stats-board-tile">
|
||||
<div class="tile-name">Device Types</div>
|
||||
<div>
|
||||
<div class="tile-icon"><i class="fw fw-devices"></i></div>
|
||||
<div class="tile-stats">
|
||||
<span id="device-types-count">{{deviceTypeCount}}</span>
|
||||
<span class="tile-stats-free">
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
{{#if deviceTypeCount}}
|
||||
<a href="{{@app.context}}/device-types">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-view fw-stack-1x"></i>
|
||||
</span>
|
||||
View
|
||||
</a>
|
||||
{{/if}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/device-type/add">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
</span>
|
||||
Add
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{else}}
|
||||
<h1 class="page-sub-title">
|
||||
Permitted None
|
||||
</h1>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/zone}}
|
||||
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 constants = require("/app/modules/constants.js");
|
||||
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
|
||||
var groupModule = require("/app/modules/business-controllers/group.js")["groupModule"];
|
||||
var policyModule = require("/app/modules/business-controllers/policy.js")["policyModule"];
|
||||
|
||||
if(!session.get(constants["TOKEN_PAIR"])){
|
||||
response.sendRedirect(context.app.context + "/welcome");
|
||||
return;
|
||||
}
|
||||
|
||||
var user = session.get(constants["USER_SESSION_KEY"]);
|
||||
var permissions = userModule.getUIPermissions();
|
||||
|
||||
if (!permissions.VIEW_DASHBOARD) {
|
||||
response.sendRedirect(devicemgtProps["appContext"] + "devices");
|
||||
return;
|
||||
}
|
||||
|
||||
var viewModel = {};
|
||||
viewModel.permissions = permissions;
|
||||
viewModel.enrollmentURL = devicemgtProps.enrollmentURL;
|
||||
viewModel.deviceCount = deviceModule.getDevicesCount();
|
||||
viewModel.groupCount = groupModule.getGroupCount();
|
||||
viewModel.userCount = userModule.getUsersCount();
|
||||
viewModel.policyCount = policyModule.getPoliciesCount();
|
||||
viewModel.deviceTypeCount = deviceModule.getDeviceTypeCount();
|
||||
viewModel.isCloud = devicemgtProps.isCloud;
|
||||
if (devicemgtProps.isCloud) {
|
||||
viewModel.roleCount = userModule.getFilteredRoles("devicemgt").content.count;
|
||||
} else {
|
||||
viewModel.roleCount = userModule.getRolesCount();
|
||||
}
|
||||
return viewModel;
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/",
|
||||
"layout": "cdmf.layout.default"
|
||||
}
|
||||
@ -0,0 +1,541 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{unit "cdmf.unit.ui.title" pageTitle="Device Management"}}
|
||||
|
||||
{{unit "cdmf.unit.data-tables-extended"}}
|
||||
{{unit "cdmf.unit.lib.ui-permissions-utility"}}
|
||||
|
||||
{{#zone "breadcrumbs"}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/">
|
||||
<i class="icon fw fw-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
{{#if group}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/groups">
|
||||
Groups
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
{{group.name}}
|
||||
</a>
|
||||
</li>
|
||||
{{else}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/devices">
|
||||
Devices
|
||||
</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "navbarActions"}}
|
||||
{{#if group}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/devices" class="cu-btn">
|
||||
<span class="icon fw-stack">
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
</span>
|
||||
Assign from My Devices
|
||||
</a>
|
||||
</li>
|
||||
<!--<li>
|
||||
<a href="{{@app.context}}/group/{{group.id}}/analytics" class="cu-btn">
|
||||
<span class="icon fw-stack">
|
||||
<i class="fw fw-statistics fw-stack-1x"></i>
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
</span>
|
||||
View Analytics
|
||||
</a>
|
||||
</li>-->
|
||||
{{else}}
|
||||
{{#if permissions.enroll}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/device/enroll" class="cu-btn">
|
||||
<span class="icon fw-stack">
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
</span>
|
||||
Enroll Device
|
||||
</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "content"}}
|
||||
{{#if group}}
|
||||
<h1 class="page-sub-title">
|
||||
{{group.name}} group
|
||||
</h1>
|
||||
<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 col-lg-2">
|
||||
<div class="icon">
|
||||
<img src="/devicemgt/public/cdmf.page.groups/images/group-icon.png"
|
||||
style="background-color: #11375b; height: 152px;">
|
||||
</div>
|
||||
</div>
|
||||
<div class="media-body asset-desc add-padding-left-5x">
|
||||
<div style="background: #11375B; color: #fff; padding: 10px; margin-bottom: 5px">
|
||||
Overview
|
||||
</div>
|
||||
<table class="table table-responsive table-striped" id="members" style="margin-bottom: 0px;">
|
||||
<tbody>
|
||||
<tr role="row" class="even">
|
||||
<td class="sorting_1" style="padding:10px 15px; width: 15%;">Owner</td>
|
||||
<td id="group_owner" style="padding:10px 15px;">{{group.owner}}</td>
|
||||
</tr>
|
||||
<tr role="row" class="odd">
|
||||
<td class="sorting_1" style="padding:10px 15px; width: 15%;">Shared with roles</td>
|
||||
<td style="padding:10px 15px;">
|
||||
{{#each roles}}
|
||||
{{this}}<br/>
|
||||
{{/each}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr role="row" class="even">
|
||||
<td class="sorting_1" style="padding:10px 15px;width: 15%;">Device Count</td>
|
||||
<td style="padding:10px 15px;">{{deviceCount}}</td>
|
||||
</tr>
|
||||
<tr role="row" class="odd">
|
||||
<td class="sorting_1" style="padding:10px 15px;width: 15%;">Description</td>
|
||||
<td style="padding:10px 15px;">{{group.description}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<h1 class="page-sub-title add-margin-top-5x">
|
||||
Devices in {{group.name}} group
|
||||
</h1>
|
||||
{{/if}}
|
||||
<div class="wr-device-list row">
|
||||
<div class="wr-hidden-operations wr-advance-operations"></div>
|
||||
<div class="col-md-12 wr-page-content">
|
||||
<div>
|
||||
<span id="permission" data-permission="{{permissions.list}}"></span>
|
||||
{{unit "cdmf.unit.device.operation-mod"}}
|
||||
{{#if deviceCount}}
|
||||
<div id="loading-content" class="col-centered">
|
||||
<i class="fw fw-wso2-logo fw-pulse fw-2x"></i>
|
||||
Loading devices . . .
|
||||
<br>
|
||||
</div>
|
||||
<div id="device-listing-status" class="raw hidden">
|
||||
<ul style="list-style-type: none;">
|
||||
<li class="message message-info">
|
||||
<h4>
|
||||
<i class="icon fw fw-info"></i>
|
||||
<a id="device-listing-status-msg"></a>
|
||||
</h4>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="device-table">
|
||||
<table class="table table-striped table-hover list-table display responsive nowrap data-table grid-view hidden"
|
||||
id="device-grid">
|
||||
<thead>
|
||||
<tr class="sort-row">
|
||||
<th class="no-sort"></th>
|
||||
<th>By Device Name</th>
|
||||
<th>By Owner</th>
|
||||
<th>By Status</th>
|
||||
<th>By Platform</th>
|
||||
<th>By Ownership</th>
|
||||
<th class="no-sort"></th>
|
||||
</tr>
|
||||
<tr class="filter-row filter-box">
|
||||
<th class="no-sort"></th>
|
||||
<th data-for="By Device name" class="text-filter"></th>
|
||||
<th data-for="By Owner" class="text-filter"></th>
|
||||
<th data-for="By Status" class="select-filter"></th>
|
||||
<th data-for="By Platform" class="select-filter data-platform"></th>
|
||||
<th data-for="By Ownership" class="select-filter"></th>
|
||||
<th class="no-sort"></th>
|
||||
</tr>
|
||||
<tr class="bulk-action-row hidden">
|
||||
<th colspan="7">
|
||||
<ul class="tiles">
|
||||
{{#unless group}}
|
||||
<li>
|
||||
<a href="#" style="width: 100px;height: 80px;;"
|
||||
data-click-event="remove-form"
|
||||
class="btn square-element add-devices-to-group-link"
|
||||
data-toggle="modal" data-target="#modalDemo">
|
||||
<span class="icon fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-group fw-stack-1x"></i>
|
||||
</span>
|
||||
Add to Group
|
||||
</a>
|
||||
</li>
|
||||
{{/unless}}
|
||||
<li>
|
||||
<a href="#" style="width: 100px;height: 80px;"
|
||||
data-click-event="remove-form"
|
||||
class="btn square-element remove-device-link"
|
||||
data-toggle="modal" data-target="#modalDemo">
|
||||
<span class="icon fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-delete fw-stack-1x"></i>
|
||||
</span>
|
||||
{{#if group}}
|
||||
Remove from group
|
||||
{{else}}
|
||||
Remove Device
|
||||
{{/if}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ast-container">
|
||||
|
||||
<br class="c-both"/>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<br class="c-both"/>
|
||||
<div id="content-filter-types" style="display: none">
|
||||
<div class="sort-title">Sort By</div>
|
||||
<div class="sort-options">
|
||||
<a href="#">By Device Name<span class="ico-sort-asc"></span></a>
|
||||
<a href="#">By Owner</a>
|
||||
<a href="#">By Status</a>
|
||||
<a href="#">By Platform</a>
|
||||
<a href="#">By Ownership</a>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div id="ast-container" class="ast-container list-view">
|
||||
<div class="ctrl-info-panel col-centered text-center wr-login">
|
||||
<h3 class="text-muted">
|
||||
<i class="fw fw-devices fw-3x"></i>
|
||||
</h3>
|
||||
<h3 class="text-muted">
|
||||
You don't have any
|
||||
{{#if group}}
|
||||
devices assigned to this group. Let's add a device!
|
||||
{{else}}
|
||||
enrolled devices. Let's enroll a device!
|
||||
{{/if}}
|
||||
|
||||
</h3>
|
||||
<h3>
|
||||
{{#if group}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/devices" class="btn-operations btn-default">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
</span>
|
||||
Assign from My Devices
|
||||
</a>
|
||||
{{else}}
|
||||
{{#if permissions.enroll}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/device/enroll" class="btn-operations btn-default">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
</span>
|
||||
Enroll New Device
|
||||
</a>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div id="group-device-modal-content" class="hide">
|
||||
<div class="modal-header">
|
||||
<h3 class="pull-left modal-title">
|
||||
<span>
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-group fw-stack-1x"></i>
|
||||
</span> Device Grouping
|
||||
</span>
|
||||
</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i
|
||||
class="fw fw-cancel"></i></button>
|
||||
</div>
|
||||
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
|
||||
<div id="notification-error-msg" class="alert alert-danger hidden" role="alert">
|
||||
<i class="icon fw fw-error"></i><span></span>
|
||||
</div>
|
||||
<div id="user-groups">Loading...</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="buttons">
|
||||
<a href="{{@app.context}}/group/add" id="group-add-link" class="btn-operations">
|
||||
Add device group
|
||||
</a>
|
||||
<a href="#" id="group-device-add-link" class="btn-operations">
|
||||
Add devices to group
|
||||
</a>
|
||||
<a href="#" id="group-device-update-link" class="btn-operations">
|
||||
Update assignment
|
||||
</a>
|
||||
<a href="#" id="group-device-cancel-link" class="btn-operations btn-default">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="group-associate-device-200-content" class="hide">
|
||||
<div class="modal-content">
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-centered">
|
||||
<h3>Successfully added the device/s to the group!</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="remove-device-modal-content" class="hide">
|
||||
<div class="modal-header">
|
||||
<h3 class="pull-left modal-title">
|
||||
{{#if group}}
|
||||
Do you really want to remove this device(s) from '{{group.name}}' group?
|
||||
{{else}}
|
||||
Do you really want to remove this device(s) from your Devices?
|
||||
{{/if}}
|
||||
</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i
|
||||
class="fw fw-cancel"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="buttons">
|
||||
<a href="#" id="remove-device-yes-link" class="btn-operations">
|
||||
Yes
|
||||
</a>
|
||||
|
||||
<a href="#" id="remove-device-cancel-link" class="btn-operations">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="remove-device-200-content" class="hide">
|
||||
<div class="modal-header">
|
||||
<h3 class="pull-left modal-title">
|
||||
{{#if group}}
|
||||
Successfully removed from '{{group.name}}' group.
|
||||
{{else}}
|
||||
Successfully removed.
|
||||
{{/if}}
|
||||
</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i
|
||||
class="fw fw-cancel"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="buttons">
|
||||
<a href="javascript:hidePopup()" class="btn-operations">Ok</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="edit-device-modal-content" class="hide">
|
||||
<div class="modal-header">
|
||||
<h3 class="pull-left modal-title">
|
||||
Please enter a new name for the device.
|
||||
</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i
|
||||
class="fw fw-cancel"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
|
||||
<input id="edit-device-name" style="color:#3f3f3f;padding:5px" type="text"
|
||||
value=""
|
||||
placeholder="Type here" size="60">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="buttons">
|
||||
<a href="#" id="edit-device-yes-link" class="btn-operations">
|
||||
Rename
|
||||
</a>
|
||||
|
||||
<a href="#" id="edit-device-cancel-link" class="btn-operations">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="edit-device-200-content" class="hide">
|
||||
<div class="modal-header">
|
||||
<h3 class="pull-left modal-title">
|
||||
Device was successfully updated.
|
||||
</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i
|
||||
class="fw fw-cancel"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="buttons">
|
||||
|
||||
<div id="edit-device-200-content" class="hide">
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>Device was successfully updated.</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="device-400-content" class="hide">
|
||||
<div class="modal-content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>Exception at backend. Try Later.</h3>
|
||||
<br/>
|
||||
<div class="buttons">
|
||||
<a href="#" id="device-400-link" class="btn-operations">
|
||||
Ok
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="device-403-content" class="hide">
|
||||
<div class="modal-content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>Operation not permitted.</h3>
|
||||
<br/>
|
||||
<div class="buttons">
|
||||
<a href="#" id="device-403-link" class="btn-operations">
|
||||
Ok
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="group-404-content" class="hide">
|
||||
<div class="modal-content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>
|
||||
You don't have any device group to add this device. Let's add a new
|
||||
device group!</h3>
|
||||
<br/>
|
||||
<div class="buttons">
|
||||
<a href="{{@app.context}}/group/add" class="btn-operations">
|
||||
Add New Group
|
||||
</a>
|
||||
|
||||
<a href="#" id="cancel-link" class="btn-operations">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="device-409-content" class="hide">
|
||||
<div class="modal-content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>Device does not exist.</h3>
|
||||
<br/>
|
||||
<div class="buttons">
|
||||
<a href="#" id="remove-device-409-link" class="btn-operations">
|
||||
Ok
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="no-device-selected" class="hide">
|
||||
<div class="modal-content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>Please select one or more devices in order to perform this
|
||||
operation.</h3>
|
||||
<br/>
|
||||
<div class="buttons">
|
||||
<a href="#" id="no-device-selected-link" class="btn-operations">
|
||||
Ok
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "bottomJs"}}
|
||||
<script id="device-listing" data-server-url="{{serverUrl}}" data-current-user="{{@user.username}}" data-device-types="{{deviceTypes}}"
|
||||
data-portal-url="{{portalUrl}}" data-user-domain="{{userDomain}}" type="text/x-handlebars-template"></script>
|
||||
{{js "js/listing.js"}}
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "topCss"}}
|
||||
<style>
|
||||
.select2-dropdown {
|
||||
z-index: 999999999;
|
||||
}
|
||||
|
||||
.wr-input-control {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.select2-selection__choice {
|
||||
font-size: medium;
|
||||
}
|
||||
</style>
|
||||
{{/zone}}
|
||||
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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 constants = require("/app/modules/constants.js");
|
||||
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
|
||||
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
|
||||
var groupModule = require("/app/modules/business-controllers/group.js")["groupModule"];
|
||||
|
||||
var groupId = request.getParameter("groupId");
|
||||
|
||||
var viewModel = {};
|
||||
var title = "Devices";
|
||||
if (groupId) {
|
||||
var group = groupModule.getGroup(groupId);
|
||||
if (group) {
|
||||
title = group.name + " " + title;
|
||||
viewModel.roles = groupModule.getRolesOfGroup(groupId);
|
||||
viewModel.group = group;
|
||||
}
|
||||
}
|
||||
viewModel.title = title;
|
||||
var currentUser = session.get(constants.USER_SESSION_KEY);
|
||||
if (currentUser) {
|
||||
viewModel.permissions = {};
|
||||
var uiPermissions = userModule.getUIPermissions();
|
||||
viewModel.permissions.list = stringify(uiPermissions);
|
||||
if (uiPermissions.ADD_DEVICE) {
|
||||
viewModel.permissions.enroll = true;
|
||||
}
|
||||
viewModel.currentUser = currentUser;
|
||||
var deviceCount = 0;
|
||||
if (groupId) {
|
||||
deviceCount = groupModule.getGroupDeviceCount(groupId);
|
||||
} else {
|
||||
deviceCount = deviceModule.getDevicesCount();
|
||||
}
|
||||
if (deviceCount > 0) {
|
||||
viewModel.deviceCount = deviceCount;
|
||||
var utility = require("/app/modules/utility.js").utility;
|
||||
var typesListResponse = deviceModule.getDeviceTypes();
|
||||
var deviceTypes = [];
|
||||
if (typesListResponse["status"] == "success") {
|
||||
var data = typesListResponse.content.deviceTypes;
|
||||
if (data) {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var config = utility.getDeviceTypeConfig(data[i]);
|
||||
var category = "iot";
|
||||
var label = data[i];
|
||||
var analyticsEnabled = "false";
|
||||
var groupingEnabled = "true";
|
||||
var analyticsView = null;
|
||||
if (config) {
|
||||
var deviceType = config.deviceType;
|
||||
category = deviceType.category;
|
||||
label = deviceType.label;
|
||||
analyticsEnabled = deviceType.analyticsEnabled;
|
||||
groupingEnabled = deviceType.groupingEnabled;
|
||||
analyticsView = deviceType.analyticsView;
|
||||
}
|
||||
|
||||
deviceTypes.push({
|
||||
"type": data[i],
|
||||
"category": category,
|
||||
"label": label,
|
||||
"thumb": utility.getDeviceThumb(data[i]),
|
||||
"analyticsEnabled": analyticsEnabled,
|
||||
"groupingEnabled": groupingEnabled,
|
||||
"analyticsView" : analyticsView
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
viewModel.deviceTypes = stringify(deviceTypes);
|
||||
}
|
||||
}
|
||||
|
||||
var mdmProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var serverUrl = mdmProps["httpsURL"];
|
||||
var portalUrl = mdmProps["portalURL"];
|
||||
var userDomain = context.user.domain;
|
||||
viewModel.serverUrl = serverUrl;
|
||||
viewModel.portalUrl = portalUrl;
|
||||
viewModel.userDomain = userDomain;
|
||||
return viewModel;
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/devices",
|
||||
"layout": "cdmf.layout.default"
|
||||
}
|
||||
@ -0,0 +1,959 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Following function would execute
|
||||
* when a user clicks on the list item
|
||||
* initial mode and with out select mode.
|
||||
*/
|
||||
function InitiateViewOption(url) {
|
||||
if ($(".select-enable-btn").text() == "Select" && !$(this).hasClass("btn")) {
|
||||
url = $(this).parent().data("url");
|
||||
$(location).attr('href', url);
|
||||
}
|
||||
}
|
||||
|
||||
(function () {
|
||||
var cache = {};
|
||||
var validateAndReturn = function (value) {
|
||||
return (value == undefined || value == null) ? "Unspecified" : value;
|
||||
};
|
||||
Handlebars.registerHelper("deviceMap", function (device) {
|
||||
device.owner = validateAndReturn(device.owner);
|
||||
device.ownership = validateAndReturn(device.ownership);
|
||||
var arr = device.properties;
|
||||
if (arr) {
|
||||
device.properties = arr.reduce(function (total, current) {
|
||||
total[current.name] = validateAndReturn(current.value);
|
||||
return total;
|
||||
}, {});
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
/*
|
||||
* Setting-up global variables.
|
||||
*/
|
||||
var deviceCheckbox = "#ast-container .ctrl-wr-asset .itm-select input[type='checkbox']";
|
||||
var assetContainer = "#ast-container";
|
||||
|
||||
var deviceListing, currentUser, groupId;
|
||||
|
||||
/*
|
||||
* DOM ready functions.
|
||||
*/
|
||||
$(document).ready(function () {
|
||||
|
||||
var permissionSet = {};
|
||||
$.setPermission = function (permission) {
|
||||
permissionSet[permission] = true;
|
||||
};
|
||||
|
||||
$.hasPermission = function (permission) {
|
||||
return permissionSet[permission];
|
||||
};
|
||||
|
||||
deviceListing = $("#device-listing");
|
||||
currentUser = deviceListing.data("current-user");
|
||||
|
||||
groupId = getParameterByName("groupId");
|
||||
|
||||
/* Adding selected class for selected devices */
|
||||
$(deviceCheckbox).each(function () {
|
||||
addDeviceSelectedClass(this);
|
||||
});
|
||||
|
||||
/* for device list sorting drop down */
|
||||
$(".ctrl-filter-type-switcher").popover({
|
||||
html: true,
|
||||
content: function () {
|
||||
return $("#content-filter-types").html();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* On Select All Device button click function.
|
||||
*
|
||||
* @param button: Select All Device button
|
||||
*/
|
||||
function selectAllDevices(button) {
|
||||
if (!$(button).data('select')) {
|
||||
$(deviceCheckbox).each(function (index) {
|
||||
$(this).prop('checked', true);
|
||||
addDeviceSelectedClass(this);
|
||||
});
|
||||
$(button).data('select', true);
|
||||
$(button).html('Deselect All Devices');
|
||||
} else {
|
||||
$(deviceCheckbox).each(function (index) {
|
||||
$(this).prop('checked', false);
|
||||
addDeviceSelectedClass(this);
|
||||
});
|
||||
$(button).data('select', false);
|
||||
$(button).html('Select All Devices');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* On listing layout toggle buttons click function.
|
||||
*
|
||||
* @param view: Selected view type
|
||||
* @param selection: Selection button
|
||||
*/
|
||||
function changeDeviceView(view, selection) {
|
||||
$(".view-toggle").each(function () {
|
||||
$(this).removeClass("selected");
|
||||
});
|
||||
$(selection).addClass("selected");
|
||||
if (view == "list") {
|
||||
$(assetContainer).addClass("list-view");
|
||||
} else {
|
||||
$(assetContainer).removeClass("list-view");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add selected style class to the parent element function.
|
||||
*
|
||||
* @param checkbox: Selected checkbox
|
||||
*/
|
||||
function addDeviceSelectedClass(checkbox) {
|
||||
if ($(checkbox).is(":checked")) {
|
||||
$(checkbox).closest(".ctrl-wr-asset").addClass("selected device-select");
|
||||
} else {
|
||||
$(checkbox).closest(".ctrl-wr-asset").removeClass("selected device-select");
|
||||
}
|
||||
}
|
||||
|
||||
function toTitleCase(str) {
|
||||
return str.replace(/\w\S*/g, function (txt) {
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||
});
|
||||
}
|
||||
|
||||
function loadDevices(searchType, searchParam) {
|
||||
var serviceURL;
|
||||
if (groupId && $.hasPermission("LIST_OWN_DEVICES")) {
|
||||
serviceURL = "/api/device-mgt/v1.0/groups/id/" + groupId + "/devices";
|
||||
} else if ($.hasPermission("LIST_DEVICES")) {
|
||||
serviceURL = "/api/device-mgt/v1.0/devices";
|
||||
} else if (permissionsUtil.hasPermission("LIST_OWN_DEVICES")) {
|
||||
//Get authenticated users devices
|
||||
serviceURL = "/api/device-mgt/v1.0/devices?user=" + currentUser;
|
||||
} else {
|
||||
$("#loading-content").remove();
|
||||
$('#device-table').addClass('hidden');
|
||||
$('#device-listing-status-msg').text('Permission denied.');
|
||||
$("#device-listing-status").removeClass(' hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
function getPropertyValue(deviceProperties, propertyName) {
|
||||
if (!deviceProperties) {
|
||||
return;
|
||||
}
|
||||
var property;
|
||||
for (var i = 0; i < deviceProperties.length; i++) {
|
||||
property = deviceProperties[i];
|
||||
if (property.name == propertyName) {
|
||||
return property.value;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
function getDeviceTypeLabel(type) {
|
||||
var deviceTypes = deviceListing.data("deviceTypes");
|
||||
for (var i = 0; i < deviceTypes.length; i++) {
|
||||
if (deviceTypes[i].type == type) {
|
||||
return deviceTypes[i].label;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function getDeviceTypeCategory(type) {
|
||||
var deviceTypes = deviceListing.data("deviceTypes");
|
||||
for (var i = 0; i < deviceTypes.length; i++) {
|
||||
if (deviceTypes[i].type == type) {
|
||||
return deviceTypes[i].category;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function getDeviceTypeThumb(type) {
|
||||
var deviceTypes = deviceListing.data("deviceTypes");
|
||||
for (var i = 0; i < deviceTypes.length; i++) {
|
||||
if (deviceTypes[i].type == type) {
|
||||
return deviceTypes[i].thumb;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function analyticsEnabled(type) {
|
||||
var deviceTypes = deviceListing.data("deviceTypes");
|
||||
for (var i = 0; i < deviceTypes.length; i++) {
|
||||
if (deviceTypes[i].type == type) {
|
||||
var analyticsEnabled = deviceTypes[i].analyticsEnabled;
|
||||
if (analyticsEnabled == undefined) {
|
||||
// By default it should be enabled
|
||||
return true;
|
||||
}
|
||||
// In JS Boolean("false") returns TRUE => http://stackoverflow.com/a/264037/1560536
|
||||
return (analyticsEnabled == "true");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read "analyticsView" from config.json and return value if exists
|
||||
function getAnalyticsView(type) {
|
||||
var deviceTypes = deviceListing.data("deviceTypes");
|
||||
for (var i = 0; i < deviceTypes.length; i++) {
|
||||
if (deviceTypes[i].type == type) {
|
||||
var analyticsView = deviceTypes[i].analyticsView;
|
||||
if (analyticsEnabled == undefined) {
|
||||
// if undefined go to default analytics view
|
||||
return "none";
|
||||
}
|
||||
return analyticsView;
|
||||
}
|
||||
}
|
||||
return "none";
|
||||
}
|
||||
|
||||
function groupingEnabled(type) {
|
||||
var deviceTypes = deviceListing.data("deviceTypes");
|
||||
for (var i = 0; i < deviceTypes.length; i++) {
|
||||
if (deviceTypes[i].type == type) {
|
||||
var groupingEnabled = deviceTypes[i].groupingEnabled;
|
||||
if (groupingEnabled == undefined) {
|
||||
// By default it should be enabled
|
||||
return true;
|
||||
}
|
||||
// In JS Boolean("false") returns TRUE => http://stackoverflow.com/a/264037/1560536
|
||||
return (groupingEnabled == "true");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var columns = [
|
||||
{
|
||||
targets: 0,
|
||||
data: 'name',
|
||||
class: 'remove-padding icon-only content-fill viewEnabledIcon',
|
||||
render: function (data, type, row, meta) {
|
||||
return '<div class="thumbnail icon"><img class="square-element text fw " src="'
|
||||
+ getDeviceTypeThumb(row.deviceType) + '"/></div>';
|
||||
}
|
||||
},
|
||||
{
|
||||
targets: 1,
|
||||
data: 'name',
|
||||
class: 'viewEnabledIcon',
|
||||
render: function (name, type, row, meta) {
|
||||
var model = getPropertyValue(row.properties, 'DEVICE_MODEL');
|
||||
var vendor = getPropertyValue(row.properties, 'VENDOR');
|
||||
var html = '<h4>' + name + '</h4>';
|
||||
if (model) {
|
||||
html += '<div>(' + vendor + '-' + model + ')</div>';
|
||||
}
|
||||
return html;
|
||||
}
|
||||
},
|
||||
{
|
||||
targets: 2,
|
||||
data: 'userPattern',
|
||||
class: 'remove-padding-top viewEnabledIcon'
|
||||
},
|
||||
{
|
||||
targets: 3,
|
||||
data: 'status',
|
||||
class: 'remove-padding-top viewEnabledIcon',
|
||||
render: function (status, type, row, meta) {
|
||||
var html;
|
||||
switch (status) {
|
||||
case 'ACTIVE' :
|
||||
html = '<span><i class="fw fw-success icon-success"></i> Active</span>';
|
||||
break;
|
||||
case 'INACTIVE' :
|
||||
html = '<span><i class="fw fw-warning icon-warning"></i> Inactive</span>';
|
||||
break;
|
||||
case 'BLOCKED' :
|
||||
html = '<span><i class="fw fw-remove icon-danger"></i> Blocked</span>';
|
||||
break;
|
||||
case 'REMOVED' :
|
||||
html = '<span><i class="fw fw-delete icon-danger"></i> Removed</span>';
|
||||
break;
|
||||
case 'UNREACHABLE' :
|
||||
html = '<span><i class="fw fw-warning icon-warning"></i> Unreachable</span>';
|
||||
break;
|
||||
}
|
||||
return html;
|
||||
}
|
||||
},
|
||||
{
|
||||
targets: 4,
|
||||
data: 'type',
|
||||
class: 'remove-padding-top viewEnabledIcon',
|
||||
render: function (status, type, row, meta) {
|
||||
return getDeviceTypeLabel(row.deviceType);
|
||||
}
|
||||
},
|
||||
{
|
||||
targets: 5,
|
||||
data: 'ownership',
|
||||
class: 'remove-padding-top viewEnabledIcon',
|
||||
render: function (status, type, row, meta) {
|
||||
if (getDeviceTypeCategory(row.deviceType) == 'mobile') {
|
||||
return row.ownership;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
targets: 6,
|
||||
data: 'action-buttons',
|
||||
class: 'text-right content-fill text-left-on-grid-view no-wrap tooltip-overflow-fix',
|
||||
render: function (status, type, row, meta) {
|
||||
var deviceType = row.deviceType;
|
||||
var deviceIdentifier = row.deviceIdentifier;
|
||||
var html = '<span></span>';
|
||||
var portalUrl = $("#device-listing").data("portal-url");
|
||||
var serverUrl = $("#device-listing").data("server-url");
|
||||
var userDomain = $("#device-listing").data("userDomain");
|
||||
var statURL;
|
||||
if (status != 'REMOVED') {
|
||||
html = '';
|
||||
|
||||
if (analyticsEnabled(row.deviceType)) {
|
||||
|
||||
// redirecting to respective analytics view depending on device configs
|
||||
switch (getAnalyticsView(deviceType)) {
|
||||
case "DAS" : { statURL =portalUrl + "/portal/t/"+ userDomain+ "/dashboards/android-iot/battery?owner=" +currentUser+"&deviceId=";break;}
|
||||
default : {statURL=context+ "/device/" + row.deviceType +"/analytics?deviceId="}
|
||||
}
|
||||
|
||||
html += '<a href="' + statURL +
|
||||
deviceIdentifier + '&deviceName=' + row.name + '" ' + 'data-click-event="remove-form"' +
|
||||
' class="btn padding-reduce-on-grid-view" data-placement="top" data-toggle="tooltip" data-original-title="Analytics"><span class="fw-stack">' +
|
||||
'<i class="fw fw-circle-outline fw-stack-2x"></i><i class="fw fw-statistics fw-stack-1x"></i></span>' +
|
||||
'<span class="hidden-xs hidden-on-grid-view">Analytics</span>';
|
||||
}
|
||||
|
||||
if (!groupId && groupingEnabled(row.deviceType)) {
|
||||
html +=
|
||||
'<a href="#" data-click-event="remove-form" class="btn padding-reduce-on-grid-view group-device-link" '
|
||||
+
|
||||
'data-deviceid="' + deviceIdentifier + '" data-devicetype="' + deviceType
|
||||
+ '" data-devicename="' +
|
||||
row.name + '" data-placement="top" data-toggle="tooltip" data-original-title="Group"><span class="fw-stack"><i class="fw fw-circle-outline fw-stack-2x"></i>' +
|
||||
'<i class="fw fw-group fw-stack-1x"></i></span>' +
|
||||
'<span class="hidden-xs hidden-on-grid-view">Group</span></a>';
|
||||
}
|
||||
|
||||
html +=
|
||||
'<a href="#" data-click-event="remove-form" class="btn padding-reduce-on-grid-view edit-device-link" '
|
||||
+ 'data-deviceid="' + deviceIdentifier + '" data-devicetype="' + deviceType
|
||||
+ '" data-devicename="' + row.name + '" data-placement="top" data-toggle="tooltip" data-original-title="Edit">'
|
||||
+ '<span class="fw-stack"><i class="fw fw-circle-outline 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>';
|
||||
var groupOwner = $('#group_owner').text();
|
||||
if (groupId && groupOwner != "wso2.system.user") {
|
||||
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 + '" data-placement="top" data-toggle="tooltip" data-original-title="Remove from group">'
|
||||
+ '<span class="fw-stack"><i class="fw fw-circle-outline fw-stack-2x"></i>'
|
||||
+ '<i class="fw fw-delete fw-stack-1x"></i></span>'
|
||||
+ '<span class="hidden-xs hidden-on-grid-view">Remove from group</span>';
|
||||
} else {
|
||||
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 + '" data-placement="top" data-toggle="tooltip" data-original-title="Delete">'
|
||||
+ '<span class="fw-stack"><i class="fw fw-circle-outline 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;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var fnCreatedRow = function (row, data, dataIndex) {
|
||||
|
||||
if(data.status != "REMOVED"){
|
||||
$(row).attr('data-type', 'selectable');
|
||||
}else{
|
||||
$(row).attr('data-type', 'non-selectable');
|
||||
}
|
||||
|
||||
$(row).attr('data-deviceid', htmlspecialchars(data.deviceIdentifier));
|
||||
$(row).attr('data-devicetype', htmlspecialchars(data.deviceType));
|
||||
$(row).attr('data-url', context + '/device/' + htmlspecialchars(data.deviceType) + '?id=' + htmlspecialchars(data.deviceIdentifier));
|
||||
var model = htmlspecialchars(getPropertyValue(data.properties, 'DEVICE_MODEL'));
|
||||
var vendor = htmlspecialchars(getPropertyValue(data.properties, 'VENDOR'));
|
||||
var owner = htmlspecialchars(data.userPattern);
|
||||
var status = htmlspecialchars(data.status);
|
||||
var ownership = htmlspecialchars(data.ownership);
|
||||
var deviceType = htmlspecialchars(data.deviceType);
|
||||
var category = getDeviceTypeCategory(deviceType);
|
||||
$.each($('td', row), function (colIndex) {
|
||||
switch (colIndex) {
|
||||
case 1:
|
||||
$(this).attr('data-search', model + ',' + vendor);
|
||||
$(this).attr('data-display', model);
|
||||
break;
|
||||
case 2:
|
||||
$(this).attr('data-grid-label', "Owner");
|
||||
$(this).attr('data-search', owner);
|
||||
$(this).attr('data-display', owner);
|
||||
break;
|
||||
case 3:
|
||||
$(this).attr('data-grid-label', "Status");
|
||||
$(this).attr('data-search', status);
|
||||
$(this).attr('data-display', status);
|
||||
break;
|
||||
case 4:
|
||||
$(this).attr('data-grid-label', "Type");
|
||||
$(this).attr('data-search', deviceType);
|
||||
$(this).attr('data-display', getDeviceTypeLabel(deviceType));
|
||||
break;
|
||||
case 5:
|
||||
if (category == 'mobile') {
|
||||
$(this).attr('data-grid-label', "Ownership");
|
||||
$(this).attr('data-search', ownership);
|
||||
$(this).attr('data-display', ownership);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function htmlspecialchars(text) {
|
||||
return jQuery('<div/>').text(text).html();
|
||||
}
|
||||
|
||||
var dataFilter = function (data) {
|
||||
data = JSON.parse(data);
|
||||
var objects = [];
|
||||
|
||||
$(data.devices).each(function (index) {
|
||||
objects.push(
|
||||
{
|
||||
model: getPropertyValue(data.devices[index].properties, "DEVICE_MODEL"),
|
||||
vendor: getPropertyValue(data.devices[index].properties, "VENDOR"),
|
||||
userPattern: data.devices[index].enrolmentInfo.owner,
|
||||
status: data.devices[index].enrolmentInfo.status,
|
||||
ownership: data.devices[index].enrolmentInfo.ownership,
|
||||
deviceType: data.devices[index].type,
|
||||
deviceIdentifier: data.devices[index].deviceIdentifier,
|
||||
name: data.devices[index].name
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
var json = {
|
||||
"recordsTotal": data.count,
|
||||
"recordsFiltered": data.count,
|
||||
"data": objects
|
||||
};
|
||||
return JSON.stringify(json);
|
||||
};
|
||||
|
||||
$('#device-grid').datatables_extended_serverside_paging(
|
||||
null,
|
||||
serviceURL,
|
||||
dataFilter,
|
||||
columns,
|
||||
fnCreatedRow,
|
||||
function () {
|
||||
$(".icon .text").res_text(0.2);
|
||||
$('#device-grid').removeClass('hidden');
|
||||
$("#loading-content").remove();
|
||||
attachDeviceEvents();
|
||||
|
||||
|
||||
// if ($('.advance-search').length < 1) {
|
||||
// $(this).closest('.dataTables_wrapper').find('div[id$=_filter] input')
|
||||
// .after('<a href="' + context + '/devices/search"' +
|
||||
// ' class="advance-search add-padding-3x">Advance Search</a>');
|
||||
// }
|
||||
|
||||
}, {
|
||||
"placeholder": "Search By Device Name",
|
||||
"searchKey": "name"
|
||||
}
|
||||
);
|
||||
|
||||
$(deviceCheckbox).click(function () {
|
||||
addDeviceSelectedClass(this);
|
||||
});
|
||||
}
|
||||
|
||||
function openCollapsedNav() {
|
||||
$('.wr-hidden-nav-toggle-btn').addClass('active');
|
||||
$('#hiddenNav').slideToggle('slideDown', function () {
|
||||
if ($(this).css('display') == 'none') {
|
||||
$('.wr-hidden-nav-toggle-btn').removeClass('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* DOM ready functions.
|
||||
*/
|
||||
$(document).ready(function () {
|
||||
/* Adding selected class for selected devices */
|
||||
$(deviceCheckbox).each(function () {
|
||||
addDeviceSelectedClass(this);
|
||||
});
|
||||
|
||||
var permissionList = $("#permission").data("permission");
|
||||
for (var key in permissionList) {
|
||||
if (permissionList.hasOwnProperty(key)) {
|
||||
$.setPermission(key);
|
||||
}
|
||||
}
|
||||
|
||||
loadDevices();
|
||||
|
||||
/* for device list sorting drop down */
|
||||
$(".ctrl-filter-type-switcher").popover({
|
||||
html: true,
|
||||
content: function () {
|
||||
return $("#content-filter-types").html();
|
||||
}
|
||||
});
|
||||
|
||||
/* for data tables*/
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
$("[data-toggle=popover]").popover();
|
||||
|
||||
$(".ctrl-filter-type-switcher").popover({
|
||||
html: true,
|
||||
content: function () {
|
||||
return $('#content-filter-types').html();
|
||||
}
|
||||
});
|
||||
|
||||
$('#nav').affix({
|
||||
offset: {
|
||||
top: $('header').height()
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
var modalPopup = ".modal";
|
||||
var modalPopupContainer = modalPopup + " .modal-content";
|
||||
var modalPopupContent = modalPopup + " .modal-content";
|
||||
var body = "body";
|
||||
|
||||
/*
|
||||
* set popup maximum height function.
|
||||
*/
|
||||
function setPopupMaxHeight() {
|
||||
$(modalPopupContent).css('max-height', ($(body).height() - ($(body).height() / 100 * 30)));
|
||||
$(modalPopupContainer).css('margin-top', (-($(modalPopupContainer).height() / 2)));
|
||||
}
|
||||
|
||||
/*
|
||||
* show popup function.
|
||||
*/
|
||||
function showPopup() {
|
||||
$(modalPopup).modal('show');
|
||||
}
|
||||
|
||||
/*
|
||||
* hide popup function.
|
||||
*/
|
||||
function hidePopup() {
|
||||
$(modalPopupContent).html("");
|
||||
$(modalPopupContent).removeClass("operation-data");
|
||||
$(modalPopup).modal('hide');
|
||||
$('body').removeClass('modal-open').css('padding-right', '0px');
|
||||
$('.modal-backdrop').remove();
|
||||
}
|
||||
|
||||
function markAlreadyAssignedGroups(deviceId, deviceType) {
|
||||
var successCallback = function (data, textStatus, xhr) {
|
||||
data = JSON.parse(data);
|
||||
if (xhr.status == 200) {
|
||||
if (data.length > 0) {
|
||||
var selectedValues = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (data[i].owner != "wso2.system.user") {
|
||||
selectedValues.push(data[i].id);
|
||||
}
|
||||
}
|
||||
$("#groups").val(selectedValues).trigger("change");
|
||||
}
|
||||
} else {
|
||||
displayErrors(xhr);
|
||||
}
|
||||
};
|
||||
|
||||
invokerUtil.get("/api/device-mgt/v1.0/groups/device?deviceId=" + deviceId + "&deviceType=" + deviceType,
|
||||
successCallback, function (message) {
|
||||
displayErrors(message);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Following functions should be triggered after AJAX request is made.
|
||||
*/
|
||||
function attachDeviceEvents() {
|
||||
|
||||
/**
|
||||
* Following click function would execute
|
||||
* when a user clicks on "Group" link
|
||||
* on Device Management page in WSO2 DeviceMgt Console.
|
||||
*/
|
||||
if ($("a.group-device-link").length > 0) {
|
||||
$("a.group-device-link").click(function () {
|
||||
var deviceId = $(this).data("deviceid");
|
||||
var deviceType = $(this).data("devicetype");
|
||||
$(modalPopupContent).html($('#group-device-modal-content').html());
|
||||
$('#user-groups').html(
|
||||
'<div style="height:100px" data-state="loading" data-loading-text="Loading..." data-loading-style="icon-only" data-loading-inverse="true"></div>');
|
||||
$("a#group-device-update-link").hide();
|
||||
showPopup();
|
||||
|
||||
var serviceURL;
|
||||
if ($.hasPermission("LIST_ALL_GROUPS")) {
|
||||
serviceURL = "/api/device-mgt/v1.0/admin/groups?limit=100";
|
||||
} else if ($.hasPermission("LIST_GROUPS")) {
|
||||
//Get authenticated users groups
|
||||
serviceURL = "/api/device-mgt/v1.0/groups?limit=100";
|
||||
}
|
||||
|
||||
invokerUtil.get(serviceURL, function (data) {
|
||||
$("a#group-device-add-link").hide();
|
||||
var groups = JSON.parse(data);
|
||||
var html = '';
|
||||
var hasGroups = false;
|
||||
for (var i = 0; i < groups.deviceGroups.length; i++) {
|
||||
if (groups.deviceGroups[i].owner != "wso2.system.user") {
|
||||
html += '<option value="' + groups.deviceGroups[i].id + '">' + groups.deviceGroups[i].name + '</option>';
|
||||
hasGroups = true;
|
||||
}
|
||||
}
|
||||
if (hasGroups) {
|
||||
html = '<br/><h4>Please select device group(s)</h4><br/>' +
|
||||
'<div class="wr-input-control">' +
|
||||
'<select id="groups" class="form-control select2" multiple="multiple">' +
|
||||
html + '</select></div>';
|
||||
markAlreadyAssignedGroups(deviceId, deviceType);
|
||||
$("a#group-device-update-link").show();
|
||||
$("a#group-add-link").hide();
|
||||
} else {
|
||||
$("a#group-device-update-link").hide();
|
||||
$("a#group-add-link").show();
|
||||
html += '<br/><h4>You don\'t have any existing device groups. Please add new device group first.</h4>'
|
||||
}
|
||||
$('#user-groups').html(html);
|
||||
$("select.select2[multiple=multiple]").select2({
|
||||
tags: false
|
||||
});
|
||||
$("a#group-device-update-link").click(function () {
|
||||
var deviceIdentifier = {"id": deviceId, "type": deviceType};
|
||||
var deviceGroupIds = $("#groups").val();
|
||||
if (!deviceGroupIds) {
|
||||
deviceGroupIds = [];
|
||||
}
|
||||
var deviceToGroupsAssignment = {
|
||||
deviceIdentifier: deviceIdentifier,
|
||||
deviceGroupIds: deviceGroupIds
|
||||
};
|
||||
serviceURL = "/api/device-mgt/v1.0/groups/device/assign";
|
||||
invokerUtil.post(serviceURL, deviceToGroupsAssignment, function (data) {
|
||||
$(modalPopupContent).html($('#group-associate-device-200-content').html());
|
||||
setTimeout(function () {
|
||||
hidePopup();
|
||||
location.reload(false);
|
||||
}, 2000);
|
||||
}, function (jqXHR) {
|
||||
displayDeviceErrors(jqXHR);
|
||||
});
|
||||
});
|
||||
}, function (jqXHR) {
|
||||
if (jqXHR.status == 404) {
|
||||
$(modalPopupContent).html($('#group-404-content').html());
|
||||
$("a#cancel-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
} else {
|
||||
displayDeviceErrors(jqXHR);
|
||||
}
|
||||
});
|
||||
|
||||
$("a#group-device-cancel-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Following click function would execute
|
||||
* when a user clicks on "Remove" link
|
||||
* on Device Management page in WSO2 MDM Console.
|
||||
*/
|
||||
$("a.remove-device-link").click(function () {
|
||||
var deviceIdentifiers = [];
|
||||
var deviceId = $(this).data("deviceid");
|
||||
var deviceType = $(this).data("devicetype");
|
||||
|
||||
if (deviceId && deviceType) {
|
||||
deviceIdentifiers = [{"id": deviceId, "type": deviceType}];
|
||||
} else {
|
||||
deviceIdentifiers = getSelectedDevices();
|
||||
}
|
||||
|
||||
if (deviceIdentifiers.length == 0) {
|
||||
$(modalPopupContent).html($('#no-device-selected').html());
|
||||
$("a#no-device-selected-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
showPopup();
|
||||
return;
|
||||
}
|
||||
|
||||
$(modalPopupContent).html($('#remove-device-modal-content').html());
|
||||
showPopup();
|
||||
|
||||
$("a#remove-device-yes-link").click(function () {
|
||||
if (groupId) {
|
||||
var serviceURL = "/api/device-mgt/v1.0/groups/id/" + groupId + "/devices/remove";
|
||||
invokerUtil.post(serviceURL, deviceIdentifiers, function (message) {
|
||||
$(modalPopupContent).html($('#remove-device-200-content').html());
|
||||
setTimeout(function () {
|
||||
hidePopup();
|
||||
location.reload(false);
|
||||
}, 2000);
|
||||
}, function (jqXHR) {
|
||||
displayDeviceErrors(jqXHR);
|
||||
});
|
||||
} else {
|
||||
removeDevices(deviceIdentifiers);
|
||||
}
|
||||
});
|
||||
|
||||
$("a#remove-device-cancel-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Following click function would execute
|
||||
* when a user clicks on "Edit" link
|
||||
* on Device Management page in WSO2 MDM Console.
|
||||
*/
|
||||
$("a.edit-device-link").click(function () {
|
||||
var deviceId = $(this).data("deviceid");
|
||||
var deviceType = $(this).data("devicetype");
|
||||
var deviceName = $(this).data("devicename");
|
||||
var serviceURL = "/api/device-mgt/v1.0/devices/type/" + deviceType + "/id/" + deviceId + "/rename";
|
||||
|
||||
$(modalPopupContent).html($('#edit-device-modal-content').html());
|
||||
$('#edit-device-name').val(deviceName);
|
||||
showPopup();
|
||||
|
||||
$("a#edit-device-yes-link").click(function () {
|
||||
var newDeviceName = $('#edit-device-name').val();
|
||||
var request = {};
|
||||
request['name'] = newDeviceName;
|
||||
invokerUtil.post(serviceURL, request, function (message) {
|
||||
$(modalPopupContent).html($('#edit-device-200-content').html());
|
||||
setTimeout(function () {
|
||||
hidePopup();
|
||||
location.reload(false);
|
||||
}, 2000);
|
||||
}, function (jqXHR) {
|
||||
displayDeviceErrors(jqXHR);
|
||||
});
|
||||
});
|
||||
|
||||
$("a#edit-device-cancel-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Following click function would execute
|
||||
* when a user clicks on "Add to Group" link
|
||||
* on Device Management page in WSO2 devicemgt Console.
|
||||
*/
|
||||
$("a.add-devices-to-group-link").click(function () {
|
||||
$("a#group-device-update-link").hide();
|
||||
var deviceIdentifiers = getSelectedDevices();
|
||||
if (deviceIdentifiers.length == 0) {
|
||||
$(modalPopupContent).html($('#no-device-selected').html());
|
||||
$("a#no-device-selected-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
showPopup();
|
||||
return;
|
||||
}
|
||||
|
||||
$(modalPopupContent).html($('#group-device-modal-content').html());
|
||||
$('#user-groups').html(
|
||||
'<div style="height:100px" data-state="loading" data-loading-text="Loading..." data-loading-style="icon-only" data-loading-inverse="true"></div>');
|
||||
$("a#group-device-add-link").hide();
|
||||
showPopup();
|
||||
|
||||
var serviceURL;
|
||||
if ($.hasPermission("LIST_ALL_GROUPS")) {
|
||||
serviceURL = "/api/device-mgt/v1.0/admin/groups?limit=100";
|
||||
} else if ($.hasPermission("LIST_GROUPS")) {
|
||||
//Get authenticated users groups
|
||||
serviceURL = "/api/device-mgt/v1.0/groups?limit=100";
|
||||
}
|
||||
|
||||
invokerUtil.get(serviceURL, function (data) {
|
||||
var groups = JSON.parse(data);
|
||||
var html = '';
|
||||
var hasGroups = false;
|
||||
for (var i = 0; i < groups.deviceGroups.length; i++) {
|
||||
if (groups.deviceGroups[i].owner != "wso2.system.user") {
|
||||
html += '<option value="' + groups.deviceGroups[i].id + '">' +
|
||||
groups.deviceGroups[i].name + '</option>';
|
||||
hasGroups = true;
|
||||
}
|
||||
}
|
||||
if (hasGroups) {
|
||||
html = '<br /><select id="assign-group-selector" style="color:#3f3f3f;padding:5px;width:250px;">' +
|
||||
html + '</select>';
|
||||
$("a#group-add-link").hide();
|
||||
$("a#group-device-add-link").show();
|
||||
} else {
|
||||
html += '<br/><h4>You don\'t have any existing device groups. Please add new device group first.</h4>';
|
||||
$("a#group-add-link").show();
|
||||
$("a#group-device-add-link").hide();
|
||||
}
|
||||
$('#user-groups').html(html);
|
||||
$("a#group-device-add-link").click(function () {
|
||||
var selectedGroup = $('#assign-group-selector').val();
|
||||
serviceURL = "/api/device-mgt/v1.0/groups/id/" + selectedGroup + "/devices/add";
|
||||
invokerUtil.post(serviceURL, deviceIdentifiers, function (data) {
|
||||
$(modalPopupContent).html($('#group-associate-device-200-content').html());
|
||||
setTimeout(function () {
|
||||
hidePopup();
|
||||
location.reload(false);
|
||||
}, 2000);
|
||||
}, function (jqXHR) {
|
||||
displayDeviceErrors(jqXHR);
|
||||
});
|
||||
});
|
||||
}, function (jqXHR) {
|
||||
if (jqXHR.status == 404) {
|
||||
$(modalPopupContent).html($('#group-404-content').html());
|
||||
$("a#cancel-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
} else {
|
||||
displayDeviceErrors(jqXHR);
|
||||
}
|
||||
});
|
||||
|
||||
$("a#group-device-cancel-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function removeDevices(deviceIdentifiers) {
|
||||
var serviceURL = "/api/device-mgt/v1.0/devices/type/" + deviceIdentifiers[0].type + "/id/" + deviceIdentifiers[0].id;
|
||||
invokerUtil.delete(serviceURL, function (message) {
|
||||
if (deviceIdentifiers.length > 1) {
|
||||
deviceIdentifiers.slice(1, deviceIdentifiers.length);
|
||||
removeDevices(deviceIdentifiers);
|
||||
} else {
|
||||
$(modalPopupContent).html($('#remove-device-200-content').html());
|
||||
setTimeout(function () {
|
||||
hidePopup();
|
||||
location.reload(false);
|
||||
}, 2000);
|
||||
}
|
||||
}, function (jqXHR) {
|
||||
displayDeviceErrors(jqXHR);
|
||||
});
|
||||
}
|
||||
|
||||
function displayDeviceErrors(jqXHR) {
|
||||
showPopup();
|
||||
if (jqXHR.status == 400) {
|
||||
$(modalPopupContent).html($('#device-400-content').html());
|
||||
$("a#device-400-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
} else if (jqXHR.status == 403) {
|
||||
$(modalPopupContent).html($('#device-403-content').html());
|
||||
$("a#device-403-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
} else if (jqXHR.status == 409) {
|
||||
$(modalPopupContent).html($('#device-409-content').html());
|
||||
$("a#device-409-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
} else {
|
||||
$(modalPopupContent).html($('#device-unexpected-error-content').html());
|
||||
$("a#device-unexpected-error-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
console.log("Error code: " + jqXHR.status);
|
||||
}
|
||||
}
|
||||
|
||||
function getParameterByName(name) {
|
||||
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
|
||||
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
|
||||
results = regex.exec(location.search);
|
||||
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to get selected devices.
|
||||
*/
|
||||
function getSelectedDevices() {
|
||||
var deviceList = [];
|
||||
var thisTable = $(".DTTT_selected").closest('.dataTables_wrapper').find('.dataTable').dataTable();
|
||||
thisTable.api().rows().every(function () {
|
||||
if ($(this.node()).hasClass('DTTT_selected')) {
|
||||
deviceList.push(
|
||||
{
|
||||
"id": $(thisTable.api().row(this).node()).data('deviceid'),
|
||||
"type": $(thisTable.api().row(this).node()).data('devicetype')
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return deviceList;
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
|
||||
{{unit "cdmf.unit.ui.title" pageTitle="Device Type Management"}}
|
||||
{{unit "cdmf.unit.data-tables-extended"}}
|
||||
{{unit "cdmf.unit.ui.modal"}}
|
||||
|
||||
{{#zone "topCss"}}
|
||||
{{css "css/custom.css"}}
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "breadcrumbs"}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/">
|
||||
<i class="icon fw fw-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/device-types">
|
||||
Device Types
|
||||
</a>
|
||||
</li>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "navbarActions"}}
|
||||
{{#unless isCloud}}
|
||||
<li>
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/device-type/add" class="cu-btn">
|
||||
<span class="icon fw-stack">
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
</span>
|
||||
Create Device Type
|
||||
</a>
|
||||
</li>
|
||||
{{/unless}}
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "content"}}
|
||||
{{#if hasDeviceTypes}}
|
||||
<div id="loading-content" class="col-centered">
|
||||
<input type="hidden" id="can-edit" value="true"/>
|
||||
<i class="fw fw-settings fw-spin fw-2x"></i>
|
||||
Loading device types . . .
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<div id="devicetype-table">
|
||||
<table class="table table-striped table-hover list-table display responsive nowrap data-table grid-view"
|
||||
id="devicetype-grid">
|
||||
<thead>
|
||||
<tr class="sort-row">
|
||||
<th>By Device Type Name</th>
|
||||
</tr>
|
||||
<tr class="bulk-action-row">
|
||||
<th colspan="3"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ast-container" data-app-context="{{@app.context}}/"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="content-filter-types" style="display: none">
|
||||
<div class="sort-title">Sort By</div>
|
||||
<div class="sort-options">
|
||||
<!--suppress HtmlUnknownTag -->
|
||||
<th>By Device Type name</th>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{else}}
|
||||
|
||||
<div id="user-created-msg" class="container col-centered wr-content">
|
||||
<div class="wr-form">
|
||||
<p class="page-sub-title">You Haven't created device types yet.</p>
|
||||
<br>Please click <b>"Create a Device Type"</b>, if you wish to create a device type.
|
||||
<hr/>
|
||||
|
||||
<a href="{{@app.context}}/device-type/add" class="cu-btn-inner">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
</span>
|
||||
Create Device Type
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{/if}}
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "bottomJs"}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<script id="devicetype-listing" data-current-user="{{@user.username}}"
|
||||
src="{{@page.publicUri}}/templates/devicetype-listing.hbs" type="text/x-handlebars-template"></script>
|
||||
{{js "js/devicetype-listing.js"}}
|
||||
{{/zone}}
|
||||
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
|
||||
var deviceMgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
|
||||
context["permissions"] = userModule.getUIPermissions();
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/admin/device-type")) {
|
||||
context["editPermitted"] = true;
|
||||
}
|
||||
var deviceTypeCount = deviceModule.getDeviceTypeCount();
|
||||
|
||||
if (deviceTypeCount > 0) {
|
||||
context["hasDeviceTypes"] = true;
|
||||
} else {
|
||||
context["hasDeviceTypes"] = false;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/device-types",
|
||||
"layout": "cdmf.layout.default"
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
#devicetype-table .dataTablesTop{
|
||||
Display : none;
|
||||
}
|
||||
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 loadDeviceTypeBasedActionURL = function (action, deviceTypeName) {
|
||||
href = $("#ast-container").data("app-context") + "device-type/" + action + "?type=" + encodeURIComponent(deviceTypeName);
|
||||
$(location).attr('href', href);
|
||||
};
|
||||
|
||||
$(function () {
|
||||
var sortableElem = '.wr-sortable';
|
||||
$(sortableElem).sortable({
|
||||
beforeStop: function () {
|
||||
$(this).sortable('toArray');
|
||||
}
|
||||
});
|
||||
$(sortableElem).disableSelection();
|
||||
});
|
||||
|
||||
var apiBasePath = "/api/device-mgt/v1.0";
|
||||
var modalPopup = ".modal";
|
||||
var modalPopupContainer = modalPopup + " .modal-content";
|
||||
var modalPopupContent = modalPopup + " .modal-content";
|
||||
var body = "body";
|
||||
var isInit = true;
|
||||
var isCloud = false;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Fires the res_text when ever a data table redraw occurs making
|
||||
* the font icons change the size to respective screen resolution.
|
||||
*
|
||||
*/
|
||||
$(document).on('draw.dt', function () {
|
||||
$(".icon .text").res_text(0.2);
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* set popup maximum height function.
|
||||
*/
|
||||
function setPopupMaxHeight() {
|
||||
$(modalPopupContent).css('max-height', ($(body).height() - ($(body).height() / 100 * 30)));
|
||||
$(modalPopupContainer).css('margin-top', (-($(modalPopupContainer).height() / 2)));
|
||||
}
|
||||
|
||||
/*
|
||||
* show popup function.
|
||||
*/
|
||||
function showPopup() {
|
||||
$(modalPopup).modal('show');
|
||||
//setPopupMaxHeight();
|
||||
}
|
||||
|
||||
/*
|
||||
* hide popup function.
|
||||
*/
|
||||
function hidePopup() {
|
||||
$(modalPopupContent).html('');
|
||||
$(modalPopup).modal('hide');
|
||||
$('body').removeClass('modal-open').css('padding-right', '0px');
|
||||
$('.modal-backdrop').remove();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Following function would execute
|
||||
* when a user clicks on the list item
|
||||
* initial mode and with out select mode.
|
||||
*/
|
||||
function InitiateViewOption() {
|
||||
// $(location).attr('href', $(this).data("url"));
|
||||
}
|
||||
|
||||
function htmlspecialchars(text) {
|
||||
return jQuery('<div/>').text(text).html();
|
||||
}
|
||||
|
||||
function loadDeviceTypes() {
|
||||
var loadingContent = $("#loading-content");
|
||||
loadingContent.show();
|
||||
|
||||
var dataFilter = function (data) {
|
||||
data = JSON.parse(data);
|
||||
var objects = [];
|
||||
$(data).each(function (index) {
|
||||
objects.push(
|
||||
{
|
||||
name: htmlspecialchars(data[index].name),
|
||||
DT_RowId: "devicetype-" + htmlspecialchars(data[index].name),
|
||||
metaDefinition: (data[index].deviceTypeMetaDefinition ? true : false)
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
var json = {
|
||||
"recordsTotal": data.length,
|
||||
"recordsFiltered": data.length,
|
||||
"data": objects
|
||||
};
|
||||
|
||||
return JSON.stringify(json);
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
var fnCreatedRow = function (nRow, aData, iDataIndex) {
|
||||
$(nRow).attr('data-type', 'selectable');
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
var columns = [
|
||||
{
|
||||
class: "remove-padding content-fill",
|
||||
data: null,
|
||||
defaultContent: "<div class='thumbnail icon'>" +
|
||||
"<i class='square-element text fw fw-devices' style='font-size: 74px;'></i>" +
|
||||
"</div>"
|
||||
},
|
||||
{
|
||||
class: "",
|
||||
data: "name",
|
||||
render: function (name, type, row, meta) {
|
||||
return '<h4>' + name.replace("devicemgt", "") + '</h4>';
|
||||
}
|
||||
},
|
||||
{
|
||||
class: "text-right content-fill text-left-on-grid-view no-wrap",
|
||||
data: null,
|
||||
render: function (data, type, row, meta) {
|
||||
var isCloud = false;
|
||||
if ($('#is-cloud').length > 0) {
|
||||
isCloud = true;
|
||||
}
|
||||
|
||||
var innerhtml = '';
|
||||
if (data.metaDefinition) {
|
||||
|
||||
var editLink = '<a onclick="javascript:loadDeviceTypeBasedActionURL(\'edit\', \'' + data.name + '\')" ' +
|
||||
'data-devicetype="' + data.name + '" ' +
|
||||
'data-click-event="edit-form" ' +
|
||||
'class="btn padding-reduce-on-grid-view edit-devicetype-link">' +
|
||||
'<span class="fw-stack">' +
|
||||
'<i class="fw fw-circle-outline fw-stack-2x"></i>' +
|
||||
'<i class="fw fw-devices fw-stack-1x"></i>' +
|
||||
'<span class="fw-stack fw-move-right fw-move-bottom">' +
|
||||
'<i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>' +
|
||||
'<i class="fw fw-circle fw-stack-2x"></i><i class="fw fw-edit fw-stack-1x fw-inverse"></i>' +
|
||||
'</span>' +
|
||||
'</span>' +
|
||||
'<span class="hidden-xs hidden-on-grid-view">Edit</span>' +
|
||||
'</a>';
|
||||
|
||||
var editEventLink = '<a onclick="javascript:loadDeviceTypeBasedActionURL(\'edit-event\', \'' + data.name + '\')" ' +
|
||||
'data-devicetype="' + data.name + '" ' +
|
||||
'data-click-event="edit-form" ' +
|
||||
'class="btn padding-reduce-on-grid-view edit-event-link">' +
|
||||
'<span class="fw-stack">' +
|
||||
'<i class="fw fw-circle-outline fw-stack-2x"></i>' +
|
||||
'<i class="fw fw-document fw-stack-1x"></i>' +
|
||||
'<span class="fw-stack fw-move-right fw-move-bottom">' +
|
||||
'<i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>' +
|
||||
'<i class="fw fw-circle fw-stack-2x"></i><i class="fw fw-edit fw-stack-1x fw-inverse"></i>' +
|
||||
'</span>' +
|
||||
'</span>' +
|
||||
'<span class="hidden-xs hidden-on-grid-view">Edit Event</span>' +
|
||||
'</a>';
|
||||
|
||||
innerhtml = editLink + editEventLink;
|
||||
}
|
||||
return innerhtml;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var options = {
|
||||
"placeholder": "Search By Device Type Name",
|
||||
"searchKey": "filter",
|
||||
"searching": false
|
||||
};
|
||||
var settings = {
|
||||
"sorting": false
|
||||
};
|
||||
var deviceTypeApiUrl = '/api/device-mgt/v1.0/admin/device-types';
|
||||
|
||||
$('#devicetype-grid').datatables_extended_serverside_paging(settings, deviceTypeApiUrl, dataFilter, columns, fnCreatedRow, null, options);
|
||||
loadingContent.hide();
|
||||
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
loadDeviceTypes();
|
||||
});
|
||||
@ -0,0 +1,44 @@
|
||||
{{#each deviceTypes}}
|
||||
<tr data-type="selectable" id="devicetype-{{deviceTypeName}}">
|
||||
<td class="remove-padding icon-only content-fill">
|
||||
<div class="thumbnail icon">
|
||||
<i class="square-element text fw fw-user"></i>
|
||||
</div>
|
||||
</td>
|
||||
<td class="remove-padding-top">{{deviceTypeName}}</td>
|
||||
<td class="text-right content-fill text-left-on-grid-view no-wrap">
|
||||
|
||||
{{#if canEdit}}
|
||||
<a onclick="javascript:loadDeviceTypeBasedActionURL('edit', '{{deviceTypeName}}')" data-devicetype="{{deviceTypeName}}"
|
||||
data-click-event="edit-form"
|
||||
class="btn padding-reduce-on-grid-view edit-devicetype-link" title="Edit Device Type">
|
||||
<span class="fw-stack fw-lg">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-user fw-stack-1x"></i>
|
||||
<span class="fw-stack fw-move-right fw-move-bottom">
|
||||
<i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>
|
||||
<i class="fw fw-circle fw-stack-2x"></i>
|
||||
<i class="fw fw-edit fw-stack-1x fw-inverse"></i>
|
||||
</span>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-on-grid-view">Edit</span>
|
||||
</a>
|
||||
<a onclick="javascript:loadDeviceTypeBasedActionURL('edit-event', '{{deviceTypeName}}')"
|
||||
data-devicetype="{{deviceTypeName}}"
|
||||
data-click-event="edit-form" class="btn padding-reduce-on-grid-view edit-permission-link"
|
||||
title="Edit Device Event">
|
||||
<span class="fw-stack fw-lg">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-security-policy fw-stack-1x"></i>
|
||||
<span class="fw-stack fw-move-right fw-move-bottom">
|
||||
<i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>
|
||||
<i class="fw fw-circle fw-stack-2x"></i>
|
||||
<i class="fw fw-edit fw-stack-1x fw-inverse"></i>
|
||||
</span>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-on-grid-view">Edit Event</span>
|
||||
</a>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
@ -0,0 +1,43 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
|
||||
{{unit "cdmf.unit.ui.title" pageTitle="Policy Management | View Policy"}}
|
||||
|
||||
{{#zone "breadcrumbs"}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/">
|
||||
<i class="icon fw fw-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/policies">
|
||||
Policies
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
View
|
||||
</a>
|
||||
</li>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "content"}}
|
||||
{{unit "cdmf.unit.device.operation-mod"}}
|
||||
{{unit "cdmf.unit.effective-policy.view"}}
|
||||
{{/zone}}
|
||||
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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 utility = require("/app/modules/utility.js")["utility"];
|
||||
var deviceType = context.uriParams.deviceType;
|
||||
var deviceId = context.uriParams.deviceId;
|
||||
return {"deviceTypePolicyView": utility.getTenantedDeviceUnitName(deviceType, deviceId,"policy-view")};
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/policy/effective-policy/",
|
||||
"layout": "cdmf.layout.default"
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{#zone "title"}}Error | {{@app.conf.appName}}{{/zone}}
|
||||
|
||||
{{#zone "messageDescription"}}
|
||||
{{@page.params.status}} - {{@page.params.message}}
|
||||
{{/zone}}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/errors/default",
|
||||
"layout" : "cdmf.layout.error"
|
||||
}
|
||||
@ -0,0 +1,420 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{unit "cdmf.unit.ui.title" pageTitle="Group Management"}}
|
||||
{{unit "cdmf.unit.ui.content.title" pageHeader="Groups"}}
|
||||
|
||||
{{unit "cdmf.unit.lib.service-invoker-utility"}}
|
||||
{{unit "cdmf.unit.data-tables-extended"}}
|
||||
{{unit "cdmf.unit.lib.ui-permissions-utility"}}
|
||||
|
||||
{{#zone "breadcrumbs"}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/">
|
||||
<i class="icon fw fw-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{@app.context}}/groups">
|
||||
Groups
|
||||
</a>
|
||||
</li>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "navbarActions"}}
|
||||
{{#if permissions.ADD_GROUP}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/group/add" class="cu-btn">
|
||||
<span class="icon fw-stack">
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
</span>
|
||||
Add Group
|
||||
</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "content"}}
|
||||
<div class="wr-device-list row">
|
||||
<div class="wr-hidden-operations wr-advance-operations"></div>
|
||||
<div class="col-md-12 wr-page-content">
|
||||
<div>
|
||||
<span id="permission" data-permission="{{permissions.list}}"></span>
|
||||
<span id="isCloud" data-isCloud="{{isCloud}}"></span>
|
||||
{{#if groupCount}}
|
||||
<div class="container-fluid" id="group-listing" data-current-user="{{@user.username}}">
|
||||
<table class="table table-striped table-hover list-table display responsive nowrap data-table table-selectable grid-view"
|
||||
id="group-grid">
|
||||
<thead>
|
||||
<tr class="sort-row">
|
||||
<th class="no-sort"></th>
|
||||
<th class="no-sort"></th>
|
||||
<th>By Owner</th>
|
||||
<th class="no-sort"></th>
|
||||
</tr>
|
||||
<tr class="filter-row filter-box">
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th data-for="By Owner" class="text-filter"></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ast-container"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{else}}
|
||||
<div id="ast-container" class="ast-container list-view">
|
||||
<div class="ctrl-info-panel col-centered text-center wr-login">
|
||||
<h3 class="text-muted">
|
||||
<i class="fw fw-group fw-3x"></i>
|
||||
</h3>
|
||||
<h3 class="text-muted">You don't have any device group. Let's add a new device group!</h3>
|
||||
{{#if permissions.ADD_GROUP}}
|
||||
<h3>
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/group/add" class="btn-operations btn-default">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
</span>
|
||||
Add New Group
|
||||
</a>
|
||||
</h3>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div id="share-group-w1-modal-content" class="hide">
|
||||
<div class="modal-header">
|
||||
<h3 class="pull-left modal-title">
|
||||
<span>
|
||||
<span class="fw-stack add-margin-right-2x">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-share fw-stack-1x"></i>
|
||||
</span> Group Sharing
|
||||
</span>
|
||||
</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i
|
||||
class="fw fw-cancel"></i></button>
|
||||
</div>
|
||||
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
|
||||
<div id="notification-error-msg" class="alert alert-danger hidden" role="alert">
|
||||
<i class="icon fw fw-error"></i><span></span>
|
||||
</div>
|
||||
<div id="user-names">
|
||||
<h4>
|
||||
Select user role(s)
|
||||
</h4>
|
||||
<div class="wr-input-control" id="rolesListing">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="buttons">
|
||||
{{#if permissions.ADD_ROLE}}
|
||||
<a href="{{@app.context}}/role/add" class="btn-operations">
|
||||
New Role
|
||||
</a>
|
||||
<a href="#" id="share-group-new-role-from-selection" class="btn-operations">
|
||||
New Role from Selection
|
||||
</a>
|
||||
{{/if}}
|
||||
<a href="#" id="share-group-next-link" class="btn-operations">
|
||||
Share
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="share-group-w3-modal-content" class="hide">
|
||||
<div class="modal-header">
|
||||
<h3 class="pull-left modal-title">
|
||||
<span>
|
||||
<span class="fw-stack add-margin-right-2x">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-bookmark fw-stack-1x"></i>
|
||||
</span> Group Sharing Role
|
||||
</span>
|
||||
</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i
|
||||
class="fw fw-cancel"></i></button>
|
||||
</div>
|
||||
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
|
||||
<div id="notification-error-msg" class="alert alert-danger hidden" role="alert">
|
||||
<i class="icon fw fw-error"></i><span></span>
|
||||
</div>
|
||||
<div id="user-roles">
|
||||
<h4>
|
||||
Enter Group Sharing Role Name
|
||||
<br><br>
|
||||
<input type="text" id="group-sharing-role-name"
|
||||
class="form-control modal-input operationDataKeys" />
|
||||
<br><br>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="buttons">
|
||||
<a href="#" id="share-group-w3-yes-link" class="btn-operations">
|
||||
OK
|
||||
</a>
|
||||
|
||||
<a href="#" id="share-group-w3-cancel-link" class="btn-operations btn-default">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="share-group-200-content" class="hide">
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>Group successfully updated.</h3>
|
||||
<br />
|
||||
Do you want to manage users?
|
||||
<div class="buttons">
|
||||
<a href="{{@app.context}}/users" id="share-group-add-users-yes-link"
|
||||
class="btn-operations">
|
||||
Yes
|
||||
</a>
|
||||
|
||||
<a href="#" class="btn-operations btn-default" data-dismiss="modal">
|
||||
No
|
||||
</a>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="create-combined-role-200-content" class="hide">
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>New Role was successfully created.</h3>
|
||||
<br />
|
||||
Do you need to Add / Remove users from the chosen roles?
|
||||
<div class="buttons">
|
||||
<a href="{{@app.context}}/users" id="share-group-add-users-yes-link"
|
||||
class="btn-operations">
|
||||
Yes
|
||||
</a>
|
||||
|
||||
<a href="#" class="btn-operations btn-default" data-dismiss="modal">
|
||||
No
|
||||
</a>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="remove-group-modal-content" class="hide">
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>Do you really want to remove this group from your Group List?</h3>
|
||||
|
||||
<div class="buttons">
|
||||
<a href="#" id="remove-group-yes-link" class="btn-operations">
|
||||
Yes
|
||||
</a>
|
||||
|
||||
<a href="#" id="remove-group-cancel-link" class="btn-operations btn-default"
|
||||
data-dismiss="modal">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="remove-group-200-content" class="hide">
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>Group was successfully removed.</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="edit-group-modal-content" class="hide">
|
||||
<div class="modal-header">
|
||||
<h3 class="pull-left modal-title">
|
||||
<span>
|
||||
<span class="fw-stack add-margin-right-2x">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-edit fw-stack-1x"></i>
|
||||
</span> Update Group
|
||||
</span>
|
||||
</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i
|
||||
class="fw fw-cancel"></i></button>
|
||||
</div>
|
||||
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
|
||||
<div id="notification-error-msg" class="alert alert-danger hidden" role="alert">
|
||||
<i class="icon fw fw-error"></i><span></span>
|
||||
</div>
|
||||
<div>
|
||||
<h4>
|
||||
Enter new name and description for the group
|
||||
<br><br>
|
||||
<input type="text" id="edit-group-name"
|
||||
class="form-control modal-input operationDataKeys" placeholder="Group Name"
|
||||
value="">
|
||||
</input>
|
||||
<br>
|
||||
<input type="text" id="edit-group-description"
|
||||
class="form-control modal-input operationDataKeys"
|
||||
placeholder="Group Description" value="">
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="buttons">
|
||||
<a href="#" id="edit-group-yes-link" class="btn-operations">
|
||||
Update
|
||||
</a>
|
||||
|
||||
<a href="#" id="edit-group-cancel-link" class="btn-operations btn-default">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="edit-group-200-content" class="hide">
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>Group was successfully updated.</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="group-400-content" class="hide">
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3 id="error-msg">Bad Request. Please contact your administrator.</h3>
|
||||
<div class="buttons">
|
||||
<a href="#" id="group-400-link" class="btn-operations">
|
||||
Ok
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="group-403-content" class="hide">
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>Operation not permitted.</h3>
|
||||
|
||||
<div class="buttons">
|
||||
<a href="#" id="group-403-link" class="btn-operations">
|
||||
Ok
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="group-404-content" class="hide">
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3 id="group-404-message">Not found.</h3>
|
||||
|
||||
<div class="buttons">
|
||||
<a href="#" id="group-404-link" class="btn-operations">
|
||||
Ok
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="group-409-content" class="hide">
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3>Group does not exist.</h3>
|
||||
|
||||
<div class="buttons">
|
||||
<a href="#" id="group-409-link" class="btn-operations">
|
||||
Ok
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="group-unexpected-error-content" class="hide">
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h3 id="unexp-error-msg">Unexpected error occurred!</h3>
|
||||
|
||||
<div class="buttons">
|
||||
<a href="#" id="group-unexpected-error-link" class="btn-operations">
|
||||
Ok
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "bottomJs"}}
|
||||
{{#if groupCount}}
|
||||
{{js "js/listing.js"}}
|
||||
{{/if}}
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "topCss"}}
|
||||
<style>
|
||||
.select2-dropdown {
|
||||
z-index: 999999999;
|
||||
}
|
||||
|
||||
.wr-input-control {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.select2-selection__choice {
|
||||
font-size: medium;
|
||||
}
|
||||
</style>
|
||||
{{/zone}}
|
||||
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 groupModule = require("/app/modules/business-controllers/group.js")["groupModule"];
|
||||
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
|
||||
var constants = require("/app/modules/constants.js");
|
||||
var deviceMgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var currentUser = session.get(constants.USER_SESSION_KEY);
|
||||
var page = {};
|
||||
if (currentUser) {
|
||||
page.permissions = userModule.getUIPermissions();
|
||||
page.permissions.list = stringify(page.permissions);
|
||||
page.currentUser = currentUser;
|
||||
var groupCount = groupModule.getGroupCount();
|
||||
if (groupCount > 0) {
|
||||
page.groupCount = groupCount;
|
||||
}
|
||||
}
|
||||
page.isCloud = deviceMgtProps.isCloud;
|
||||
return page;
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/groups",
|
||||
"layout": "cdmf.layout.default"
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
@ -0,0 +1,646 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Following function would execute
|
||||
* when a user clicks on the list item
|
||||
* initial mode and with out select mode.
|
||||
*/
|
||||
function InitiateViewOption(url) {
|
||||
if ($(".select-enable-btn").text() == "Select") {
|
||||
url = $(this).parent().data("url");
|
||||
$(location).attr('href', url);
|
||||
}
|
||||
}
|
||||
|
||||
(function () {
|
||||
var cache = {};
|
||||
var validateAndReturn = function (value) {
|
||||
return (value == undefined || value == null) ? "Unspecified" : value;
|
||||
};
|
||||
Handlebars.registerHelper("deviceMap", function (device) {
|
||||
device.owner = validateAndReturn(device.owner);
|
||||
device.ownership = validateAndReturn(device.ownership);
|
||||
var arr = device.properties;
|
||||
if (arr) {
|
||||
device.properties = arr.reduce(function (total, current) {
|
||||
total[current.name] = validateAndReturn(current.value);
|
||||
return total;
|
||||
}, {});
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
/*
|
||||
* Setting-up global variables.
|
||||
*/
|
||||
var groupCheckbox = "#ast-container .ctrl-wr-asset .itm-select input[type='checkbox']";
|
||||
var assetContainer = "#ast-container";
|
||||
|
||||
/*
|
||||
* On Select All Groups button click function.
|
||||
*
|
||||
* @param button: Select All Groups button
|
||||
*/
|
||||
function selectAllDevices(button) {
|
||||
if (!$(button).data('select')) {
|
||||
$(groupCheckbox).each(function (index) {
|
||||
$(this).prop('checked', true);
|
||||
addGroupSelectedClass(this);
|
||||
});
|
||||
$(button).data('select', true);
|
||||
$(button).html('Deselect All Groups');
|
||||
} else {
|
||||
$(groupCheckbox).each(function (index) {
|
||||
$(this).prop('checked', false);
|
||||
addGroupSelectedClass(this);
|
||||
});
|
||||
$(button).data('select', false);
|
||||
$(button).html('Select All Groups');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* On listing layout toggle buttons click function.
|
||||
*
|
||||
* @param view: Selected view type
|
||||
* @param selection: Selection button
|
||||
*/
|
||||
function changeDeviceView(view, selection) {
|
||||
$(".view-toggle").each(function () {
|
||||
$(this).removeClass("selected");
|
||||
});
|
||||
$(selection).addClass("selected");
|
||||
if (view == "list") {
|
||||
$(assetContainer).addClass("list-view");
|
||||
} else {
|
||||
$(assetContainer).removeClass("list-view");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add selected style class to the parent element function.
|
||||
*
|
||||
* @param checkbox: Selected checkbox
|
||||
*/
|
||||
function addGroupSelectedClass(checkbox) {
|
||||
if ($(checkbox).is(":checked")) {
|
||||
$(checkbox).closest(".ctrl-wr-asset").addClass("selected device-select");
|
||||
} else {
|
||||
$(checkbox).closest(".ctrl-wr-asset").removeClass("selected device-select");
|
||||
}
|
||||
}
|
||||
|
||||
function toTitleCase(str) {
|
||||
return str.replace(/\w\S*/g, function (txt) {
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||
});
|
||||
}
|
||||
|
||||
function htmlspecialchars(text) {
|
||||
return jQuery('<div/>').text(text).html();
|
||||
}
|
||||
|
||||
function loadGroups() {
|
||||
var groupListing = $("#group-listing");
|
||||
var currentUser = groupListing.data("currentUser");
|
||||
var serviceURL;
|
||||
if ($.hasPermission("LIST_ALL_GROUPS")) {
|
||||
serviceURL = "/api/device-mgt/v1.0/admin/groups";
|
||||
} else if ($.hasPermission("LIST_GROUPS")) {
|
||||
//Get authenticated users groups
|
||||
serviceURL = "/api/device-mgt/v1.0/groups";
|
||||
} else {
|
||||
$("#loading-content").remove();
|
||||
$('#device-table').addClass('hidden');
|
||||
$('#device-listing-status-msg').text('Permission denied.');
|
||||
$("#device-listing-status").removeClass(' hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
var dataFilter = function (data) {
|
||||
data = JSON.parse(data);
|
||||
var objects = [];
|
||||
$(data.deviceGroups).each(function (index) {
|
||||
objects.push({
|
||||
groupId: htmlspecialchars(data.deviceGroups[index].id),
|
||||
name: htmlspecialchars(data.deviceGroups[index].name),
|
||||
description: htmlspecialchars(data.deviceGroups[index].description),
|
||||
owner: htmlspecialchars(data.deviceGroups[index].owner)
|
||||
})
|
||||
});
|
||||
var json = {
|
||||
"recordsTotal": data.count,
|
||||
"recordsFiltered": data.count,
|
||||
"data": objects
|
||||
};
|
||||
return JSON.stringify(json);
|
||||
};
|
||||
|
||||
var columns = [
|
||||
{
|
||||
targets: 0,
|
||||
data: 'id',
|
||||
class: 'remove-padding icon-only content-fill viewEnabledIcon',
|
||||
render: function (data, type, row, meta) {
|
||||
return '<div class="thumbnail icon"><img class="square-element text fw " ' +
|
||||
'src="public/cdmf.page.groups/images/group-icon.png"/></div>';
|
||||
}
|
||||
},
|
||||
{
|
||||
targets: 1,
|
||||
data: 'name',
|
||||
class: 'viewEnabledIcon'
|
||||
},
|
||||
{
|
||||
targets: 2,
|
||||
data: 'owner',
|
||||
class: 'remove-padding-top viewEnabledIcon'
|
||||
},
|
||||
{
|
||||
targets: 3,
|
||||
data: 'description',
|
||||
class: 'remove-padding-top viewEnabledIcon'
|
||||
},
|
||||
{
|
||||
targets: 4,
|
||||
data: 'id',
|
||||
class: 'text-right content-fill text-left-on-grid-view no-wrap tooltip-overflow-fix',
|
||||
render: function (id, type, row, meta) {
|
||||
var html = '';
|
||||
if ($.hasPermission("VIEW_GROUP_DEVICES")) {
|
||||
/*html += '<a href="group/' + row.groupId
|
||||
+ '/analytics" data-click-event="remove-form" class="btn padding-reduce-on-grid-view">' +
|
||||
'<span class="fw-stack"><i class="fw fw-circle-outline 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>';*/
|
||||
}
|
||||
if (row.owner != "wso2.system.user") {
|
||||
if ($.hasPermission("SHARE_GROUP")) {
|
||||
html +=
|
||||
'<a href="#" data-click-event="remove-form" class="btn padding-reduce-on-grid-view share-group-link" data-group-id="'
|
||||
+ row.groupId + '" ' +
|
||||
'data-group-owner="' + row.owner
|
||||
+ '" data-placement="top" data-toggle="tooltip" data-original-title="Share"><span class="fw-stack"><i class="fw fw-circle-outline fw-stack-2x"></i><i class="fw fw-share fw-stack-1x"></i></span>'
|
||||
+
|
||||
'<span class="hidden-xs hidden-on-grid-view">Share</span></a>';
|
||||
}
|
||||
if ($.hasPermission("UPDATE_GROUP")) {
|
||||
html +=
|
||||
'<a href="#" data-click-event="remove-form" class="btn padding-reduce-on-grid-view edit-group-link" data-group-name="'
|
||||
+ row.name + '" ' +
|
||||
'data-group-owner="' + row.owner + '" data-group-description="' + row.description
|
||||
+ '" data-group-id="' + row.groupId
|
||||
+ '" data-placement="top" data-toggle="tooltip" data-original-title="Edit"><span class="fw-stack"><i class="fw fw-circle-outline 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>';
|
||||
}
|
||||
if ($.hasPermission("REMOVE_GROUP")) {
|
||||
html +=
|
||||
'<a href="#" data-click-event="remove-form" class="btn padding-reduce-on-grid-view remove-group-link" data-group-id="'
|
||||
+ row.groupId + '" ' +
|
||||
'data-group-owner="' + row.owner
|
||||
+ '" data-placement="top" data-toggle="tooltip" data-original-title="Delete"><span class="fw-stack"><i class="fw fw-circle-outline 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>';
|
||||
}
|
||||
}
|
||||
return html;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var fnCreatedRow = function (row, data) {
|
||||
$(row).attr('data-type', 'selectable');
|
||||
if ($.hasPermission("VIEW_GROUP_DEVICES")) {
|
||||
$(row).attr('data-url', 'devices?groupId=' + data.groupId + '&groupName=' + data.name);
|
||||
}
|
||||
$.each($('td', row), function (colIndex) {
|
||||
switch (colIndex) {
|
||||
case 1:
|
||||
//TODO : The following line encodes html entities.
|
||||
//Should check for a better solution since it only changes the presentation layer
|
||||
$(this).text($("<textarea></textarea>").html(this.innerText).text())
|
||||
$(this).attr('data-grid-label', "Name");
|
||||
$(this).attr('data-search', data.name);
|
||||
$(this).attr('data-display', data.name);
|
||||
break;
|
||||
case 2:
|
||||
$(this).attr('data-grid-label', "Owner");
|
||||
$(this).attr('data-search', data.owner);
|
||||
$(this).attr('data-display', data.owner);
|
||||
break;
|
||||
case 3:
|
||||
$(this).attr('data-grid-label', "Description");
|
||||
$(this).attr('data-search', data.description);
|
||||
$(this).attr('data-display', data.description);
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#group-grid').datatables_extended_serverside_paging(
|
||||
null,
|
||||
serviceURL,
|
||||
dataFilter,
|
||||
columns,
|
||||
fnCreatedRow,
|
||||
function (oSettings) {
|
||||
$(".icon .text").res_text(0.2);
|
||||
attachEvents();
|
||||
var thisTable = $(this).closest('.dataTables_wrapper').find('.dataTable').dataTable();
|
||||
thisTable.removeClass("table-selectable");
|
||||
},
|
||||
{
|
||||
"placeholder": "Search By Group Name",
|
||||
"searchKey": "name"
|
||||
}
|
||||
);
|
||||
$(groupCheckbox).click(function () {
|
||||
addGroupSelectedClass(this);
|
||||
});
|
||||
}
|
||||
|
||||
function openCollapsedNav() {
|
||||
$('.wr-hidden-nav-toggle-btn').addClass('active');
|
||||
$('#hiddenNav').slideToggle('slideDown', function () {
|
||||
if ($(this).css('display') == 'none') {
|
||||
$('.wr-hidden-nav-toggle-btn').removeClass('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* DOM ready functions.
|
||||
*/
|
||||
$(document).ready(function () {
|
||||
|
||||
/* Adding selected class for selected devices */
|
||||
$(groupCheckbox).each(function () {
|
||||
addGroupSelectedClass(this);
|
||||
});
|
||||
|
||||
var permissionSet = {};
|
||||
|
||||
//This method is used to setup permission for device listing
|
||||
$.setPermission = function (permission) {
|
||||
permissionSet[permission] = true;
|
||||
};
|
||||
|
||||
$.hasPermission = function (permission) {
|
||||
return permissionSet[permission];
|
||||
};
|
||||
|
||||
var permissionList = $("#permission").data("permission");
|
||||
for (var key in permissionList) {
|
||||
if (permissionList.hasOwnProperty(key)) {
|
||||
$.setPermission(key);
|
||||
}
|
||||
}
|
||||
|
||||
loadGroups();
|
||||
//$('#device-grid').datatables_extended();
|
||||
|
||||
/* for device list sorting drop down */
|
||||
$(".ctrl-filter-type-switcher").popover(
|
||||
{
|
||||
html: true,
|
||||
content: function () {
|
||||
return $("#content-filter-types").html();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/* for data tables*/
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
$("[data-toggle=popover]").popover();
|
||||
|
||||
$(".ctrl-filter-type-switcher").popover(
|
||||
{
|
||||
html: true,
|
||||
content: function () {
|
||||
return $('#content-filter-types').html();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$('#nav').affix(
|
||||
{
|
||||
offset: {
|
||||
top: $('header').height()
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
var modalPopup = ".modal";
|
||||
var modalPopupContainer = modalPopup + " .modal-content";
|
||||
var modalPopupContent = modalPopup + " .modal-content";
|
||||
var body = "body";
|
||||
|
||||
/*
|
||||
* set popup maximum height function.
|
||||
*/
|
||||
function setPopupMaxHeight() {
|
||||
$(modalPopupContent).css('max-height', ($(body).height() - ($(body).height() / 100 * 30)));
|
||||
$(modalPopupContainer).css('margin-top', (-($(modalPopupContainer).height() / 2)));
|
||||
}
|
||||
|
||||
/*
|
||||
* show popup function.
|
||||
*/
|
||||
function showPopup() {
|
||||
$(modalPopup).modal('show');
|
||||
}
|
||||
|
||||
/*
|
||||
* hide popup function.
|
||||
*/
|
||||
function hidePopup() {
|
||||
$(modalPopupContent).html("");
|
||||
$(modalPopupContent).removeClass("operation-data");
|
||||
$(modalPopup).modal('hide');
|
||||
$('body').removeClass('modal-open').css('padding-right', '0px');
|
||||
$('.modal-backdrop').remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Following functions should be triggered after AJAX request is made.
|
||||
*/
|
||||
function attachEvents() {
|
||||
/**
|
||||
* Following click function would execute
|
||||
* when a user clicks on "Share" link
|
||||
* on Group Management page in WSO2 Device Management Server Console.
|
||||
*/
|
||||
$("a.share-group-link").click(function () {
|
||||
var groupId = $(this).data("group-id");
|
||||
var groupOwner = $(this).data("group-owner");
|
||||
|
||||
$(modalPopupContent).html($('#share-group-w1-modal-content').html());
|
||||
showPopup();
|
||||
|
||||
listAllRoles(groupId);
|
||||
var shareGroupNextLink = $("a#share-group-next-link");
|
||||
shareGroupNextLink.click(function () {
|
||||
var roles = $("#roles").val();
|
||||
updateGroupShare(groupId, roles);
|
||||
});
|
||||
|
||||
var shareGroupNewRoleFromSelectionLink = $("a#share-group-new-role-from-selection");
|
||||
shareGroupNewRoleFromSelectionLink.click(function () {
|
||||
var roles = $("#roles").val();
|
||||
if (roles && roles.length >= 2) {
|
||||
addNewRole(roles);
|
||||
} else {
|
||||
var errorMsgWrapper = "#notification-error-msg";
|
||||
var errorMsg = "#notification-error-msg span";
|
||||
$(errorMsg).text("To create a new role with the combination of roles, at least two roles should be" +
|
||||
" selected.");
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Following click function would execute
|
||||
* when a user clicks on "Remove" link
|
||||
* on Group Management page in WSO2 IoT Server Console.
|
||||
*/
|
||||
$("a.remove-group-link").click(function () {
|
||||
var groupId = $(this).data("group-id");
|
||||
var groupOwner = $(this).data("group-owner");
|
||||
|
||||
$(modalPopupContent).html($('#remove-group-modal-content').html());
|
||||
showPopup();
|
||||
|
||||
$("a#remove-group-yes-link").click(function () {
|
||||
var successCallback = function (data, textStatus, xhr) {
|
||||
if (xhr.status == 200) {
|
||||
$(modalPopupContent).html($('#remove-group-200-content').html());
|
||||
setTimeout(function () {
|
||||
hidePopup();
|
||||
location.reload(false);
|
||||
}, 2000);
|
||||
} else {
|
||||
displayErrors(xhr);
|
||||
}
|
||||
};
|
||||
|
||||
invokerUtil.delete("/api/device-mgt/v1.0/groups/id/" + groupId,
|
||||
successCallback, function (message) {
|
||||
displayErrors(message);
|
||||
});
|
||||
});
|
||||
|
||||
$("a#remove-group-cancel-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* Following click function would execute
|
||||
* when a user clicks on "Edit" link
|
||||
* on Device Management page in WSO2 MDM Console.
|
||||
*/
|
||||
$("a.edit-group-link").click(function () {
|
||||
var groupId = $(this).data("group-id");
|
||||
var groupName = $(this).data("group-name");
|
||||
var groupOwner = $(this).data("group-owner");
|
||||
var groupDescription = $(this).data("group-description");
|
||||
|
||||
$(modalPopupContent).html($('#edit-group-modal-content').html());
|
||||
$('#edit-group-name').val(groupName);
|
||||
$('#edit-group-description').val(groupDescription);
|
||||
showPopup();
|
||||
|
||||
$("a#edit-group-yes-link").click(function () {
|
||||
var newGroupName = $('#edit-group-name').val();
|
||||
var newGroupDescription = $('#edit-group-description').val();
|
||||
var group = {"name": newGroupName, "description": newGroupDescription, "owner": groupOwner};
|
||||
|
||||
var successCallback = function (data, textStatus, xhr) {
|
||||
if (xhr.status == 200) {
|
||||
$(modalPopupContent).html($('#edit-group-200-content').html());
|
||||
setTimeout(function () {
|
||||
hidePopup();
|
||||
location.reload(false);
|
||||
}, 2000);
|
||||
} else {
|
||||
displayErrors(xhr);
|
||||
}
|
||||
};
|
||||
|
||||
invokerUtil.put("/api/device-mgt/v1.0/groups/id/" + groupId, group,
|
||||
successCallback, function (message) {
|
||||
displayErrors(message);
|
||||
});
|
||||
});
|
||||
|
||||
$("a#edit-group-cancel-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function markAlreadySavedUsersRoles(groupId) {
|
||||
var successCallback = function (data, textStatus, xhr) {
|
||||
data = JSON.parse(data);
|
||||
if (xhr.status == 200) {
|
||||
if (data.roles.length > 0) {
|
||||
var selectedValues = [];
|
||||
for (var i = 0; i < data.roles.length; i++) {
|
||||
selectedValues.push(data.roles[i]);
|
||||
}
|
||||
$("#roles").val(selectedValues).trigger("change");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
displayErrors(xhr);
|
||||
}
|
||||
};
|
||||
|
||||
invokerUtil.get("/api/device-mgt/v1.0/groups/id/" + groupId + "/roles",
|
||||
successCallback, function (message) {
|
||||
displayErrors(message);
|
||||
});
|
||||
}
|
||||
|
||||
function listAllRoles(groupId) {
|
||||
var successCallback = function (data, textStatus, xhr) {
|
||||
data = JSON.parse(data);
|
||||
if (xhr.status == 200) {
|
||||
if (data.roles.length > 0) {
|
||||
var html = '<select id="roles" class="form-control select2" multiple="multiple">';
|
||||
for (var i = 0; i < data.roles.length; i++) {
|
||||
html += '<option value="' + data.roles[i] + '">' + data.roles[i] + '</option>';
|
||||
}
|
||||
html += '</select>';
|
||||
$("#rolesListing").html(html);
|
||||
markAlreadySavedUsersRoles(groupId);
|
||||
$("select.select2[multiple=multiple]").select2({tags: false}).on("select2:select", function () {
|
||||
$("#notification-error-msg").addClass("hidden");
|
||||
});
|
||||
} else {
|
||||
$("#rolesListing").html("No roles available");
|
||||
}
|
||||
} else {
|
||||
displayErrors(xhr);
|
||||
}
|
||||
};
|
||||
|
||||
invokerUtil.get("/api/device-mgt/v1.0/roles?offset=0&limit=100&user-store=all",
|
||||
successCallback, function (message) {
|
||||
displayErrors(message);
|
||||
});
|
||||
}
|
||||
|
||||
function addNewRole(roles) {
|
||||
$(modalPopupContent).html($('#share-group-w3-modal-content').html());
|
||||
$("a#share-group-w3-yes-link").click(function () {
|
||||
var roleName = $('#group-sharing-role-name').val();
|
||||
if (roleName) {
|
||||
createNewCombinedRole(roleName, roles);
|
||||
} else {
|
||||
var errorMsgWrapper = "#notification-error-msg";
|
||||
var errorMsg = "#notification-error-msg span";
|
||||
$(errorMsg).text("Role name cannot be empty.");
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
}
|
||||
});
|
||||
$("a#share-group-w3-cancel-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
}
|
||||
|
||||
function togglePermissionAction(element) {
|
||||
$(element).data('value', 'checked');
|
||||
var icon = $(element).find("i")[1];
|
||||
if ($(icon).hasClass('fw-minus')) {
|
||||
$(icon).removeClass('fw-minus');
|
||||
$(icon).addClass('fw-add');
|
||||
$(element).data('value', 'unchecked');
|
||||
} else {
|
||||
$(icon).removeClass('fw-add');
|
||||
$(icon).addClass('fw-minus');
|
||||
$(element).data('value', 'checked');
|
||||
}
|
||||
}
|
||||
|
||||
function updateGroupShare(groupId, roles) {
|
||||
var successCallback = function (data) {
|
||||
$(modalPopupContent).html($('#share-group-200-content').html());
|
||||
};
|
||||
|
||||
invokerUtil.post("/api/device-mgt/v1.0/groups/id/" + groupId + "/share",
|
||||
roles, successCallback, function (message) {
|
||||
displayErrors(message);
|
||||
});
|
||||
}
|
||||
|
||||
function createNewCombinedRole(roleName, roleList) {
|
||||
var successCallback = function (data, status, jqXHR, isLast) {
|
||||
$(modalPopupContent).html($('#create-combined-role-200-content').html());
|
||||
showPopup();
|
||||
};
|
||||
invokerUtil.post("/api/device-mgt/v1.0/roles/create-combined-role/" + roleName, roleList,
|
||||
successCallback, function (message) {
|
||||
displayErrors(message);
|
||||
});
|
||||
}
|
||||
|
||||
function displayErrors(jqXHR) {
|
||||
showPopup();
|
||||
if (jqXHR.status == 400) {
|
||||
$(modalPopupContent).html($('#group-400-content').html());
|
||||
if (jqXHR.responseText) {
|
||||
$('#error-msg').html(jqXHR.responseText.replace(new RegExp("\"", 'g'), ""));
|
||||
}
|
||||
$("a#group-400-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
} else if (jqXHR.status == 403) {
|
||||
$(modalPopupContent).html($('#group-403-content').html());
|
||||
$("a#group-403-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
} else if (jqXHR.status == 404) {
|
||||
$(modalPopupContent).html($('#group-404-content').html());
|
||||
$("#group-404-message").html(jqXHR.responseText);
|
||||
$("a#group-404-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
} else if (jqXHR.status == 409) {
|
||||
$(modalPopupContent).html($('#group-409-content').html());
|
||||
$("a#group-409-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
} else {
|
||||
$(modalPopupContent).html($('#group-unexpected-error-content').html());
|
||||
if (jqXHR.responseText) {
|
||||
$('#unexp-error-msg').html(jqXHR.responseText.replace(new RegExp("\"", 'g'), ""));
|
||||
}
|
||||
$("a#group-unexpected-error-link").click(function () {
|
||||
hidePopup();
|
||||
});
|
||||
console.log("Error code: " + jqXHR.status);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{unit "cdmf.unit.data-tables-extended"}}
|
||||
{{unit "cdmf.unit.ui.title" pageTitle="Notification Listing"}}
|
||||
{{#zone "breadcrumbs"}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/">
|
||||
<i class="icon fw fw-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{@app.context}}/notification-listing">
|
||||
Notifications
|
||||
</a>
|
||||
</li>
|
||||
{{/zone}}
|
||||
{{#zone "content"}}
|
||||
{{unit "cdmf.unit.notification.listing"}}
|
||||
{{/zone}}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/notification-listing",
|
||||
"layout": "cdmf.layout.default"
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{unit "cdmf.unit.ui.title" pageTitle="Home"}}
|
||||
|
||||
{{#zone "breadcrumbs"}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/">
|
||||
<i class="icon fw fw-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "content"}}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
Loading...Please Wait
|
||||
</div>
|
||||
</div>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "bottomJs"}}
|
||||
<script type="text/javascript">
|
||||
$('body').attr("data-toggle", "loading")
|
||||
.attr("data-loading-style", "overlay")
|
||||
.attr("data-loading-text", "SETTING UP YOUR ENVIRONMENT . . .");
|
||||
$('[data-toggle="loading"]').loading('show');
|
||||
</script>
|
||||
{{js "/js/script.js"}}
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "topCss"}}
|
||||
<style>
|
||||
.loading[data-loading-style=overlay] .loading-bg{
|
||||
background: #11375B;
|
||||
opacity: 1;
|
||||
filter: alpha(opacity=100);
|
||||
}
|
||||
.loading .loading-animation{
|
||||
width : 200px;
|
||||
}
|
||||
</style>
|
||||
{{/zone}}
|
||||
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 constants = require("/app/modules/constants.js");
|
||||
var skipWelcomeScreen = session.get(constants.SKIP_WELCOME_SCREEN);
|
||||
if (skipWelcomeScreen) {
|
||||
response.sendRedirect(context.app.context + "/");
|
||||
exit();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/welcome",
|
||||
"layout": "cdmf.layout.loading"
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
var pollingCount = 24;
|
||||
function poll() {
|
||||
$.ajax({
|
||||
url: context + "/api/user/environment-loaded",
|
||||
type: "GET",
|
||||
success: function (data) {
|
||||
if (data.isLoaded) {
|
||||
window.location = context + "/";
|
||||
}
|
||||
},
|
||||
dataType: "json",
|
||||
complete: setTimeout(function () {
|
||||
pollingCount = pollingCount - 1;
|
||||
if (pollingCount > 0) {
|
||||
poll();
|
||||
} else {
|
||||
$(".loading-animation .logo").hide();
|
||||
$(".loading-animation").prepend(
|
||||
'<i class="fw fw-error fw-inverse fw-2x" style="float: left;"></i>');
|
||||
$(".loading-animation p").css("width", "150%")
|
||||
.html("Ops... it seems something went wrong.<br/> Refresh the page to retry!");
|
||||
}
|
||||
}, 5000),
|
||||
timeout: 5000
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
poll();
|
||||
});
|
||||
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks if provided input is valid against RegEx input.
|
||||
*
|
||||
* @param regExp Regular expression
|
||||
* @param inputString Input string to check
|
||||
* @returns {boolean} Returns true if input matches RegEx
|
||||
*/
|
||||
function inputIsValid(regExp, inputString) {
|
||||
regExp = new RegExp(regExp);
|
||||
return regExp.test(inputString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an email address has the valid format or not.
|
||||
*
|
||||
* @param email Email address
|
||||
* @returns {boolean} true if email has the valid format, otherwise false.
|
||||
*/
|
||||
function emailIsValid(email) {
|
||||
var regExp = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
|
||||
return regExp.test(email);
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
/**
|
||||
* Following click function would execute
|
||||
* when a user clicks on "Add User" button
|
||||
* on Add User page in WSO2 Devicemgt Console.
|
||||
*/
|
||||
$("button#add-user-btn").click(function () {
|
||||
|
||||
var usernameInput = $("input#user_name");
|
||||
var firstnameInput = $("input#first_name");
|
||||
var lastnameInput = $("input#last_name");
|
||||
var emailInput = $("input#email");
|
||||
var passwordInput = $("input#password");
|
||||
var passwordConfirmationInput = $("input#password_confirmation");
|
||||
|
||||
var username = usernameInput.val().trim();
|
||||
var firstname = firstnameInput.val();
|
||||
var lastname = lastnameInput.val();
|
||||
var emailAddress = emailInput.val();
|
||||
var password = passwordInput.val();
|
||||
var passwordConfirmation = passwordConfirmationInput.val();
|
||||
var errorMsgWrapper = "#user-create-error-msg";
|
||||
var errorMsg = "#user-create-error-msg span";
|
||||
|
||||
if (!firstname) {
|
||||
$(errorMsg).text("Firstname is a required field. It cannot be empty.");
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
} else if (!inputIsValid(firstnameInput.data("regex"), firstname)) {
|
||||
$(errorMsg).text(firstnameInput.data("errormsg"));
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
} else if (!lastname) {
|
||||
$(errorMsg).text("Lastname is a required field. It cannot be empty.");
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
} else if (!inputIsValid(lastnameInput.data("regex"), lastname)) {
|
||||
$(errorMsg).text(lastnameInput.data("errormsg"));
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
} else if (!username) {
|
||||
$(errorMsg).text("Username is a required field. It cannot be empty.");
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
} else if (!inputIsValid(usernameInput.data("regex"), username)) {
|
||||
$(errorMsg).text(usernameInput.data("errormsg"));
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
} else if (!emailAddress) {
|
||||
$(errorMsg).text("Email is a required field. It cannot be empty.");
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
} else if (!emailIsValid(emailAddress)) {
|
||||
$(errorMsg).text(emailInput.data("errormsg"));
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
} else if (!password) {
|
||||
$(errorMsg).text("Password is a required field. It cannot be empty.");
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
} else if (password.length < 6) {
|
||||
$(errorMsg).text("Password should contain a minimum of 6 characters.");
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
} else if (password != passwordConfirmation) {
|
||||
$(errorMsg).text("Please enter the same password for confirmation.");
|
||||
$(errorMsgWrapper).removeClass("hidden");
|
||||
} else {
|
||||
$(errorMsgWrapper).addClass("hidden");
|
||||
$("#add-user-btn").prop('disabled', true);
|
||||
|
||||
var addUserFormData = {};
|
||||
addUserFormData.username = username;
|
||||
addUserFormData.firstname = firstname;
|
||||
addUserFormData.lastname = lastname;
|
||||
addUserFormData.emailAddress = emailAddress;
|
||||
addUserFormData.password = $("input#password").val();
|
||||
addUserFormData.userRoles = null;
|
||||
|
||||
var context = $(".form-login-box").data("context");
|
||||
var addUserAPI = context + "/api/user/register";
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: addUserAPI,
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(addUserFormData),
|
||||
success: function (data) {
|
||||
$("#add-user-btn").prop('disabled', false);
|
||||
if (data == 200) {
|
||||
$('.wr-validation-summary strong').html(
|
||||
"<i class=\"icon fw fw-success\"></i> Successfully Submitted.");
|
||||
$('.wr-validation-summary').removeClass("alert-danger");
|
||||
$('.wr-validation-summary').addClass("alert-success");
|
||||
} else if (data == 201) {
|
||||
$('.wr-validation-summary strong').html(
|
||||
"<i class=\"icon fw fw-success\"></i> User created succssfully. You will be " +
|
||||
"redirected to login page.");
|
||||
$('.wr-validation-summary').removeClass("alert-danger");
|
||||
$('.wr-validation-summary').addClass("alert-success");
|
||||
$("#add-user-btn").prop('disabled', true);
|
||||
setTimeout(function () {
|
||||
window.location = context + "/login";
|
||||
}, 2000);
|
||||
} else if (data == 400) {
|
||||
$('.wr-validation-summary strong').html(
|
||||
"<i class=\"icon fw fw-error\"></i> Exception at backend.");
|
||||
$('.wr-validation-summary').removeClass("alert-danger");
|
||||
$('.wr-validation-summary').addClass("alert-warning");
|
||||
} else if (data == 403) {
|
||||
$('.wr-validation-summary strong').html("Action not permitted.");
|
||||
} else if (data == 409) {
|
||||
$('.wr-validation-summary strong').html(
|
||||
"<i class=\"icon fw fw-info\"></i> User name already exists.");
|
||||
$('.wr-validation-summary').removeClass("alert-default");
|
||||
$('.wr-validation-summary').addClass("alert-success");
|
||||
}
|
||||
$('.wr-validation-summary').removeClass("hidden");
|
||||
$('#password').val('');
|
||||
$('#password_confirmation').val('');
|
||||
},
|
||||
error: function (err) {
|
||||
$("#add-user-btn").prop('disabled', false);
|
||||
$('.wr-validation-summary strong').html(
|
||||
"<i class=\"icon fw fw-error\"></i> An unexpected error occurred.");
|
||||
$('.wr-validation-summary').removeClass("hidden");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,75 @@
|
||||
{{unit "cdmf.unit.ui.title" pageTitle="Register"}}
|
||||
|
||||
{{#zone "content"}}
|
||||
{{unit "uuf.unit.lib.form-validation"}}
|
||||
|
||||
<div class="container col-xs-12 col-sm-10 col-md-8 col-lg-6 col-centered wr-content wr-login col-centered sign-panel">
|
||||
|
||||
<p class="page-sub-title">Register</p>
|
||||
|
||||
<p>Create new account on WSO2 IoT (All fields are required.)</p>
|
||||
<hr/>
|
||||
<!-- validation -->
|
||||
<div class="wr-validation-summary hidden alert alert-danger">
|
||||
<strong></strong>
|
||||
<button type="button" class="close" aria-label="close" data-dismiss="alert">
|
||||
<span aria-hidden="true">
|
||||
<i class="fw fw-cancel"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-login-box" id="registerForm" data-context="{{@app.context}}">
|
||||
<div id="user-create-error-msg" class="alert alert-danger hidden" role="alert">
|
||||
<i class="icon fw fw-error"></i><span></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="first_name" class="wr-input-label">First Name</label>
|
||||
<input type="text" id="first_name" name="first_name" class="form-control" placeholder="First Name"
|
||||
data-regex="{{firstnameJSRegEx}}" data-lengthmsg="{{usernameHelpText}}"
|
||||
data-errormsg="{{firstnameRegExViolationErrorMsg}}"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="last_name" class="wr-input-label">Last Name</label>
|
||||
<input type="text" id="last_name" name="last_name" class="form-control" placeholder="Last Name"
|
||||
data-regex="{{lastnameJSRegEx}}" data-errormsg="{{lastnameRegExViolationErrorMsg}}"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="user_name" class="wr-input-label">Username ( {{usernameHelpText}} )</label>
|
||||
<input type="text" id="user_name" name="user_name" class="form-control" placeholder="Username"
|
||||
data-regex="{{usernameJSRegEx}}" data-errormsg="{{usernameRegExViolationErrorMsg}}"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="email" class="wr-input-label">Email</label>
|
||||
<input type="text" id="email" name="email" class="form-control" placeholder="Email"
|
||||
data-regex="{{emailJSRegEx}}" data-errormsg="{{emailRegExViolationErrorMsg}}"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password" class="wr-input-label">Password</label>
|
||||
<input type="password" id="password" name="password" class="form-control"
|
||||
placeholder="Password"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password_confirmation" class="wr-input-label">Confirm Password</label>
|
||||
<input type="password" id="password_confirmation" name="password_confirmation"
|
||||
class="form-control" placeholder="Confirm Password"/>
|
||||
</div>
|
||||
|
||||
<div class="wr-input-control">
|
||||
<button class="wr-btn" id="add-user-btn">Register</button>
|
||||
<button class="wr-btn" onclick="document.location.href='{{@app.context}}/login';">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "bottomJs"}}
|
||||
{{js "js/validate-register.js"}}
|
||||
{{/zone}}
|
||||
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the dynamic state to be populated by add-user page.
|
||||
*
|
||||
* @param context Object that gets updated with the dynamic state of this page to be presented
|
||||
* @returns {*} A context object that returns the dynamic state of this page to be presented
|
||||
*/
|
||||
function onRequest(context) {
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var page = {};
|
||||
page["usernameJSRegEx"] = devicemgtProps.userValidationConfig.usernameJSRegEx;
|
||||
page["usernameHelpText"] = devicemgtProps.userValidationConfig.usernameHelpMsg;
|
||||
page["usernameRegExViolationErrorMsg"] = devicemgtProps.userValidationConfig.usernameRegExViolationErrorMsg;
|
||||
page["firstnameJSRegEx"] = devicemgtProps.userValidationConfig.firstnameJSRegEx;
|
||||
page["firstnameRegExViolationErrorMsg"] = devicemgtProps.userValidationConfig.firstnameRegExViolationErrorMsg;
|
||||
page["lastnameJSRegEx"] = devicemgtProps.userValidationConfig.lastnameJSRegEx;
|
||||
page["lastnameRegExViolationErrorMsg"] = devicemgtProps.userValidationConfig.lastnameRegExViolationErrorMsg;
|
||||
page["emailJSRegEx"] = devicemgtProps.userValidationConfig.emailJSRegEx;
|
||||
page["emailRegExViolationErrorMsg"] = devicemgtProps.userValidationConfig.emailRegExViolationErrorMsg;
|
||||
return page;
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/register",
|
||||
"isAnonymous": true,
|
||||
"layout": "uuf.layout.sign-in"
|
||||
}
|
||||
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 loadRoleBasedActionURL = function (action, rolename) {
|
||||
href = $("#ast-container").data("app-context") + "role/" + action + "/?rolename=" + encodeURIComponent(rolename);
|
||||
$(location).attr('href', href);
|
||||
};
|
||||
|
||||
$(function () {
|
||||
var sortableElem = '.wr-sortable';
|
||||
$(sortableElem).sortable({
|
||||
beforeStop: function () {
|
||||
$(this).sortable('toArray');
|
||||
}
|
||||
});
|
||||
$(sortableElem).disableSelection();
|
||||
});
|
||||
|
||||
var apiBasePath = "/api/device-mgt/v1.0";
|
||||
var modalPopup = ".modal";
|
||||
var modalPopupContainer = modalPopup + " .modal-content";
|
||||
var modalPopupContent = modalPopup + " .modal-content";
|
||||
var body = "body";
|
||||
var isInit = true;
|
||||
var isCloud = false;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Fires the res_text when ever a data table redraw occurs making
|
||||
* the font icons change the size to respective screen resolution.
|
||||
*
|
||||
*/
|
||||
$(document).on('draw.dt', function () {
|
||||
$(".icon .text").res_text(0.2);
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* set popup maximum height function.
|
||||
*/
|
||||
function setPopupMaxHeight() {
|
||||
$(modalPopupContent).css('max-height', ($(body).height() - ($(body).height() / 100 * 30)));
|
||||
$(modalPopupContainer).css('margin-top', (-($(modalPopupContainer).height() / 2)));
|
||||
}
|
||||
|
||||
/*
|
||||
* show popup function.
|
||||
*/
|
||||
function showPopup() {
|
||||
$(modalPopup).modal('show');
|
||||
//setPopupMaxHeight();
|
||||
}
|
||||
|
||||
/*
|
||||
* hide popup function.
|
||||
*/
|
||||
function hidePopup() {
|
||||
$(modalPopupContent).html('');
|
||||
$(modalPopup).modal('hide');
|
||||
$('body').removeClass('modal-open').css('padding-right', '0px');
|
||||
$('.modal-backdrop').remove();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Following function would execute
|
||||
* when a user clicks on the list item
|
||||
* initial mode and with out select mode.
|
||||
*/
|
||||
function InitiateViewOption() {
|
||||
// $(location).attr('href', $(this).data("url"));
|
||||
}
|
||||
|
||||
function htmlspecialchars(text) {
|
||||
return jQuery('<div/>').text(text).html();
|
||||
}
|
||||
|
||||
function loadRoles() {
|
||||
isCloud = $("#role-table").data("cloud");
|
||||
var loadingContent = $("#loading-content");
|
||||
loadingContent.show();
|
||||
|
||||
var dataFilter = function (data) {
|
||||
data = JSON.parse(data);
|
||||
var objects = [];
|
||||
var count = 0;
|
||||
$(data.roles).each(function (index) {
|
||||
objects.push(
|
||||
{
|
||||
name: htmlspecialchars(data.roles[index]),
|
||||
DT_RowId: "role-" + htmlspecialchars(data.roles[index])
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
var json = {
|
||||
"recordsTotal": data.count,
|
||||
"recordsFiltered": data.count,
|
||||
"data": objects
|
||||
};
|
||||
|
||||
return JSON.stringify(json);
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
var fnCreatedRow = function (nRow, aData, iDataIndex) {
|
||||
$(nRow).attr('data-type', 'selectable');
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
var columns = [
|
||||
{
|
||||
class: "remove-padding icon-only content-fill",
|
||||
data: null,
|
||||
defaultContent: "<div class='thumbnail icon'>" +
|
||||
"<i class='square-element text fw fw-bookmark' style='font-size: 74px;'></i>" +
|
||||
"</div>"
|
||||
},
|
||||
{
|
||||
class: "",
|
||||
data: "name",
|
||||
render: function (name, type, row, meta) {
|
||||
return '<h4>' + name.replace("devicemgt", ""); + '</h4>';
|
||||
}
|
||||
},
|
||||
{
|
||||
class: "text-right content-fill text-left-on-grid-view no-wrap",
|
||||
data: null,
|
||||
render: function (data, type, row, meta) {
|
||||
var isCloud = false;
|
||||
if ($('#is-cloud').length > 0) {
|
||||
isCloud = true;
|
||||
}
|
||||
|
||||
var innerhtml = '';
|
||||
|
||||
var editLink = '<a onclick="javascript:loadRoleBasedActionURL(\'edit\', \'' + data.name + '\')" ' +
|
||||
'data-role="' + data.name + '" ' +
|
||||
'data-click-event="edit-form" ' +
|
||||
'class="btn padding-reduce-on-grid-view edit-role-link">' +
|
||||
'<span class="fw-stack">' +
|
||||
'<i class="fw fw-circle-outline fw-stack-2x"></i>' +
|
||||
'<i class="fw fw-bookmark fw-stack-1x"></i>' +
|
||||
'<span class="fw-stack fw-move-right fw-move-bottom">' +
|
||||
'<i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>' +
|
||||
'<i class="fw fw-circle fw-stack-2x"></i><i class="fw fw-edit fw-stack-1x fw-inverse"></i>' +
|
||||
'</span>' +
|
||||
'</span>' +
|
||||
'<span class="hidden-xs hidden-on-grid-view">Edit</span>' +
|
||||
'</a>';
|
||||
|
||||
var editPermissionLink = '<a onclick="javascript:loadRoleBasedActionURL(\'edit-permission\', \'' + data.name + '\')" ' +
|
||||
'data-role="' + data.name + '" ' +
|
||||
'data-click-event="edit-form" ' +
|
||||
'class="btn padding-reduce-on-grid-view edit-permission-link">' +
|
||||
'<span class="fw-stack">' +
|
||||
'<i class="fw fw-circle-outline fw-stack-2x"></i>' +
|
||||
'<i class="fw fw-security-policy fw-stack-1x"></i>' +
|
||||
'<span class="fw-stack fw-move-right fw-move-bottom">' +
|
||||
'<i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>' +
|
||||
'<i class="fw fw-circle fw-stack-2x"></i><i class="fw fw-edit fw-stack-1x fw-inverse"></i>' +
|
||||
'</span>' +
|
||||
'</span>' +
|
||||
'<span class="hidden-xs hidden-on-grid-view">Edit Permission</span>' +
|
||||
'</a>';
|
||||
|
||||
var removeLink = '<a data-role="' + data.name + '" ' +
|
||||
'data-click-event="remove-form" ' +
|
||||
'class="btn padding-reduce-on-grid-view remove-role-link">' +
|
||||
'<span class="fw-stack">' +
|
||||
'<i class="fw fw-circle-outline fw-stack-2x"></i>' +
|
||||
'<i class="fw fw-delete fw-stack-1x"></i>' +
|
||||
'</span>' +
|
||||
'<span class="hidden-xs hidden-on-grid-view">Remove</span>' +
|
||||
'</a>';
|
||||
|
||||
if (!isCloud) {
|
||||
innerhtml = editLink + editPermissionLink + removeLink;
|
||||
}
|
||||
return innerhtml;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var options = {
|
||||
"placeholder": "Search By Role Name",
|
||||
"searchKey": "filter"
|
||||
};
|
||||
var settings = {
|
||||
"sorting": false
|
||||
};
|
||||
var roleApiUrl = '/api/device-mgt/v1.0/roles?user-store=all';
|
||||
if (isCloud) {
|
||||
roleApiUrl = '/api/device-mgt/v1.0/roles/filter/devicemgt?user-store=all';
|
||||
}
|
||||
|
||||
$('#role-grid').datatables_extended_serverside_paging(settings, roleApiUrl, dataFilter, columns, fnCreatedRow, null, options);
|
||||
loadingContent.hide();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Following click function would execute
|
||||
* when a user clicks on "Remove" link
|
||||
* on Role Listing page in WSO2 Devicemgt Console.
|
||||
*/
|
||||
$("#role-grid").on("click", ".remove-role-link", function () {
|
||||
var role = $(this).data("role");
|
||||
var userStore;
|
||||
if (role.indexOf('/') > 0) {
|
||||
userStore = role.substr(0, role.indexOf('/'));
|
||||
role = role.substr(role.indexOf('/') + 1);
|
||||
}
|
||||
var removeRoleAPI = apiBasePath + "/roles/" + encodeURIComponent(role);
|
||||
if (userStore) {
|
||||
removeRoleAPI += "?user-store=" + encodeURIComponent(userStore);
|
||||
}
|
||||
modalDialog.header('Do you really want to remove this role ?');
|
||||
modalDialog.footer('<div class="buttons"><a href="#" id="remove-role-yes-link" class="btn-operations">Remove</a>' +
|
||||
'<a href="#" id="remove-role-cancel-link" class="btn-operations btn-default">Cancel</a></div>');
|
||||
modalDialog.show();
|
||||
|
||||
$("a#remove-role-yes-link").click(function () {
|
||||
invokerUtil.delete(
|
||||
removeRoleAPI,
|
||||
function () {
|
||||
if (userStore) {
|
||||
role = userStore + '/' + role;
|
||||
}
|
||||
$('[id="role-' + role + '"]').remove();
|
||||
modalDialog.header('Done. Role was successfully removed.');
|
||||
modalDialog.footer('<div class="buttons"><a href="#" id="remove-role-success-link" ' +
|
||||
'class="btn-operations">Ok</a></div>');
|
||||
$("a#remove-role-success-link").click(function () {
|
||||
modalDialog.hide();
|
||||
});
|
||||
},
|
||||
function () {
|
||||
// $(modalPopupContent).html($('#remove-role-error-content').html());
|
||||
modalDialog.header('An unexpected error occurred. Please try again later.');
|
||||
modalDialog.footer('<div class="buttons"><a href="#" id="remove-role-error-link" ' +
|
||||
'class="btn-operations">Ok</a></div>');
|
||||
modalDialog.showAsError();
|
||||
$("a#remove-role-error-link").click(function () {
|
||||
modalDialog.hide();
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$("a#remove-role-cancel-link").click(function () {
|
||||
modalDialog.hide();
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready(function () {
|
||||
loadRoles();
|
||||
});
|
||||
@ -0,0 +1,56 @@
|
||||
{{#each roles}}
|
||||
<tr data-type="selectable" id="role-{{roleName}}">
|
||||
<td class="remove-padding icon-only content-fill">
|
||||
<div class="thumbnail icon">
|
||||
<i class="square-element text fw fw-user"></i>
|
||||
</div>
|
||||
</td>
|
||||
<td class="remove-padding-top">{{roleName}}</td>
|
||||
<td class="text-right content-fill text-left-on-grid-view no-wrap">
|
||||
|
||||
{{#unequal adminRole roleName }}
|
||||
{{#if canEdit}}
|
||||
<a onclick="javascript:loadRoleBasedActionURL('edit', '{{roleName}}')" data-role="{{roleName}}"
|
||||
data-click-event="edit-form"
|
||||
class="btn padding-reduce-on-grid-view edit-role-link" title="Edit Role">
|
||||
<span class="fw-stack fw-lg">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-user fw-stack-1x"></i>
|
||||
<span class="fw-stack fw-move-right fw-move-bottom">
|
||||
<i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>
|
||||
<i class="fw fw-circle fw-stack-2x"></i>
|
||||
<i class="fw fw-edit fw-stack-1x fw-inverse"></i>
|
||||
</span>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-on-grid-view">Edit</span>
|
||||
</a>
|
||||
<a onclick="javascript:loadRoleBasedActionURL('edit-permission', '{{roleName}}')"
|
||||
data-role="{{roleName}}"
|
||||
data-click-event="edit-form" class="btn padding-reduce-on-grid-view edit-permission-link"
|
||||
title="Edit Role Permissions">
|
||||
<span class="fw-stack fw-lg">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-security-policy fw-stack-1x"></i>
|
||||
<span class="fw-stack fw-move-right fw-move-bottom">
|
||||
<i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>
|
||||
<i class="fw fw-circle fw-stack-2x"></i>
|
||||
<i class="fw fw-edit fw-stack-1x fw-inverse"></i>
|
||||
</span>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-on-grid-view">Edit Permission</span>
|
||||
</a>
|
||||
{{/if}}
|
||||
{{#if canRemove}}
|
||||
<a data-role="{{roleName}}" data-click-event="remove-form"
|
||||
class="btn padding-reduce-on-grid-view remove-role-link" title="Remove Role">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-delete fw-stack-1x"></i>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-on-grid-view">Remove</span>
|
||||
</a>
|
||||
{{/if}}
|
||||
{{/unequal}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
@ -0,0 +1,120 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
|
||||
{{unit "cdmf.unit.ui.title" pageTitle="Role Management"}}
|
||||
{{unit "cdmf.unit.data-tables-extended"}}
|
||||
{{unit "cdmf.unit.ui.modal"}}
|
||||
|
||||
{{#zone "breadcrumbs"}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/">
|
||||
<i class="icon fw fw-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/roles">
|
||||
Roles
|
||||
</a>
|
||||
</li>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "navbarActions"}}
|
||||
{{#unless isCloud}}
|
||||
<li>
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<a href="{{@app.context}}/role/add" class="cu-btn">
|
||||
<span class="icon fw-stack">
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
</span>
|
||||
Add Role
|
||||
</a>
|
||||
</li>
|
||||
{{/unless}}
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "content"}}
|
||||
{{#if hasRoles}}
|
||||
<div id="loading-content" class="col-centered">
|
||||
{{#unless isCloud}}
|
||||
{{#if removePermitted}}
|
||||
<input type="hidden" id="can-remove" value="true"/>
|
||||
{{/if}}
|
||||
{{#if editPermitted}}
|
||||
<input type="hidden" id="can-edit" value="true"/>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{#if isCloud}}
|
||||
<input type="hidden" id="is-cloud" value="true"/>
|
||||
{{/if}}
|
||||
<i class="fw fw-settings fw-spin fw-2x"></i>
|
||||
Loading roles . . .
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<div id="role-table" data-cloud={{isCloud}} data-role={{adminRole}}>
|
||||
<table class="table table-striped table-hover list-table display responsive nowrap data-table grid-view"
|
||||
id="role-grid">
|
||||
<thead>
|
||||
<tr class="sort-row">
|
||||
<th>By Role Name</th>
|
||||
</tr>
|
||||
<tr class="bulk-action-row">
|
||||
<th colspan="3"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ast-container" data-app-context="{{@app.context}}/"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="content-filter-types" style="display: none">
|
||||
<div class="sort-title">Sort By</div>
|
||||
<div class="sort-options">
|
||||
<!--suppress HtmlUnknownTag -->
|
||||
<th>By Role name</th>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{else}}
|
||||
|
||||
<div id="user-created-msg" class="container col-centered wr-content">
|
||||
<div class="wr-form">
|
||||
<p class="page-sub-title">You Haven't created roles yet.</p>
|
||||
<br>Please click <b>"Add A New Role"</b>, if you wish to add a role.
|
||||
<hr/>
|
||||
|
||||
<a href="{{@app.context}}/role/add" class="cu-btn-inner">
|
||||
<span class="fw-stack">
|
||||
<i class="fw fw-circle-outline fw-stack-2x"></i>
|
||||
<i class="fw fw-add fw-stack-1x"></i>
|
||||
</span>
|
||||
Add Role
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{/if}}
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "bottomJs"}}
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<script id="role-listing" data-current-user="{{@user.username}}"
|
||||
src="{{@page.publicUri}}/templates/role-listing.hbs" type="text/x-handlebars-template"></script>
|
||||
{{js "js/role-listing.js"}}
|
||||
{{/zone}}
|
||||
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 userModule = require("/app/modules/business-controllers/user.js")["userModule"];
|
||||
var deviceMgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
|
||||
context["permissions"] = userModule.getUIPermissions();
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/roles/delete")) {
|
||||
context["removePermitted"] = true;
|
||||
}
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/roles/update")) {
|
||||
context["editPermitted"] = true;
|
||||
}
|
||||
if (userModule.isAuthorized("/permission/admin/device-mgt/roles/remove")) {
|
||||
context["removePermitted"] = true;
|
||||
}
|
||||
|
||||
context["adminRole"] = deviceMgtProps["adminRole"];
|
||||
context["isCloud"] = deviceMgtProps["isCloud"];
|
||||
var roleCount = userModule.getRolesCount()
|
||||
if (deviceMgtProps["isCloud"]) {
|
||||
roleCount = userModule.getFilteredRoles("devicemgt").content.count;
|
||||
}
|
||||
|
||||
if (roleCount > 0) {
|
||||
context["hasRoles"] = true;
|
||||
} else {
|
||||
context["hasRoles"] = false;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/roles",
|
||||
"layout": "cdmf.layout.default"
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{#zone "title"}}{{! to override parent page title }}{{/zone}}
|
||||
{{unit "cdmf.unit.ui.title" pageTitle="Login"}}
|
||||
|
||||
{{#zone "content"}}
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-4 col-sm-offset-3 col-md-offset-3 col-lg-offset-4">
|
||||
|
||||
<p class="page-sub-title">Login</p>
|
||||
<hr />
|
||||
{{#if message}}
|
||||
<div class="alert alert-danger" style="padding-right: 15px;">
|
||||
<i class="icon fw fw-warning"></i> {{message}}!
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="panel-body">
|
||||
<form id="signInForm" method="POST" action="{{loginActionUrl}}">
|
||||
<div class="form-group">
|
||||
<label for="username">Username *</label>
|
||||
<input type="text" name="username" class="form-control" placeholder="Enter your username"
|
||||
autofocus="autofocus" required="required" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password *</label>
|
||||
<input type="password" name="password" class="form-control" autocomplete="off"
|
||||
placeholder="Enter your password" required="required" />
|
||||
</div>
|
||||
{{#if sessionDataKey}}
|
||||
<input type="hidden" name="sessionDataKey" value="{{sessionDataKey}}" />
|
||||
{{/if}}
|
||||
{{#if referer}}
|
||||
<input type="hidden" name="referer" value="{{referer}}" />
|
||||
{{/if}}
|
||||
<div class="wr-input-control wr-btn-grp">
|
||||
<button class="wr-btn btn-download-agent">
|
||||
Log in
|
||||
</button>
|
||||
<div id="register-link-wrapper" style="float: right; padding-top: 10px;">
|
||||
<a href="{{@app.context}}/register" class="pull-right create-account">Create an account</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/zone}}
|
||||
@ -0,0 +1,32 @@
|
||||
function onRequest(context) {
|
||||
var authModuleConfigs = context.app.conf["authModule"];
|
||||
var sessionDataKey = request.getParameter("sessionDataKey");
|
||||
var authFailure = request.getParameter("authFailure");
|
||||
|
||||
//if sso enabled and sessionDataKey is empty redirect
|
||||
var ssoConfigs = authModuleConfigs["sso"];
|
||||
if (ssoConfigs && (ssoConfigs["enabled"].toString() == "true") && !sessionDataKey) {
|
||||
// SSO is enabled in Auth module.
|
||||
var redirectUri = context.app.context + "/uuf/login";
|
||||
var queryString = request.getQueryString();
|
||||
if (queryString && (queryString.length > 0)) {
|
||||
redirectUri = redirectUri + "?" + queryString;
|
||||
}
|
||||
response.sendRedirect(encodeURI(redirectUri));
|
||||
exit();
|
||||
}
|
||||
|
||||
var viewModel = {};
|
||||
var loginActionUrl = context.app.context + "/uuf/login";
|
||||
if (sessionDataKey) {
|
||||
loginActionUrl = "/commonauth";
|
||||
}
|
||||
|
||||
if (authFailure) {
|
||||
viewModel.message = "Login failed! Please recheck the username and password and try again.";
|
||||
}
|
||||
|
||||
viewModel.sessionDataKey = sessionDataKey;
|
||||
viewModel.loginActionUrl = loginActionUrl;
|
||||
return viewModel;
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"layout": "uuf.layout.sign-in",
|
||||
"uri": "/login",
|
||||
"isAnonymous": true
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/logout",
|
||||
"extends": "uuf.page.sign-out"
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{#zone "title"}}Error | {{@app.conf.appName}}{{/zone}}
|
||||
|
||||
{{#zone "breadcrumbs"}}
|
||||
<li>
|
||||
<a href="{{@app.context}}/">
|
||||
<i class="icon fw fw-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "content"}}
|
||||
<div class="message message-danger">
|
||||
<h4><i class="icon fw fw-error"></i>An Error Occurred!</h4>
|
||||
|
||||
<div style="padding-left: 25px;">
|
||||
<h5><b>HTTP Status : {{@page.params.status}}</b></h5>
|
||||
|
||||
<p style="white-space: pre-wrap;">{{@page.params.message}}</p>
|
||||
</div>
|
||||
</div>
|
||||
{{/zone}}
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/error/default",
|
||||
"layout": "uuf.layout.default",
|
||||
"isAnonymous": true
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
$(document).ready(function(){
|
||||
$("#signInForm").validate({
|
||||
rules: {
|
||||
username: {
|
||||
required: true,
|
||||
minlength: 3
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
minlength: 3
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
username: {
|
||||
required: "Please enter a username",
|
||||
minlength: "Your username must consist of at least 3 characters"
|
||||
},
|
||||
password: {
|
||||
required: "Please provide a password",
|
||||
minlength: "Your password must be at least 3 characters long"
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,63 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{#zone "title"}}Sign In | {{@app.conf.appName}}{{/zone}}
|
||||
|
||||
{{~#zone "content"}}
|
||||
<div class="col-sm-7 col-md-4 center-block" style="float: none; margin-top: 10%;">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
{{#defineZone "signIn-title" scope="protected"}}Sign In to UUF Template App{{/defineZone}}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{{#if message}}
|
||||
<div id="_uuf_login-error-msg" class="alert alert-danger">
|
||||
<i class="icon fw fw-warning"></i> {{message}}!
|
||||
</div>
|
||||
{{/if}}
|
||||
<form id="signInForm" method="POST"
|
||||
class="{{defineZone "signInForm-class" scope="protected"}}"
|
||||
action="{{#defineZone "signInForm-action" scope="protected"}}{{@app.context}}/uuf/login{{/defineZone}}">
|
||||
<div class="form-group">
|
||||
<input type="text" name="username" class="form-control"
|
||||
placeholder="User Name" required="required" autofocus="autofocus" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" name="password" class="form-control" autocomplete="off"
|
||||
placeholder="Password" required="required" />
|
||||
</div>
|
||||
{{#if referer}}
|
||||
<input type="hidden" name="referer" value="{{referer}}" />
|
||||
{{/if}}
|
||||
<div class="form-group" style="padding-top: 10px;">
|
||||
<input type="submit" name="signInBtn" class="btn btn-primary btn-block"
|
||||
value="Sign In" />
|
||||
</div>
|
||||
{{defineZone "signInForm-below" scope="protected"}}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/zone}}
|
||||
|
||||
{{! sign-in form validation}}
|
||||
{{~unit "uuf.unit.lib.form-validation"}}
|
||||
{{~#zone "bottomJs"}}
|
||||
{{~js "js/sign-in-validations.js"}}
|
||||
{{/zone}}
|
||||
@ -0,0 +1,30 @@
|
||||
function onRequest(context) {
|
||||
var authModuleConfigs = context.app.conf["authModule"];
|
||||
if (authModuleConfigs && (authModuleConfigs["enabled"].toString() == "true")) {
|
||||
// Auth module is enabled.
|
||||
if (context.user) {
|
||||
// User is already logged in.
|
||||
response.sendRedirect(context.app.context + "/");
|
||||
exit();
|
||||
} else {
|
||||
// User is not logged in.
|
||||
var ssoConfigs = authModuleConfigs["sso"];
|
||||
if (ssoConfigs && (ssoConfigs["enabled"].toString() == "true")) {
|
||||
// SSO is enabled in Auth module.
|
||||
var redirectUri = context.app.context + "/uuf/login";
|
||||
var queryString = request.getQueryString();
|
||||
if (queryString && (queryString.length > 0)) {
|
||||
redirectUri = redirectUri + "?" + queryString;
|
||||
}
|
||||
response.sendRedirect(encodeURI(redirectUri));
|
||||
exit();
|
||||
} else {
|
||||
// Generic login process is enabled.
|
||||
return {
|
||||
message: request.getParameter("error"),
|
||||
referer: request.getParameter("referer")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/signin",
|
||||
"layout": "uuf.layout.sign-in",
|
||||
"isAnonymous": true
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{! This template won't be rendered. So nothing is here }}
|
||||
@ -0,0 +1,16 @@
|
||||
function onRequest(context) {
|
||||
var authModuleConfigs = context.app.conf["authModule"];
|
||||
if (authModuleConfigs && (authModuleConfigs["enabled"].toString() == "true")) {
|
||||
// Auth module is enabled.
|
||||
if (context.user) {
|
||||
// User is logged in.
|
||||
response.sendRedirect(context.app.context + "/uuf/logout");
|
||||
exit();
|
||||
} else {
|
||||
// User is already logged out.
|
||||
response.sendRedirect(context.app.context + "/");
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "/signout",
|
||||
"layout": "uuf.layout.sign-in"
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{#zone "title"}}Sign In | {{@app.conf.appName}}{{/zone}}
|
||||
|
||||
{{unit "uuf.unit.theme"}}
|
||||
{{unit "uuf.unit.header.logo"}}{{unit "uuf.unit.header"}}
|
||||
{{unit "uuf.unit.footer"}}
|
||||
|
||||
{{#zone "content"}}
|
||||
<div class="jumbotron">
|
||||
<p>
|
||||
You are now being redirected to Identity Server. If the redirection fails, please click
|
||||
on the button below.
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<form method="post" action="{{@page.params.identityProviderUrl}}">
|
||||
<input type="hidden" name="SAMLRequest"
|
||||
value="{{@page.params.encodedSAMLAuthRequest}}" />
|
||||
<input type="hidden" name="RelayState" value="{{@page.params.relayState}}" />
|
||||
<input type="hidden" name="SSOAuthSessionID" value="{{@page.params.sessionId}}" />
|
||||
<button type="submit" class="btn btn-primary">Redirect manually</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "bottomJs"}}
|
||||
<script type="text/javascript">document.forms[0].submit();</script>
|
||||
{{/zone}}
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"uri": "//",
|
||||
"layout": "uuf.layout.sign-in",
|
||||
"isAnonymous": true
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{#zone "topCss"}}
|
||||
{{css "css/daterangepicker.css"}}
|
||||
{{/zone}}
|
||||
<span id="device-type-details" data-devicetypes="{{deviceTypes}}"></span>
|
||||
<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>
|
||||
{{#zone "bottomJs"}}
|
||||
{{js "js/moment.js"}}
|
||||
{{js "js/jquery.daterangepicker.js"}}
|
||||
{{js "js/date-picker.js"}}
|
||||
{{/zone}}
|
||||
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 deviceTypes = context.unit.params.deviceTypes;
|
||||
var deviceType = context.uriParams.deviceType;
|
||||
|
||||
var deviceTypesList = [];
|
||||
if (deviceTypes) {
|
||||
for (var i = 0; i < deviceTypes.length; i++) {
|
||||
deviceTypesList.push(deviceTypes[i].type);
|
||||
}
|
||||
} else if (deviceType) {
|
||||
deviceTypesList.push(deviceType);
|
||||
}
|
||||
return {"deviceTypes": stringify(deviceTypesList)};
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "1.0.0"
|
||||
}
|
||||
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
.date-range {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
#dateRangePickerContainer button.active {
|
||||
background-color: #e6e6e6 !important;
|
||||
}
|
||||
|
||||
#dateRangePickerContainer .btn-default:hover {
|
||||
background-color: #b2b2b2;
|
||||
border-color: #000000;
|
||||
}
|
||||
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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());
|
||||
|
||||
function initDate() {
|
||||
currentDay = new Date();
|
||||
}
|
||||
|
||||
var DateRange = convertDate(startDate) + " to " + convertDate(endDate);
|
||||
|
||||
$(document).ready(function () {
|
||||
initDate();
|
||||
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;
|
||||
}
|
||||
};
|
||||
$('#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;
|
||||
drawGraph(fromDate, toDate);
|
||||
}
|
||||
);
|
||||
setDateTime(currentDay.getTime() - 3600000, currentDay.getTime());
|
||||
$('#hour-btn').addClass('active');
|
||||
});
|
||||
|
||||
//hour
|
||||
$('#hour-btn').on('click', function () {
|
||||
initDate();
|
||||
setDateTime(currentDay.getTime() - 3600000, currentDay.getTime());
|
||||
});
|
||||
|
||||
//12 hours
|
||||
$('#h12-btn').on('click', function () {
|
||||
initDate();
|
||||
setDateTime(currentDay.getTime() - (3600000 * 12), currentDay.getTime());
|
||||
});
|
||||
|
||||
//24 hours
|
||||
$('#h24-btn').on('click', function () {
|
||||
initDate();
|
||||
setDateTime(currentDay.getTime() - (3600000 * 24), currentDay.getTime());
|
||||
});
|
||||
|
||||
//48 hours
|
||||
$('#h48-btn').on('click', function () {
|
||||
initDate();
|
||||
setDateTime(currentDay.getTime() - (3600000 * 48), currentDay.getTime());
|
||||
});
|
||||
|
||||
$('body').on('click', '.btn-group button', function (e) {
|
||||
$(this).addClass('active');
|
||||
$(this).siblings().removeClass('active');
|
||||
});
|
||||
|
||||
function setDateTime(from, to) {
|
||||
fromDate = from;
|
||||
toDate = to;
|
||||
startDate = new Date(from);
|
||||
endDate = new Date(to);
|
||||
DateRange = convertDate(startDate) + " to " + convertDate(endDate);
|
||||
$('#date-range').html(DateRange);
|
||||
var tzOffset = new Date().getTimezoneOffset() * 60 / 1000;
|
||||
from += tzOffset;
|
||||
to += tzOffset;
|
||||
|
||||
// Implement drawGraph_<device type name> method in your UI unit for analytics.
|
||||
var deviceTypes = $("#device-type-details").data("devicetypes");
|
||||
for (var i = 0; i < deviceTypes.length; i++){
|
||||
try{
|
||||
window["drawGraph_" + deviceTypes](parseInt(from / 1000), parseInt(to / 1000));
|
||||
}catch(e){
|
||||
}
|
||||
try{
|
||||
window["drawTable"](parseInt(from / 1000), parseInt(to / 1000));
|
||||
}catch(e){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,28 @@
|
||||
{{!
|
||||
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.
|
||||
}}
|
||||
{{#zone "topCss"}}
|
||||
{{~css "css/dataTables.bootstrap.css"}}
|
||||
{{~css "css/dataTables.responsive.css"}}
|
||||
{{/zone}}
|
||||
{{#zone "bottomJs"}}
|
||||
{{~js "js/jquery.dataTables.min.js"}}
|
||||
{{~js "js/dataTables.bootstrap.js"}}
|
||||
{{~js "js/dataTables.responsive.min.js"}}
|
||||
{{~js "js/dataTables.extended.js"}}
|
||||
{{~js "js/dataTables.extended.serversidepaging.js"}}
|
||||
{{/zone}}
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"version" : "1.0.0"
|
||||
}
|
||||
@ -0,0 +1,372 @@
|
||||
div.dataTables_length label {
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.dataTables_length select {
|
||||
width: 75px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
div.dataTables_filter {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.dataTables_filter label {
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.dataTables_filter input {
|
||||
margin-left: 0.5em;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
div.dataTables_info {
|
||||
padding-top: 8px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.dataTables_paginate {
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.dataTables_paginate ul.pagination {
|
||||
margin: 2px 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
div.dataTables_wrapper > div.row > div,
|
||||
div.dataTables_length,
|
||||
div.dataTables_filter,
|
||||
div.dataTables_info,
|
||||
div.dataTables_paginate {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.DTTT {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
table.dataTable td,
|
||||
table.dataTable th {
|
||||
-webkit-box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
|
||||
table.dataTable {
|
||||
clear: both;
|
||||
margin-top: 6px !important;
|
||||
margin-bottom: 6px !important;
|
||||
max-width: none !important;
|
||||
}
|
||||
|
||||
table.dataTable thead .sorting,
|
||||
table.dataTable thead .sorting_asc,
|
||||
table.dataTable thead .sorting_desc,
|
||||
table.dataTable thead .sorting_asc_disabled,
|
||||
table.dataTable thead .sorting_desc_disabled {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
table.dataTable thead .sorting:after,
|
||||
table.dataTable thead .sorting_asc:after,
|
||||
table.dataTable thead .sorting_desc:after {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
display: block;
|
||||
font-family: 'Glyphicons Halflings';
|
||||
opacity: 0.5;
|
||||
}
|
||||
table.dataTable thead .sorting:after {
|
||||
opacity: 0.2;
|
||||
content: "\e150"; /* sort */
|
||||
}
|
||||
table.dataTable thead .sorting_asc:after {
|
||||
content: "\e155"; /* sort-by-attributes */
|
||||
}
|
||||
table.dataTable thead .sorting_desc:after {
|
||||
content: "\e156"; /* sort-by-attributes-alt */
|
||||
}
|
||||
div.dataTables_scrollBody table.dataTable thead .sorting:after,
|
||||
div.dataTables_scrollBody table.dataTable thead .sorting_asc:after,
|
||||
div.dataTables_scrollBody table.dataTable thead .sorting_desc:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
table.dataTable thead .sorting_asc_disabled:after,
|
||||
table.dataTable thead .sorting_desc_disabled:after {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
table.dataTable thead > tr > th {
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
table.dataTable th:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
|
||||
/* Condensed */
|
||||
table.dataTable.table-condensed thead > tr > th {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
table.dataTable.table-condensed thead .sorting:after,
|
||||
table.dataTable.table-condensed thead .sorting_asc:after,
|
||||
table.dataTable.table-condensed thead .sorting_desc:after {
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
}
|
||||
|
||||
/* Scrolling */
|
||||
div.dataTables_scrollHead table {
|
||||
margin-bottom: 0 !important;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
div.dataTables_scrollHead table thead tr:last-child th:first-child,
|
||||
div.dataTables_scrollHead table thead tr:last-child td:first-child {
|
||||
border-bottom-left-radius: 0 !important;
|
||||
border-bottom-right-radius: 0 !important;
|
||||
}
|
||||
|
||||
div.dataTables_scrollBody table {
|
||||
border-top: none;
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
div.dataTables_scrollBody tbody tr:first-child th,
|
||||
div.dataTables_scrollBody tbody tr:first-child td {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
div.dataTables_scrollFoot table {
|
||||
margin-top: 0 !important;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
/* Frustratingly the border-collapse:collapse used by Bootstrap makes the column
|
||||
width calculations when using scrolling impossible to align columns. We have
|
||||
to use separate
|
||||
*/
|
||||
table.table-bordered.dataTable {
|
||||
border-collapse: separate !important;
|
||||
}
|
||||
table.table-bordered thead th,
|
||||
table.table-bordered thead td {
|
||||
border-left-width: 0;
|
||||
border-top-width: 0;
|
||||
}
|
||||
table.table-bordered tbody th,
|
||||
table.table-bordered tbody td {
|
||||
border-left-width: 0;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
table.table-bordered tfoot th,
|
||||
table.table-bordered tfoot td {
|
||||
border-left-width: 0;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
table.table-bordered th:last-child,
|
||||
table.table-bordered td:last-child {
|
||||
border-right-width: 0;
|
||||
}
|
||||
div.dataTables_scrollHead table.table-bordered {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* TableTools styles
|
||||
*/
|
||||
.table.dataTable tbody tr.active td,
|
||||
.table.dataTable tbody tr.active th {
|
||||
background-color: #08C;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.table.dataTable tbody tr.active:hover td,
|
||||
.table.dataTable tbody tr.active:hover th {
|
||||
background-color: #0075b0 !important;
|
||||
}
|
||||
|
||||
.table.dataTable tbody tr.active th > a,
|
||||
.table.dataTable tbody tr.active td > a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.table-striped.dataTable tbody tr.active:nth-child(odd) td,
|
||||
.table-striped.dataTable tbody tr.active:nth-child(odd) th {
|
||||
background-color: #017ebc;
|
||||
}
|
||||
|
||||
table.DTTT_selectable tbody tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.DTTT .btn:hover {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
ul.DTTT_dropdown.dropdown-menu {
|
||||
z-index: 2003;
|
||||
}
|
||||
|
||||
ul.DTTT_dropdown.dropdown-menu a {
|
||||
color: #333 !important; /* needed only when demo_page.css is included */
|
||||
}
|
||||
|
||||
ul.DTTT_dropdown.dropdown-menu li {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
ul.DTTT_dropdown.dropdown-menu li:hover a {
|
||||
background-color: #0088cc;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
div.DTTT_collection_background {
|
||||
z-index: 2002;
|
||||
}
|
||||
|
||||
/* TableTools information display */
|
||||
div.DTTT_print_info {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 400px;
|
||||
height: 150px;
|
||||
margin-left: -200px;
|
||||
margin-top: -75px;
|
||||
text-align: center;
|
||||
color: #333;
|
||||
padding: 10px 30px;
|
||||
opacity: 0.95;
|
||||
|
||||
background-color: white;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
border-radius: 6px;
|
||||
|
||||
-webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
div.DTTT_print_info h6 {
|
||||
font-weight: normal;
|
||||
font-size: 28px;
|
||||
line-height: 28px;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
div.DTTT_print_info p {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
div.dataTables_processing {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
margin-left: -50%;
|
||||
margin-top: -25px;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
background-color: white;
|
||||
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255,255,255,0)), color-stop(25%, rgba(255,255,255,0.9)), color-stop(75%, rgba(255,255,255,0.9)), color-stop(100%, rgba(255,255,255,0)));
|
||||
background: -webkit-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);
|
||||
background: -moz-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);
|
||||
background: -ms-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);
|
||||
background: -o-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);
|
||||
background: linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* FixedColumns styles
|
||||
*/
|
||||
div.DTFC_LeftHeadWrapper table,
|
||||
div.DTFC_LeftFootWrapper table,
|
||||
div.DTFC_RightHeadWrapper table,
|
||||
div.DTFC_RightFootWrapper table,
|
||||
table.DTFC_Cloned tr.even {
|
||||
background-color: white;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.DTFC_RightHeadWrapper table ,
|
||||
div.DTFC_LeftHeadWrapper table {
|
||||
border-bottom: none !important;
|
||||
margin-bottom: 0 !important;
|
||||
border-top-right-radius: 0 !important;
|
||||
border-bottom-left-radius: 0 !important;
|
||||
border-bottom-right-radius: 0 !important;
|
||||
}
|
||||
|
||||
div.DTFC_RightHeadWrapper table thead tr:last-child th:first-child,
|
||||
div.DTFC_RightHeadWrapper table thead tr:last-child td:first-child,
|
||||
div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child,
|
||||
div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child {
|
||||
border-bottom-left-radius: 0 !important;
|
||||
border-bottom-right-radius: 0 !important;
|
||||
}
|
||||
|
||||
div.DTFC_RightBodyWrapper table,
|
||||
div.DTFC_LeftBodyWrapper table {
|
||||
border-top: none;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
div.DTFC_RightBodyWrapper tbody tr:first-child th,
|
||||
div.DTFC_RightBodyWrapper tbody tr:first-child td,
|
||||
div.DTFC_LeftBodyWrapper tbody tr:first-child th,
|
||||
div.DTFC_LeftBodyWrapper tbody tr:first-child td {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
div.DTFC_RightFootWrapper table,
|
||||
div.DTFC_LeftFootWrapper table {
|
||||
border-top: none;
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
div.DTFC_LeftBodyWrapper table.dataTable thead .sorting:after,
|
||||
div.DTFC_LeftBodyWrapper table.dataTable thead .sorting_asc:after,
|
||||
div.DTFC_LeftBodyWrapper table.dataTable thead .sorting_desc:after,
|
||||
div.DTFC_RightBodyWrapper table.dataTable thead .sorting:after,
|
||||
div.DTFC_RightBodyWrapper table.dataTable thead .sorting_asc:after,
|
||||
div.DTFC_RightBodyWrapper table.dataTable thead .sorting_desc:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FixedHeader styles
|
||||
*/
|
||||
div.FixedHeader_Cloned table {
|
||||
margin: 0 !important
|
||||
}
|
||||
|
||||
@ -0,0 +1,106 @@
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child {
|
||||
position: relative;
|
||||
padding-left: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child:before,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child:before {
|
||||
top: 8px;
|
||||
left: 4px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
color: white;
|
||||
border: 2px solid white;
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
line-height: 14px;
|
||||
box-shadow: 0 0 3px #444;
|
||||
box-sizing: content-box;
|
||||
content: '+';
|
||||
background-color: #31b131;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child.dataTables_empty:before,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child.dataTables_empty:before {
|
||||
display: none;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td:first-child:before,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th:first-child:before {
|
||||
content: '-';
|
||||
background-color: #d33333;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr.child td:before {
|
||||
display: none;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child,
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child {
|
||||
padding-left: 27px;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child:before,
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child:before {
|
||||
top: 5px;
|
||||
left: 4px;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
border-radius: 14px;
|
||||
line-height: 12px;
|
||||
}
|
||||
table.dataTable.dtr-column > tbody > tr > td.control,
|
||||
table.dataTable.dtr-column > tbody > tr > th.control {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
table.dataTable.dtr-column > tbody > tr > td.control:before,
|
||||
table.dataTable.dtr-column > tbody > tr > th.control:before {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin-top: -10px;
|
||||
margin-left: -10px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
color: white;
|
||||
border: 2px solid white;
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
line-height: 14px;
|
||||
box-shadow: 0 0 3px #444;
|
||||
box-sizing: content-box;
|
||||
content: '+';
|
||||
background-color: #31b131;
|
||||
}
|
||||
table.dataTable.dtr-column > tbody > tr.parent td.control:before,
|
||||
table.dataTable.dtr-column > tbody > tr.parent th.control:before {
|
||||
content: '-';
|
||||
background-color: #d33333;
|
||||
}
|
||||
table.dataTable > tbody > tr.child {
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
table.dataTable > tbody > tr.child:hover {
|
||||
background: transparent !important;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul {
|
||||
display: inline-block;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul li {
|
||||
border-bottom: 1px solid #efefef;
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul li:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
table.dataTable > tbody > tr.child span.dtr-title {
|
||||
display: inline-block;
|
||||
min-width: 75px;
|
||||
font-weight: bold;
|
||||
}
|
||||
@ -0,0 +1,206 @@
|
||||
/*! DataTables Bootstrap 3 integration
|
||||
* ©2011-2014 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* DataTables integration for Bootstrap 3. This requires Bootstrap 3 and
|
||||
* DataTables 1.10 or newer.
|
||||
*
|
||||
* This file sets the defaults and adds options to DataTables to style its
|
||||
* controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
|
||||
* for further information.
|
||||
*/
|
||||
(function(window, document, undefined){
|
||||
|
||||
var factory = function( $, DataTable ) {
|
||||
"use strict";
|
||||
|
||||
|
||||
/* Set the defaults for DataTables initialisation */
|
||||
$.extend( true, DataTable.defaults, {
|
||||
dom:
|
||||
"<'row'<'col-sm-6'l><'col-sm-6'f>>" +
|
||||
"<'row'<'col-sm-12'tr>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
renderer: 'bootstrap'
|
||||
} );
|
||||
|
||||
|
||||
/* Default class modification */
|
||||
$.extend( DataTable.ext.classes, {
|
||||
sWrapper: "dataTables_wrapper form-inline dt-bootstrap",
|
||||
sFilterInput: "form-control input-sm",
|
||||
sLengthSelect: "form-control input-sm"
|
||||
} );
|
||||
|
||||
|
||||
/* Bootstrap paging button renderer */
|
||||
DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
|
||||
var api = new DataTable.Api( settings );
|
||||
var classes = settings.oClasses;
|
||||
var lang = settings.oLanguage.oPaginate;
|
||||
var btnDisplay, btnClass, counter=0;
|
||||
|
||||
var attach = function( container, buttons ) {
|
||||
var i, ien, node, button;
|
||||
var clickHandler = function ( e ) {
|
||||
e.preventDefault();
|
||||
if ( !$(e.currentTarget).hasClass('disabled') ) {
|
||||
api.page( e.data.action ).draw( false );
|
||||
}
|
||||
};
|
||||
|
||||
for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
|
||||
button = buttons[i];
|
||||
|
||||
if ( $.isArray( button ) ) {
|
||||
attach( container, button );
|
||||
}
|
||||
else {
|
||||
btnDisplay = '';
|
||||
btnClass = '';
|
||||
|
||||
switch ( button ) {
|
||||
case 'ellipsis':
|
||||
btnDisplay = '…';
|
||||
btnClass = 'disabled';
|
||||
break;
|
||||
|
||||
case 'first':
|
||||
btnDisplay = lang.sFirst;
|
||||
btnClass = button + (page > 0 ?
|
||||
'' : ' disabled');
|
||||
break;
|
||||
|
||||
case 'previous':
|
||||
btnDisplay = lang.sPrevious;
|
||||
btnClass = button + (page > 0 ?
|
||||
'' : ' disabled');
|
||||
break;
|
||||
|
||||
case 'next':
|
||||
btnDisplay = lang.sNext;
|
||||
btnClass = button + (page < pages-1 ?
|
||||
'' : ' disabled');
|
||||
break;
|
||||
|
||||
case 'last':
|
||||
btnDisplay = lang.sLast;
|
||||
btnClass = button + (page < pages-1 ?
|
||||
'' : ' disabled');
|
||||
break;
|
||||
|
||||
default:
|
||||
btnDisplay = button + 1;
|
||||
btnClass = page === button ?
|
||||
'active' : '';
|
||||
break;
|
||||
}
|
||||
|
||||
if ( btnDisplay ) {
|
||||
node = $('<li>', {
|
||||
'class': classes.sPageButton+' '+btnClass,
|
||||
'id': idx === 0 && typeof button === 'string' ?
|
||||
settings.sTableId +'_'+ button :
|
||||
null
|
||||
} )
|
||||
.append( $('<a>', {
|
||||
'href': '#',
|
||||
'aria-controls': settings.sTableId,
|
||||
'data-dt-idx': counter,
|
||||
'tabindex': settings.iTabIndex
|
||||
} )
|
||||
.html( btnDisplay )
|
||||
)
|
||||
.appendTo( container );
|
||||
|
||||
settings.oApi._fnBindAction(
|
||||
node, {action: button}, clickHandler
|
||||
);
|
||||
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// IE9 throws an 'unknown error' if document.activeElement is used
|
||||
// inside an iframe or frame.
|
||||
var activeEl;
|
||||
|
||||
try {
|
||||
// Because this approach is destroying and recreating the paging
|
||||
// elements, focus is lost on the select button which is bad for
|
||||
// accessibility. So we want to restore focus once the draw has
|
||||
// completed
|
||||
activeEl = $(document.activeElement).data('dt-idx');
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
attach(
|
||||
$(host).empty().html('<ul class="pagination"/>').children('ul'),
|
||||
buttons
|
||||
);
|
||||
|
||||
if ( activeEl ) {
|
||||
$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* TableTools Bootstrap compatibility
|
||||
* Required TableTools 2.1+
|
||||
*/
|
||||
if ( DataTable.TableTools ) {
|
||||
// Set the classes that TableTools uses to something suitable for Bootstrap
|
||||
$.extend( true, DataTable.TableTools.classes, {
|
||||
"container": "DTTT btn-group",
|
||||
"buttons": {
|
||||
"normal": "btn btn-default",
|
||||
"disabled": "disabled"
|
||||
},
|
||||
"collection": {
|
||||
"container": "DTTT_dropdown dropdown-menu",
|
||||
"buttons": {
|
||||
"normal": "",
|
||||
"disabled": "disabled"
|
||||
}
|
||||
},
|
||||
"print": {
|
||||
"info": "DTTT_print_info"
|
||||
},
|
||||
"select": {
|
||||
"row": "active"
|
||||
}
|
||||
} );
|
||||
|
||||
// Have the collection use a bootstrap compatible drop down
|
||||
$.extend( true, DataTable.TableTools.DEFAULTS.oTags, {
|
||||
"collection": {
|
||||
"container": "ul",
|
||||
"button": "li",
|
||||
"liner": "a"
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
}; // /factory
|
||||
|
||||
|
||||
// Define as an AMD module if possible
|
||||
if ( typeof define === 'function' && define.amd ) {
|
||||
define( ['jquery', 'datatables'], factory );
|
||||
}
|
||||
else if ( typeof exports === 'object' ) {
|
||||
// Node/CommonJS
|
||||
factory( require('jquery'), require('datatables') );
|
||||
}
|
||||
else if ( jQuery ) {
|
||||
// Otherwise simply initialise as normal, stopping multiple evaluation
|
||||
factory( jQuery, jQuery.fn.dataTable );
|
||||
}
|
||||
|
||||
|
||||
})(window, document);
|
||||
|
||||
@ -0,0 +1,294 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* ========================================================================
|
||||
* datatables_extended function
|
||||
* ======================================================================== */
|
||||
$.fn.datatables_extended = function(settings){
|
||||
|
||||
var elem = $(this);
|
||||
|
||||
// EMM related function
|
||||
if (InitiateViewOption) {
|
||||
$(document).on('click','.viewEnabledIcon',InitiateViewOption);
|
||||
}
|
||||
//--- End of EMM related codes
|
||||
|
||||
/*
|
||||
* Work around for accessing settings params inside datatable functions
|
||||
*/
|
||||
if(settings != null && settings.sorting != null && settings.sorting != undefined && settings.sorting){
|
||||
elem.addClass('sorting-enabled');
|
||||
}else{
|
||||
elem.addClass('sorting-disabled');
|
||||
}
|
||||
|
||||
$(elem).DataTable(
|
||||
$.extend({},{
|
||||
bSortCellsTop: true,
|
||||
responsive: false,
|
||||
autoWidth: false,
|
||||
dom:'<"dataTablesTop"' +
|
||||
'f' +
|
||||
'<"dataTables_toolbar">' +
|
||||
'>' +
|
||||
'rt' +
|
||||
'<"dataTablesBottom"' +
|
||||
'lip' +
|
||||
'>',
|
||||
language: {
|
||||
searchPlaceholder: 'Search ...',
|
||||
search: ''
|
||||
},
|
||||
initComplete: function(){
|
||||
|
||||
this.api().columns().every(function(){
|
||||
|
||||
var column = this;
|
||||
var filterColumn = $('.filter-row th', elem);
|
||||
|
||||
/**
|
||||
* Create & add select/text filters to each column
|
||||
*/
|
||||
if (filterColumn.eq(column.index()).hasClass('select-filter')) {
|
||||
var select = $('<select class="form-control"><option value="">All</option></select>')
|
||||
.appendTo(filterColumn.eq(column.index()).empty())
|
||||
.on('change', function () {
|
||||
var val = $.fn.dataTable.util.escapeRegex(
|
||||
$(this).val()
|
||||
);
|
||||
|
||||
column
|
||||
//.search(val ? '^' + val + '$' : '', true, false)
|
||||
.search(val ? val : '', true, false)
|
||||
.draw();
|
||||
|
||||
if (filterColumn.eq(column.index()).hasClass('data-platform')){
|
||||
if(val == null || val == undefined || val == ""){
|
||||
$("#operation-bar").hide();
|
||||
$( "#operation-guide" ).show();
|
||||
$( "#operation-bar" ).addClass("hidden");
|
||||
}else{
|
||||
$( "#operation-guide" ).hide();
|
||||
$( "#operation-bar" ).removeClass("hidden");
|
||||
$("#operation-bar").show();
|
||||
//TODO: Enable after adding iot operations bar
|
||||
//loadOperationBar(val);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
$(column).each(function () {
|
||||
if ($(column.nodes()).attr('data-search')) {
|
||||
var values = [];
|
||||
column.nodes().unique().sort().each(function (d, j) {
|
||||
var title = $(d).attr('data-display');
|
||||
var value = $(d).attr('data-search');
|
||||
if ($.inArray(value, values) < 0) {
|
||||
values.push(value);
|
||||
if (value !== undefined) {
|
||||
select.append('<option value="' + value + '">' + title + '</option>')
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
column.data().unique().sort().each(function (d, j) {
|
||||
select.append('<option value="' + d + '">' + d + '</option>')
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (filterColumn.eq(column.index()).hasClass('text-filter')) {
|
||||
var title = filterColumn.eq(column.index()).attr('data-for');
|
||||
$(filterColumn.eq(column.index()).empty()).html('<input type="text" class="form-control" placeholder="Search ' + title + '" />');
|
||||
|
||||
filterColumn.eq(column.index()).find('input').on('keyup change', function () {
|
||||
column.search($(this).val()).draw();
|
||||
if($('.dataTables_empty').length > 0) {
|
||||
$('.bulk-action-row').addClass("hidden");
|
||||
} else {
|
||||
$('.bulk-action-row').removeClass("hidden");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* search input default styles override
|
||||
*/
|
||||
var search_input = $(this).closest('.dataTables_wrapper').find('div[id$=_filter] input');
|
||||
search_input.before('<i class="fw fw-search search-icon"></i>').removeClass('input-sm');
|
||||
|
||||
/**
|
||||
* create sorting dropdown menu for list table advance operations
|
||||
*/
|
||||
var table = this;
|
||||
if(table.hasClass('sorting-enabled')){
|
||||
var dropdownmenu = $('<ul class="dropdown-menu arrow arrow-top-right dark sort-list add-margin-top-2x"><li class="dropdown-header">Sort by</li></ul>');
|
||||
$('.sort-row th', elem).each(function () {
|
||||
if (!$(this).hasClass('no-sort')) {
|
||||
dropdownmenu.append('<li><a href="#' + $(this).html() + '" data-column="' + $(this).index() + '">' + $(this).html() + '</a></li>');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getAdvanceToolBar(){
|
||||
if (!table.hasClass('no-toolbar')) {
|
||||
if (table.hasClass('sorting-enabled')) {
|
||||
return '<ul class="nav nav-pills navbar-right remove-margin" role="tablist">' +
|
||||
'<li><button data-click-event="toggle-selectable" class="btn btn-default btn-primary select-enable-btn">Select</li>' +
|
||||
'<li><button data-click-event="toggle-selected" id="dt-select-all" class="btn btn-default btn-primary disabled">Select All</li>' +
|
||||
'<li><button data-click-event="toggle-list-view" data-view="grid" class="btn btn-default"><i class="fw fw-grid"></i></button></li>' +
|
||||
'<li><button data-click-event="toggle-list-view" data-view="list" class="btn btn-default"><i class="fw fw-list"></i></button></li>' +
|
||||
'<li><button class="btn btn-default" data-toggle="dropdown"><i class="fw fw-sort"></i></button>' + dropdownmenu[0].outerHTML + '</li>' +
|
||||
'</ul>'
|
||||
} else {
|
||||
return '<ul class="nav nav-pills navbar-right remove-margin" role="tablist">' +
|
||||
'<li><button data-click-event="toggle-selectable" class="btn btn-default btn-primary select-enable-btn">Select</li>' +
|
||||
'<li><button data-click-event="toggle-selected" id="dt-select-all" class="btn btn-default btn-primary disabled">Select All</li>' +
|
||||
'<li><button data-click-event="toggle-list-view" data-view="grid" class="btn btn-default"><i class="fw fw-grid"></i></button></li>' +
|
||||
'<li><button data-click-event="toggle-list-view" data-view="list" class="btn btn-default"><i class="fw fw-list"></i></button></li>' +
|
||||
'</ul>'
|
||||
}
|
||||
}else{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* append advance operations to list table toolbar
|
||||
*/
|
||||
$('.dataTable.list-table').closest('.dataTables_wrapper').find('.dataTablesTop .dataTables_toolbar').html(
|
||||
getAdvanceToolBar()
|
||||
);
|
||||
|
||||
/**
|
||||
* sorting dropdown menu select function
|
||||
*/
|
||||
$('.dataTables_wrapper .sort-list li a').click(function() {
|
||||
$(this).closest('li').siblings('li').find('a').removeClass('sorting_asc').removeClass('sorting_desc');
|
||||
|
||||
var thisTable = $(this).closest('.dataTables_wrapper').find('.dataTable').dataTable();
|
||||
|
||||
if (!($(this).hasClass('sorting_asc')) && !($(this).hasClass('sorting_desc'))) {
|
||||
$(this).addClass('sorting_asc');
|
||||
thisTable.fnSort( [ [$(this).attr('data-column'),'asc'] ] );
|
||||
}
|
||||
else if($(this).hasClass('sorting_asc')) {
|
||||
$(this).switchClass('sorting_asc', 'sorting_desc');
|
||||
thisTable.fnSort( [ [$(this).attr('data-column'),'desc'] ] );
|
||||
}
|
||||
else if($(this).hasClass('sorting_desc')) {
|
||||
$(this).switchClass('sorting_desc', 'sorting_asc');
|
||||
thisTable.fnSort( [ [$(this).attr('data-column'),'asc'] ] );
|
||||
}
|
||||
});
|
||||
|
||||
var rowSelectedClass = 'DTTT_selected selected';
|
||||
|
||||
/**
|
||||
* Enable/Disable selection on rows
|
||||
*/
|
||||
$('.dataTables_wrapper [data-click-event=toggle-selectable]').click(function () {
|
||||
var button = this,
|
||||
thisTable = $(this).closest('.dataTables_wrapper').find('.dataTable').dataTable();
|
||||
if ($(button).html() == 'Select') {
|
||||
thisTable.addClass("table-selectable");
|
||||
$(button).addClass("active").html('Cancel');
|
||||
$(button).parent().next().children("button").removeClass("disabled");
|
||||
// EMM related code
|
||||
$(document).off('click','.viewEnabledIcon');
|
||||
//--- End of EMM related codes
|
||||
} else if ($(button).html() == 'Cancel'){
|
||||
$('.bulk-action-row').addClass('hidden');
|
||||
thisTable.removeClass("table-selectable");
|
||||
$(button).addClass("active").html('Select');
|
||||
$(button).parent().next().children().addClass("disabled");
|
||||
// EMM related function
|
||||
$(document).on('click','.viewEnabledIcon',InitiateViewOption);
|
||||
//--- End of EMM related codes
|
||||
}
|
||||
});
|
||||
/**
|
||||
* select/deselect all rows function
|
||||
*/
|
||||
$('.dataTables_wrapper [data-click-event=toggle-selected]').click(function() {
|
||||
var button = this,
|
||||
thisTable = $(this).closest('.dataTables_wrapper').find('.dataTable').dataTable();
|
||||
if(!$(button).hasClass('disabled')){
|
||||
if($(button).html() == 'Select All') {
|
||||
thisTable.api().rows().every(function () {
|
||||
$(this.node()).addClass(rowSelectedClass);
|
||||
$(button).html('Deselect All');
|
||||
});
|
||||
}
|
||||
else if($(button).html() == 'Deselect All') {
|
||||
thisTable.api().rows().every(function () {
|
||||
$(this.node()).removeClass(rowSelectedClass);
|
||||
$(button).html('Select All');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* on row click select/deselect row function
|
||||
*/
|
||||
$('body').on('click', '[data-type=selectable]', function(){
|
||||
var rowSelectedClass = 'DTTT_selected selected';
|
||||
$(this).toggleClass(rowSelectedClass);
|
||||
if ($('.table-selectable .DTTT_selected').length > 0) {
|
||||
$('.bulk-action-row').removeClass('hidden');
|
||||
} else {
|
||||
$('.bulk-action-row').addClass('hidden');
|
||||
}
|
||||
var button = this,
|
||||
thisTable = $(this).closest('.dataTables_wrapper').find('.dataTable').dataTable();
|
||||
|
||||
thisTable.api().rows().every(function () {
|
||||
if(!$(this.node()).hasClass(rowSelectedClass)){
|
||||
$(button).closest('.dataTables_wrapper').find('[data-click-event=toggle-selected]').html('Select All');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* list table list/grid view toggle function
|
||||
*/
|
||||
var toggleButton = $('[data-click-event=toggle-list-view]');
|
||||
toggleButton.click(function(){
|
||||
if($(this).attr('data-view') == 'grid') {
|
||||
$(this).closest('.dataTables_wrapper').find('.dataTable').addClass('grid-view');
|
||||
//$(this).closest('li').hide();
|
||||
//$(this).closest('li').siblings().show();
|
||||
}
|
||||
else {
|
||||
$(this).closest('.dataTables_wrapper').find('.dataTable').removeClass('grid-view');
|
||||
//$(this).closest('li').hide();
|
||||
//$(this).closest('li').siblings().show();
|
||||
}
|
||||
});
|
||||
}
|
||||
},settings)
|
||||
);
|
||||
|
||||
};
|
||||
@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* =========================================================
|
||||
* data-tables extended function (Server-side Pagination)
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* @namespace $
|
||||
* The $ is just a function.
|
||||
* It is actually an alias for the function called jQuery.
|
||||
* For ex: $(this) means jQuery(this) and S.fn.x means jQuery.fn.x
|
||||
*/
|
||||
|
||||
$.fn.datatables_extended_serverside_paging = function (settings, url, dataFilter,
|
||||
columns, fnCreatedRow, fnDrawCallback, options) {
|
||||
var elem = $(this);
|
||||
|
||||
// EMM related function
|
||||
if (InitiateViewOption) {
|
||||
$(document).on('click', '.viewEnabledIcon', InitiateViewOption);
|
||||
}
|
||||
//--- End of EMM related codes
|
||||
|
||||
/*
|
||||
* Work around for accessing settings params inside datatable functions
|
||||
*/
|
||||
if (settings != null && settings.sorting != null && settings.sorting != undefined && settings.sorting) {
|
||||
elem.addClass('sorting-enabled');
|
||||
} else {
|
||||
elem.addClass('sorting-disabled');
|
||||
}
|
||||
|
||||
var deviceType;
|
||||
var ownership;
|
||||
var searching = true;
|
||||
if (options) {
|
||||
if (typeof options.searching !== 'undefined') {
|
||||
searching = options.searching;
|
||||
}
|
||||
}
|
||||
|
||||
//--- End of EMM related codes
|
||||
|
||||
$(elem).DataTable(
|
||||
$.extend({}, {
|
||||
serverSide: true,
|
||||
processing: false,
|
||||
searching: searching,
|
||||
ordering: false,
|
||||
filter: false,
|
||||
bSortCellsTop: true,
|
||||
ajax: {
|
||||
url: context + "/api/data-tables/invoker",
|
||||
data: function (params) {
|
||||
var i;
|
||||
var searchParams = {};
|
||||
for (i = 0; i < params.columns.length; i++) {
|
||||
searchParams[params.columns[i].data] = encodeURIComponent(params.columns[i].search.value);
|
||||
}
|
||||
if (options) {
|
||||
searchParams[options.searchKey] = encodeURIComponent(params.search.value);
|
||||
}
|
||||
params.filter = JSON.stringify(searchParams);
|
||||
params.offset = params.start;
|
||||
params.limit = params.length;
|
||||
// if(params.search.value){
|
||||
// params.filter = params.search.value;
|
||||
// }
|
||||
params.url = url;
|
||||
|
||||
//Remove this line to add url parameters which is included by data tables it self
|
||||
delete params.columns;
|
||||
},
|
||||
dataFilter: dataFilter
|
||||
},
|
||||
columns: columns,
|
||||
responsive: false,
|
||||
autoWidth: false,
|
||||
dom: '<"dataTablesTop"' +
|
||||
'f' +
|
||||
'<"dataTables_toolbar">' +
|
||||
'>' +
|
||||
'rt' +
|
||||
'<"dataTablesBottom"' +
|
||||
'lip' +
|
||||
'>',
|
||||
language: {
|
||||
searchPlaceholder: options.placeholder,
|
||||
search: ''
|
||||
},
|
||||
fnCreatedRow: fnCreatedRow,
|
||||
"fnDrawCallback": fnDrawCallback,
|
||||
initComplete: function () {
|
||||
|
||||
//loading tooltips
|
||||
if (typeof $.fn.tooltip == 'function') {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
} else {
|
||||
console.warn('Warning : Dependency missing - Bootstrap Tooltip Library');
|
||||
}
|
||||
|
||||
this.api().columns().every(function () {
|
||||
|
||||
var column = this;
|
||||
var filterColumn = $('.filter-row th', elem);
|
||||
|
||||
/**
|
||||
* Create & add select/text filters to each column
|
||||
*/
|
||||
if (filterColumn.eq(column.index()).hasClass('select-filter')) {
|
||||
var select = $('<select class="form-control"><option value="">All</option></select>')
|
||||
.appendTo(filterColumn.eq(column.index()).empty())
|
||||
.on('change', function () {
|
||||
var val = $.fn.dataTable.util.escapeRegex(
|
||||
$(this).val()
|
||||
);
|
||||
|
||||
column
|
||||
//.search(val ? '^' + val + '$' : '', true, false)
|
||||
.search(val ? val : '', true, false)
|
||||
.draw();
|
||||
|
||||
if (filterColumn.eq(column.index()).hasClass('data-platform')) {
|
||||
deviceType = val;
|
||||
if (!deviceType || !ownership) {
|
||||
$("#operation-bar").addClass("hidden");
|
||||
$("#operation-guide").removeClass("hidden");
|
||||
} else {
|
||||
$("#operation-guide").addClass("hidden");
|
||||
$("#operation-bar").removeClass("hidden");
|
||||
//noinspection JSUnresolvedFunction
|
||||
if (deviceType && ownership) {
|
||||
loadOperationBar(deviceType, ownership, operationBarModeConstants.BULK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (filterColumn.eq(column.index()).hasClass('data-ownership')) {
|
||||
ownership = val;
|
||||
if (!deviceType || !ownership) {
|
||||
$("#operation-bar").addClass("hidden");
|
||||
$("#operation-guide").removeClass("hidden");
|
||||
} else {
|
||||
$("#operation-guide").addClass("hidden");
|
||||
$("#operation-bar").removeClass("hidden");
|
||||
//noinspection JSUnresolvedFunction
|
||||
if (deviceType && ownership) {
|
||||
loadOperationBar(deviceType, ownership, operationBarModeConstants.BULK);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(column).each(function () {
|
||||
if ($(column.nodes()).attr('data-search')) {
|
||||
var titles = [];
|
||||
column.nodes().unique().sort().each(function (d, j) {
|
||||
var title = $(d).attr('data-display');
|
||||
var searchVal = $(d).attr('data-search');
|
||||
if ($.inArray(title, titles) < 0) {
|
||||
titles.push(title);
|
||||
if (title !== undefined) {
|
||||
select.append('<option value="' + searchVal + '">' + title + '</option>')
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
column.data().unique().sort().each(function (d, j) {
|
||||
select.append('<option value="' + d + '">' + d + '</option>')
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (filterColumn.eq(column.index()).hasClass('text-filter')) {
|
||||
var title = filterColumn.eq(column.index()).attr('data-for');
|
||||
$(filterColumn.eq(column.index()).empty()).html('<input type="text" class="form-control" placeholder="Search ' + title + '" />');
|
||||
|
||||
//noinspection SpellCheckingInspection
|
||||
filterColumn.eq(column.index()).find('input').on('keyup', function () {
|
||||
column.search($(this).val()).draw();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* search input default styles override
|
||||
*/
|
||||
var search_input = $(this).closest('.dataTables_wrapper').find('div[id$=_filter] input');
|
||||
search_input.before('<i class="fw fw-search search-icon"></i>').removeClass('input-sm');
|
||||
|
||||
/**
|
||||
* create sorting dropdown menu for list table advance operations
|
||||
*/
|
||||
var table = this;
|
||||
if (table.hasClass('sorting-enabled')) {
|
||||
var dropdownmenu = $('<ul class="dropdown-menu arrow arrow-top-right dark sort-list add-margin-top-2x"><li class="dropdown-header">Sort by</li></ul>');
|
||||
$('.sort-row th', elem).each(function () {
|
||||
if (!$(this).hasClass('no-sort')) {
|
||||
dropdownmenu.append('<li><a href="#' + $(this).html() + '" data-column="' + $(this).index() + '">' + $(this).html() + '</a></li>');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getAdvanceToolBar() {
|
||||
if (table.hasClass('sorting-enabled')) {
|
||||
return '<ul class="nav nav-pills navbar-right remove-margin" role="tablist">' +
|
||||
'<li><button data-click-event="toggle-selectable" class="btn btn-default btn-primary select-enable-btn">Select</li>' +
|
||||
'<li><button data-click-event="toggle-selected" id="dt-select-all" class="btn btn-default btn-primary disabled">Select All</li>' +
|
||||
'<li><button data-click-event="toggle-list-view" data-view="grid" class="btn btn-default"><i class="fw fw-grid"></i></button></li>' +
|
||||
'<li><button data-click-event="toggle-list-view" data-view="list" class="btn btn-default"><i class="fw fw-list"></i></button></li>' +
|
||||
'<li><button class="btn btn-default" data-toggle="dropdown"><i class="fw fw-sort"></i></button>' + dropdownmenu[0].outerHTML + '</li>' +
|
||||
'</ul>'
|
||||
} else {
|
||||
return '<ul class="nav nav-pills navbar-right remove-margin" role="tablist">' +
|
||||
'<li><button data-click-event="toggle-selectable" class="btn btn-default btn-primary select-enable-btn">Select</li>' +
|
||||
'<li><button data-click-event="toggle-selected" id="dt-select-all" class="btn btn-default btn-primary disabled">Select All</li>' +
|
||||
'<li><button data-click-event="toggle-list-view" data-view="grid" class="btn btn-default"><i class="fw fw-grid"></i></button></li>' +
|
||||
'<li><button data-click-event="toggle-list-view" data-view="list" class="btn btn-default"><i class="fw fw-list"></i></button></li>' +
|
||||
'</ul>'
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* append advance operations to list table toolbar
|
||||
*/
|
||||
$('.dataTable.list-table').closest('.dataTables_wrapper').find('.dataTablesTop .dataTables_toolbar').html(
|
||||
getAdvanceToolBar()
|
||||
);
|
||||
|
||||
/**
|
||||
* sorting dropdown menu select function
|
||||
*/
|
||||
$('.dataTables_wrapper .sort-list li a').click(function () {
|
||||
$(this).closest('li').siblings('li').find('a').removeClass('sorting_asc').removeClass('sorting_desc');
|
||||
|
||||
var thisTable = $(this).closest('.dataTables_wrapper').find('.dataTable').dataTable();
|
||||
|
||||
if (!($(this).hasClass('sorting_asc')) && !($(this).hasClass('sorting_desc'))) {
|
||||
$(this).addClass('sorting_asc');
|
||||
thisTable.fnSort([[$(this).attr('data-column'), 'asc']]);
|
||||
}
|
||||
else if ($(this).hasClass('sorting_asc')) {
|
||||
$(this).switchClass('sorting_asc', 'sorting_desc');
|
||||
thisTable.fnSort([[$(this).attr('data-column'), 'desc']]);
|
||||
}
|
||||
else if ($(this).hasClass('sorting_desc')) {
|
||||
$(this).switchClass('sorting_desc', 'sorting_asc');
|
||||
thisTable.fnSort([[$(this).attr('data-column'), 'asc']]);
|
||||
}
|
||||
});
|
||||
|
||||
var rowSelectedClass = 'DTTT_selected selected';
|
||||
|
||||
/**
|
||||
* Enable/Disable selection on rows
|
||||
*/
|
||||
$('.dataTables_wrapper [data-click-event=toggle-selectable]').click(function () {
|
||||
var button = this,
|
||||
thisTable = $(this).closest('.dataTables_wrapper').find('.dataTable').dataTable();
|
||||
if ($(button).html() == 'Select') {
|
||||
thisTable.addClass("table-selectable");
|
||||
$(button).addClass("active").html('Cancel');
|
||||
$(button).parent().next().children("button").removeClass("disabled");
|
||||
// EMM related code
|
||||
$(document).off('click', '.viewEnabledIcon');
|
||||
//--- End of EMM related codes
|
||||
} else if ($(button).html() == 'Cancel') {
|
||||
$('.bulk-action-row').addClass('hidden');
|
||||
thisTable.removeClass("table-selectable");
|
||||
$(button).addClass("active").html('Select');
|
||||
$(button).parent().next().children().addClass("disabled");
|
||||
$('.DTTT_selected.selected').removeClass(rowSelectedClass);
|
||||
// EMM related function
|
||||
$(document).on('click', '.viewEnabledIcon', InitiateViewOption);
|
||||
//--- End of EMM related codes
|
||||
}
|
||||
});
|
||||
/**
|
||||
* select/deselect all rows function
|
||||
*/
|
||||
$('.dataTables_wrapper [data-click-event=toggle-selected]').click(function () {
|
||||
var button = this,
|
||||
thisTable = $(this).closest('.dataTables_wrapper').find('.dataTable').dataTable();
|
||||
if (!$(button).hasClass('disabled')) {
|
||||
if ($(button).html() == 'Select All') {
|
||||
thisTable.api().rows().every(function () {
|
||||
$(this.node()).addClass(rowSelectedClass);
|
||||
$(button).html('Deselect All');
|
||||
});
|
||||
}
|
||||
else if ($(button).html() == 'Deselect All') {
|
||||
thisTable.api().rows().every(function () {
|
||||
$(this.node()).removeClass(rowSelectedClass);
|
||||
$(button).html('Select All');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* on row click select/deselect row function
|
||||
*/
|
||||
$('body').on('click', '[data-type=selectable]', function () {
|
||||
var rowSelectedClass = 'DTTT_selected selected';
|
||||
$(this).toggleClass(rowSelectedClass);
|
||||
if ($('.table-selectable .DTTT_selected').length > 0) {
|
||||
$('.bulk-action-row').removeClass('hidden');
|
||||
} else {
|
||||
$('.bulk-action-row').addClass('hidden');
|
||||
}
|
||||
var button = this,
|
||||
thisTable = $(this).closest('.dataTables_wrapper').find('.dataTable').dataTable();
|
||||
|
||||
thisTable.api().rows().every(function () {
|
||||
if (!$(this.node()).hasClass(rowSelectedClass)) {
|
||||
$(button).closest('.dataTables_wrapper').find('[data-click-event=toggle-selected]').html('Select All');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* list table list/grid view toggle function
|
||||
*/
|
||||
var toggleButton = $('[data-click-event=toggle-list-view]');
|
||||
toggleButton.click(function () {
|
||||
if ($(this).attr('data-view') == 'grid') {
|
||||
$(this).closest('.dataTables_wrapper').find('.dataTable').addClass('grid-view');
|
||||
//$(this).closest('li').hide();
|
||||
//$(this).closest('li').siblings().show();
|
||||
}
|
||||
else {
|
||||
$(this).closest('.dataTables_wrapper').find('.dataTable').removeClass('grid-view');
|
||||
//$(this).closest('li').hide();
|
||||
//$(this).closest('li').siblings().show();
|
||||
}
|
||||
})
|
||||
}
|
||||
}, settings)
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,19 @@
|
||||
/*!
|
||||
Responsive 1.0.6
|
||||
2014-2015 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
(function(n,p){var o=function(e,k){var h=function(d,a){if(!k.versionCheck||!k.versionCheck("1.10.1"))throw"DataTables Responsive requires DataTables 1.10.1 or newer";this.s={dt:new k.Api(d),columns:[]};this.s.dt.settings()[0].responsive||(a&&"string"===typeof a.details&&(a.details={type:a.details}),this.c=e.extend(!0,{},h.defaults,k.defaults.responsive,a),d.responsive=this,this._constructor())};h.prototype={_constructor:function(){var d=this,a=this.s.dt;a.settings()[0]._responsive=this;e(n).on("resize.dtr orientationchange.dtr",
|
||||
a.settings()[0].oApi._fnThrottle(function(){d._resize()}));a.on("destroy.dtr",function(){e(n).off("resize.dtr orientationchange.dtr draw.dtr")});this.c.breakpoints.sort(function(a,c){return a.width<c.width?1:a.width>c.width?-1:0});this._classLogic();this._resizeAuto();var c=this.c.details;c.type&&(d._detailsInit(),this._detailsVis(),a.on("column-visibility.dtr",function(){d._detailsVis()}),a.on("draw.dtr",function(){a.rows({page:"current"}).iterator("row",function(b,c){var f=a.row(c);if(f.child.isShown()){var i=
|
||||
d.c.details.renderer(a,c);f.child(i,"child").show()}})}),e(a.table().node()).addClass("dtr-"+c.type));this._resize()},_columnsVisiblity:function(d){var a=this.s.dt,c=this.s.columns,b,g,f=e.map(c,function(a){return a.auto&&null===a.minWidth?!1:!0===a.auto?"-":-1!==e.inArray(d,a.includeIn)}),i=0;b=0;for(g=f.length;b<g;b++)!0===f[b]&&(i+=c[b].minWidth);b=a.settings()[0].oScroll;b=b.sY||b.sX?b.iBarWidth:0;a=a.table().container().offsetWidth-b-i;b=0;for(g=f.length;b<g;b++)c[b].control&&(a-=c[b].minWidth);
|
||||
i=!1;b=0;for(g=f.length;b<g;b++)"-"===f[b]&&!c[b].control&&(i||0>a-c[b].minWidth?(i=!0,f[b]=!1):f[b]=!0,a-=c[b].minWidth);a=!1;b=0;for(g=c.length;b<g;b++)if(!c[b].control&&!c[b].never&&!f[b]){a=!0;break}b=0;for(g=c.length;b<g;b++)c[b].control&&(f[b]=a);-1===e.inArray(!0,f)&&(f[0]=!0);return f},_classLogic:function(){var d=this,a=this.c.breakpoints,c=this.s.dt.columns().eq(0).map(function(a){a=this.column(a).header().className;return{className:a,includeIn:[],auto:!1,control:!1,never:a.match(/\bnever\b/)?
|
||||
!0:!1}}),b=function(a,b){var d=c[a].includeIn;-1===e.inArray(b,d)&&d.push(b)},g=function(f,g,e,j){if(e)if("max-"===e){j=d._find(g).width;g=0;for(e=a.length;g<e;g++)a[g].width<=j&&b(f,a[g].name)}else if("min-"===e){j=d._find(g).width;g=0;for(e=a.length;g<e;g++)a[g].width>=j&&b(f,a[g].name)}else{if("not-"===e){g=0;for(e=a.length;g<e;g++)-1===a[g].name.indexOf(j)&&b(f,a[g].name)}}else c[f].includeIn.push(g)};c.each(function(b,c){for(var d=b.className.split(" "),j=!1,h=0,k=d.length;h<k;h++){var l=e.trim(d[h]);
|
||||
if("all"===l){j=!0;b.includeIn=e.map(a,function(a){return a.name});return}if("none"===l||"never"===l){j=!0;return}if("control"===l){j=!0;b.control=!0;return}e.each(a,function(a,b){var d=b.name.split("-"),e=l.match(RegExp("(min\\-|max\\-|not\\-)?("+d[0]+")(\\-[_a-zA-Z0-9])?"));e&&(j=!0,e[2]===d[0]&&e[3]==="-"+d[1]?g(c,b.name,e[1],e[2]+e[3]):e[2]===d[0]&&!e[3]&&g(c,b.name,e[1],e[2]))})}j||(b.auto=!0)});this.s.columns=c},_detailsInit:function(){var d=this,a=this.s.dt,c=this.c.details;"inline"===c.type&&
|
||||
(c.target="td:first-child");var b=c.target;e(a.table().body()).on("click","string"===typeof b?b:"td",function(){if(e(a.table().node()).hasClass("collapsed")&&a.row(e(this).closest("tr")).length){if(typeof b==="number"){var c=b<0?a.columns().eq(0).length+b:b;if(a.cell(this).index().column!==c)return}c=a.row(e(this).closest("tr"));if(c.child.isShown()){c.child(false);e(c.node()).removeClass("parent")}else{var f=d.c.details.renderer(a,c[0]);c.child(f,"child").show();e(c.node()).addClass("parent")}}})},
|
||||
_detailsVis:function(){var d=this,a=this.s.dt,c=a.columns().indexes().filter(function(b){var c=a.column(b);return c.visible()?null:e(c.header()).hasClass("never")?null:b}),b=!0;if(0===c.length||1===c.length&&this.s.columns[c[0]].control)b=!1;b?a.rows({page:"current"}).eq(0).each(function(b){b=a.row(b);if(b.child()){var c=d.c.details.renderer(a,b[0]);!1===c?b.child.hide():b.child(c,"child").show()}}):a.rows({page:"current"}).eq(0).each(function(b){a.row(b).child.hide()})},_find:function(d){for(var a=
|
||||
this.c.breakpoints,c=0,b=a.length;c<b;c++)if(a[c].name===d)return a[c]},_resize:function(){var d=this.s.dt,a=e(n).width(),c=this.c.breakpoints,b=c[0].name,g=this.s.columns,f;for(f=c.length-1;0<=f;f--)if(a<=c[f].width){b=c[f].name;break}var i=this._columnsVisiblity(b),c=!1;f=0;for(a=g.length;f<a;f++)if(!1===i[f]&&!g[f].never){c=!0;break}e(d.table().node()).toggleClass("collapsed",c);d.columns().eq(0).each(function(a,b){d.column(a).visible(i[b])})},_resizeAuto:function(){var d=this.s.dt,a=this.s.columns;
|
||||
if(this.c.auto&&-1!==e.inArray(!0,e.map(a,function(a){return a.auto}))){d.table().node();var c=d.table().node().cloneNode(!1),b=e(d.table().header().cloneNode(!1)).appendTo(c),g=e(d.table().body().cloneNode(!1)).appendTo(c);e(d.table().footer()).clone(!1).appendTo(c);d.rows({page:"current"}).indexes().flatten().each(function(a){var b=d.row(a).node().cloneNode(!0);d.columns(":hidden").flatten().length&&e(b).append(d.cells(a,":hidden").nodes().to$().clone());e(b).appendTo(g)});var f=d.columns().header().to$().clone(!1);
|
||||
e("<tr/>").append(f).appendTo(b);"inline"===this.c.details.type&&e(c).addClass("dtr-inline collapsed");c=e("<div/>").css({width:1,height:1,overflow:"hidden"}).append(c);c.find("th.never, td.never").remove();c.insertBefore(d.table().node());d.columns().eq(0).each(function(b){a[b].minWidth=f[b].offsetWidth||0});c.remove()}}};h.breakpoints=[{name:"desktop",width:Infinity},{name:"tablet-l",width:1024},{name:"tablet-p",width:768},{name:"mobile-l",width:480},{name:"mobile-p",width:320}];h.defaults={breakpoints:h.breakpoints,
|
||||
auto:!0,details:{renderer:function(d,a){var c=d.cells(a,":hidden").eq(0).map(function(a){var c=e(d.column(a.column).header()),a=d.cell(a).index();if(c.hasClass("control")||c.hasClass("never"))return"";var f=d.settings()[0],f=f.oApi._fnGetCellData(f,a.row,a.column,"display");(c=c.text())&&(c+=":");return'<li data-dtr-index="'+a.column+'"><span class="dtr-title">'+c+'</span> <span class="dtr-data">'+f+"</span></li>"}).toArray().join("");return c?e('<ul data-dtr-index="'+a+'"/>').append(c):!1},target:0,
|
||||
type:"inline"}};var m=e.fn.dataTable.Api;m.register("responsive()",function(){return this});m.register("responsive.index()",function(d){d=e(d);return{column:d.data("dtr-index"),row:d.parent().data("dtr-index")}});m.register("responsive.rebuild()",function(){return this.iterator("table",function(d){d._responsive&&d._responsive._classLogic()})});m.register("responsive.recalc()",function(){return this.iterator("table",function(d){d._responsive&&(d._responsive._resizeAuto(),d._responsive._resize())})});
|
||||
h.version="1.0.6";e.fn.dataTable.Responsive=h;e.fn.DataTable.Responsive=h;e(p).on("init.dt.dtr",function(d,a){if("dt"===d.namespace&&(e(a.nTable).hasClass("responsive")||e(a.nTable).hasClass("dt-responsive")||a.oInit.responsive||k.defaults.responsive)){var c=a.oInit.responsive;!1!==c&&new h(a,e.isPlainObject(c)?c:{})}});return h};"function"===typeof define&&define.amd?define(["jquery","datatables"],o):"object"===typeof exports?o(require("jquery"),require("datatables")):jQuery&&!jQuery.fn.dataTable.Responsive&&
|
||||
o(jQuery,jQuery.fn.dataTable)})(window,document);
|
||||
@ -0,0 +1,163 @@
|
||||
/*!
|
||||
DataTables 1.10.9
|
||||
©2008-2015 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
(function(Fa,T,k){var S=function(h){function X(a){var b,c,d={};h.each(a,function(e){if((b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=e.replace(b[0],b[2].toLowerCase()),d[c]=e,"o"===b[1]&&X(a[e])});a._hungarianMap=d}function I(a,b,c){a._hungarianMap||X(a);var d;h.each(b,function(e){d=a._hungarianMap[e];if(d!==k&&(c||b[d]===k))"o"===d.charAt(0)?(b[d]||(b[d]={}),h.extend(!0,b[d],b[e]),I(a[d],b[d],c)):b[d]=b[e]})}function S(a){var b=m.defaults.oLanguage,c=a.sZeroRecords;
|
||||
!a.sEmptyTable&&(c&&"No data available in table"===b.sEmptyTable)&&F(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(c&&"Loading..."===b.sLoadingRecords)&&F(a,a,"sZeroRecords","sLoadingRecords");a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&cb(a)}function db(a){A(a,"ordering","bSort");A(a,"orderMulti","bSortMulti");A(a,"orderClasses","bSortClasses");A(a,"orderCellsTop","bSortCellsTop");A(a,"order","aaSorting");A(a,"orderFixed","aaSortingFixed");A(a,"paging","bPaginate");
|
||||
A(a,"pagingType","sPaginationType");A(a,"pageLength","iDisplayLength");A(a,"searching","bFilter");"boolean"===typeof a.sScrollX&&(a.sScrollX=a.sScrollX?"100%":"");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&I(m.models.oSearch,a[b])}function eb(a){A(a,"orderable","bSortable");A(a,"orderData","aDataSort");A(a,"orderSequence","asSorting");A(a,"orderDataType","sortDataType");var b=a.aDataSort;b&&!h.isArray(b)&&(a.aDataSort=[b])}function fb(a){if(!m.__browser){var b={};m.__browser=b;var c=
|
||||
h("<div/>").css({position:"fixed",top:0,left:0,height:1,width:1,overflow:"hidden"}).append(h("<div/>").css({position:"absolute",top:1,left:1,width:100,overflow:"scroll"}).append(h("<div/>").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}h.extend(a.oBrowser,
|
||||
m.__browser);a.oScroll.iBarWidth=m.__browser.barWidth}function gb(a,b,c,d,e,f){var g,i=!1;c!==k&&(g=c,i=!0);for(;d!==e;)a.hasOwnProperty(d)&&(g=i?b(g,a[d],d,a):a[d],i=!0,d+=f);return g}function Ga(a,b){var c=m.defaults.column,d=a.aoColumns.length,c=h.extend({},m.models.oColumn,c,{nTh:b?b:T.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=h.extend({},m.models.oSearch,c[d]);
|
||||
la(a,d,h(b).data())}function la(a,b,c){var b=a.aoColumns[b],d=a.oClasses,e=h(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var f=(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);f&&(b.sWidthOrig=f[1])}c!==k&&null!==c&&(eb(c),I(m.defaults.column,c),c.mDataProp!==k&&!c.mData&&(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),h.extend(b,c),F(b,c,"sWidth","sWidthOrig"),c.iDataSort!==k&&(b.aDataSort=[c.iDataSort]),F(b,c,"aDataSort"));
|
||||
var g=b.mData,i=P(g),j=b.mRender?P(b.mRender):null,c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=h.isPlainObject(g)&&(c(g.sort)||c(g.type)||c(g.filter));b.fnGetData=function(a,b,c){var d=i(a,b,k,c);return j&&b?j(d,b,a,c):d};b.fnSetData=function(a,b,c){return Q(g)(a,b,c)};"number"!==typeof g&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==h.inArray("asc",b.asSorting);c=-1!==h.inArray("desc",b.asSorting);!b.bSortable||!a&&!c?
|
||||
(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI=""):a&&!c?(b.sSortingClass=d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI)}function Y(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Ha(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;(""!==b.sY||""!==b.sX)&&Z(a);w(a,null,"column-sizing",[a])}function $(a,b){var c=
|
||||
aa(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function ba(a,b){var c=aa(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}function ca(a){return aa(a,"bVisible").length}function aa(a,b){var c=[];h.map(a.aoColumns,function(a,e){a[b]&&c.push(e)});return c}function Ia(a){var b=a.aoColumns,c=a.aoData,d=m.ext.type.detect,e,f,g,i,j,h,l,r,q;e=0;for(f=b.length;e<f;e++)if(l=b[e],q=[],!l.sType&&l._sManualType)l.sType=l._sManualType;else if(!l.sType){g=0;for(i=d.length;g<i;g++){j=0;for(h=c.length;j<
|
||||
h;j++){q[j]===k&&(q[j]=B(a,j,e,"type"));r=d[g](q[j],a);if(!r&&g!==d.length-1)break;if("html"===r)break}if(r){l.sType=r;break}}l.sType||(l.sType="string")}}function hb(a,b,c,d){var e,f,g,i,j,n,l=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){n=b[e];var r=n.targets!==k?n.targets:n.aTargets;h.isArray(r)||(r=[r]);f=0;for(g=r.length;f<g;f++)if("number"===typeof r[f]&&0<=r[f]){for(;l.length<=r[f];)Ga(a);d(r[f],n)}else if("number"===typeof r[f]&&0>r[f])d(l.length+r[f],n);else if("string"===typeof r[f]){i=0;
|
||||
for(j=l.length;i<j;i++)("_all"==r[f]||h(l[i].nTh).hasClass(r[f]))&&d(i,n)}}if(c){e=0;for(a=c.length;e<a;e++)d(e,c[e])}}function L(a,b,c,d){var e=a.aoData.length,f=h.extend(!0,{},m.models.oRow,{src:c?"dom":"data",idx:e});f._aData=b;a.aoData.push(f);for(var g=a.aoColumns,i=0,j=g.length;i<j;i++)g[i].sType=null;a.aiDisplayMaster.push(e);b=a.rowIdFn(b);b!==k&&(a.aIds[b]=f);(c||!a.oFeatures.bDeferRender)&&Ja(a,e,c,d);return e}function ma(a,b){var c;b instanceof h||(b=h(b));return b.map(function(b,e){c=
|
||||
Ka(a,e);return L(a,c.data,e,c.cells)})}function B(a,b,c,d){var e=a.iDraw,f=a.aoColumns[c],g=a.aoData[b]._aData,i=f.sDefaultContent,c=f.fnGetData(g,d,{settings:a,row:b,col:c});if(c===k)return a.iDrawError!=e&&null===i&&(J(a,0,"Requested unknown parameter "+("function"==typeof f.mData?"{function}":"'"+f.mData+"'")+" for row "+b,4),a.iDrawError=e),i;if((c===g||null===c)&&null!==i)c=i;else if("function"===typeof c)return c.call(g);return null===c&&"display"==d?"":c}function ib(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,
|
||||
d,{settings:a,row:b,col:c})}function La(a){return h.map(a.match(/(\\.|[^\.])+/g)||[""],function(a){return a.replace(/\\./g,".")})}function P(a){if(h.isPlainObject(a)){var b={};h.each(a,function(a,c){c&&(b[a]=P(c))});return function(a,c,f,g){var i=b[c]||b._;return i!==k?i(a,c,f,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,c,f,g){return a(b,c,f,g)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var c=function(a,b,
|
||||
f){var g,i;if(""!==f){i=La(f);for(var j=0,n=i.length;j<n;j++){f=i[j].match(da);g=i[j].match(U);if(f){i[j]=i[j].replace(da,"");""!==i[j]&&(a=a[i[j]]);g=[];i.splice(0,j+1);i=i.join(".");if(h.isArray(a)){j=0;for(n=a.length;j<n;j++)g.push(c(a[j],b,i))}a=f[0].substring(1,f[0].length-1);a=""===a?g:g.join(a);break}else if(g){i[j]=i[j].replace(U,"");a=a[i[j]]();continue}if(null===a||a[i[j]]===k)return k;a=a[i[j]]}}return a};return function(b,e){return c(b,e,a)}}return function(b){return b[a]}}function Q(a){if(h.isPlainObject(a))return Q(a._);
|
||||
if(null===a)return function(){};if("function"===typeof a)return function(b,d,e){a(b,"set",d,e)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var b=function(a,d,e){var e=La(e),f;f=e[e.length-1];for(var g,i,j=0,n=e.length-1;j<n;j++){g=e[j].match(da);i=e[j].match(U);if(g){e[j]=e[j].replace(da,"");a[e[j]]=[];f=e.slice();f.splice(0,j+1);g=f.join(".");if(h.isArray(d)){i=0;for(n=d.length;i<n;i++)f={},b(f,d[i],g),a[e[j]].push(f)}else a[e[j]]=d;return}i&&(e[j]=e[j].replace(U,
|
||||
""),a=a[e[j]](d));if(null===a[e[j]]||a[e[j]]===k)a[e[j]]={};a=a[e[j]]}if(f.match(U))a[f.replace(U,"")](d);else a[f.replace(da,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Ma(a){return D(a.aoData,"_aData")}function na(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0;a.aIds={}}function oa(a,b,c){for(var d=-1,e=0,f=a.length;e<f;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===k&&a.splice(d,1)}function ea(a,b,c,d){var e=a.aoData[b],f,g=function(c,d){for(;c.childNodes.length;)c.removeChild(c.firstChild);
|
||||
c.innerHTML=B(a,b,d,"display")};if("dom"===c||(!c||"auto"===c)&&"dom"===e.src)e._aData=Ka(a,e,d,d===k?k:e._aData).data;else{var i=e.anCells;if(i)if(d!==k)g(i[d],d);else{c=0;for(f=i.length;c<f;c++)g(i[c],c)}}e._aSortData=null;e._aFilterData=null;g=a.aoColumns;if(d!==k)g[d].sType=null;else{c=0;for(f=g.length;c<f;c++)g[c].sType=null;Na(a,e)}}function Ka(a,b,c,d){var e=[],f=b.firstChild,g,i,j=0,n,l=a.aoColumns,r=a._rowReadObject,d=d!==k?d:r?{}:[],q=function(a,b){if("string"===typeof a){var c=a.indexOf("@");
|
||||
-1!==c&&(c=a.substring(c+1),Q(a)(d,b.getAttribute(c)))}},jb=function(a){if(c===k||c===j)i=l[j],n=h.trim(a.innerHTML),i&&i._bAttrSrc?(Q(i.mData._)(d,n),q(i.mData.sort,a),q(i.mData.type,a),q(i.mData.filter,a)):r?(i._setter||(i._setter=Q(i.mData)),i._setter(d,n)):d[j]=n;j++};if(f)for(;f;){g=f.nodeName.toUpperCase();if("TD"==g||"TH"==g)jb(f),e.push(f);f=f.nextSibling}else{e=b.anCells;g=0;for(var o=e.length;g<o;g++)jb(e[g])}if(b=f?b:b.nTr)(b=b.getAttribute("id"))&&Q(a.rowId)(d,b);return{data:d,cells:e}}
|
||||
function Ja(a,b,c,d){var e=a.aoData[b],f=e._aData,g=[],i,j,h,l,r;if(null===e.nTr){i=c||T.createElement("tr");e.nTr=i;e.anCells=g;i._DT_RowIndex=b;Na(a,e);l=0;for(r=a.aoColumns.length;l<r;l++){h=a.aoColumns[l];j=c?d[l]:T.createElement(h.sCellType);g.push(j);if(!c||h.mRender||h.mData!==l)j.innerHTML=B(a,b,l,"display");h.sClass&&(j.className+=" "+h.sClass);h.bVisible&&!c?i.appendChild(j):!h.bVisible&&c&&j.parentNode.removeChild(j);h.fnCreatedCell&&h.fnCreatedCell.call(a.oInstance,j,B(a,b,l),f,b,l)}w(a,
|
||||
"aoRowCreatedCallback",null,[i,f,b])}e.nTr.setAttribute("role","row")}function Na(a,b){var c=b.nTr,d=b._aData;if(c){var e=a.rowIdFn(d);e&&(c.id=e);d.DT_RowClass&&(e=d.DT_RowClass.split(" "),b.__rowc=b.__rowc?pa(b.__rowc.concat(e)):e,h(c).removeClass(b.__rowc.join(" ")).addClass(d.DT_RowClass));d.DT_RowAttr&&h(c).attr(d.DT_RowAttr);d.DT_RowData&&h(c).data(d.DT_RowData)}}function kb(a){var b,c,d,e,f,g=a.nTHead,i=a.nTFoot,j=0===h("th, td",g).length,n=a.oClasses,l=a.aoColumns;j&&(e=h("<tr/>").appendTo(g));
|
||||
b=0;for(c=l.length;b<c;b++)f=l[b],d=h(f.nTh).addClass(f.sClass),j&&d.appendTo(e),a.oFeatures.bSort&&(d.addClass(f.sSortingClass),!1!==f.bSortable&&(d.attr("tabindex",a.iTabIndex).attr("aria-controls",a.sTableId),Oa(a,f.nTh,b))),f.sTitle!=d[0].innerHTML&&d.html(f.sTitle),Pa(a,"header")(a,d,f,n);j&&fa(a.aoHeader,g);h(g).find(">tr").attr("role","row");h(g).find(">tr>th, >tr>td").addClass(n.sHeaderTH);h(i).find(">tr>th, >tr>td").addClass(n.sFooterTH);if(null!==i){a=a.aoFooter[0];b=0;for(c=a.length;b<
|
||||
c;b++)f=l[b],f.nTf=a[b].cell,f.sClass&&h(f.nTf).addClass(f.sClass)}}function ga(a,b,c){var d,e,f,g=[],i=[],j=a.aoColumns.length,n;if(b){c===k&&(c=!1);d=0;for(e=b.length;d<e;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=j-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[d].splice(f,1);i.push([])}d=0;for(e=g.length;d<e;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(n=j=1,i[d][f]===k){a.appendChild(g[d][f].cell);for(i[d][f]=1;g[d+j]!==k&&g[d][f].cell==g[d+j][f].cell;)i[d+
|
||||
j][f]=1,j++;for(;g[d][f+n]!==k&&g[d][f].cell==g[d][f+n].cell;){for(c=0;c<j;c++)i[d+c][f+n]=1;n++}h(g[d][f].cell).attr("rowspan",j).attr("colspan",n)}}}}function M(a){var b=w(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))C(a,!1);else{var b=[],c=0,d=a.asStripeClasses,e=d.length,f=a.oLanguage,g=a.iInitDisplayStart,i="ssp"==y(a),j=a.aiDisplay;a.bDrawing=!0;g!==k&&-1!==g&&(a._iDisplayStart=i?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=-1);var g=a._iDisplayStart,n=a.fnDisplayEnd();
|
||||
if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,C(a,!1);else if(i){if(!a.bDestroying&&!lb(a))return}else a.iDraw++;if(0!==j.length){f=i?a.aoData.length:n;for(i=i?0:g;i<f;i++){var l=j[i],r=a.aoData[l];null===r.nTr&&Ja(a,l);l=r.nTr;if(0!==e){var q=d[c%e];r._sRowStripe!=q&&(h(l).removeClass(r._sRowStripe).addClass(q),r._sRowStripe=q)}w(a,"aoRowCallback",null,[l,r._aData,c,i]);b.push(l);c++}}else c=f.sZeroRecords,1==a.iDraw&&"ajax"==y(a)?c=f.sLoadingRecords:f.sEmptyTable&&0===a.fnRecordsTotal()&&(c=f.sEmptyTable),
|
||||
b[0]=h("<tr/>",{"class":e?d[0]:""}).append(h("<td />",{valign:"top",colSpan:ca(a),"class":a.oClasses.sRowEmpty}).html(c))[0];w(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Ma(a),g,n,j]);w(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],Ma(a),g,n,j]);d=h(a.nTBody);d.children().detach();d.append(h(b));w(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function R(a,b){var c=a.oFeatures,d=c.bFilter;c.bSort&&mb(a);d?ha(a,a.oPreviousSearch):a.aiDisplay=
|
||||
a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;M(a);a._drawHold=!1}function nb(a){var b=a.oClasses,c=h(a.nTable),c=h("<div/>").insertBefore(c),d=a.oFeatures,e=h("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var f=a.sDom.split(""),g,i,j,n,l,r,q=0;q<f.length;q++){g=null;i=f[q];if("<"==i){j=h("<div/>")[0];n=f[q+1];if("'"==n||'"'==n){l="";for(r=2;f[q+r]!=n;)l+=
|
||||
f[q+r],r++;"H"==l?l=b.sJUIHeader:"F"==l&&(l=b.sJUIFooter);-1!=l.indexOf(".")?(n=l.split("."),j.id=n[0].substr(1,n[0].length-1),j.className=n[1]):"#"==l.charAt(0)?j.id=l.substr(1,l.length-1):j.className=l;q+=r}e.append(j);e=h(j)}else if(">"==i)e=e.parent();else if("l"==i&&d.bPaginate&&d.bLengthChange)g=ob(a);else if("f"==i&&d.bFilter)g=pb(a);else if("r"==i&&d.bProcessing)g=qb(a);else if("t"==i)g=rb(a);else if("i"==i&&d.bInfo)g=sb(a);else if("p"==i&&d.bPaginate)g=tb(a);else if(0!==m.ext.feature.length){j=
|
||||
m.ext.feature;r=0;for(n=j.length;r<n;r++)if(i==j[r].cFeature){g=j[r].fnInit(a);break}}g&&(j=a.aanFeatures,j[i]||(j[i]=[]),j[i].push(g),e.append(g))}c.replaceWith(e);a.nHolding=null}function fa(a,b){var c=h(b).children("tr"),d,e,f,g,i,j,n,l,r,q;a.splice(0,a.length);f=0;for(j=c.length;f<j;f++)a.push([]);f=0;for(j=c.length;f<j;f++){d=c[f];for(e=d.firstChild;e;){if("TD"==e.nodeName.toUpperCase()||"TH"==e.nodeName.toUpperCase()){l=1*e.getAttribute("colspan");r=1*e.getAttribute("rowspan");l=!l||0===l||
|
||||
1===l?1:l;r=!r||0===r||1===r?1:r;g=0;for(i=a[f];i[g];)g++;n=g;q=1===l?!0:!1;for(i=0;i<l;i++)for(g=0;g<r;g++)a[f+g][n+i]={cell:e,unique:q},a[f+g].nTr=d}e=e.nextSibling}}}function qa(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],fa(c,b)));for(var b=0,e=c.length;b<e;b++)for(var f=0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function ra(a,b,c){w(a,"aoServerParams","serverParams",[b]);if(b&&h.isArray(b)){var d={},e=/(.*?)\[\]$/;h.each(b,function(a,b){var c=
|
||||
b.name.match(e);c?(c=c[0],d[c]||(d[c]=[]),d[c].push(b.value)):d[b.name]=b.value});b=d}var f,g=a.ajax,i=a.oInstance,j=function(b){w(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(h.isPlainObject(g)&&g.data){f=g.data;var n=h.isFunction(f)?f(b,a):f,b=h.isFunction(f)&&n?n:h.extend(!0,b,n);delete g.data}n={data:b,success:function(b){var c=b.error||b.sError;c&&J(a,0,c);a.json=b;j(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,c){var d=w(a,null,"xhr",[a,null,a.jqXHR]);-1===h.inArray(!0,d)&&("parsererror"==
|
||||
c?J(a,0,"Invalid JSON response",1):4===b.readyState&&J(a,0,"Ajax error",7));C(a,!1)}};a.oAjaxData=b;w(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(i,a.sAjaxSource,h.map(b,function(a,b){return{name:b,value:a}}),j,a):a.sAjaxSource||"string"===typeof g?a.jqXHR=h.ajax(h.extend(n,{url:g||a.sAjaxSource})):h.isFunction(g)?a.jqXHR=g.call(i,b,j,a):(a.jqXHR=h.ajax(h.extend(n,g)),g.data=f)}function lb(a){return a.bAjaxDataGet?(a.iDraw++,C(a,!0),ra(a,ub(a),function(b){vb(a,b)}),!1):!0}function ub(a){var b=
|
||||
a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,f=a.aoPreSearchCols,g,i=[],j,n,l,r=V(a);g=a._iDisplayStart;j=!1!==d.bPaginate?a._iDisplayLength:-1;var q=function(a,b){i.push({name:a,value:b})};q("sEcho",a.iDraw);q("iColumns",c);q("sColumns",D(b,"sName").join(","));q("iDisplayStart",g);q("iDisplayLength",j);var k={draw:a.iDraw,columns:[],order:[],start:g,length:j,search:{value:e.sSearch,regex:e.bRegex}};for(g=0;g<c;g++)n=b[g],l=f[g],j="function"==typeof n.mData?"function":n.mData,k.columns.push({data:j,
|
||||
name:n.sName,searchable:n.bSearchable,orderable:n.bSortable,search:{value:l.sSearch,regex:l.bRegex}}),q("mDataProp_"+g,j),d.bFilter&&(q("sSearch_"+g,l.sSearch),q("bRegex_"+g,l.bRegex),q("bSearchable_"+g,n.bSearchable)),d.bSort&&q("bSortable_"+g,n.bSortable);d.bFilter&&(q("sSearch",e.sSearch),q("bRegex",e.bRegex));d.bSort&&(h.each(r,function(a,b){k.order.push({column:b.col,dir:b.dir});q("iSortCol_"+a,b.col);q("sSortDir_"+a,b.dir)}),q("iSortingCols",r.length));b=m.ext.legacy.ajax;return null===b?a.sAjaxSource?
|
||||
i:k:b?i:k}function vb(a,b){var c=sa(a,b),d=b.sEcho!==k?b.sEcho:b.draw,e=b.iTotalRecords!==k?b.iTotalRecords:b.recordsTotal,f=b.iTotalDisplayRecords!==k?b.iTotalDisplayRecords:b.recordsFiltered;if(d){if(1*d<a.iDraw)return;a.iDraw=1*d}na(a);a._iRecordsTotal=parseInt(e,10);a._iRecordsDisplay=parseInt(f,10);d=0;for(e=c.length;d<e;d++)L(a,c[d]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;M(a);a._bInitComplete||ta(a,b);a.bAjaxDataGet=!0;C(a,!1)}function sa(a,b){var c=h.isPlainObject(a.ajax)&&
|
||||
a.ajax.dataSrc!==k?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===c?b.aaData||b[c]:""!==c?P(c)(b):b}function pb(a){var b=a.oClasses,c=a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,f=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',i=d.sSearch,i=i.match(/_INPUT_/)?i.replace("_INPUT_",g):i+g,b=h("<div/>",{id:!f.f?c+"_filter":null,"class":b.sFilter}).append(h("<label/>").append(i)),f=function(){var b=!this.value?"":this.value;b!=e.sSearch&&(ha(a,{sSearch:b,bRegex:e.bRegex,bSmart:e.bSmart,
|
||||
bCaseInsensitive:e.bCaseInsensitive}),a._iDisplayStart=0,M(a))},g=null!==a.searchDelay?a.searchDelay:"ssp"===y(a)?400:0,j=h("input",b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).bind("keyup.DT search.DT input.DT paste.DT cut.DT",g?ua(f,g):f).bind("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);h(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{j[0]!==T.activeElement&&j.val(e.sSearch)}catch(d){}});return b[0]}function ha(a,b,c){var d=a.oPreviousSearch,
|
||||
e=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};Ia(a);if("ssp"!=y(a)){wb(a,b.sSearch,c,b.bEscapeRegex!==k?!b.bEscapeRegex:b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<e.length;b++)xb(a,e[b].sSearch,b,e[b].bEscapeRegex!==k?!e[b].bEscapeRegex:e[b].bRegex,e[b].bSmart,e[b].bCaseInsensitive);yb(a)}else f(b);a.bFiltered=!0;w(a,null,"search",[a])}function yb(a){for(var b=m.ext.search,c=a.aiDisplay,d,e,f=0,g=b.length;f<
|
||||
g;f++){for(var i=[],j=0,n=c.length;j<n;j++)e=c[j],d=a.aoData[e],b[f](a,d._aFilterData,e,d._aData,j)&&i.push(e);c.length=0;h.merge(c,i)}}function xb(a,b,c,d,e,f){if(""!==b)for(var g=a.aiDisplay,d=Qa(b,d,e,f),e=g.length-1;0<=e;e--)b=a.aoData[g[e]]._aFilterData[c],d.test(b)||g.splice(e,1)}function wb(a,b,c,d,e,f){var d=Qa(b,d,e,f),e=a.oPreviousSearch.sSearch,f=a.aiDisplayMaster,g;0!==m.ext.search.length&&(c=!0);g=zb(a);if(0>=b.length)a.aiDisplay=f.slice();else{if(g||c||e.length>b.length||0!==b.indexOf(e)||
|
||||
a.bSorted)a.aiDisplay=f.slice();b=a.aiDisplay;for(c=b.length-1;0<=c;c--)d.test(a.aoData[b[c]]._sFilterRow)||b.splice(c,1)}}function Qa(a,b,c,d){a=b?a:va(a);c&&(a="^(?=.*?"+h.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===a.charAt(0))var b=a.match(/^"(.*)"$/),a=b?b[1]:a;return a.replace('"',"")}).join(")(?=.*?")+").*$");return RegExp(a,d?"i":"")}function va(a){return a.replace(Yb,"\\$1")}function zb(a){var b=a.aoColumns,c,d,e,f,g,i,j,h,l=m.ext.type.search;c=!1;d=0;for(f=a.aoData.length;d<
|
||||
f;d++)if(h=a.aoData[d],!h._aFilterData){i=[];e=0;for(g=b.length;e<g;e++)c=b[e],c.bSearchable?(j=B(a,d,e,"filter"),l[c.sType]&&(j=l[c.sType](j)),null===j&&(j=""),"string"!==typeof j&&j.toString&&(j=j.toString())):j="",j.indexOf&&-1!==j.indexOf("&")&&(wa.innerHTML=j,j=Zb?wa.textContent:wa.innerText),j.replace&&(j=j.replace(/[\r\n]/g,"")),i.push(j);h._aFilterData=i;h._sFilterRow=i.join(" ");c=!0}return c}function Ab(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,caseInsensitive:a.bCaseInsensitive}}
|
||||
function Bb(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function sb(a){var b=a.sTableId,c=a.aanFeatures.i,d=h("<div/>",{"class":a.oClasses.sInfo,id:!c?b+"_info":null});c||(a.aoDrawCallback.push({fn:Cb,sName:"information"}),d.attr("role","status").attr("aria-live","polite"),h(a.nTable).attr("aria-describedby",b+"_info"));return d[0]}function Cb(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+1,e=a.fnDisplayEnd(),f=a.fnRecordsTotal(),
|
||||
g=a.fnRecordsDisplay(),i=g?c.sInfo:c.sInfoEmpty;g!==f&&(i+=" "+c.sInfoFiltered);i+=c.sInfoPostFix;i=Db(a,i);c=c.fnInfoCallback;null!==c&&(i=c.call(a.oInstance,a,d,e,f,g,i));h(b).html(i)}}function Db(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,f=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/
|
||||
e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/e)))}function ia(a){var b,c,d=a.iInitDisplayStart,e=a.aoColumns,f;c=a.oFeatures;var g=a.bDeferLoading;if(a.bInitialised){nb(a);kb(a);ga(a,a.aoHeader);ga(a,a.aoFooter);C(a,!0);c.bAutoWidth&&Ha(a);b=0;for(c=e.length;b<c;b++)f=e[b],f.sWidth&&(f.nTh.style.width=u(f.sWidth));w(a,null,"preInit",[a]);R(a);e=y(a);if("ssp"!=e||g)"ajax"==e?ra(a,[],function(c){var f=sa(a,c);for(b=0;b<f.length;b++)L(a,f[b]);a.iInitDisplayStart=d;R(a);C(a,!1);ta(a,c)},a):(C(a,!1),
|
||||
ta(a))}else setTimeout(function(){ia(a)},200)}function ta(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&Y(a);w(a,"aoInitComplete","init",[a,b])}function Ra(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Sa(a);w(a,null,"length",[a,c])}function ob(a){for(var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=h.isArray(d[0]),f=e?d[0]:d,d=e?d[1]:d,e=h("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect}),g=0,i=f.length;g<i;g++)e[0][g]=new Option(d[g],f[g]);var j=h("<div><label/></div>").addClass(b.sLength);
|
||||
a.aanFeatures.l||(j[0].id=c+"_length");j.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));h("select",j).val(a._iDisplayLength).bind("change.DT",function(){Ra(a,h(this).val());M(a)});h(a.nTable).bind("length.dt.DT",function(b,c,d){a===c&&h("select",j).val(d)});return j[0]}function tb(a){var b=a.sPaginationType,c=m.ext.pager[b],d="function"===typeof c,e=function(a){M(a)},b=h("<div/>").addClass(a.oClasses.sPaging+b)[0],f=a.aanFeatures;d||c.fnInit(a,b,e);f.p||(b.id=a.sTableId+
|
||||
"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,j=a._iDisplayLength,h=a.fnRecordsDisplay(),l=-1===j,b=l?0:Math.ceil(b/j),j=l?1:Math.ceil(h/j),h=c(b,j),k,l=0;for(k=f.p.length;l<k;l++)Pa(a,"pageButton")(a,f.p[l],l,h,b,j)}else c.fnUpdate(a,e)},sName:"pagination"}));return b}function Ta(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===e?d=0:"number"===typeof b?(d=b*e,d>f&&(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==
|
||||
b?d+e<f&&(d+=e):"last"==b?d=Math.floor((f-1)/e)*e:J(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(w(a,null,"page",[a]),c&&M(a));return b}function qb(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function C(a,b){a.oFeatures.bProcessing&&h(a.aanFeatures.r).css("display",b?"block":"none");w(a,null,"processing",[a,b])}function rb(a){var b=h(a.nTable);b.attr("role",
|
||||
"grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,f=a.oClasses,g=b.children("caption"),i=g.length?g[0]._captionSide:null,j=h(b[0].cloneNode(!1)),n=h(b[0].cloneNode(!1)),l=b.children("tfoot");c.sX&&"100%"===b.attr("width")&&b.removeAttr("width");l.length||(l=null);j=h("<div/>",{"class":f.sScrollWrapper}).append(h("<div/>",{"class":f.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?!d?null:u(d):"100%"}).append(h("<div/>",{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box",
|
||||
width:c.sXInner||"100%"}).append(j.removeAttr("id").css("margin-left",0).append("top"===i?g:null).append(b.children("thead"))))).append(h("<div/>",{"class":f.sScrollBody}).css({position:"relative",overflow:"auto",width:!d?null:u(d)}).append(b));l&&j.append(h("<div/>",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:d?!d?null:u(d):"100%"}).append(h("<div/>",{"class":f.sScrollFootInner}).append(n.removeAttr("id").css("margin-left",0).append("bottom"===i?g:null).append(b.children("tfoot")))));
|
||||
var b=j.children(),k=b[0],f=b[1],q=l?b[2]:null;if(d)h(f).on("scroll.DT",function(){var a=this.scrollLeft;k.scrollLeft=a;l&&(q.scrollLeft=a)});h(f).css(e&&c.bCollapse?"max-height":"height",e);a.nScrollHead=k;a.nScrollBody=f;a.nScrollFoot=q;a.aoDrawCallback.push({fn:Z,sName:"scrolling"});return j[0]}function Z(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY,b=b.iBarWidth,f=h(a.nScrollHead),g=f[0].style,i=f.children("div"),j=i[0].style,n=i.children("table"),i=a.nScrollBody,l=h(i),k=i.style,q=h(a.nScrollFoot).children("div"),
|
||||
m=q.children("table"),o=h(a.nTHead),E=h(a.nTable),p=E[0],t=p.style,N=a.nTFoot?h(a.nTFoot):null,Eb=a.oBrowser,w=Eb.bScrollOversize,s,v,O,x,y=[],z=[],A=[],B,C=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};E.children("thead, tfoot").remove();x=o.clone().prependTo(E);o=o.find("tr");v=x.find("tr");x.find("th, td").removeAttr("tabindex");N&&(O=N.clone().prependTo(E),s=N.find("tr"),O=O.find("tr"));c||(k.width="100%",f[0].style.width="100%");
|
||||
h.each(qa(a,x),function(b,c){B=$(a,b);c.style.width=a.aoColumns[B].sWidth});N&&H(function(a){a.style.width=""},O);f=E.outerWidth();if(""===c){t.width="100%";if(w&&(E.find("tbody").height()>i.offsetHeight||"scroll"==l.css("overflow-y")))t.width=u(E.outerWidth()-b);f=E.outerWidth()}else""!==d&&(t.width=u(d),f=E.outerWidth());H(C,v);H(function(a){A.push(a.innerHTML);y.push(u(h(a).css("width")))},v);H(function(a,b){a.style.width=y[b]},o);h(v).height(0);N&&(H(C,O),H(function(a){z.push(u(h(a).css("width")))},
|
||||
O),H(function(a,b){a.style.width=z[b]},s),h(O).height(0));H(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+A[b]+"</div>";a.style.width=y[b]},v);N&&H(function(a,b){a.innerHTML="";a.style.width=z[b]},O);if(E.outerWidth()<f){s=i.scrollHeight>i.offsetHeight||"scroll"==l.css("overflow-y")?f+b:f;if(w&&(i.scrollHeight>i.offsetHeight||"scroll"==l.css("overflow-y")))t.width=u(s-b);(""===c||""!==d)&&J(a,1,"Possible column misalignment",6)}else s="100%";k.width=
|
||||
u(s);g.width=u(s);N&&(a.nScrollFoot.style.width=u(s));!e&&w&&(k.height=u(p.offsetHeight+b));c=E.outerWidth();n[0].style.width=u(c);j.width=u(c);d=E.height()>i.clientHeight||"scroll"==l.css("overflow-y");e="padding"+(Eb.bScrollbarLeft?"Left":"Right");j[e]=d?b+"px":"0px";N&&(m[0].style.width=u(c),q[0].style.width=u(c),q[0].style[e]=d?b+"px":"0px");l.scroll();if((a.bSorted||a.bFiltered)&&!a._drawHold)i.scrollTop=0}function H(a,b,c){for(var d=0,e=0,f=b.length,g,i;e<f;){g=b[e].firstChild;for(i=c?c[e].firstChild:
|
||||
null;g;)1===g.nodeType&&(c?a(g,i,d):a(g,d),d++),g=g.nextSibling,i=c?i.nextSibling:null;e++}}function Ha(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,e=d.sY,f=d.sX,g=d.sXInner,i=c.length,j=aa(a,"bVisible"),n=h("th",a.nTHead),l=b.getAttribute("width"),k=b.parentNode,q=!1,m,o,p;p=a.oBrowser;d=p.bScrollOversize;(m=b.style.width)&&-1!==m.indexOf("%")&&(l=m);for(m=0;m<j.length;m++)o=c[j[m]],null!==o.sWidth&&(o.sWidth=Fb(o.sWidthOrig,k),q=!0);if(d||!q&&!f&&!e&&i==ca(a)&&i==n.length)for(m=0;m<i;m++){if(j=
|
||||
$(a,m))c[j].sWidth=u(n.eq(m).width())}else{i=h(b).clone().css("visibility","hidden").removeAttr("id");i.find("tbody tr").remove();var t=h("<tr/>").appendTo(i.find("tbody"));i.find("thead, tfoot").remove();i.append(h(a.nTHead).clone()).append(h(a.nTFoot).clone());i.find("tfoot th, tfoot td").css("width","");n=qa(a,i.find("thead")[0]);for(m=0;m<j.length;m++)o=c[j[m]],n[m].style.width=null!==o.sWidthOrig&&""!==o.sWidthOrig?u(o.sWidthOrig):"";if(a.aoData.length)for(m=0;m<j.length;m++)q=j[m],o=c[q],h(Gb(a,
|
||||
q)).clone(!1).append(o.sContentPadding).appendTo(t);q=h("<div/>").css(f||e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(i).appendTo(k);f&&g?i.width(g):f?(i.css("width","auto"),i.width()<k.clientWidth&&i.width(k.clientWidth)):e?i.width(k.clientWidth):l&&i.width(l);if(f){for(m=g=0;m<j.length;m++)o=c[j[m]],e=p.bBounding?n[m].getBoundingClientRect().width:h(n[m]).outerWidth(),g+=null===o.sWidthOrig?e:parseInt(o.sWidth,10)+e-h(n[m]).width();i.width(u(g));b.style.width=
|
||||
u(g)}for(m=0;m<j.length;m++)if(o=c[j[m]],p=h(n[m]).width())o.sWidth=u(p);b.style.width=u(i.css("width"));q.remove()}l&&(b.style.width=u(l));if((l||f)&&!a._reszEvt)b=function(){h(Fa).bind("resize.DT-"+a.sInstance,ua(function(){Y(a)}))},d?setTimeout(b,1E3):b(),a._reszEvt=!0}function ua(a,b){var c=b!==k?b:200,d,e;return function(){var b=this,g=+new Date,i=arguments;d&&g<d+c?(clearTimeout(e),e=setTimeout(function(){d=k;a.apply(b,i)},c)):(d=g,a.apply(b,i))}}function Fb(a,b){if(!a)return 0;var c=h("<div/>").css("width",
|
||||
u(a)).appendTo(b||T.body),d=c[0].offsetWidth;c.remove();return d}function Gb(a,b){var c=Hb(a,b);if(0>c)return null;var d=a.aoData[c];return!d.nTr?h("<td/>").html(B(a,c,b,"display"))[0]:d.anCells[b]}function Hb(a,b){for(var c,d=-1,e=-1,f=0,g=a.aoData.length;f<g;f++)c=B(a,f,b,"display")+"",c=c.replace($b,""),c.length>d&&(d=c.length,e=f);return e}function u(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function V(a){var b,c,d=[],e=a.aoColumns,f,g,i,j;b=a.aaSortingFixed;
|
||||
c=h.isPlainObject(b);var n=[];f=function(a){a.length&&!h.isArray(a[0])?n.push(a):h.merge(n,a)};h.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;a<n.length;a++){j=n[a][0];f=e[j].aDataSort;b=0;for(c=f.length;b<c;b++)g=f[b],i=e[g].sType||"string",n[a]._idx===k&&(n[a]._idx=h.inArray(n[a][1],e[g].asSorting)),d.push({src:j,col:g,dir:n[a][1],index:n[a]._idx,type:i,formatter:m.ext.type.order[i+"-pre"]})}return d}function mb(a){var b,c,d=[],e=m.ext.type.order,f=a.aoData,g=
|
||||
0,i,j=a.aiDisplayMaster,h;Ia(a);h=V(a);b=0;for(c=h.length;b<c;b++)i=h[b],i.formatter&&g++,Ib(a,i.col);if("ssp"!=y(a)&&0!==h.length){b=0;for(c=j.length;b<c;b++)d[j[b]]=b;g===h.length?j.sort(function(a,b){var c,e,g,i,j=h.length,k=f[a]._aSortData,m=f[b]._aSortData;for(g=0;g<j;g++)if(i=h[g],c=k[i.col],e=m[i.col],c=c<e?-1:c>e?1:0,0!==c)return"asc"===i.dir?c:-c;c=d[a];e=d[b];return c<e?-1:c>e?1:0}):j.sort(function(a,b){var c,g,i,j,k=h.length,m=f[a]._aSortData,p=f[b]._aSortData;for(i=0;i<k;i++)if(j=h[i],
|
||||
c=m[j.col],g=p[j.col],j=e[j.type+"-"+j.dir]||e["string-"+j.dir],c=j(c,g),0!==c)return c;c=d[a];g=d[b];return c<g?-1:c>g?1:0})}a.bSorted=!0}function Jb(a){for(var b,c,d=a.aoColumns,e=V(a),a=a.oLanguage.oAria,f=0,g=d.length;f<g;f++){c=d[f];var i=c.asSorting;b=c.sTitle.replace(/<.*?>/g,"");var j=c.nTh;j.removeAttribute("aria-sort");c.bSortable&&(0<e.length&&e[0].col==f?(j.setAttribute("aria-sort","asc"==e[0].dir?"ascending":"descending"),c=i[e[0].index+1]||i[0]):c=i[0],b+="asc"===c?a.sSortAscending:
|
||||
a.sSortDescending);j.setAttribute("aria-label",b)}}function Ua(a,b,c,d){var e=a.aaSorting,f=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===k&&(c=h.inArray(a[1],f));return c+1<f.length?c+1:b?null:0};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=h.inArray(b,D(e,"0")),-1!==c?(b=g(e[c],!0),null===b&&1===e.length&&(b=0),null===b?e.splice(c,1):(e[c][1]=f[b],e[c]._idx=b)):(e.push([b,f[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=g(e[0]),e.length=1,e[0][1]=f[b],
|
||||
e[0]._idx=b):(e.length=0,e.push([b,f[0]]),e[0]._idx=0);R(a);"function"==typeof d&&d(a)}function Oa(a,b,c,d){var e=a.aoColumns[c];Va(b,{},function(b){!1!==e.bSortable&&(a.oFeatures.bProcessing?(C(a,!0),setTimeout(function(){Ua(a,c,b.shiftKey,d);"ssp"!==y(a)&&C(a,!1)},0)):Ua(a,c,b.shiftKey,d))})}function xa(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=V(a),e=a.oFeatures,f,g;if(e.bSort&&e.bSortClasses){e=0;for(f=b.length;e<f;e++)g=b[e].src,h(D(a.aoData,"anCells",g)).removeClass(c+(2>e?e+1:3));e=0;
|
||||
for(f=d.length;e<f;e++)g=d[e].src,h(D(a.aoData,"anCells",g)).addClass(c+(2>e?e+1:3))}a.aLastSort=d}function Ib(a,b){var c=a.aoColumns[b],d=m.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,ba(a,b)));for(var f,g=m.ext.type.order[c.sType+"-pre"],i=0,h=a.aoData.length;i<h;i++)if(c=a.aoData[i],c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)f=d?e[i]:B(a,i,b,"sort"),c._aSortData[b]=g?g(f):f}function ya(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,
|
||||
length:a._iDisplayLength,order:h.extend(!0,[],a.aaSorting),search:Ab(a.oPreviousSearch),columns:h.map(a.aoColumns,function(b,d){return{visible:b.bVisible,search:Ab(a.aoPreSearchCols[d])}})};w(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a,b)}}function Kb(a){var b,c,d=a.aoColumns;if(a.oFeatures.bStateSave){var e=a.fnStateLoadCallback.call(a.oInstance,a);if(e&&e.time&&(b=w(a,"aoStateLoadParams","stateLoadParams",[a,e]),-1===h.inArray(!1,b)&&(b=
|
||||
a.iStateDuration,!(0<b&&e.time<+new Date-1E3*b)&&d.length===e.columns.length))){a.oLoadedState=h.extend(!0,{},e);e.start!==k&&(a._iDisplayStart=e.start,a.iInitDisplayStart=e.start);e.length!==k&&(a._iDisplayLength=e.length);e.order!==k&&(a.aaSorting=[],h.each(e.order,function(b,c){a.aaSorting.push(c[0]>=d.length?[0,c[1]]:c)}));e.search!==k&&h.extend(a.oPreviousSearch,Bb(e.search));b=0;for(c=e.columns.length;b<c;b++){var f=e.columns[b];f.visible!==k&&(d[b].bVisible=f.visible);f.search!==k&&h.extend(a.aoPreSearchCols[b],
|
||||
Bb(f.search))}w(a,"aoStateLoaded","stateLoaded",[a,e])}}}function za(a){var b=m.settings,a=h.inArray(a,D(b,"nTable"));return-1!==a?b[a]:null}function J(a,b,c,d){c="DataTables warning: "+(a?"table id="+a.sTableId+" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+d);if(b)Fa.console&&console.log&&console.log(c);else if(b=m.ext,b=b.sErrMode||b.errMode,a&&w(a,null,"error",[a,d,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==typeof b&&
|
||||
b(a,d,c)}}function F(a,b,c,d){h.isArray(c)?h.each(c,function(c,d){h.isArray(d)?F(a,b,d[0],d[1]):F(a,b,d)}):(d===k&&(d=c),b[c]!==k&&(a[d]=b[c]))}function Lb(a,b,c){var d,e;for(e in b)b.hasOwnProperty(e)&&(d=b[e],h.isPlainObject(d)?(h.isPlainObject(a[e])||(a[e]={}),h.extend(!0,a[e],d)):a[e]=c&&"data"!==e&&"aaData"!==e&&h.isArray(d)?d.slice():d);return a}function Va(a,b,c){h(a).bind("click.DT",b,function(b){a.blur();c(b)}).bind("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).bind("selectstart.DT",
|
||||
function(){return!1})}function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function w(a,b,c,d){var e=[];b&&(e=h.map(a[b].slice().reverse(),function(b){return b.fn.apply(a.oInstance,d)}));null!==c&&(b=h.Event(c+".dt"),h(a.nTable).trigger(b,d),e.push(b.result));return e}function Sa(a){var b=a._iDisplayStart,c=a.fnDisplayEnd(),d=a._iDisplayLength;b>=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function Pa(a,b){var c=a.renderer,d=m.ext.renderer[b];return h.isPlainObject(c)&&c[b]?d[c[b]]||d._:"string"===
|
||||
typeof c?d[c]||d._:d._}function y(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function Aa(a,b){var c=[],c=Mb.numbers_length,d=Math.floor(c/2);b<=c?c=W(0,b):a<=d?(c=W(0,c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-d?c=W(b-(c-2),b):(c=W(a-d+2,a+d-1),c.push("ellipsis"),c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,0,0));c.DT_el="span";return c}function cb(a){h.each({num:function(b){return Ba(b,a)},"num-fmt":function(b){return Ba(b,a,Wa)},"html-num":function(b){return Ba(b,
|
||||
a,Ca)},"html-num-fmt":function(b){return Ba(b,a,Ca,Wa)}},function(b,c){v.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(v.type.search[b+a]=v.type.search.html)})}function Nb(a){return function(){var b=[za(this[m.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return m.ext.internal[a].apply(this,b)}}var m,v,t,p,s,Xa={},Ob=/[\r\n]/g,Ca=/<.*?>/g,ac=/^[\w\+\-]/,bc=/[\w\+\-]$/,Yb=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),Wa=/[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi,
|
||||
K=function(a){return!a||!0===a||"-"===a?!0:!1},Pb=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Qb=function(a,b){Xa[b]||(Xa[b]=RegExp(va(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace(Xa[b],"."):a},Ya=function(a,b,c){var d="string"===typeof a;if(K(a))return!0;b&&d&&(a=Qb(a,b));c&&d&&(a=a.replace(Wa,""));return!isNaN(parseFloat(a))&&isFinite(a)},Rb=function(a,b,c){return K(a)?!0:!(K(a)||"string"===typeof a)?null:Ya(a.replace(Ca,""),b,c)?!0:null},D=function(a,
|
||||
b,c){var d=[],e=0,f=a.length;if(c!==k)for(;e<f;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<f;e++)a[e]&&d.push(a[e][b]);return d},ja=function(a,b,c,d){var e=[],f=0,g=b.length;if(d!==k)for(;f<g;f++)a[b[f]][c]&&e.push(a[b[f]][c][d]);else for(;f<g;f++)e.push(a[b[f]][c]);return e},W=function(a,b){var c=[],d;b===k?(b=0,d=a):(d=b,b=a);for(var e=b;e<d;e++)c.push(e);return c},Sb=function(a){for(var b=[],c=0,d=a.length;c<d;c++)a[c]&&b.push(a[c]);return b},pa=function(a){var b=[],c,d,e=a.length,f,g=0;
|
||||
d=0;a:for(;d<e;d++){c=a[d];for(f=0;f<g;f++)if(b[f]===c)continue a;b.push(c);g++}return b},A=function(a,b,c){a[b]!==k&&(a[c]=a[b])},da=/\[.*?\]$/,U=/\(\)$/,wa=h("<div>")[0],Zb=wa.textContent!==k,$b=/<.*?>/g;m=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new t(za(this[v.iApiIndex])):new t(this)};this.fnAddData=function(a,b){var c=this.api(!0),d=h.isArray(a)&&(h.isArray(a[0])||h.isPlainObject(a[0]))?
|
||||
c.rows.add(a):c.row.add(a);(b===k||b)&&c.draw();return d.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===k||a?b.draw(!1):(""!==d.sX||""!==d.sY)&&Z(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===k||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0),a=d.rows(a),e=a.settings()[0],h=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,h);
|
||||
(c===k||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};this.fnFilter=function(a,b,c,d,e,h){e=this.api(!0);null===b||b===k?e.search(a,c,d,h):e.column(b).search(a,c,d,h);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==k){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==k||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);
|
||||
return a!==k?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===k||b)&&c.draw(!1)};this.fnSetColumnVis=
|
||||
function(a,b,c){a=this.api(!0).column(a).visible(b);(c===k||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return za(this[v.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===k||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===k||e)&&h.columns.adjust();(d===k||d)&&h.draw();return 0};this.fnVersionCheck=v.fnVersionCheck;var b=this,c=a===k,d=this.length;
|
||||
c&&(a={});this.oApi=this.internal=v.internal;for(var e in m.ext.internal)e&&(this[e]=Nb(e));this.each(function(){var e={},e=1<d?Lb(e,a,!0):a,g=0,i,j=this.getAttribute("id"),n=!1,l=m.defaults,r=h(this);if("table"!=this.nodeName.toLowerCase())J(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{db(l);eb(l.column);I(l,l,!0);I(l.column,l.column,!0);I(l,h.extend(e,r.data()));var q=m.settings,g=0;for(i=q.length;g<i;g++){var p=q[g];if(p.nTable==this||p.nTHead.parentNode==this||p.nTFoot&&
|
||||
p.nTFoot.parentNode==this){g=e.bRetrieve!==k?e.bRetrieve:l.bRetrieve;if(c||g)return p.oInstance;if(e.bDestroy!==k?e.bDestroy:l.bDestroy){p.oInstance.fnDestroy();break}else{J(p,0,"Cannot reinitialise DataTable",3);return}}if(p.sTableId==this.id){q.splice(g,1);break}}if(null===j||""===j)this.id=j="DataTables_Table_"+m.ext._unique++;var o=h.extend(!0,{},m.models.oSettings,{sDestroyWidth:r[0].style.width,sInstance:j,sTableId:j});o.nTable=this;o.oApi=b.internal;o.oInit=e;q.push(o);o.oInstance=1===b.length?
|
||||
b:r.dataTable();db(e);e.oLanguage&&S(e.oLanguage);e.aLengthMenu&&!e.iDisplayLength&&(e.iDisplayLength=h.isArray(e.aLengthMenu[0])?e.aLengthMenu[0][0]:e.aLengthMenu[0]);e=Lb(h.extend(!0,{},l),e);F(o.oFeatures,e,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));F(o,e,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp",
|
||||
"iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer","searchDelay","rowId",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols","aoPreSearchCols"],["iDisplayLength","_iDisplayLength"],["bJQueryUI","bJUI"]]);F(o.oScroll,e,[["sScrollX","sX"],["sScrollXInner","sXInner"],["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);F(o.oLanguage,e,"fnInfoCallback");z(o,"aoDrawCallback",e.fnDrawCallback,"user");z(o,"aoServerParams",
|
||||
e.fnServerParams,"user");z(o,"aoStateSaveParams",e.fnStateSaveParams,"user");z(o,"aoStateLoadParams",e.fnStateLoadParams,"user");z(o,"aoStateLoaded",e.fnStateLoaded,"user");z(o,"aoRowCallback",e.fnRowCallback,"user");z(o,"aoRowCreatedCallback",e.fnCreatedRow,"user");z(o,"aoHeaderCallback",e.fnHeaderCallback,"user");z(o,"aoFooterCallback",e.fnFooterCallback,"user");z(o,"aoInitComplete",e.fnInitComplete,"user");z(o,"aoPreDrawCallback",e.fnPreDrawCallback,"user");o.rowIdFn=P(e.rowId);fb(o);j=o.oClasses;
|
||||
e.bJQueryUI?(h.extend(j,m.ext.oJUIClasses,e.oClasses),e.sDom===l.sDom&&"lfrtip"===l.sDom&&(o.sDom='<"H"lfr>t<"F"ip>'),o.renderer)?h.isPlainObject(o.renderer)&&!o.renderer.header&&(o.renderer.header="jqueryui"):o.renderer="jqueryui":h.extend(j,m.ext.classes,e.oClasses);r.addClass(j.sTable);o.iInitDisplayStart===k&&(o.iInitDisplayStart=e.iDisplayStart,o._iDisplayStart=e.iDisplayStart);null!==e.iDeferLoading&&(o.bDeferLoading=!0,g=h.isArray(e.iDeferLoading),o._iRecordsDisplay=g?e.iDeferLoading[0]:e.iDeferLoading,
|
||||
o._iRecordsTotal=g?e.iDeferLoading[1]:e.iDeferLoading);var t=o.oLanguage;h.extend(!0,t,e.oLanguage);""!==t.sUrl&&(h.ajax({dataType:"json",url:t.sUrl,success:function(a){S(a);I(l.oLanguage,a);h.extend(true,t,a);ia(o)},error:function(){ia(o)}}),n=!0);null===e.asStripeClasses&&(o.asStripeClasses=[j.sStripeOdd,j.sStripeEven]);var g=o.asStripeClasses,s=r.children("tbody").find("tr").eq(0);-1!==h.inArray(!0,h.map(g,function(a){return s.hasClass(a)}))&&(h("tbody tr",this).removeClass(g.join(" ")),o.asDestroyStripes=
|
||||
g.slice());q=[];g=this.getElementsByTagName("thead");0!==g.length&&(fa(o.aoHeader,g[0]),q=qa(o));if(null===e.aoColumns){p=[];g=0;for(i=q.length;g<i;g++)p.push(null)}else p=e.aoColumns;g=0;for(i=p.length;g<i;g++)Ga(o,q?q[g]:null);hb(o,e.aoColumnDefs,p,function(a,b){la(o,a,b)});if(s.length){var u=function(a,b){return a.getAttribute("data-"+b)!==null?b:null};h(s[0]).children("th, td").each(function(a,b){var c=o.aoColumns[a];if(c.mData===a){var d=u(b,"sort")||u(b,"order"),e=u(b,"filter")||u(b,"search");
|
||||
if(d!==null||e!==null){c.mData={_:a+".display",sort:d!==null?a+".@data-"+d:k,type:d!==null?a+".@data-"+d:k,filter:e!==null?a+".@data-"+e:k};la(o,a)}}})}var v=o.oFeatures;e.bStateSave&&(v.bStateSave=!0,Kb(o,e),z(o,"aoDrawCallback",ya,"state_save"));if(e.aaSorting===k){q=o.aaSorting;g=0;for(i=q.length;g<i;g++)q[g][1]=o.aoColumns[g].asSorting[0]}xa(o);v.bSort&&z(o,"aoDrawCallback",function(){if(o.bSorted){var a=V(o),b={};h.each(a,function(a,c){b[c.src]=c.dir});w(o,null,"order",[o,a,b]);Jb(o)}});z(o,
|
||||
"aoDrawCallback",function(){(o.bSorted||y(o)==="ssp"||v.bDeferRender)&&xa(o)},"sc");g=r.children("caption").each(function(){this._captionSide=r.css("caption-side")});i=r.children("thead");0===i.length&&(i=h("<thead/>").appendTo(this));o.nTHead=i[0];i=r.children("tbody");0===i.length&&(i=h("<tbody/>").appendTo(this));o.nTBody=i[0];i=r.children("tfoot");if(0===i.length&&0<g.length&&(""!==o.oScroll.sX||""!==o.oScroll.sY))i=h("<tfoot/>").appendTo(this);0===i.length||0===i.children().length?r.addClass(j.sNoFooter):
|
||||
0<i.length&&(o.nTFoot=i[0],fa(o.aoFooter,o.nTFoot));if(e.aaData)for(g=0;g<e.aaData.length;g++)L(o,e.aaData[g]);else(o.bDeferLoading||"dom"==y(o))&&ma(o,h(o.nTBody).children("tr"));o.aiDisplay=o.aiDisplayMaster.slice();o.bInitialised=!0;!1===n&&ia(o)}});b=null;return this};var Tb=[],x=Array.prototype,cc=function(a){var b,c,d=m.settings,e=h.map(d,function(a){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase())return b=h.inArray(a,e),-1!==b?[d[b]]:
|
||||
null;if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?c=h(a):a instanceof h&&(c=a)}else return[];if(c)return c.map(function(){b=h.inArray(this,e);return-1!==b?d[b]:null}).toArray()};t=function(a,b){if(!(this instanceof t))return new t(a,b);var c=[],d=function(a){(a=cc(a))&&(c=c.concat(a))};if(h.isArray(a))for(var e=0,f=a.length;e<f;e++)d(a[e]);else d(a);this.context=pa(c);b&&h.merge(this,b);this.selector={rows:null,cols:null,opts:null};t.extend(this,this,Tb)};
|
||||
m.Api=t;h.extend(t.prototype,{any:function(){return 0!==this.count()},concat:x.concat,context:[],count:function(){return this.flatten().length},each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new t(b[a],this[a]):null},filter:function(a){var b=[];if(x.filter)b=x.filter.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new t(this.context,b)},flatten:function(){var a=
|
||||
[];return new t(this.context,a.concat.apply(a,this.toArray()))},join:x.join,indexOf:x.indexOf||function(a,b){for(var c=b||0,d=this.length;c<d;c++)if(this[c]===a)return c;return-1},iterator:function(a,b,c,d){var e=[],f,g,h,j,n,l=this.context,m,q,p=this.selector;"string"===typeof a&&(d=c,c=b,b=a,a=!1);g=0;for(h=l.length;g<h;g++){var o=new t(l[g]);if("table"===b)f=c.call(o,l[g],g),f!==k&&e.push(f);else if("columns"===b||"rows"===b)f=c.call(o,l[g],this[g],g),f!==k&&e.push(f);else if("column"===b||"column-rows"===
|
||||
b||"row"===b||"cell"===b){q=this[g];"column-rows"===b&&(m=Da(l[g],p.opts));j=0;for(n=q.length;j<n;j++)f=q[j],f="cell"===b?c.call(o,l[g],f.row,f.column,g,j):c.call(o,l[g],f,g,j,m),f!==k&&e.push(f)}}return e.length||d?(a=new t(l,a?e.concat.apply([],e):e),b=a.selector,b.rows=p.rows,b.cols=p.cols,b.opts=p.opts,a):this},lastIndexOf:x.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(x.map)b=x.map.call(this,a,this);else for(var c=
|
||||
0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new t(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},pop:x.pop,push:x.push,reduce:x.reduce||function(a,b){return gb(this,a,b,0,this.length,1)},reduceRight:x.reduceRight||function(a,b){return gb(this,a,b,this.length-1,-1,-1)},reverse:x.reverse,selector:null,shift:x.shift,sort:x.sort,splice:x.splice,toArray:function(){return x.slice.call(this)},to$:function(){return h(this)},toJQuery:function(){return h(this)},
|
||||
unique:function(){return new t(this.context,pa(this))},unshift:x.unshift});t.extend=function(a,b,c){if(c.length&&b&&(b instanceof t||b.__dt_wrapper)){var d,e,f,g=function(a,b,c){return function(){var d=b.apply(a,arguments);t.extend(d,d,c.methodExt);return d}};d=0;for(e=c.length;d<e;d++)f=c[d],b[f.name]="function"===typeof f.val?g(a,f.val,f):h.isPlainObject(f.val)?{}:f.val,b[f.name].__dt_wrapper=!0,t.extend(a,b[f.name],f.propExt)}};t.register=p=function(a,b){if(h.isArray(a))for(var c=0,d=a.length;c<
|
||||
d;c++)t.register(a[c],b);else for(var e=a.split("."),f=Tb,g,i,c=0,d=e.length;c<d;c++){g=(i=-1!==e[c].indexOf("()"))?e[c].replace("()",""):e[c];var j;a:{j=0;for(var n=f.length;j<n;j++)if(f[j].name===g){j=f[j];break a}j=null}j||(j={name:g,val:{},methodExt:[],propExt:[]},f.push(j));c===d-1?j.val=b:f=i?j.methodExt:j.propExt}};t.registerPlural=s=function(a,b,c){t.register(a,c);t.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof t?a.length?h.isArray(a[0])?new t(a.context,
|
||||
a[0]):a[0]:k:a})};p("tables()",function(a){var b;if(a){b=t;var c=this.context;if("number"===typeof a)a=[c[a]];else var d=h.map(c,function(a){return a.nTable}),a=h(d).filter(a).map(function(){var a=h.inArray(this,d);return c[a]}).toArray();b=new b(a)}else b=this;return b});p("table()",function(a){var a=this.tables(a),b=a.context;return b.length?new t(b[0]):a});s("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});s("tables().body()","table().body()",
|
||||
function(){return this.iterator("table",function(a){return a.nTBody},1)});s("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});s("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});s("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});p("draw()",function(a){return this.iterator("table",function(b){"page"===
|
||||
a?M(b):("string"===typeof a&&(a="full-hold"===a?!1:!0),R(b,!1===a))})});p("page()",function(a){return a===k?this.page.info().page:this.iterator("table",function(b){Ta(b,a)})});p("page.info()",function(){if(0===this.context.length)return k;var a=this.context[0],b=a._iDisplayStart,c=a._iDisplayLength,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),pages:e?1:Math.ceil(d/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d,serverSide:"ssp"===y(a)}});
|
||||
p("page.len()",function(a){return a===k?0!==this.context.length?this.context[0]._iDisplayLength:k:this.iterator("table",function(b){Ra(b,a)})});var Ub=function(a,b,c){if(c){var d=new t(a);d.one("draw",function(){c(d.ajax.json())})}if("ssp"==y(a))R(a,b);else{C(a,!0);var e=a.jqXHR;e&&4!==e.readyState&&e.abort();ra(a,[],function(c){na(a);for(var c=sa(a,c),d=0,e=c.length;d<e;d++)L(a,c[d]);R(a,b);C(a,!1)})}};p("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});p("ajax.params()",
|
||||
function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});p("ajax.reload()",function(a,b){return this.iterator("table",function(c){Ub(c,!1===b,a)})});p("ajax.url()",function(a){var b=this.context;if(a===k){if(0===b.length)return k;b=b[0];return b.ajax?h.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){h.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});p("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Ub(c,!1===b,a)})});
|
||||
var Za=function(a,b,c,d,e){var f=[],g,i,j,n,l,m;j=typeof b;if(!b||"string"===j||"function"===j||b.length===k)b=[b];j=0;for(n=b.length;j<n;j++){i=b[j]&&b[j].split?b[j].split(","):[b[j]];l=0;for(m=i.length;l<m;l++)(g=c("string"===typeof i[l]?h.trim(i[l]):i[l]))&&g.length&&(f=f.concat(g))}a=v.selector[a];if(a.length){j=0;for(n=a.length;j<n;j++)f=a[j](d,e,f)}return pa(f)},$a=function(a){a||(a={});a.filter&&a.search===k&&(a.search=a.filter);return h.extend({search:"none",order:"current",page:"all"},a)},
|
||||
ab=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a},Da=function(a,b){var c,d,e,f=[],g=a.aiDisplay;c=a.aiDisplayMaster;var i=b.search;d=b.order;e=b.page;if("ssp"==y(a))return"removed"===i?[]:W(0,c.length);if("current"==e){c=a._iDisplayStart;for(d=a.fnDisplayEnd();c<d;c++)f.push(g[c])}else if("current"==d||"applied"==d)f="none"==i?c.slice():"applied"==i?g.slice():h.map(c,function(a){return-1===h.inArray(a,
|
||||
g)?a:null});else if("index"==d||"original"==d){c=0;for(d=a.aoData.length;c<d;c++)"none"==i?f.push(c):(e=h.inArray(c,g),(-1===e&&"removed"==i||0<=e&&"applied"==i)&&f.push(c))}return f};p("rows()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=$a(b),c=this.iterator("table",function(c){var e=b;return Za("row",a,function(a){var b=Pb(a);if(b!==null&&!e)return[b];var i=Da(c,e);if(b!==null&&h.inArray(b,i)!==-1)return[b];if(!a)return i;if(typeof a==="function")return h.map(i,function(b){var e=
|
||||
c.aoData[b];return a(b,e._aData,e.nTr)?b:null});b=Sb(ja(c.aoData,i,"nTr"));if(a.nodeName&&h.inArray(a,b)!==-1)return[a._DT_RowIndex];if(typeof a==="string"&&a.charAt(0)==="#"){i=c.aIds[a.replace(/^#/,"")];if(i!==k)return[i.idx]}return h(b).filter(a).map(function(){return this._DT_RowIndex}).toArray()},c,e)},1);c.selector.rows=a;c.selector.opts=b;return c});p("rows().nodes()",function(){return this.iterator("row",function(a,b){return a.aoData[b].nTr||k},1)});p("rows().data()",function(){return this.iterator(!0,
|
||||
"rows",function(a,b){return ja(a.aoData,b,"_aData")},1)});s("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){var d=b.aoData[c];return"search"===a?d._aFilterData:d._aSortData},1)});s("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",function(b,c){ea(b,c,a)})});s("rows().indexes()","row().index()",function(){return this.iterator("row",function(a,b){return b},1)});s("rows().ids()","row().id()",function(a){for(var b=[],c=this.context,
|
||||
d=0,e=c.length;d<e;d++)for(var f=0,g=this[d].length;f<g;f++){var h=c[d].rowIdFn(c[d].aoData[this[d][f]]._aData);b.push((!0===a?"#":"")+h)}return new t(c,b)});s("rows().remove()","row().remove()",function(){var a=this;this.iterator("row",function(b,c,d){var e=b.aoData,f=e[c];e.splice(c,1);for(var g=0,h=e.length;g<h;g++)null!==e[g].nTr&&(e[g].nTr._DT_RowIndex=g);oa(b.aiDisplayMaster,c);oa(b.aiDisplay,c);oa(a[d],c,!1);Sa(b);c=b.rowIdFn(f._aData);c!==k&&delete b.aIds[c]});this.iterator("table",function(a){for(var c=
|
||||
0,d=a.aoData.length;c<d;c++)a.aoData[c].idx=c});return this});p("rows.add()",function(a){var b=this.iterator("table",function(b){var c,f,g,h=[];f=0;for(g=a.length;f<g;f++)c=a[f],c.nodeName&&"TR"===c.nodeName.toUpperCase()?h.push(ma(b,c)[0]):h.push(L(b,c));return h},1),c=this.rows(-1);c.pop();h.merge(c,b);return c});p("row()",function(a,b){return ab(this.rows(a,b))});p("row().data()",function(a){var b=this.context;if(a===k)return b.length&&this.length?b[0].aoData[this[0]]._aData:k;b[0].aoData[this[0]]._aData=
|
||||
a;ea(b[0],this[0],"data");return this});p("row().node()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]].nTr||null:null});p("row.add()",function(a){a instanceof h&&a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?ma(b,a)[0]:L(b,a)});return this.row(b[0])});var bb=function(a,b){var c=a.context;if(c.length&&(c=c[0].aoData[b!==k?b:a[0]])&&c._details)c._details.remove(),c._detailsShow=k,c._details=k},Vb=function(a,
|
||||
b){var c=a.context;if(c.length&&a.length){var d=c[0].aoData[a[0]];if(d._details){(d._detailsShow=b)?d._details.insertAfter(d.nTr):d._details.detach();var e=c[0],f=new t(e),g=e.aoData;f.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0<D(g,"_details").length&&(f.on("draw.dt.DT_details",function(a,b){e===b&&f.rows({page:"current"}).eq(0).each(function(a){a=g[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),f.on("column-visibility.dt.DT_details",function(a,b){if(e===
|
||||
b)for(var c,d=ca(b),f=0,h=g.length;f<h;f++)c=g[f],c._details&&c._details.children("td[colspan]").attr("colspan",d)}),f.on("destroy.dt.DT_details",function(a,b){if(e===b)for(var c=0,d=g.length;c<d;c++)g[c]._details&&bb(f,c)}))}}};p("row().child()",function(a,b){var c=this.context;if(a===k)return c.length&&this.length?c[0].aoData[this[0]]._details:k;if(!0===a)this.child.show();else if(!1===a)bb(this);else if(c.length&&this.length){var d=c[0],c=c[0].aoData[this[0]],e=[],f=function(a,b){if(h.isArray(a)||
|
||||
a instanceof h)for(var c=0,k=a.length;c<k;c++)f(a[c],b);else a.nodeName&&"tr"===a.nodeName.toLowerCase()?e.push(a):(c=h("<tr><td/></tr>").addClass(b),h("td",c).addClass(b).html(a)[0].colSpan=ca(d),e.push(c[0]))};f(a,b);c._details&&c._details.remove();c._details=h(e);c._detailsShow&&c._details.insertAfter(c.nTr)}return this});p(["row().child.show()","row().child().show()"],function(){Vb(this,!0);return this});p(["row().child.hide()","row().child().hide()"],function(){Vb(this,!1);return this});p(["row().child.remove()",
|
||||
"row().child().remove()"],function(){bb(this);return this});p("row().child.isShown()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var dc=/^(.+):(name|visIdx|visible)$/,Wb=function(a,b,c,d,e){for(var c=[],d=0,f=e.length;d<f;d++)c.push(B(a,e[d],b));return c};p("columns()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=$a(b),c=this.iterator("table",function(c){var e=a,f=b,g=c.aoColumns,i=D(g,"sName"),j=D(g,"nTh");return Za("column",
|
||||
e,function(a){var b=Pb(a);if(a==="")return W(g.length);if(b!==null)return[b>=0?b:g.length+b];if(typeof a==="function"){var e=Da(c,f);return h.map(g,function(b,f){return a(f,Wb(c,f,0,0,e),j[f])?f:null})}var k=typeof a==="string"?a.match(dc):"";if(k)switch(k[2]){case "visIdx":case "visible":b=parseInt(k[1],10);if(b<0){var m=h.map(g,function(a,b){return a.bVisible?b:null});return[m[m.length+b]]}return[$(c,b)];case "name":return h.map(i,function(a,b){return a===k[1]?b:null})}else return h(j).filter(a).map(function(){return h.inArray(this,
|
||||
j)}).toArray()},c,f)},1);c.selector.cols=a;c.selector.opts=b;return c});s("columns().header()","column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});s("columns().footer()","column().footer()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});s("columns().data()","column().data()",function(){return this.iterator("column-rows",Wb,1)});s("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",
|
||||
function(a,b){return a.aoColumns[b].mData},1)});s("columns().cache()","column().cache()",function(a){return this.iterator("column-rows",function(b,c,d,e,f){return ja(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});s("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return ja(a.aoData,e,"anCells",b)},1)});s("columns().visible()","column().visible()",function(a,b){return this.iterator("column",function(c,d){if(a===k)return c.aoColumns[d].bVisible;
|
||||
var e=c.aoColumns,f=e[d],g=c.aoData,i,j,m;if(a!==k&&f.bVisible!==a){if(a){var l=h.inArray(!0,D(e,"bVisible"),d+1);i=0;for(j=g.length;i<j;i++)m=g[i].nTr,e=g[i].anCells,m&&m.insertBefore(e[d],e[l]||null)}else h(D(c.aoData,"anCells",d)).detach();f.bVisible=a;ga(c,c.aoHeader);ga(c,c.aoFooter);if(b===k||b)Y(c),(c.oScroll.sX||c.oScroll.sY)&&Z(c);w(c,null,"column-visibility",[c,d,a]);ya(c)}})});s("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===
|
||||
a?ba(b,c):c},1)});p("columns.adjust()",function(){return this.iterator("table",function(a){Y(a)},1)});p("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return $(c,b);if("fromData"===a||"toVisible"===a)return ba(c,b)}});p("column()",function(a,b){return ab(this.columns(a,b))});p("cells()",function(a,b,c){h.isPlainObject(a)&&(a.row===k?(c=a,a=null):(c=b,b=null));h.isPlainObject(b)&&(c=b,b=null);if(null===b||b===k)return this.iterator("table",
|
||||
function(b){var d=a,e=$a(c),f=b.aoData,g=Da(b,e),i=Sb(ja(f,g,"anCells")),j=h([].concat.apply([],i)),l,m=b.aoColumns.length,n,p,t,s,u,v;return Za("cell",d,function(a){var c=typeof a==="function";if(a===null||a===k||c){n=[];p=0;for(t=g.length;p<t;p++){l=g[p];for(s=0;s<m;s++){u={row:l,column:s};if(c){v=f[l];a(u,B(b,l,s),v.anCells?v.anCells[s]:null)&&n.push(u)}else n.push(u)}}return n}return h.isPlainObject(a)?[a]:j.filter(a).map(function(a,b){if(b.parentNode)l=b.parentNode._DT_RowIndex;else{a=0;for(t=
|
||||
f.length;a<t;a++)if(h.inArray(b,f[a].anCells)!==-1){l=a;break}}return{row:l,column:h.inArray(b,f[l].anCells)}}).toArray()},b,e)});var d=this.columns(b,c),e=this.rows(a,c),f,g,i,j,m,l=this.iterator("table",function(a,b){f=[];g=0;for(i=e[b].length;g<i;g++){j=0;for(m=d[b].length;j<m;j++)f.push({row:e[b][g],column:d[b][j]})}return f},1);h.extend(l.selector,{cols:b,rows:a,opts:c});return l});s("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=a.aoData[b].anCells)?
|
||||
a[c]:k},1)});p("cells().data()",function(){return this.iterator("cell",function(a,b,c){return B(a,b,c)},1)});s("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]},1)});s("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,d){return B(b,c,d,a)},1)});s("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a,b,c){return{row:b,
|
||||
column:c,columnVisible:ba(a,c)}},1)});s("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,d){ea(b,c,a,d)})});p("cell()",function(a,b,c){return ab(this.cells(a,b,c))});p("cell().data()",function(a){var b=this.context,c=this[0];if(a===k)return b.length&&c.length?B(b[0],c[0].row,c[0].column):k;ib(b[0],c[0].row,c[0].column,a);ea(b[0],c[0].row,"data",c[0].column);return this});p("order()",function(a,b){var c=this.context;if(a===k)return 0!==c.length?c[0].aaSorting:
|
||||
k;"number"===typeof a?a=[[a,b]]:h.isArray(a[0])||(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})});p("order.listener()",function(a,b,c){return this.iterator("table",function(d){Oa(d,a,b,c)})});p(["columns().order()","column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];h.each(b[d],function(b,c){e.push([c,a])});c.aaSorting=e})});p("search()",function(a,b,c,d){var e=this.context;return a===k?0!==e.length?
|
||||
e[0].oPreviousSearch.sSearch:k:this.iterator("table",function(e){e.oFeatures.bFilter&&ha(e,h.extend({},e.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),1)})});s("columns().search()","column().search()",function(a,b,c,d){return this.iterator("column",function(e,f){var g=e.aoPreSearchCols;if(a===k)return g[f].sSearch;e.oFeatures.bFilter&&(h.extend(g[f],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),ha(e,
|
||||
e.oPreviousSearch,1))})});p("state()",function(){return this.context.length?this.context[0].oSavedState:null});p("state.clear()",function(){return this.iterator("table",function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});p("state.loaded()",function(){return this.context.length?this.context[0].oLoadedState:null});p("state.save()",function(){return this.iterator("table",function(a){ya(a)})});m.versionCheck=m.fnVersionCheck=function(a){for(var b=m.version.split("."),a=a.split("."),c,d,e=0,f=
|
||||
a.length;e<f;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};m.isDataTable=m.fnIsDataTable=function(a){var b=h(a).get(0),c=!1;h.each(m.settings,function(a,e){var f=e.nScrollHead?h("table",e.nScrollHead)[0]:null,g=e.nScrollFoot?h("table",e.nScrollFoot)[0]:null;if(e.nTable===b||f===b||g===b)c=!0});return c};m.tables=m.fnTables=function(a){var b=!1;h.isPlainObject(a)&&(b=a.api,a=a.visible);var c=h.map(m.settings,function(b){if(!a||a&&h(b.nTable).is(":visible"))return b.nTable});
|
||||
return b?new t(c):c};m.util={throttle:ua,escapeRegex:va};m.camelToHungarian=I;p("$()",function(a,b){var c=this.rows(b).nodes(),c=h(c);return h([].concat(c.filter(a).toArray(),c.find(a).toArray()))});h.each(["on","one","off"],function(a,b){p(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0].match(/\.dt\b/)||(a[0]+=".dt");var d=h(this.tables().nodes());d[b].apply(d,a);return this})});p("clear()",function(){return this.iterator("table",function(a){na(a)})});p("settings()",function(){return new t(this.context,
|
||||
this.context)});p("init()",function(){var a=this.context;return a.length?a[0].oInit:null});p("data()",function(){return this.iterator("table",function(a){return D(a.aoData,"_aData")}).flatten()});p("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,d=b.oClasses,e=b.nTable,f=b.nTBody,g=b.nTHead,i=b.nTFoot,j=h(e),f=h(f),k=h(b.nTableWrapper),l=h.map(b.aoData,function(a){return a.nTr}),p;b.bDestroying=!0;w(b,"aoDestroyCallback","destroy",[b]);a||
|
||||
(new t(b)).columns().visible(!0);k.unbind(".DT").find(":not(tbody *)").unbind(".DT");h(Fa).unbind(".DT-"+b.sInstance);e!=g.parentNode&&(j.children("thead").detach(),j.append(g));i&&e!=i.parentNode&&(j.children("tfoot").detach(),j.append(i));b.aaSorting=[];b.aaSortingFixed=[];xa(b);h(l).removeClass(b.asStripeClasses.join(" "));h("th, td",g).removeClass(d.sSortable+" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);b.bJUI&&(h("th span."+d.sSortIcon+", td span."+d.sSortIcon,g).detach(),h("th, td",
|
||||
g).each(function(){var a=h("div."+d.sSortJUIWrapper,this);h(this).append(a.contents());a.detach()}));f.children().detach();f.append(l);g=a?"remove":"detach";j[g]();k[g]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),j.css("width",b.sDestroyWidth).removeClass(d.sTable),(p=b.asDestroyStripes.length)&&f.children().each(function(a){h(this).addClass(b.asDestroyStripes[a%p])}));c=h.inArray(b,m.settings);-1!==c&&m.settings.splice(c,1)})});h.each(["column","row","cell"],function(a,b){p(b+"s().every()",
|
||||
function(a){return this.iterator(b,function(d,e,f,g,h){a.call((new t(d))[b](e,"cell"===b?f:k),e,f,g,h)})})});p("i18n()",function(a,b,c){var d=this.context[0],a=P(a)(d.oLanguage);a===k&&(a=b);c!==k&&h.isPlainObject(a)&&(a=a[c]!==k?a[c]:a._);return a.replace("%d",c)});m.version="1.10.9";m.settings=[];m.models={};m.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};m.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,
|
||||
idx:-1};m.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};m.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,
|
||||
25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,
|
||||
fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},
|
||||
fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",
|
||||
sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},m.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null,rowId:"DT_RowId"};X(m.defaults);m.defaults.column={aDataSort:null,
|
||||
iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};X(m.defaults.column);m.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,
|
||||
iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],
|
||||
aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:k,oAjaxData:k,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,
|
||||
iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==y(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==y(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=
|
||||
this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};m.ext=v={buttons:{},classes:{},errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:m.fnVersionCheck,
|
||||
iApiIndex:0,oJUIClasses:{},sVersion:m.version};h.extend(v,{afnFiltering:v.search,aTypes:v.type.detect,ofnSearch:v.type.search,oSort:v.type.order,afnSortData:v.order,aoFeatures:v.feature,oApi:v.internal,oStdClasses:v.classes,oPagination:v.pager});h.extend(m.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",
|
||||
sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",
|
||||
sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var Ea="",Ea="",G=Ea+"ui-state-default",ka=Ea+"css_right ui-icon ui-icon-",Xb=Ea+"fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix";h.extend(m.ext.oJUIClasses,m.ext.classes,{sPageButton:"fg-button ui-button "+G,sPageButtonActive:"ui-state-disabled",
|
||||
sPageButtonDisabled:"ui-state-disabled",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",sSortAsc:G+" sorting_asc",sSortDesc:G+" sorting_desc",sSortable:G+" sorting",sSortableAsc:G+" sorting_asc_disabled",sSortableDesc:G+" sorting_desc_disabled",sSortableNone:G+" sorting_disabled",sSortJUIAsc:ka+"triangle-1-n",sSortJUIDesc:ka+"triangle-1-s",sSortJUI:ka+"carat-2-n-s",sSortJUIAscAllowed:ka+"carat-1-n",sSortJUIDescAllowed:ka+"carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",
|
||||
sSortIcon:"DataTables_sort_icon",sScrollHead:"dataTables_scrollHead "+G,sScrollFoot:"dataTables_scrollFoot "+G,sHeaderTH:G,sFooterTH:G,sJUIHeader:Xb+" ui-corner-tl ui-corner-tr",sJUIFooter:Xb+" ui-corner-bl ui-corner-br"});var Mb=m.ext.pager;h.extend(Mb,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},numbers:function(a,b){return[Aa(a,b)]},simple_numbers:function(a,b){return["previous",Aa(a,b),"next"]},full_numbers:function(a,b){return["first",
|
||||
"previous",Aa(a,b),"next","last"]},_numbers:Aa,numbers_length:7});h.extend(!0,m.ext.renderer,{pageButton:{_:function(a,b,c,d,e,f){var g=a.oClasses,i=a.oLanguage.oPaginate,j,k,l=0,m=function(b,d){var p,q,t,s,u=function(b){Ta(a,b.data.action,true)};p=0;for(q=d.length;p<q;p++){s=d[p];if(h.isArray(s)){t=h("<"+(s.DT_el||"div")+"/>").appendTo(b);m(t,s)}else{j=null;k="";switch(s){case "ellipsis":b.append('<span class="ellipsis">…</span>');break;case "first":j=i.sFirst;k=s+(e>0?"":" "+g.sPageButtonDisabled);
|
||||
break;case "previous":j=i.sPrevious;k=s+(e>0?"":" "+g.sPageButtonDisabled);break;case "next":j=i.sNext;k=s+(e<f-1?"":" "+g.sPageButtonDisabled);break;case "last":j=i.sLast;k=s+(e<f-1?"":" "+g.sPageButtonDisabled);break;default:j=s+1;k=e===s?g.sPageButtonActive:""}if(j!==null){t=h("<a>",{"class":g.sPageButton+" "+k,"aria-controls":a.sTableId,"data-dt-idx":l,tabindex:a.iTabIndex,id:c===0&&typeof s==="string"?a.sTableId+"_"+s:null}).html(j).appendTo(b);Va(t,{action:s},u);l++}}}},p;try{p=h(b).find(T.activeElement).data("dt-idx")}catch(t){}m(h(b).empty(),
|
||||
d);p&&h(b).find("[data-dt-idx="+p+"]").focus()}}});h.extend(m.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return Ya(a,c)?"num"+c:null},function(a){if(a&&!(a instanceof Date)&&(!ac.test(a)||!bc.test(a)))return null;var b=Date.parse(a);return null!==b&&!isNaN(b)||K(a)?"date":null},function(a,b){var c=b.oLanguage.sDecimal;return Ya(a,c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c,
|
||||
!0)?"html-num-fmt"+c:null},function(a){return K(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);h.extend(m.ext.type.search,{html:function(a){return K(a)?a:"string"===typeof a?a.replace(Ob," ").replace(Ca,""):""},string:function(a){return K(a)?a:"string"===typeof a?a.replace(Ob," "):a}});var Ba=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Qb(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};h.extend(v.type.order,{"date-pre":function(a){return Date.parse(a)||
|
||||
0},"html-pre":function(a){return K(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return K(a)?"":"string"===typeof a?a.toLowerCase():!a.toString?"":a.toString()},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a,b){return a<b?1:a>b?-1:0}});cb("");h.extend(!0,m.ext.renderer,{header:{_:function(a,b,c,d){h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass(h[e]==
|
||||
"asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass)}})},jqueryui:function(a,b,c,d){h("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(h("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass);b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+
|
||||
d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass(h[e]=="asc"?d.sSortJUIAsc:h[e]=="desc"?d.sSortJUIDesc:c.sSortingClassJUI)}})}}});m.render={number:function(a,b,c,d,e){return{display:function(f){if("number"!==typeof f&&"string"!==typeof f)return f;var g=0>f?"-":"",f=Math.abs(parseFloat(f)),h=parseInt(f,10),f=c?b+(f-h).toFixed(c).substring(2):"";return g+(d||"")+h.toString().replace(/\B(?=(\d{3})+(?!\d))/g,a)+f+(e||"")}}}};h.extend(m.ext.internal,{_fnExternApiFunc:Nb,_fnBuildAjax:ra,_fnAjaxUpdate:lb,
|
||||
_fnAjaxParameters:ub,_fnAjaxUpdateDraw:vb,_fnAjaxDataSrc:sa,_fnAddColumn:Ga,_fnColumnOptions:la,_fnAdjustColumnSizing:Y,_fnVisibleToColumnIndex:$,_fnColumnIndexToVisible:ba,_fnVisbleColumns:ca,_fnGetColumns:aa,_fnColumnTypes:Ia,_fnApplyColumnDefs:hb,_fnHungarianMap:X,_fnCamelToHungarian:I,_fnLanguageCompat:S,_fnBrowserDetect:fb,_fnAddData:L,_fnAddTr:ma,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==k?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return h.inArray(c,a.aoData[b].anCells)},
|
||||
_fnGetCellData:B,_fnSetCellData:ib,_fnSplitObjNotation:La,_fnGetObjectDataFn:P,_fnSetObjectDataFn:Q,_fnGetDataMaster:Ma,_fnClearTable:na,_fnDeleteIndex:oa,_fnInvalidate:ea,_fnGetRowElements:Ka,_fnCreateTr:Ja,_fnBuildHead:kb,_fnDrawHead:ga,_fnDraw:M,_fnReDraw:R,_fnAddOptionsHtml:nb,_fnDetectHeader:fa,_fnGetUniqueThs:qa,_fnFeatureHtmlFilter:pb,_fnFilterComplete:ha,_fnFilterCustom:yb,_fnFilterColumn:xb,_fnFilter:wb,_fnFilterCreateSearch:Qa,_fnEscapeRegex:va,_fnFilterData:zb,_fnFeatureHtmlInfo:sb,_fnUpdateInfo:Cb,
|
||||
_fnInfoMacros:Db,_fnInitialise:ia,_fnInitComplete:ta,_fnLengthChange:Ra,_fnFeatureHtmlLength:ob,_fnFeatureHtmlPaginate:tb,_fnPageChange:Ta,_fnFeatureHtmlProcessing:qb,_fnProcessingDisplay:C,_fnFeatureHtmlTable:rb,_fnScrollDraw:Z,_fnApplyToChildren:H,_fnCalculateColumnWidths:Ha,_fnThrottle:ua,_fnConvertToWidth:Fb,_fnGetWidestNode:Gb,_fnGetMaxLenString:Hb,_fnStringToCss:u,_fnSortFlatten:V,_fnSort:mb,_fnSortAria:Jb,_fnSortListener:Ua,_fnSortAttachListener:Oa,_fnSortingClasses:xa,_fnSortData:Ib,_fnSaveState:ya,
|
||||
_fnLoadState:Kb,_fnSettingsFromNode:za,_fnLog:J,_fnMap:F,_fnBindAction:Va,_fnCallbackReg:z,_fnCallbackFire:w,_fnLengthOverflow:Sa,_fnRenderer:Pa,_fnDataSource:y,_fnRowAttributes:Na,_fnCalculateEnd:function(){}});h.fn.dataTable=m;h.fn.dataTableSettings=m.settings;h.fn.dataTableExt=m.ext;h.fn.DataTable=function(a){return h(this).dataTable(a).api()};h.each(m,function(a,b){h.fn.DataTable[a]=b});return h.fn.dataTable};"function"===typeof define&&define.amd?define("datatables",["jquery"],S):"object"===
|
||||
typeof exports?module.exports=S(require("jquery")):jQuery&&!jQuery.fn.dataTable&&S(jQuery)})(window,document);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user