Add QR code generate capability to enroll android agent

revert-dabc3590
Dharmakeerthi Lasantha 5 years ago
commit 8e3fe481a1

@ -19,7 +19,7 @@
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading" role="tab"> <div class="panel-heading" role="tab">
<h2 class="sub-title panel-title"> <h2 class="sub-title panel-title">
Platform Configuration - Windows Platform Configuration - Android
</h2> </h2>
</div> </div>
<div id="android-config-body" class="panel-collapse panel-body" role="tabpanel"> <div id="android-config-body" class="panel-collapse panel-body" role="tabpanel">
@ -87,9 +87,9 @@
<div class="wr-input-control"> <div class="wr-input-control">
<label class="wr-input-label" for="android-kiosk-config-admin-component"> <label class="wr-input-label" for="android-kiosk-config-admin-component">
PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME
<!--<span class="helper" title="Time interval after which Android agent will contact IoT Server each time to fetch data">--> <span class="helper" title="Package name of the Entgra Android agent.">
<!--<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>--> <span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
<!--</span>--> </span>
<br> <br>
( ex: io.entgra.iot.agent/org.wso2.iot.agent.services.AgentDeviceAdminReceiver ) ( ex: io.entgra.iot.agent/org.wso2.iot.agent.services.AgentDeviceAdminReceiver )
</label> </label>
@ -99,9 +99,9 @@
<div class="wr-input-control"> <div class="wr-input-control">
<label class="wr-input-label" for="android-kiosk-config-checksum"> <label class="wr-input-label" for="android-kiosk-config-checksum">
PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
<!--<span class="helper" title="Time interval after which Android agent will contact IoT Server each time to fetch data">--> <span class="helper" title="Checksum value of the android agent.">
<!--<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>--> <span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
<!--</span>--> </span>
<br> <br>
( ex: gJD2YwtOiWJHkSMkkIfLRlj-quNqG1fb6v100QmzM9w= ) ( ex: gJD2YwtOiWJHkSMkkIfLRlj-quNqG1fb6v100QmzM9w= )
</label> </label>
@ -111,9 +111,9 @@
<div class="wr-input-control"> <div class="wr-input-control">
<label class="wr-input-label" for="android-kiosk-config-download-url"> <label class="wr-input-label" for="android-kiosk-config-download-url">
PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION
<!--<span class="helper" title="Time interval after which Android agent will contact IoT Server each time to fetch data">--> <span class="helper" title="Android agent download location.">
<!--<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>--> <span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
<!--</span>--> </span>
<br> <br>
( ex: http://192.168.8.20:8080/android.apk ) ( ex: http://192.168.8.20:8080/android.apk )
</label> </label>
@ -123,9 +123,9 @@
<div class="wr-input-control"> <div class="wr-input-control">
<label class="wr-input-label" for="android-kiosk-config-wifi-ssid"> <label class="wr-input-label" for="android-kiosk-config-wifi-ssid">
PROVISIONING_WIFI_SSID PROVISIONING_WIFI_SSID
<!--<span class="helper" title="Time interval after which Android agent will contact IoT Server each time to fetch data">--> <span class="helper" title="SSID of WI-FI network.">
<!--<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>--> <span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
<!--</span>--> </span>
<br> <br>
( ex: Entgra ) ( ex: Entgra )
</label> </label>
@ -135,9 +135,9 @@
<div class="wr-input-control"> <div class="wr-input-control">
<label class="wr-input-label" for="android-kiosk-config-wifi-sec"> <label class="wr-input-label" for="android-kiosk-config-wifi-sec">
PROVISIONING_WIFI_SECURITY_TYPE PROVISIONING_WIFI_SECURITY_TYPE
<!--<span class="helper" title="Time interval after which Android agent will contact IoT Server each time to fetch data">--> <span class="helper" title="Wi-Fi security type of network.">
<!--<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>--> <span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
<!--</span>--> </span>
<br> <br>
</label> </label>
<select id="android-kiosk-config-wifi-sec" class="form-control" data-default="0"> <select id="android-kiosk-config-wifi-sec" class="form-control" data-default="0">
@ -151,21 +151,32 @@
<div class="wr-input-control"> <div class="wr-input-control">
<label class="wr-input-label" for="android-kiosk-config-wifi-password"> <label class="wr-input-label" for="android-kiosk-config-wifi-password">
PROVISIONING_WIFI_PASSWORD PROVISIONING_WIFI_PASSWORD
<!--<span class="helper" title="Time interval after which Android agent will contact IoT Server each time to fetch data">--> <span class="helper" title="Password of the Wi-Fi network.">
<!--<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>--> <span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
<!--</span>--> </span>
<br> <br>
</label> </label>
<input id="android-kiosk-config-wifi-password" type="text" class="form-control" > <input id="android-kiosk-config-wifi-password" type="text" class="form-control" >
</div> </div>
<div class="wr-input-control">
<label class="wr-input-label" for="android-kiosk-config-server-ip">
SERVER_ADDRESS
<span class="helper" title="Server address (Ex-www.abc.com:8280)">
<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
</span>
<br>
</label>
<input id="android-kiosk-config-server-ip" type="text" class="form-control" >
</div>
<div class="wr-input-control"> <div class="wr-input-control">
<label class="wr-input-label" for="android-kiosk-config-encryption"> <label class="wr-input-label" for="android-kiosk-config-encryption">
PROVISIONING_SKIP_ENCRYPTION PROVISIONING_SKIP_ENCRYPTION
<!--<span class="helper" title="Time interval after which Android agent will contact IoT Server each time to fetch data">--> <span class="helper" title="Set value false to enroll KIOSK device without encrypting.">
<!--<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>--> <span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
<!--</span>--> </span>
<br> <br>
</label> </label>
<select id="android-kiosk-config-encryption" class="form-control" data-default="0"> <select id="android-kiosk-config-encryption" class="form-control" data-default="0">
@ -174,6 +185,21 @@
</select> </select>
</div> </div>
<div class="wr-input-control">
<label class="wr-input-label" for="android-kiosk-config-defaultOwner">
DEFAULT_OWNERSHIP
<span class="helper" title="Type of ownership">
<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
</span>
<br>
</label>
<select id="android-kiosk-config-defaultOwner" class="form-control" data-default="0">
<option value="BYOD">BYOD</option>
<option value="COPE">COPE</option>
<option value="COSU">COSU</option>
<option value="WORK_PROFILE">WORK_PROFILE</option>
</select>
</div>
</div> </div>
<!-- End of KIOSK Configs --> <!-- End of KIOSK Configs -->

@ -87,7 +87,9 @@ var kioskConfigs = {
"wifiSecurity" : "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE", "wifiSecurity" : "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE",
"skipEncryption" : "android.app.extra.PROVISIONING_SKIP_ENCRYPTION", "skipEncryption" : "android.app.extra.PROVISIONING_SKIP_ENCRYPTION",
"checksum" : "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM", "checksum" : "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM",
"downloadURL" : "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION" "downloadURL" : "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION",
"defaultOwnership" : "android.app.extra.defaultOwner",
"serverIP" : "android.app.extra.serverIp"
}; };
$(document).ready(function () { $(document).ready(function () {
@ -150,6 +152,10 @@ $(document).ready(function () {
$("input#android-kiosk-config-download-url").val(config.value); $("input#android-kiosk-config-download-url").val(config.value);
} else if (config.name === kioskConfigs["skipEncryption"]) { } else if (config.name === kioskConfigs["skipEncryption"]) {
$("#android-kiosk-config-encryption").val(config.value); $("#android-kiosk-config-encryption").val(config.value);
} else if (config.name === kioskConfigs["defaultOwnership"]) {
$("#android-kiosk-config-defaultOwner").val(config.value);
} else if (config.name === kioskConfigs["serverIP"]) {
$("#android-kiosk-config-server-ip").val(config.value);
} }
} }
} }
@ -194,6 +200,8 @@ $(document).ready(function () {
var wifiPassword = $("input#android-kiosk-config-wifi-password").val(); var wifiPassword = $("input#android-kiosk-config-wifi-password").val();
var encryption = $("#android-kiosk-config-encryption").find("option:selected").attr("value"); var encryption = $("#android-kiosk-config-encryption").find("option:selected").attr("value");
var wifiSecurity = $("#android-kiosk-config-wifi-sec").find("option:selected").attr("value"); var wifiSecurity = $("#android-kiosk-config-wifi-sec").find("option:selected").attr("value");
var defaultOwner = $("#android-kiosk-config-defaultOwner").find("option:selected").attr("value");
var serverIp = $("#android-kiosk-config-server-ip").val();
if (notifierType === notifierTypeConstants["LOCAL"] && !notifierFrequency) { if (notifierType === notifierTypeConstants["LOCAL"] && !notifierFrequency) {
$(errorMsg).text("Notifier frequency is a required field. It cannot be empty."); $(errorMsg).text("Notifier frequency is a required field. It cannot be empty.");
@ -281,6 +289,18 @@ $(document).ready(function () {
"contentType": "text" "contentType": "text"
}; };
var kioskDefaultOwner = {
"name": kioskConfigs["defaultOwnership"],
"value": defaultOwner,
"contentType": "text"
};
var kioskServerIp = {
"name": kioskConfigs["serverIP"],
"value": serverIp,
"contentType": "text"
};
configList.push(type); configList.push(type);
configList.push(frequency); configList.push(frequency);
configList.push(androidEula); configList.push(androidEula);
@ -292,6 +312,8 @@ $(document).ready(function () {
configList.push(kioskWifiSSID); configList.push(kioskWifiSSID);
configList.push(kioskWifiPassword); configList.push(kioskWifiPassword);
configList.push(kioskWifiSecurity); configList.push(kioskWifiSecurity);
configList.push(kioskDefaultOwner);
configList.push(kioskServerIp);
if (notifierType === notifierTypeConstants["FCM"]) { if (notifierType === notifierTypeConstants["FCM"]) {
configList.push(fcmKey); configList.push(fcmKey);

@ -59,7 +59,7 @@ hr {
color: #006eff; color: #006eff;
} }
.enrollment-qr-container canvas { .enrollment-qr-container canvas {
width: 14%; width: 15%;
} }
@media (min-width:992px){ @media (min-width:992px){

@ -0,0 +1,2 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" height="512px" viewBox="-96 0 496 496" width="512px" class=""><g><path d="m96 168v48c0 4.425781 3.585938 8 8 8h48c4.414062 0 8-3.574219 8-8v-48c0-4.425781-3.585938-8-8-8h-48c-4.414062 0-8 3.574219-8 8zm16 8h32v32h-32zm0 0" data-original="#000000" class="active-path" data-old_color="#000000" fill="#007E97"/><path d="m272 168c0-4.425781-3.585938-8-8-8h-48c-4.414062 0-8 3.574219-8 8v48c0 4.425781 3.585938 8 8 8h48c4.414062 0 8-3.574219 8-8zm-16 40h-32v-32h32zm0 0" data-original="#000000" class="active-path" data-old_color="#000000" fill="#007E97"/><path d="m160 328v-48c0-4.425781-3.585938-8-8-8h-48c-4.414062 0-8 3.574219-8 8v48c0 4.425781 3.585938 8 8 8h48c4.414062 0 8-3.574219 8-8zm-16-8h-32v-32h32zm0 0" data-original="#000000" class="active-path" data-old_color="#000000" fill="#007E97"/><path d="m272 240h-80v-80h-16v80h-80v16h80v80h16v-80h80zm0 0" data-original="#000000" class="active-path" data-old_color="#000000" fill="#007E97"/><path d="m272 272h-56c-4.414062 0-8 3.574219-8 8v56h16v-48h48zm0 0" data-original="#000000" class="active-path" data-old_color="#000000" fill="#007E97"/><path d="m240 296h16v40h-16zm0 0" data-original="#000000" class="active-path" data-old_color="#000000" fill="#007E97"/><path d="m304 192v-56c0-4.425781-3.585938-8-8-8h-24v-88c0-22.054688-17.945312-40-40-40h-192c-22.054688 0-40 17.945312-40 40v416c0 22.054688 17.945312 40 40 40h192c22.054688 0 40-17.945312 40-40v-88h24c4.414062 0 8-3.574219 8-8v-56h-16v48h-48v16h16v88c0 13.230469-10.769531 24-24 24h-8v-8c0-13.230469-10.769531-24-24-24h-128c-13.230469 0-24 10.769531-24 24v8h-8c-13.230469 0-24-10.769531-24-24v-416c0-9.902344 6.03125-18.414062 14.609375-22.078125l43.734375 43.734375c1.496094 1.503906 3.535156 2.34375 5.65625 2.34375h112c2.121094 0 4.160156-.839844 5.65625-2.34375l43.734375-43.734375c8.578125 3.664063 14.609375 12.175781 14.609375 22.078125v88h-16v16h48v48zm-240 280c0-4.414062 3.59375-8 8-8h128c4.40625 0 8 3.585938 8 8v8h-144zm124.6875-424h-105.375l-32-32h169.375zm0 0" data-original="#000000" class="active-path" data-old_color="#000000" fill="#007E97"/><path d="m64 136v56h16v-48h48v-16h-56c-4.414062 0-8 3.574219-8 8zm0 0" data-original="#000000" class="active-path" data-old_color="#000000" fill="#007E97"/><path d="m64 360c0 4.425781 3.585938 8 8 8h56v-16h-48v-48h-16zm0 0" data-original="#000000" class="active-path" data-old_color="#000000" fill="#007E97"/></g> </svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@ -32,15 +32,17 @@ var backendEndBasePath = "/api/device-mgt/v1.0";
//} //}
var kioskConfigs = { var kioskConfigs = {
"adminComponentName" : "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME", "adminComponentName": "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME",
"wifiSSID" : "android.app.extra.PROVISIONING_WIFI_SSID", "wifiSSID": "android.app.extra.PROVISIONING_WIFI_SSID",
"wifiPassword" : "android.app.extra.PROVISIONING_WIFI_PASSWORD", "wifiPassword": "android.app.extra.PROVISIONING_WIFI_PASSWORD",
"wifiSecurity" : "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE", "wifiSecurity": "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE",
"skipEncryption" : "android.app.extra.PROVISIONING_SKIP_ENCRYPTION", "skipEncryption": "android.app.extra.PROVISIONING_SKIP_ENCRYPTION",
"checksum" : "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM", "checksum": "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM",
"downloadURL" : "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION", "downloadURL": "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION",
"androidExtra" : "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE", "androidExtra": "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE",
"accessToken" : "android.app.extra.token" "accessToken": "android.app.extra.token",
"defaultOwnership": "android.app.extra.defaultOwner",
"serverIp": "android.app.extra.serverIp"
}; };
/* /*
@ -68,19 +70,19 @@ function hidePopup() {
$(modalPopupContent).html(""); $(modalPopupContent).html("");
$(modalPopupContent).removeClass("operation-data"); $(modalPopupContent).removeClass("operation-data");
$(modalPopup).modal('hide'); $(modalPopup).modal('hide');
$('body').removeClass('modal-open').css('padding-right','0px'); $('body').removeClass('modal-open').css('padding-right', '0px');
$('.modal-backdrop').remove(); $('.modal-backdrop').remove();
} }
/* /*
* QR-code generation function. * QR-code generation function.
*/ */
function generateQRCode(qrCodeClass) { function generateQRCode() {
var enrollmentURL = $("#qr-code-modal").data("enrollment-url"); var enrollmentURL = $("#qr-code-modal").data("enrollment-url");
$(qrCodeClass).qrcode({ $(qrCodeClass).qrcode({
text: enrollmentURL, text: enrollmentURL,
width: 200, width: 150,
height: 200 height: 150
}); });
} }
@ -89,38 +91,63 @@ function generateQRCode(qrCodeClass) {
*/ */
function generateKIOSKQRCode(qrCodeClass) { function generateKIOSKQRCode(qrCodeClass) {
var androidConfigAPI = "/api/device-mgt/android/v1.0/configuration";
var payload = {}; var payload = {};
var androidConfigAPI = "/api/device-mgt/android/v1.0/configuration";
var isKioskConfigured = false; var isKioskConfigured = false;
var defaultOwnerVal = {};
var serverIp = {};
$("#android-qr-code").show();
$("#enrollment_qr_content").show();
$("#qr-code-img").hide();
$("#enroll-qr-heading").show();
var ownership_type = $("#android-device-ownership").find("option:selected").attr("value");
invokerUtil.get( invokerUtil.get(
androidConfigAPI, androidConfigAPI,
function (data) { function(data) {
data = JSON.parse(data); data = JSON.parse(data);
if (data != null && data.configuration != null) { if (data != null && data.configuration != null) {
for (var i = 0; i < data.configuration.length; i++) { if (ownership_type == "COSU") {
var config = data.configuration[i]; for (var i = 0; i < data.configuration.length; i++) {
var config = data.configuration[i];
if (config.name === kioskConfigs["adminComponentName"]) { if (config.name === kioskConfigs["adminComponentName"]) {
isKioskConfigured = true; isKioskConfigured = true;
payload[config.name] = config.value; payload[config.name] = config.value;
} else if (config.name === kioskConfigs["wifiSSID"]) { } else if (config.name === kioskConfigs["wifiSSID"]) {
payload[config.name] = config.value; payload[config.name] = config.value;
} else if (config.name === kioskConfigs["wifiPassword"]) { } else if (config.name === kioskConfigs["wifiPassword"]) {
payload[config.name] = config.value; payload[config.name] = config.value;
} else if (config.name === kioskConfigs["wifiSecurity"]) { } else if (config.name === kioskConfigs["wifiSecurity"]) {
payload[config.name] = config.value; payload[config.name] = config.value;
} else if (config.name === kioskConfigs["checksum"]) { } else if (config.name === kioskConfigs["checksum"]) {
payload[config.name] = config.value; payload[config.name] = config.value;
} else if (config.name === kioskConfigs["downloadURL"]) { } else if (config.name === kioskConfigs["downloadURL"]) {
payload[config.name] = config.value; payload[config.name] = config.value;
} else if (config.name === kioskConfigs["skipEncryption"]) { } else if (config.name === kioskConfigs["skipEncryption"]) {
payload[config.name] = Boolean(config.value); payload[config.name] = Boolean(config.value);
} else if (config.name === kioskConfigs["defaultOwnership"]) {
defaultOwnerVal[config.name] = ownership_type;
} else if (config.name === kioskConfigs["serverIp"]) {
serverIp[config.name] = config.value;
}
}
} else {
for (var i = 0; i < data.configuration.length; i++) {
var config = data.configuration[i];
if (config.name === kioskConfigs["adminComponentName"]) {
isKioskConfigured = true;
payload[config.name] = config.value;
} else if (config.name === kioskConfigs["defaultOwnership"]) {
defaultOwnerVal[config.name] = ownership_type;
} else if (config.name === kioskConfigs["serverIp"]) {
serverIp[config.name] = config.value;
}
} }
} }
} }
}, function (data) { },
function(data) {
console.log(data); console.log(data);
}); });
@ -129,27 +156,57 @@ function generateKIOSKQRCode(qrCodeClass) {
var accessToken = {}; var accessToken = {};
accessToken[kioskConfigs["accessToken"]] = tokenPair["accessToken"]; accessToken[kioskConfigs["accessToken"]] = tokenPair["accessToken"];
payload[kioskConfigs["androidExtra"]] = accessToken; var sumExtra = $.extend(accessToken, defaultOwnerVal, serverIp);
payload[kioskConfigs["androidExtra"]] = sumExtra;
$(".kiosk-enrollment-qr-container").empty();
if (isKioskConfigured) { if (isKioskConfigured) {
$(qrCodeClass).qrcode({ $(qrCodeClass).qrcode({
text: JSON.stringify(payload), text: JSON.stringify(payload),
width: 300, width: 350,
height: 300 height: 350
}); });
} else { } else {
$("#kiosk_heading").hide(); $("#android-configurations-alert").fadeToggle(500);
$("#kiosk_content").hide(); $("#kiosk_content").hide();
} }
} }
function displayAgentDownloadQR() {
$(".enrollment-qr-container").empty();
generateQRCode(".enrollment-qr-container");
$("#download-agent-qr").fadeToggle(1000);
$("#enroll-agent-qr").fadeOut(1000);
$("#android-enroll-manually-instructions").fadeOut(1000);
$('html,body').animate({
scrollTop: $('#download-agent-qr').position().top
}, 800);
}
function displayEnrollmentQR() {
$("#download-agent-qr").fadeOut(1000);
$("#enroll-agent-qr").fadeToggle(1000);
$("#android-enroll-manually-instructions").fadeOut(1000);
$('html,body').animate({
scrollTop: $('#enroll-agent-qr').position().top
}, 800);
}
function manualEnrollmentGuide() {
$("#enroll-agent-qr").fadeOut(1000);
$("#download-agent-qr").fadeOut(1000);
$("#android-enroll-manually-instructions").fadeToggle(1000);
$('html,body').animate({
scrollTop: $('#android-enroll-manually-instructions').position().top
}, 800);
}
function toggleEnrollment() { function toggleEnrollment() {
$(".modal-content").html($("#qr-code-modal").html()); $(".modal-content").html($("#qr-code-modal").html());
generateQRCode(".modal-content .qr-code"); generateQRCode(".modal-content .qr-code");
modalDialog.show(); modalDialog.show();
} }
var updateNotificationCountOnSuccess = function (data, textStatus, jqXHR) { var updateNotificationCountOnSuccess = function(data, textStatus, jqXHR) {
var notificationBubble = "#notification-bubble"; var notificationBubble = "#notification-bubble";
if (jqXHR.status == 200 && data) { if (jqXHR.status == 200 && data) {
var responsePayload = JSON.parse(data); var responsePayload = JSON.parse(data);
@ -187,12 +244,12 @@ function loadNewNotifications() {
var notifications = $("#notifications"); var notifications = $("#notifications");
var currentUser = notifications.data("currentUser"); var currentUser = notifications.data("currentUser");
$.template("notification-listing", notifications.attr("src"), function (template) { $.template("notification-listing", notifications.attr("src"), function(template) {
var serviceURL = backendEndBasePath + "/notifications?offset=0&limit=5&status=NEW"; var serviceURL = backendEndBasePath + "/notifications?offset=0&limit=5&status=NEW";
invokerUtil.get( invokerUtil.get(
serviceURL, serviceURL,
// on success // on success
function (data, textStatus, jqXHR) { function(data, textStatus, jqXHR) {
if (jqXHR.status == 200 && data) { if (jqXHR.status == 200 && data) {
var viewModel = {}; var viewModel = {};
var responsePayload = JSON.parse(data); var responsePayload = JSON.parse(data);
@ -214,7 +271,7 @@ function loadNewNotifications() {
} }
}, },
// on error // on error
function (jqXHR) { function(jqXHR) {
if (jqXHR.status = 500) { if (jqXHR.status = 500) {
$(messageSideBar).html("<h4 class ='message-danger'>Unexpected error occurred while trying " + $(messageSideBar).html("<h4 class ='message-danger'>Unexpected error occurred while trying " +
"to retrieve any new notifications.</h4>"); "to retrieve any new notifications.</h4>");
@ -230,7 +287,7 @@ function loadNewNotifications() {
* notification listing sidebar. * notification listing sidebar.
* @return {Null} * @return {Null}
*/ */
$.sidebar_toggle = function (action, target, container) { $.sidebar_toggle = function(action, target, container) {
var elem = '[data-toggle=sidebar]', var elem = '[data-toggle=sidebar]',
button, button,
containerOffsetLeft, containerOffsetLeft,
@ -244,7 +301,7 @@ $.sidebar_toggle = function (action, target, container) {
buttonParent; buttonParent;
var sidebar_window = { var sidebar_window = {
update: function (target, container, button) { update: function(target, container, button) {
containerOffsetLeft = $(container).data('offset-left') ? $(container).data('offset-left') : 0; containerOffsetLeft = $(container).data('offset-left') ? $(container).data('offset-left') : 0;
containerOffsetRight = $(container).data('offset-right') ? $(container).data('offset-right') : 0; containerOffsetRight = $(container).data('offset-right') ? $(container).data('offset-right') : 0;
targetOffsetLeft = $(target).data('offset-left') ? $(target).data('offset-left') : 0; targetOffsetLeft = $(target).data('offset-left') ? $(target).data('offset-left') : 0;
@ -259,7 +316,7 @@ $.sidebar_toggle = function (action, target, container) {
} }
}, },
show: function () { show: function() {
if ($(target).data('sidebar-fixed') == true) { if ($(target).data('sidebar-fixed') == true) {
$(target).height($(window).height() - $(target).data('fixed-offset')); $(target).height($(window).height() - $(target).data('fixed-offset'));
} }
@ -303,7 +360,7 @@ $.sidebar_toggle = function (action, target, container) {
$(target).trigger('shown.sidebar'); $(target).trigger('shown.sidebar');
}, },
hide: function () { hide: function() {
$(target).trigger('hide.sidebar'); $(target).trigger('hide.sidebar');
$(target).removeClass('toggled'); $(target).removeClass('toggled');
if (button !== undefined) { if (button !== undefined) {
@ -350,7 +407,7 @@ $.sidebar_toggle = function (action, target, container) {
// binding click function // binding click function
var body = 'body'; var body = 'body';
$(body).off('click', elem); $(body).off('click', elem);
$(body).on('click', elem, function (e) { $(body).on('click', elem, function(e) {
e.preventDefault(); e.preventDefault();
button = $(this); button = $(this);
container = button.data('container'); container = button.data('container');
@ -368,41 +425,41 @@ $.sidebar_toggle = function (action, target, container) {
}); });
}; };
$.fn.collapse_nav_sub = function () { $.fn.collapse_nav_sub = function() {
var navSelector = 'ul.nav'; var navSelector = 'ul.nav';
if (!$(navSelector).hasClass('collapse-nav-sub')) { if (!$(navSelector).hasClass('collapse-nav-sub')) {
$(navSelector + ' > li', this).each(function () { $(navSelector + ' > li', this).each(function() {
var position = $(this).offset().left - $(this).parent().scrollLeft(); var position = $(this).offset().left - $(this).parent().scrollLeft();
$(this).attr('data-absolute-position', (position + 5)); $(this).attr('data-absolute-position', (position + 5));
}); });
$(navSelector + ' li', this).each(function () { $(navSelector + ' li', this).each(function() {
if ($('ul', this).length !== 0) { if ($('ul', this).length !== 0) {
$(this).addClass('has-sub'); $(this).addClass('has-sub');
} }
}); });
$(navSelector + ' > li', this).each(function () { $(navSelector + ' > li', this).each(function() {
$(this).css({ $(this).css({
'left': $(this).data('absolute-position'), 'left': $(this).data('absolute-position'),
'position': 'absolute' 'position': 'absolute'
}); });
}); });
$(navSelector + ' li.has-sub', this).on('click', function () { $(navSelector + ' li.has-sub', this).on('click', function() {
var elem = $(this); var elem = $(this);
if (elem.attr('aria-expanded') !== 'true') { if (elem.attr('aria-expanded') !== 'true') {
elem.siblings().fadeOut(100, function () { elem.siblings().fadeOut(100, function() {
elem.animate({'left': '15'}, 200, function () { elem.animate({ 'left': '15' }, 200, function() {
$(elem).first().children('ul').fadeIn(200); $(elem).first().children('ul').fadeIn(200);
}); });
}); });
elem.siblings().attr('aria-expanded', 'false'); elem.siblings().attr('aria-expanded', 'false');
elem.attr('aria-expanded', 'true'); elem.attr('aria-expanded', 'true');
} else { } else {
$(elem).first().children('ul').fadeOut(100, function () { $(elem).first().children('ul').fadeOut(100, function() {
elem.animate({'left': $(elem).data('absolute-position')}, 200, function () { elem.animate({ 'left': $(elem).data('absolute-position') }, 200, function() {
elem.siblings().fadeIn(100); elem.siblings().fadeIn(100);
}); });
}); });
@ -411,27 +468,24 @@ $.fn.collapse_nav_sub = function () {
} }
}); });
$(navSelector + ' > li.has-sub ul', this).on('click', function (e) { $(navSelector + ' > li.has-sub ul', this).on('click', function(e) {
e.stopPropagation(); e.stopPropagation();
}); });
$(navSelector).addClass('collapse-nav-sub'); $(navSelector).addClass('collapse-nav-sub');
} }
}; };
$(document).ready(function () { $(document).ready(function() {
$.sidebar_toggle(); $.sidebar_toggle();
generateQRCode(".enrollment-qr-container");
generateKIOSKQRCode(".kiosk-enrollment-qr-container");
if (typeof $.fn.collapse == 'function') { if (typeof $.fn.collapse == 'function') {
$('.navbar-collapse.tiles').on('shown.bs.collapse', function () { $('.navbar-collapse.tiles').on('shown.bs.collapse', function() {
$(this).collapse_nav_sub(); $(this).collapse_nav_sub();
}); });
} }
loadNewNotificationsOnSideViewPanel(); loadNewNotificationsOnSideViewPanel();
$("#right-sidebar").on("click", ".new-notification", function () { $("#right-sidebar").on("click", ".new-notification", function() {
var notificationId = $(this).data("id"); var notificationId = $(this).data("id");
var redirectUrl = $(this).data("url"); var redirectUrl = $(this).data("url");
var markAsReadNotificationsEpr = backendEndBasePath + "/notifications/" + notificationId + "/mark-checked"; var markAsReadNotificationsEpr = backendEndBasePath + "/notifications/" + notificationId + "/mark-checked";
@ -441,14 +495,14 @@ $(document).ready(function () {
markAsReadNotificationsEpr, markAsReadNotificationsEpr,
null, null,
// on success // on success
function (data) { function(data) {
data = JSON.parse(data); data = JSON.parse(data);
if (data.statusCode == responseCodes["ACCEPTED"]) { if (data.statusCode == responseCodes["ACCEPTED"]) {
location.href = redirectUrl; location.href = redirectUrl;
} }
}, },
// on error // on error
function () { function() {
var content = "<li class='message message-danger'><h4><i class='icon fw fw-error'></i>Warning</h4>" + var content = "<li class='message message-danger'><h4><i class='icon fw fw-error'></i>Warning</h4>" +
"<p>Unexpected error occurred while loading notification. Please refresh the pa{{#if isCloud}}ge and" + "<p>Unexpected error occurred while loading notification. Please refresh the pa{{#if isCloud}}ge and" +
" try again</p></li>"; " try again</p></li>";

@ -1,77 +1,150 @@
{{unit "cdmf.unit.lib.qrcode"}}
{{unit "cdmf.unit.device.type.qr-modal" enrollmentURL=enrollmentURL deviceTypeName="Android"}} {{unit "cdmf.unit.device.type.qr-modal" enrollmentURL=enrollmentURL deviceTypeName="Android"}}
{{unit "cdmf.unit.device.type.email.invite-modal" deviceTypeView="android"}}
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">
{{#if isVirtual}} {{#if isVirtual}}
<h1 class="grey ">DOWNLOAD THE VIRTUAL ANDROID DEVICE</h1> <h1 class="grey ">DOWNLOAD THE VIRTUAL ANDROID DEVICE</h1>
{{else}} {{else}}
<h1 class="grey ">DOWNLOAD THE ANDROID AGENT</h1> <h2 class="grey ">ENROLL THE ANDROID AGENT</h2>
{{/if}} {{/if}}
<hr> <hr>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<!--<div class="col-xs-12 col-sm-4 col-md-3 col-lg-3 add-padding-top-2x"> <h3>Step 01 - Get your Android Agent.</h3>
<hr><br>
<p>The Android agent can be downloaded by 2 methods.
Either the generated QR code can be scanned, and the agent APK downloaded from the link,
or the agent APK can be manually downloaded via the "Download APK" button, transferred to
the device and then installed.</p>
<br>
<button id="button-download-qr" onclick="displayAgentDownloadQR();" class="btn btn-default btn-primary">Get Android Agent</button>
<br>
{{!-- Agent download qr class --}}
<div id="download-agent-qr" style="display:none" class="row">
{{!-- <div class="col-xs-12 col-sm-4 col-md-3 col-lg-3 add-padding-top-2x">
<img src="{{@unit.publicUri}}/images/android-icon.png" class="img-responsive"> <img src="{{@unit.publicUri}}/images/android-icon.png" class="img-responsive">
</div>--> </div> --}}
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 add-padding-top-2x add-padding-bottom-2x"> <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 add-padding-top-2x add-padding-bottom-2x">
{{#if isVirtual}} {{#if isVirtual}}
<h3 class="text-center add-padding-bottom-4x">Download our virtual Android device, enroll it with WSO2 <h3 class="text-center add-padding-bottom-4x">Download our virtual Android device, enroll it with WSO2
{{#if isCloud}} {{#if isCloud}}
Device Cloud Device Cloud
{{else}} {{else}}
IoT Server IoT Server
{{/if}}and try it out!</h3> {{/if}}and try it out!</h3>
<div class="text-center"><a <div class="text-center"><a
href="{{@unit.publicUri}}/assets/android-tryit.ZIP" href="{{@unit.publicUri}}/assets/android-tryit.ZIP"
class="btn-operations remove-margin download_agent"> class="btn-operations remove-margin download_agent">
<i class="fw fw-download fw-inverse fw-lg add-margin-1x"></i>Download the virtual Android device</a> <i class="fw fw-download fw-inverse fw-lg add-margin-1x"></i>Download the virtual Android device</a>
</div> </div>
{{else}} {{else}}
<h3 class="text-center">Scan to get the Android Agent.</h3> <h3 class="text-center">Scan to get the Android Agent.</h3>
<div class="enrollment-qr-container text-center"></div> <div class="enrollment-qr-container text-center"></div>
<h3 class="text-center add-margin-bottom-2x add-margin-top-2x">or</h3> <h3 class="text-center add-margin-bottom-2x add-margin-top-2x">or</h3>
{{#if isCloud}}
<div class="text-center">
<a href='https://play.google.com/store/apps/details?id=org.wso2.iot.agent&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'
target="_blank">
<img alt='Get it on Google Play'
src='{{@unit.publicUri}}/images/en_badge_web_generic_export.png'/>
</a>
</div>
{{else}}
<div class="text-center">
<a href="{{enrollmentURL}}"
class="btn-operations remove-margin download_agent">
<i class="fw fw-download fw-inverse fw-lg add-margin-1x"></i> Download APK</a>
</div>
{{/if}}
{{/if}}
</div>
{{#if isCloud}} {{#if isCloud}}
<div class="text-center"> <p class="doc-link text-center">Need help? Read <a
<a href='https://play.google.com/store/apps/details?id=org.wso2.iot.agent&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1' {{#if isVirtual}}
target="_blank"> href="https://docs.wso2.com/display/DeviceCloud/Quick+Start+Guide"
<img alt='Get it on Google Play' {{else}}
src='{{@unit.publicUri}}/images/en_badge_web_generic_export.png'/> href="https://docs.wso2.com/display/DeviceCloud/Enrolling+an+Android+Device"
</a> {{/if}}
</div> target="_blank">Entgra Device Cloud documentation.</a>
</p>
{{else}} {{else}}
<div class="text-center"> <p class="doc-link text-center">Need help? Read <a
<a href="{{enrollmentURL}}" {{#if isVirtual}}
class="btn-operations remove-margin download_agent"> href="https://entgra.atlassian.net/wiki/spaces/IoTS340/pages/28278950/Android+Virtual+Device"
<i class="fw fw-download fw-inverse fw-lg add-margin-1x"></i> Download APK</a> {{else}}
</div> href="https://entgra.atlassian.net/wiki/spaces/IoTS340/pages/28278906/Android"
{{/if}}
target="_blank">Entgra IoT Server documentation.</a></p>
{{/if}} {{/if}}
{{/if}} </div>
</div> <hr>
{{#if isCloud}} <h3>Step 02 - Enroll the Android Agent.</h3><br>
<p class="doc-link text-center">Need help? Read <a <p>Your device can be enrolled with Entgra IoTS automatically via QR code or manually by a wizard.
{{#if isVirtual}} To enroll automatically; first download agent as mentioned in Step 1 then proceed with the ENROLL WITH QR option from the device setup activity.
href="https://docs.wso2.com/display/DeviceCloud/Quick+Start+Guide" Thereafter select the ownership configuration and scan the generated QR to complete the process.
{{else}} To enroll manually; select the Manual enrollment option from the setup activity and follow the succeeding steps.</p>
href="https://docs.wso2.com/display/DeviceCloud/Enrolling+an+Android+Device" <br>
{{/if}} {{#unless isVirtual}}
target="_blank">Entgra Device Cloud documentation.</a> {{#unless isCloud}}
</p> <div>
{{else}} <button id="button-enroll-qr" onclick="displayEnrollmentQR();" class="btn btn-default btn-primary">Enroll using QR</button>
<p class="doc-link text-center">Need help? Read <a <button id="button-enroll-manual" onclick="manualEnrollmentGuide();" class="btn btn-default btn-primary">Enroll manually</button>
{{#if isVirtual}} </div>
href="https://entgra.atlassian.net/wiki/spaces/IoTS340/pages/28278950/Android+Virtual+Device" {{/unless}}
{{else}} {{else}}
href="https://entgra.atlassian.net/wiki/spaces/IoTS340/pages/28278906/Android" <button id="button-enroll-manual" onclick="manualEnrollmentGuide();" class="btn btn-default btn-primary">Enroll manually</button>
{{/if}} {{/unless}}
target="_blank">Entgra IoT Server documentation.</a></p>
{{/if}} {{!-- Agent enroll QR code class --}}
<div id="enroll-agent-qr" style="display:none" class="row">
{{#unless isVirtual}}
{{#unless isCloud}}
<h3 class="text-center">Generate QR code to QR based Provisioning.</h3>
<hr>
<div class="text-center">
<label class="text-center add-margin-bottom-2x add-margin-top-2x">Select device ownership</label>
<select id="android-device-ownership" class="text-center" data-default="0" onchange="generateKIOSKQRCode('.kiosk-enrollment-qr-container');">
<option value="BYOD">Select</option>
<option value="BYOD">BYOD</option>
<option value="COPE">COPE</option>
<option value="COSU">COSU (KIOSK)</option>
<option value="WORK_PROFILE">WORK PROFILE</option>
</select>
</div>
<div class="text-center" id="android-qr-code">
<div class="a-token" data-atoken="{{accessToken}}"></div>
<div class="row" id="enrollment_qr_content">
<div class="col-xs-12 col-sm-12.enrollment-qr-container canvas col-md-12 col-lg-12 add-padding-top-2x add-padding-bottom-2x">
<div class="kiosk-enrollment-qr-container text-center" data-toggle="popover"
data-trigger="focus" data-placement="bottom">
</div>
</div>
</div>
</div>
<div class="text-center">
<div class="text-center " alt="Responsive image" id="qr-code-img">
<img src="{{@unit.publicUri}}/images/application.svg" height="300" width="300" style="width:50%;">
</div>
<h3 id="enroll-qr-heading" style="display:none" class="text-center fw fw-lg add-margin-1x">Scan to enroll android agent</h3>
</div>
<hr>
{{/unless}}
{{/unless}}
</div> </div>
<div class="row"> {{!-- Warning message --}}
<div id="android-configurations-alert" style="display:none" class="alert alert-warning text-center ">
<strong>Warning!</strong> Android Platform Configurations is empty. Please set Platform Configurations before generating QR code.
</div>
<div id="android-enroll-manually-instructions" class="row" style="display:none">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-12 add-padding-top-2x "> <div class="col-xs-12 col-sm-12 col-md-8 col-lg-12 add-padding-top-2x ">
{{#if isVirtual}} {{#if isVirtual}}
<h3 class="uppercase">TRY OUT THE VIRTUAL ANDROID DEVICE</h3> <h3 class="uppercase">TRY OUT THE VIRTUAL ANDROID DEVICE</h3>
@ -81,8 +154,6 @@
<hr> <hr>
</div> </div>
</div> </div>
<div class="row grey-bg">
{{#if isCloud}} {{#if isCloud}}
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4 add-padding-top-2x add-padding-bottom-2x"> <div class="col-xs-12 col-sm-6 col-md-4 col-lg-4 add-padding-top-2x add-padding-bottom-2x">
<h5><strong>Step 1</strong></h5> <h5><strong>Step 1</strong></h5>
@ -109,14 +180,14 @@
</li> </li>
</ol> </ol>
</div> </div>
<img src="{{@unit.publicUri}}/images/android-tryit.png" class="img-responsive"> <img src="{{@unit.publicUri}}/images/android-tryit.png" style="width:70%;" class="img-responsive">
{{else}} {{else}}
<div class="add-min-height"> <div class="add-min-height">
<p>Let's start by opening the Android agent on your device. <p>Let's start by opening the Android agent on your device.
<br/>Tap on <b>WSO2 Device Management Agent</b>. <br/>Tap on <b>WSO2 Device Management Agent</b>.
</p> </p>
</div> </div>
<img src="{{@unit.publicUri}}/images/launch_agent.png" class="img-responsive"> <img src="{{@unit.publicUri}}/images/launch_agent.png" style="width:70%;" class="img-responsive">
{{/if}} {{/if}}
</div> </div>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 col-md-offset-1 col-lg-offset-1 add-padding-top-2x add-padding-bottom-2x"> <div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 col-md-offset-1 col-lg-offset-1 add-padding-top-2x add-padding-bottom-2x">
@ -128,7 +199,7 @@
<li>Password: <i>Your Cloud password.</i></li> <li>Password: <i>Your Cloud password.</i></li>
</ul> </ul>
</div> </div>
<img src="{{@unit.publicUri}}/images/register-cloud.png" class="img-responsive"> <img src="{{@unit.publicUri}}/images/register-cloud.png" style="width:70%;" class="img-responsive">
</div> </div>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 col-md-offset-1 col-lg-offset-1 add-padding-top-2x add-padding-bottom-2x"> <div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 col-md-offset-1 col-lg-offset-1 add-padding-top-2x add-padding-bottom-2x">
<h5><strong>Step 3</strong></h5> <h5><strong>Step 3</strong></h5>
@ -168,29 +239,28 @@
</li> </li>
</ol> </ol>
</div> </div>
<img src="{{@unit.publicUri}}/images/android-tryit.png" class="img-responsive"> <img src="{{@unit.publicUri}}/images/android-tryit.png" style="width:70%;" class="img-responsive">
{{else}} {{else}}
<div class="add-min-height"> <div class="add-min-height">
<p>Let's start by installing the Android agent on your device. Open the downloaded file, and tap <p>Let's start by installing the Android agent on your device. Open the downloaded file, and tap
<b>INSTALL</b>.</p> <b>INSTALL</b>.</p>
</div> </div>
<img src="{{@unit.publicUri}}/images/install_agent.png" class="img-responsive"> <img src="{{@unit.publicUri}}/images/install_agent.png" style="width:70%;" class="img-responsive">
{{/if}} {{/if}}
</div> </div>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 add-padding-top-2x add-padding-bottom-2x"> <div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 add-padding-top-2x add-padding-bottom-2x">
<h5><strong>Step 2</strong></h5> <h5><strong>Step 2</strong></h5>
<div class="add-min-height"> <div class="add-min-height">
<p>Tap Skip to proceed with the default enrollment process.</p> <p>Tap Skip to proceed with the default enrollment process.</p>
</div> </div>
<img src="{{@unit.publicUri}}/images/set_profile.png" class="img-responsive"> <img src="{{@unit.publicUri}}/images/set_profile.png" style="width:70%;" class="img-responsive">
</div> </div>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 add-padding-top-2x add-padding-bottom-2x"> <div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 add-padding-top-2x add-padding-bottom-2x">
<h5><strong>Step 3</strong></h5> <h5><strong>Step 3</strong></h5>
<div class="add-min-height"> <div class="add-min-height">
<p>Enter the server address based on your environment, in the text box provided.</p> <p>Enter the server address based on your environment, in the text box provided.</p>
</div> </div>
<img src="{{@unit.publicUri}}/images/registration.png" class="img-responsive"> <img src="{{@unit.publicUri}}/images/registration.png" style="width:70%;" class="img-responsive">
</div> </div>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 add-padding-top-2x add-padding-bottom-2x"> <div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 add-padding-top-2x add-padding-bottom-2x">
<h5><strong>Step 4</strong></h5> <h5><strong>Step 4</strong></h5>
@ -202,27 +272,11 @@
<li>Password: <i>Your password.</i></li> <li>Password: <i>Your password.</i></li>
</ul> </ul>
</div> </div>
<img src="{{@unit.publicUri}}/images/register.png" class="img-responsive"> <img src="{{@unit.publicUri}}/images/register.png" style="width:70%;" class="img-responsive">
</div> </div>
{{/if}} {{/if}}
</div> </div>
<div class="row" id="kiosk_heading">
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-12 add-padding-top-2x ">
<h3 class="uppercase">PROVISION YOUR KIOSK DEVICE</h3>
<hr>
</div>
</div>
<div class="a-token" data-atoken="{{accessToken}}"></div>
<div class="row" id="kiosk_content">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 add-padding-top-2x add-padding-bottom-2x">
<h3 class="text-center">Scan to provision the KIOSK device</h3>
<div class="kiosk-enrollment-qr-container text-center"></div>
</div>
</div>
{{#zone "topCss"}} {{#zone "topCss"}}
{{css "css/styles.css"}} {{css "css/styles.css"}}
{{/zone}} {{/zone}}

Loading…
Cancel
Save