IOTS-296: Generalizing policy UI for policy create wizard

This commit is done to seperate policy related client side logic and UIs from device type specific logics.
This is a part of creating self contained plugins  for device types.

This commit generalizes the policy creation wizard in the CDMF core and removes device type specific UIs and client side logic from the core. Also, this introduces a generic policy configuration UI in a new unit.
revert-70aa11f8
Madawa Soysa 8 years ago
parent 8431b30ddc
commit 0dfde40b7c

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

@ -0,0 +1,14 @@
{{#zone "topCss"}}
{{css "css/codemirror.css"}}
{{/zone}}
<div class="wr-input-control">
<div class="cus-col-100">
<textarea id="policy-definition-input" placeholder="Enter the policy"></textarea>
</div>
<br class="c-both"/>
</div>
{{#zone "bottomJs"}}
{{js "js/codemirror.js"}}
{{js "js/sql.js"}}
{{js "js/editor.js"}}
{{/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.
*/
window.queryEditor = CodeMirror.fromTextArea(document.getElementById('policy-definition-input'), {
mode: MIME_TYPE_SIDDHI_QL,
indentWithTabs: true,
smartIndent: true,
lineNumbers: true,
matchBrackets: true,
autofocus: true,
extraKeys: {
"Shift-2": function (cm) {
insertStr(cm, cm.getCursor(), '@');
CodeMirror.showHint(cm, getAnnotationHints);
},
"Ctrl-Space": "autocomplete"
}
});
var validatePolicyProfile = function () {
return true;
};

@ -33,12 +33,26 @@
callback(template); callback(template);
} }
}; };
$.isResourceExists = function (location, callback) {
$.ajax({
url: location,
type: 'HEAD',
success: function () {
callback(true);
},
error: function () {
callback(false);
}
});
};
$.registerPartial = function (name, location, callback) { $.registerPartial = function (name, location, callback) {
$.get(location, function (data) { $.get(location, function (data) {
Handlebars.registerPartial( name, data); Handlebars.registerPartial(name, data);
console.log("Partial " + name + " has been registered"); console.log("Partial " + name + " has been registered");
callback(); callback();
}); });
}; };
})(); })();

@ -1,74 +1,293 @@
{{!
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 "content"}} {{#zone "content"}}
{{#if isAuthorized}} {{#if isAuthorized}}
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="container col-centered wr-content policy-platform">
<div class="wr-steps hidden">
<div class="col-md-3 col-xs-3">
<div class="itm-wiz itm-wiz-current" data-step="policy-platform">
<div class="wiz-no">1</div>
<div class="wiz-lbl hidden-xs"><span>Select a platform</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-profile">
<div class="wiz-no">2</div>
<div class="wiz-lbl hidden-xs"><span>Configure profile</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-criteria">
<div class="wiz-no">3</div>
<div class="wiz-lbl hidden-xs"><span>Assign to groups</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-naming">
<div class="wiz-no">4</div>
<div class="wiz-lbl hidden-xs"><span>Publish to devices</span></div>
</div>
<br class="c-both"/>
</div>
</div>
<div class="col-centered policy-message hidden">
<div class="wr-form"> <div class="wr-form">
<h1 id="policy-platform-page-wizard-title" class="page-sub-title">ADD POLICY</h1> <h1 id="policy-message-page-wizard-title" class="page-sub-title">Policy creation is
successful.</h1>
<br>Please click <b>"Add Another Policy"</b>, if you wish to add another policy or click
<b>"View policy list"</b> to complete the process and go back to the policy list.
<hr>
<button class="wr-btn wizard-stepper" data-current="policy-message"
data-direct="{{@app.context}}/policies/">
View policy list
</button>
<!--suppress HtmlUnknownTarget -->
<a href="{{@app.context}}/policy/add" class="cu-btn-inner">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-add fw-stack-1x"></i>
</span>
Add another policy
</a>
</div>
</div>
<div class="col-centered wr-content policy-naming hidden">
<div class="wr-form">
<h1 id="policy-naming-page-wizard-title" class="page-sub-title">ADD POLICY</h1>
<hr>
<div id="policy-naming-wizard-steps" class="row wr-wizard"></div>
<hr> <hr>
<div id="policy-platform-wizard-steps" class="row wr-wizard"> <div class="row">
<div class="col-md-3 col-xs-3"> <div class="col-lg-12">
<div class="itm-wiz itm-wiz-current" data-step="policy-platform"> <h4 class="hidden-xs">Step 4: Publish to devices</h4>
<div class="wiz-no">1</div> <br>
<div class="wiz-lbl hidden-xs"><span>Select a platform</span></div> <div id="policy-naming-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div> </div>
<br class="c-both"/> <div class="clearfix">
</div> <label class="wr-input-label">Set a Name for your Policy *</label>
<div class="col-md-3 col-xs-3"> <br/>
<div class="itm-wiz" data-step="policy-profile"> <label class="wr-input-label">
<div class="wiz-no">2</div> (Policy name should be 1-to-30 characters long)
<div class="wiz-lbl hidden-xs"><span>Configure profile</span></div> </label>
<div id="policyNameField" class="wr-input-control">
<div class="cus-col-50 form-group wr-input-control">
<!--suppress HtmlFormInputWithoutLabel -->
<input id="policy-name-input" class="form-control" type="text" value=""/>
<label class="error nameEmpty hidden" for="summary">Policy name is required
&
Should be be 1-to-30
characters long.</label>
</div>
<br class="c-both"/>
</div>
<br class="c-both"/>
<label class="wr-input-label">
Add a description
</label>
<div class="wr-input-control">
<div class="cus-col-50">
<textarea id="policy-description-input" class="form-control" rows="10"
placeholder="[ Summary about the policy ]"></textarea>
</div>
<br class="c-both"/>
</div>
</div>
<div class="wr-input-control wr-btn-grp">
<a href="javascript:void(0)" class="wr-btn wizard-stepper" data-is-back-btn="true"
data-current="policy-naming" data-next="policy-criteria">Back</a>
<a href="javascript:void(0)" class="wr-btn wizard-stepper"
data-current="policy-naming-publish" data-next="policy-message"
data-validate="true">Publish</a>
<a href="javascript:void(0)" class="wr-btn wizard-stepper"
data-current="policy-naming"
data-next="policy-message" data-validate="true">Save</a>
</div> </div>
<br class="c-both"/>
</div> </div>
<div class="col-md-3 col-xs-3"> </div>
<div class="itm-wiz" data-step="policy-criteria"> </div>
<div class="wiz-no">3</div> </div>
<div class="wiz-lbl hidden-xs"><span>Assign</span></div>
<div class="col-centered wr-content policy-criteria hidden">
<div class="wr-form">
<h1 id="policy-criteria-page-wizard-title" class="page-sub-title">ADD POLICY</h1>
<hr>
<div id="policy-criteria-wizard-steps" class="row wr-wizard"></div>
<hr>
<div class="row">
<div class="col-lg-12">
<h4 class="hidden-xs">Step 3: Assign to groups</h4>
<br>
<div id="policy-criteria-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<div>
<label class="wr-input-label">
Set device ownership type
</label>
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="ownership-input" class="form-control">
<option value="ANY" selected>ANY</option>
<option value="BYOD">BYOD (Bring Your Own Device)</option>
<option value="COPE">COPE (Corporate-Owned, Personally Enabled)</option>
</select>
</div>
<br class="c-both"/>
</div>
<div class="wr-input-control">
{{#if isAuthorizedViewRoles}}
<label class="wr-input-control radio light">
<input id="user-roles-radio-btn" type="radio"
name="select-users-radio-btn"
class="select-users-radio" checked/>
<span class="helper">Set user role(s)</span>
</label>
{{/if}}
{{#if isAuthorizedViewUsers}}
<label class="wr-input-control radio light" rel="assetfilter">
<input id="users-radio-btn" type="radio" name="select-users-radio-btn"
class="select-users-radio"/>
<span class="helper">Set user(s)</span>
</label>
{{/if}}
</div>
{{#if isAuthorizedViewRoles}}
<div id="user-roles-select-field" class="select-users">
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="user-roles-input" class="form-control select2"
multiple="multiple">
<option value="ANY" selected>ANY</option>
{{#each roles}}
<option>{{this}}</option>
{{/each}}
</select>
</div>
<br class="c-both"/>
</div>
</div>
{{/if}}
{{#if isAuthorizedViewUsers}}
<div id="users-select-field" class="select-users">
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="users-input" class="form-control select2"
multiple="multiple">
</select>
</div>
<br class="c-both"/>
</div>
</div>
{{/if}}
<br>
<label class="wr-input-label" title="">
Set an action upon non-compliance
</label>
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="action-input" class="form-control">
<option data-action="enforce" selected>Enforce</option>
<option data-action="warn">Warn</option>
<option data-action="monitor">Monitor</option>
</select>
</div>
<br class="c-both"/>
</div>
</div>
<div class="wr-input-control wr-btn-grp">
<a href="javascript:void(0)" class="wr-btn wizard-stepper" data-is-back-btn="true"
data-current="policy-criteria" data-next="policy-profile">Back</a>
<a href="javascript:void(0)" class="wr-btn wizard-stepper"
data-current="policy-criteria" data-next="policy-naming" data-validate="true">Continue</a>
</div> </div>
<br class="c-both"/>
</div> </div>
<div class="col-md-3 col-xs-3"> </div>
<div class="itm-wiz" data-step="policy-naming"> </div>
<div class="wiz-no">4</div> </div>
<div class="wiz-lbl hidden-xs"><span>Publish to devices</span></div>
<div class="col-centered wr-content policy-profile hidden">
<div class="wr-form">
<h1 id="policy-profile-page-wizard-title" class="page-sub-title">ADD POLICY</h1>
<hr>
<div id="policy-profile-wizard-steps" class="row wr-wizard"></div>
<hr>
<div class="row">
<div class="col-lg-12">
<h4 class="hidden-xs">Step 2: Configure profile</h4>
<br>
<div id="policy-profile-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<div class="wr-advance-operations">
<div class='wr-advance-operations-init'>
<br/>
<i class='fw fw-settings fw-spin fw-2x'></i>
Loading Platform Features . . .
<br/>
<br/>
</div>
<div id="device-type-policy-operations" class="hidden">
</div>
<div id="generic-policy-operations" class="hidden">
{{unit "cdmf.unit.device.type.generic.policy-wizard"}}
</div>
</div>
<div class="wr-input-control wr-btn-grp">
<a href="javascript:void(0)" class="wr-btn wizard-stepper" data-is-back-btn="true"
data-current="policy-profile" data-next="policy-platform">Back</a>
<a href="javascript:void(0)" class="wr-btn wizard-stepper"
data-current="policy-profile"
data-next="policy-criteria" data-validate="true">Continue</a>
</div> </div>
<br class="c-both"/>
</div> </div>
</div> </div>
</div>
</div>
<div id="loading-content" class="col-centered">
<br><br>
<i class="fw fw-settings fw-spin fw-2x"></i>
Loading policy creation wizard . . .
<br><br>
</div>
<div class=" col-centered wr-content policy-platform hidden">
<div class="wr-form">
<h1 id="policy-platform-page-wizard-title" class="page-sub-title">ADD POLICY</h1>
<hr> <hr>
<div id="policy-platform-wizard-steps" class="row wr-wizard"></div>
<hr>
<!--<div id="policy-platform-main-error-msg" class="alert alert-danger hidden" role="alert">-->
<!--<i class="icon fw fw-error"></i><span></span>-->
<!--</div>-->
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">
<h4>Step 1: Select a platform</h4> <h4 class="hidden-xs"> Step 1: Select a platform</h4>
<br> <br>
<div id="policy-platform-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<div class="row wr-tile-buttons-list"> <div class="row wr-tile-buttons-list">
<div class="wr-input-control"> <div class="wr-input-control">
<ul class="tile-buttons row"> <ul class="tile-buttons row">
{{#each types}} {{#each types}}
<li class="col-lg-4" <li class="col-xs-12 col-sm-12 col-md-4 col-lg-4"
style="margin-top: 5px;margin-bottom: 5px;"> style="margin-top: 5px; margin-bottom: 5px;">
<a href="{{@app.context}}/policy/add/{{name}}" <a href="javascript:void(0)"
class="wizard-stepper"> class="{{name}}-platform wizard-stepper"
<img src="{{icon}}" width="50px" data-current="policy-platform"
height="50px"><br><br> data-next="policy-profile"
data-platform="{{name}}"
data-validate="false">
<img src="{{icon}}" width="50px" height="50px"><br><br>
<b>{{label}}</b> <b>{{label}}</b>
</a> </a>
</li> </li>
@ -83,12 +302,8 @@
<!-- content --> <!-- content -->
</div> </div>
</div> </div>
{{else}}
<h1 class="page-sub-title">
Permission Denied
</h1>
<br>
You not authorized to enter Policy Management Section.
<br>
{{/if}} {{/if}}
{{/zone}} {{/zone}}
{{#zone "bottomJs"}}
{{js "/js/policy-create.js"}}
{{/zone}}

@ -0,0 +1,532 @@
/*
*
* 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 stepForwardFrom = {};
var stepBackFrom = {};
var policy = {};
var configuredOperations = [];
var validateInline = {};
var clearInline = {};
var validateStep = {};
var enableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
var errorSignIdentifier = "#" + inputField + " ." + errorSign;
if (inputField) {
$(fieldIdentifier).addClass(" has-error has-feedback");
}
if (errorMsg) {
$(errorMsgIdentifier).removeClass(" hidden");
}
if (errorSign) {
$(errorSignIdentifier).removeClass(" hidden");
}
};
var disableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
var errorSignIdentifier = "#" + inputField + " ." + errorSign;
if (inputField) {
$(fieldIdentifier).removeClass(" has-error has-feedback");
}
if (errorMsg) {
$(errorMsgIdentifier).addClass(" hidden");
}
if (errorSign) {
$(errorSignIdentifier).addClass(" hidden");
}
};
/**
*clear inline validation messages.
*/
clearInline["policy-name"] = function () {
disableInlineError("policyNameField", "nameEmpty", "nameError");
};
/**
* Validate if provided policy name is valid against RegEx configures.
*/
validateInline["policy-name"] = function () {
var policyName = $("input#policy-name-input").val();
if (policyName && inputIsValidAgainstLength(policyName, 1, 30)) {
disableInlineError("policyNameField", "nameEmpty", "nameError");
} else {
enableInlineError("policyNameField", "nameEmpty", "nameError");
}
};
$("#policy-name-input").focus(function(){
clearInline["policy-name"]();
}).blur(function(){
validateInline["policy-name"]();
});
stepForwardFrom["policy-platform"] = function (actionButton) {
$("#device-type-policy-operations").html("").addClass("hidden");
$("#generic-policy-operations").addClass("hidden");
policy["platform"] = $(actionButton).data("platform");
policy["platformId"] = $(actionButton).data("platform-type");
// updating next-page wizard title with selected platform
$("#policy-profile-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
var deviceType = policy["platform"];
var policyOperationsTemplateSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/templates/' + deviceType + '-policy-operations.hbs';
var policyOperationsScriptSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/js/' + deviceType + '-policy-operations.js';
var policyOperationsStylesSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/css/' + deviceType + '-policy-operations.css';
var policyOperationsTemplateCacheKey = deviceType + '-policy-operations';
$.isResourceExists(policyOperationsTemplateSrc, function (status) {
if (status) {
$.template(policyOperationsTemplateCacheKey, policyOperationsTemplateSrc, function (template) {
var content = template();
$("#device-type-policy-operations").html(content).removeClass("hidden");
// $("#device-type-policy-operations").removeClass("hidden");
$(".policy-platform").addClass("hidden");
});
$.isResourceExists(policyOperationsScriptSrc, function (status) {
if (status) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = policyOperationsScriptSrc;
$(".wr-advance-operations").prepend(script);
}
});
$.isResourceExists(policyOperationsStylesSrc, function (status) {
if (status) {
var style = document.createElement('link');
style.type = 'text/css';
style.rel = 'stylesheet';
style.href = policyOperationsStylesSrc;
$(".wr-advance-operations").prepend(style);
}
});
} else {
$("#generic-policy-operations").removeClass("hidden");
}
$(".wr-advance-operations-init").addClass("hidden");
});
};
stepForwardFrom["policy-profile"] = function () {
policy["profile"] = operationModule.generateProfile(policy["platform"], configuredOperations);
// updating next-page wizard title with selected platform
$("#policy-criteria-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
};
stepBackFrom["policy-profile"] = function () {
// reinitialize configuredOperations
configuredOperations = [];
};
stepForwardFrom["policy-criteria"] = function () {
$("input[type='radio'].select-users-radio").each(function () {
if ($(this).is(':radio')) {
if ($(this).is(":checked")) {
if ($(this).attr("id") == "users-radio-btn") {
policy["selectedUsers"] = $("#users-input").val();
policy["selectedUserRoles"] = null;
} else if ($(this).attr("id") == "user-roles-radio-btn") {
policy["selectedUsers"] = null;
policy["selectedUserRoles"] = $("#user-roles-input").val();
}
}
}
});
policy["selectedNonCompliantAction"] = $("#action-input").find(":selected").data("action");
policy["selectedOwnership"] = $("#ownership-input").val();
//updating next-page wizard title with selected platform
$("#policy-naming-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
};
/**
* Checks if provided input is valid against provided length range.
*
* @param input Alphanumeric or non-alphanumeric input
* @param minLength Minimum Required Length
* @param maxLength Maximum Required Length
* @returns {boolean} Returns true if input matches the provided minimum length and maximum length
*/
var inputIsValidAgainstLength = function (input, minLength, maxLength) {
var length = input.length;
return (length == minLength || (length > minLength && length < maxLength) || length == maxLength);
};
validateStep["policy-criteria"] = function () {
var validationStatus = {};
var selectedAssignees;
var selectedField = "Role(s)";
$("input[type='radio'].select-users-radio").each(function () {
if ($(this).is(":checked")) {
if ($(this).attr("id") == "users-radio-btn") {
selectedAssignees = $("#users-input").val();
selectedField = "User(s)";
} else if ($(this).attr("id") == "user-roles-radio-btn") {
selectedAssignees = $("#user-roles-input").val();
}
return false;
}
});
if (selectedAssignees) {
validationStatus["error"] = false;
} else {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = selectedField + " is a required field. It cannot be empty";
}
var wizardIsToBeContinued;
if (validationStatus["error"]) {
wizardIsToBeContinued = false;
var mainErrorMsgWrapper = "#policy-criteria-main-error-msg";
var mainErrorMsg = mainErrorMsgWrapper + " span";
$(mainErrorMsg).text(validationStatus["mainErrorMsg"]);
$(mainErrorMsgWrapper).removeClass("hidden");
} else {
wizardIsToBeContinued = true;
}
return wizardIsToBeContinued;
};
validateStep["policy-naming"] = function () {
var validationStatus = {};
// taking values of inputs to be validated
var policyName = $("input#policy-name-input").val();
// starting validation process and updating validationStatus
if (!policyName) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = "Policy name is empty. You cannot proceed.";
} else if (!inputIsValidAgainstLength(policyName, 1, 30)) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] =
"Policy name exceeds maximum allowed length.";
} else {
validationStatus["error"] = false;
}
// ending validation process
// start taking specific actions upon validation
var wizardIsToBeContinued;
if (validationStatus["error"]) {
wizardIsToBeContinued = false;
var mainErrorMsgWrapper = "#policy-naming-main-error-msg";
var mainErrorMsg = mainErrorMsgWrapper + " span";
$(mainErrorMsg).text(validationStatus["mainErrorMsg"]);
$(mainErrorMsgWrapper).removeClass("hidden");
} else {
wizardIsToBeContinued = true;
}
return wizardIsToBeContinued;
};
validateStep["policy-platform"] = function () {
return false;
};
validateStep["policy-naming-publish"] = function () {
var validationStatus = {};
// taking values of inputs to be validated
var policyName = $("input#policy-name-input").val();
// starting validation process and updating validationStatus
if (!policyName) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = "Policy name is empty. You cannot proceed.";
} else if (!inputIsValidAgainstLength(policyName, 1, 30)) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] =
"Policy name exceeds maximum allowed length.";
} else {
validationStatus["error"] = false;
}
// ending validation process
// start taking specific actions upon validation
var wizardIsToBeContinued;
if (validationStatus["error"]) {
wizardIsToBeContinued = false;
var mainErrorMsgWrapper = "#policy-naming-main-error-msg";
var mainErrorMsg = mainErrorMsgWrapper + " span";
$(mainErrorMsg).text(validationStatus["mainErrorMsg"]);
$(mainErrorMsgWrapper).removeClass("hidden");
} else {
wizardIsToBeContinued = true;
}
return wizardIsToBeContinued;
};
stepForwardFrom["policy-naming-publish"] = function () {
policy["policyName"] = $("#policy-name-input").val();
policy["description"] = $("#policy-description-input").val();
//All data is collected. Policy can now be updated.
savePolicy(policy, true, "/api/device-mgt/v1.0/policies/");
};
stepForwardFrom["policy-naming"] = function () {
policy["policyName"] = $("#policy-name-input").val();
policy["description"] = $("#policy-description-input").val();
//All data is collected. Policy can now be updated.
savePolicy(policy, false, "/api/device-mgt/v1.0/policies/");
};
var savePolicy = function (policy, isActive, serviceURL) {
var profilePayloads = [];
// traverses key by key in policy["profile"]
var key;
for (key in policy["profile"]) {
if (policy["profile"].hasOwnProperty(key)) {
profilePayloads.push({
"featureCode": key,
"deviceType": policy["platform"],
"content": policy["profile"][key]
});
}
}
$.each(profilePayloads, function (i, item) {
$.each(item.content, function (key, value) {
//cannot add a true check since it will catch value = false as well
if (value === null || value === undefined || value === "") {
item.content[key] = null;
}
});
});
var payload = {
"policyName": policy["policyName"],
"description": policy["description"],
"compliance": policy["selectedNonCompliantAction"],
"ownershipType": policy["selectedOwnership"],
"active": isActive,
"profile": {
"profileName": policy["policyName"],
"deviceType": policy["platform"],
"profileFeaturesList": profilePayloads
}
};
if (policy["selectedUsers"]) {
payload["users"] = policy["selectedUsers"];
} else if (policy["selectedUserRoles"]) {
payload["roles"] = policy["selectedUserRoles"];
} else {
payload["users"] = [];
payload["roles"] = [];
}
invokerUtil.post(
serviceURL,
payload,
function () {
$(".add-policy").addClass("hidden");
$(".policy-naming").addClass("hidden");
$(".policy-message").removeClass("hidden");
},
function (data) {
}
);
};
function formatRepo(user) {
if (user.loading) {
return user.text;
}
if (!user.username) {
return;
}
var markup = '<div class="clearfix">' +
'<div clas="col-sm-8">' +
'<div class="clearfix">' +
'<div class="col-sm-3">' + user.username + '</div>';
if (user.firstname) {
markup += '<div class="col-sm-3"><i class="fa fa-code-fork"></i> ' + user.firstname + '</div>';
}
if (user.emailAddress) {
markup += '<div class="col-sm-2"><i class="fa fa-star"></i> ' + user.emailAddress + '</div></div>';
}
markup += '</div></div>';
return markup;
}
function formatRepoSelection(user) {
return user.username || user.text;
}
// End of functions related to grid-input-view
$(document).ready(function () {
$("#users-input").select2({
multiple: true,
tags: false,
ajax: {
url: context + "/api/invoker/execute/",
method: "POST",
dataType: 'json',
delay: 250,
id: function (user) {
return user.username;
},
data: function (params) {
var postData = {};
postData.requestMethod = "GET";
postData.requestURL = "/api/device-mgt/v1.0/users/search/usernames?filter=" + params.term;
postData.requestPayload = null;
return JSON.stringify(postData);
},
processResults: function (data) {
var newData = [];
$.each(data, function (index, value) {
value.id = value.username;
newData.push(value);
});
return {
results: newData
};
},
cache: true
},
escapeMarkup: function (markup) {
return markup;
}, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
$("#loading-content").remove();
$(".policy-platform").removeClass("hidden");
// Adding initial state of wizard-steps.
$("#policy-platform-wizard-steps").html($(".wr-steps").html());
$("select.select2[multiple=multiple]").select2({
"tags": false
});
$("#users-select-field").hide();
$("#user-roles-select-field").show();
$("input[type='radio'].select-users-radio").change(function () {
if ($("#users-radio-btn").is(":checked")) {
$("#user-roles-select-field").hide();
$("#users-select-field").show();
}
if ($("#user-roles-radio-btn").is(":checked")) {
$("#users-select-field").hide();
$("#user-roles-select-field").show();
}
});
// Support for special input type "ANY" on user(s) & user-role(s) selection
$("#user-roles-input").select2({
"tags": false
}).on("select2:select", function (e) {
if (e.params.data.id == "ANY") {
$(this).val("ANY").trigger("change");
} else {
$("option[value=ANY]", this).prop("selected", false).parent().trigger("change");
}
});
//Policy wizard stepper
$(".wizard-stepper").click(function () {
// button clicked here can be either a continue button or a back button.
var currentStep = $(this).data("current");
var validationIsRequired = $(this).data("validate");
var wizardIsToBeContinued;
if (validationIsRequired) {
if (currentStep == "policy-profile") {
wizardIsToBeContinued = validatePolicyProfile();
} else {
wizardIsToBeContinued = validateStep[currentStep]();
}
} else {
wizardIsToBeContinued = true;
}
if (wizardIsToBeContinued) {
// When moving back and forth, following code segment will
// remove if there are any visible error-messages.
var errorMsgWrappers = ".alert.alert-danger";
$(errorMsgWrappers).each(
function () {
if (!$(this).hasClass("hidden")) {
$(this).addClass("hidden");
}
}
);
var nextStep = $(this).data("next");
var isBackBtn = $(this).data("is-back-btn");
// if current button is a continuation...
if (!isBackBtn) {
// initiate stepForwardFrom[*] functions to gather form data.
if (stepForwardFrom[currentStep]) {
stepForwardFrom[currentStep](this);
}
} else {
// initiate stepBackFrom[*] functions to rollback.
if (stepBackFrom[currentStep]) {
stepBackFrom[currentStep]();
}
}
// following step occurs only at the last stage of the wizard.
if (!nextStep) {
window.location.href = $(this).data("direct");
}
// updating next wizard step as current.
$(".itm-wiz").each(function () {
var step = $(this).data("step");
if (step == nextStep) {
$(this).addClass("itm-wiz-current");
} else {
$(this).removeClass("itm-wiz-current");
}
});
// adding next update of wizard-steps.
$("#" + nextStep + "-wizard-steps").html($(".wr-steps").html());
// hiding current section of the wizard and showing next section.
$("." + currentStep).addClass("hidden");
$("." + nextStep).removeClass("hidden");
}
});
});

@ -1,17 +1,16 @@
/* /*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* *
* WSO2 Inc. licenses this file to you under the Apache License, * WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except * Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. * in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, * Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an * software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* KIND, either express or implied. See the License for the * either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
@ -21,60 +20,120 @@ var stepForwardFrom = {};
var stepBackFrom = {}; var stepBackFrom = {};
var policy = {}; var policy = {};
var configuredOperations = []; var configuredOperations = [];
var deviceTypeLabel; var validateInline = {};
var clearInline = {};
/** var enableInlineError = function (inputField, errorMsg, errorSign) {
* Method to update the visibility of grouped input. var fieldIdentifier = "#" + inputField;
* @param domElement HTML grouped-input element with class name "grouped-input" var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
*/ var errorSignIdentifier = "#" + inputField + " ." + errorSign;
var updateGroupedInputVisibility = function (domElement) {
if ($(".parent-input:first", domElement).is(":checked")) { if (inputField) {
if ($(".grouped-child-input:first", domElement).hasClass("disabled")) { $(fieldIdentifier).addClass(" has-error has-feedback");
$(".grouped-child-input:first", domElement).removeClass("disabled"); }
}
$(".child-input", domElement).each(function () { if (errorMsg) {
$(this).prop('disabled', false); $(errorMsgIdentifier).removeClass(" hidden");
}); }
} else {
if (!$(".grouped-child-input:first", domElement).hasClass("disabled")) { if (errorSign) {
$(".grouped-child-input:first", domElement).addClass("disabled"); $(errorSignIdentifier).removeClass(" hidden");
} }
$(".child-input", domElement).each(function () { };
$(this).prop('disabled', true);
}); var disableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
var errorSignIdentifier = "#" + inputField + " ." + errorSign;
if (inputField) {
$(fieldIdentifier).removeClass(" has-error has-feedback");
}
if (errorMsg) {
$(errorMsgIdentifier).addClass(" hidden");
}
if (errorSign) {
$(errorSignIdentifier).addClass(" hidden");
} }
}; };
/** /**
* Checks if provided number is valid against a range. *clear inline validation messages.
*
* @param numberInput Number Input
* @param min Minimum Limit
* @param max Maximum Limit
* @returns {boolean} Returns true if input is within the specified range
*/ */
var inputIsValidAgainstRange = function (numberInput, min, max) { clearInline["policy-name"] = function () {
return (numberInput == min || (numberInput > min && numberInput < max) || numberInput == max); disableInlineError("policyNameField", "nameEmpty", "nameError");
}; };
/** /**
* Checks if provided input is valid against RegEx input. * Validate if provided policy name is valid against RegEx configures.
*
* @param regExp Regular expression
* @param input Input string to check
* @returns {boolean} Returns true if input matches RegEx
*/ */
var inputIsValidAgainstRegExp = function (regExp, input) { validateInline["policy-name"] = function () {
return regExp.test(input); var policyName = $("input#policy-name-input").val();
if (policyName && inputIsValidAgainstLength(policyName, 1, 30)) {
disableInlineError("policyNameField", "nameEmpty", "nameError");
} else {
enableInlineError("policyNameField", "nameEmpty", "nameError");
}
}; };
validateStep["policy-profile"] = function () { $("#policy-name-input").focus(function(){
return true; clearInline["policy-name"]();
}).blur(function(){
validateInline["policy-name"]();
});
stepForwardFrom["policy-platform"] = function (actionButton) {
policy["platform"] = $(actionButton).data("platform");
policy["platformId"] = $(actionButton).data("platform-type");
// updating next-page wizard title with selected platform
$("#policy-profile-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
var deviceType = policy["platform"];
var policyOperationsTemplateSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/templates/' + deviceType + '-policy-operations.hbs';
var policyOperationsScriptSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/js/' + deviceType + '-policy-operations.js';
var policyOperationsStylesSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/css/' + deviceType + '-policy-operations.css';
var policyOperationsTemplateCacheKey = deviceType + '-policy-operations';
$.isResourceExists(policyOperationsTemplateSrc, function (status) {
if (status) {
$.template(policyOperationsTemplateCacheKey, policyOperationsTemplateSrc, function (template) {
var content = template();
$(".wr-advance-operations").html(content);
$(".policy-platform").addClass("hidden");
});
}
});
$.isResourceExists(policyOperationsScriptSrc, function (status) {
if (status) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = policyOperationsScriptSrc;
$(".wr-advance-operations").prepend(script);
}
});
$.isResourceExists(policyOperationsStylesSrc, function (status) {
if (status) {
var style = document.createElement('link');
style.type = 'text/css';
style.rel = 'stylesheet';
style.href = policyOperationsStylesSrc;
$(".wr-advance-operations").prepend(style);
}
});
}; };
stepForwardFrom["policy-profile"] = function () { stepForwardFrom["policy-profile"] = function () {
policy["profile"] = operationModule.generateProfile(policy["platform"], configuredOperations);
// updating next-page wizard title with selected platform // updating next-page wizard title with selected platform
$("#policy-criteria-page-wizard-title").text("ADD " + deviceTypeLabel + " POLICY"); $("#policy-criteria-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
}; };
stepBackFrom["policy-profile"] = function () { stepBackFrom["policy-profile"] = function () {
@ -84,15 +143,13 @@ stepBackFrom["policy-profile"] = function () {
// so that, the wrong content would not be shown at the first glance, in case // so that, the wrong content would not be shown at the first glance, in case
// the user selects a different platform // the user selects a different platform
$(".wr-advance-operations").html( $(".wr-advance-operations").html(
"<div class='wr-advance-operations-init'>" + "<div class='wr-advance-operations-init'>" +
"<br>" + "<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + "<i class='fw fw-settings fw-spin fw-2x'></i>" +
"<i class='fw fw-settings fw-spin fw-2x'></i>" + "Loading Platform Features . . ." +
"&nbsp;&nbsp;&nbsp;&nbsp;" + "<br>" +
"Loading Platform Features . . ." + "<br>" +
"<br>" + "</div>"
"<br>" +
"</div>"
); );
}; };
@ -102,18 +159,18 @@ stepForwardFrom["policy-criteria"] = function () {
if ($(this).is(":checked")) { if ($(this).is(":checked")) {
if ($(this).attr("id") == "users-radio-btn") { if ($(this).attr("id") == "users-radio-btn") {
policy["selectedUsers"] = $("#users-input").val(); policy["selectedUsers"] = $("#users-input").val();
policy["selectedUserRoles"] = null;
} else if ($(this).attr("id") == "user-roles-radio-btn") { } else if ($(this).attr("id") == "user-roles-radio-btn") {
policy["selectedUsers"] = null;
policy["selectedUserRoles"] = $("#user-roles-input").val(); policy["selectedUserRoles"] = $("#user-roles-input").val();
} else if ($(this).attr("id") == "groups-radio-btn") {
policy["selectedUserGroups"] = $("#groups-input").val();
} }
} }
} }
}); });
policy["selectedNonCompliantAction"] = $("#action-input").find(":selected").data("action"); policy["selectedNonCompliantAction"] = $("#action-input").find(":selected").data("action");
policy["selectedOwnership"] = $("#ownership-input").val(); policy["selectedOwnership"] = $("#ownership-input").val();
// updating next-page wizard title with selected platform //updating next-page wizard title with selected platform
$("#policy-naming-page-wizard-title").text("ADD " + deviceTypeLabel + " POLICY"); $("#policy-naming-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
}; };
/** /**
@ -129,6 +186,44 @@ var inputIsValidAgainstLength = function (input, minLength, maxLength) {
return (length == minLength || (length > minLength && length < maxLength) || length == maxLength); return (length == minLength || (length > minLength && length < maxLength) || length == maxLength);
}; };
validateStep["policy-criteria"] = function () {
var validationStatus = {};
var selectedAssignees;
var selectedField = "Role(s)";
$("input[type='radio'].select-users-radio").each(function () {
if ($(this).is(":checked")) {
if ($(this).attr("id") == "users-radio-btn") {
selectedAssignees = $("#users-input").val();
selectedField = "User(s)";
} else if ($(this).attr("id") == "user-roles-radio-btn") {
selectedAssignees = $("#user-roles-input").val();
}
return false;
}
});
if (selectedAssignees) {
validationStatus["error"] = false;
} else {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = selectedField + " is a required field. It cannot be empty";
}
var wizardIsToBeContinued;
if (validationStatus["error"]) {
wizardIsToBeContinued = false;
var mainErrorMsgWrapper = "#policy-criteria-main-error-msg";
var mainErrorMsg = mainErrorMsgWrapper + " span";
$(mainErrorMsg).text(validationStatus["mainErrorMsg"]);
$(mainErrorMsgWrapper).removeClass("hidden");
} else {
wizardIsToBeContinued = true;
}
return wizardIsToBeContinued;
};
validateStep["policy-naming"] = function () { validateStep["policy-naming"] = function () {
var validationStatus = {}; var validationStatus = {};
@ -141,7 +236,7 @@ validateStep["policy-naming"] = function () {
} else if (!inputIsValidAgainstLength(policyName, 1, 30)) { } else if (!inputIsValidAgainstLength(policyName, 1, 30)) {
validationStatus["error"] = true; validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = validationStatus["mainErrorMsg"] =
"Policy name exceeds maximum allowed length. Please check."; "Policy name exceeds maximum allowed length.";
} else { } else {
validationStatus["error"] = false; validationStatus["error"] = false;
} }
@ -162,6 +257,10 @@ validateStep["policy-naming"] = function () {
return wizardIsToBeContinued; return wizardIsToBeContinued;
}; };
validateStep["policy-platform"] = function () {
return false;
};
validateStep["policy-naming-publish"] = function () { validateStep["policy-naming-publish"] = function () {
var validationStatus = {}; var validationStatus = {};
@ -174,7 +273,7 @@ validateStep["policy-naming-publish"] = function () {
} else if (!inputIsValidAgainstLength(policyName, 1, 30)) { } else if (!inputIsValidAgainstLength(policyName, 1, 30)) {
validationStatus["error"] = true; validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = validationStatus["mainErrorMsg"] =
"Policy name exceeds maximum allowed length. Please check."; "Policy name exceeds maximum allowed length.";
} else { } else {
validationStatus["error"] = false; validationStatus["error"] = false;
} }
@ -199,34 +298,48 @@ stepForwardFrom["policy-naming-publish"] = function () {
policy["policyName"] = $("#policy-name-input").val(); policy["policyName"] = $("#policy-name-input").val();
policy["description"] = $("#policy-description-input").val(); policy["description"] = $("#policy-description-input").val();
//All data is collected. Policy can now be updated. //All data is collected. Policy can now be updated.
savePolicy(policy, "publish"); savePolicy(policy, true, "/api/device-mgt/v1.0/policies/");
}; };
stepForwardFrom["policy-naming"] = function () { stepForwardFrom["policy-naming"] = function () {
policy["policyName"] = $("#policy-name-input").val(); policy["policyName"] = $("#policy-name-input").val();
policy["description"] = $("#policy-description-input").val(); policy["description"] = $("#policy-description-input").val();
//All data is collected. Policy can now be updated. //All data is collected. Policy can now be updated.
savePolicy(policy, "save"); savePolicy(policy, false, "/api/device-mgt/v1.0/policies/");
}; };
var savePolicy = function (policy, state) { var savePolicy = function (policy, isActive, serviceURL) {
var profilePayloads = [{ var profilePayloads = [];
"featureCode": "CONFIG", // traverses key by key in policy["profile"]
"deviceTypeId": policy["platformId"], var key;
"content": {"policyDefinition": window.queryEditor.getValue()} for (key in policy["profile"]) {
}]; if (policy["profile"].hasOwnProperty(key)) {
profilePayloads.push({
"featureCode": key,
"deviceType": policy["platform"],
"content": policy["profile"][key]
});
}
}
$.each(profilePayloads, function (i, item) {
$.each(item.content, function (key, value) {
//cannot add a true check since it will catch value = false as well
if (value === null || value === undefined || value === "") {
item.content[key] = null;
}
});
});
var payload = { var payload = {
"policyName": policy["policyName"], "policyName": policy["policyName"],
"description": policy["description"], "description": policy["description"],
"compliance": policy["selectedNonCompliantAction"], "compliance": policy["selectedNonCompliantAction"],
"ownershipType": "ANY", "ownershipType": policy["selectedOwnership"],
"active": (state != "save"), "active": isActive,
"profile": { "profile": {
"profileName": policy["policyName"], "profileName": policy["policyName"],
"deviceType": { "deviceType": policy["platform"],
"id": policy["platformId"],
"name": policy["platform"]
},
"profileFeaturesList": profilePayloads "profileFeaturesList": profilePayloads
} }
}; };
@ -241,101 +354,29 @@ var savePolicy = function (policy, state) {
} }
invokerUtil.post( invokerUtil.post(
"/api/device-mgt/v1.0/policies", serviceURL,
payload, payload,
function (response) { function () {
response = JSON.parse(response); $(".add-policy").addClass("hidden");
if (response["statusCode"] == 201) { $(".policy-naming").addClass("hidden");
$(".add-policy").addClass("hidden"); $(".policy-message").removeClass("hidden");
$(".policy-naming").addClass("hidden"); },
$(".policy-message").removeClass("hidden"); function (data) {
if (state == "publish") {
publishToDevice();
}
}
},
function (err) {
console.log(err);
}
);
};
function publishToDevice() {
var payload = {
"policyName": policy["policyName"],
"description": policy["description"],
"compliance": policy["selectedNonCompliantAction"],
"ownershipType": "ANY",
"deviceId": getParameterByName('deviceId'),
"profile": {
"profileName": policy["policyName"],
"deviceType": {
"id": policy["platformId"],
"name": policy["platform"]
},
"policyDefinition": window.queryEditor.getValue(),
"policyDescription": policy["description"]
}
};
var successCallback = function (data, status) {
console.log("Data: " + data + "\nStatus: " + status);
};
var data = {
url: "/devicemgt/api/policies/add",
type: "POST",
contentType: "application/json",
accept: "application/json",
success: successCallback,
data: JSON.stringify(payload)
};
$.ajax(data).fail(function (jqXHR) {
console.log("Error: " + jqXHR);
});
}
// Start of functions related to grid-input-view
/**
* Method to set count id to cloned elements.
* @param {object} addFormContainer
*/
var setId = function (addFormContainer) {
$(addFormContainer).find("[data-add-form-clone]").each(function (i) {
$(this).attr("id", $(this).attr("data-add-form-clone").slice(1) + "-" + (i + 1));
if ($(this).find(".index").length > 0) {
$(this).find(".index").html(i + 1);
} }
}); );
};
/**
* Method to set count id to cloned elements.
* @param {object} addFormContainer
*/
var showHideHelpText = function (addFormContainer) {
var helpText = "[data-help-text=add-form]";
if ($(addFormContainer).find("[data-add-form-clone]").length > 0) {
$(addFormContainer).find(helpText).hide();
} else {
$(addFormContainer).find(helpText).show();
}
}; };
function formatRepo(user) { function formatRepo(user) {
if (user.loading) { if (user.loading) {
return user.text return user.text;
} }
if (!user.username) { if (!user.username) {
return; return;
} }
var markup = '<div class="clearfix">' + var markup = '<div class="clearfix">' +
'<div clas="col-sm-8">' + '<div clas="col-sm-8">' +
'<div class="clearfix">' + '<div class="clearfix">' +
'<div class="col-sm-3">' + user.username + '</div>'; '<div class="col-sm-3">' + user.username + '</div>';
if (user.firstname) { if (user.firstname) {
markup += '<div class="col-sm-3"><i class="fa fa-code-fork"></i> ' + user.firstname + '</div>'; markup += '<div class="col-sm-3"><i class="fa fa-code-fork"></i> ' + user.firstname + '</div>';
} }
@ -350,170 +391,74 @@ function formatRepoSelection(user) {
return user.username || user.text; return user.username || user.text;
} }
function formatGroupRepo(group) {
if (group.loading) {
return group.text
}
if (!group.name) {
return;
}
var markup = '<div class="clearfix">' +
'<div clas="col-sm-8">' +
'<div class="clearfix">' +
'<div class="col-sm-3">' + group.name + '</div>';
if (group.name) {
markup += '<div class="col-sm-3"><i class="fa fa-code-fork"></i> ' + group.name + '</div>';
}
if (group.owner) {
markup += '<div class="col-sm-2"><i class="fa fa-star"></i> ' + group.owner + '</div></div>';
}
markup += '</div></div>';
return markup;
}
function formatGroupRepoSelection(group) {
return group.name || group.text;
}
// End of functions related to grid-input-view // End of functions related to grid-input-view
$(document).ready(function () { $(document).ready(function () {
window.queryEditor = CodeMirror.fromTextArea(document.getElementById('policy-definition-input'), { $("#users-input").select2({
mode: MIME_TYPE_SIDDHI_QL, multiple: true,
indentWithTabs: true, tags: false,
smartIndent: true, ajax: {
lineNumbers: true, url: context + "/api/invoker/execute/",
matchBrackets: true, method: "POST",
autofocus: true, dataType: 'json',
extraKeys: { delay: 250,
"Shift-2": function (cm) { id: function (user) {
insertStr(cm, cm.getCursor(), '@'); return user.username;
CodeMirror.showHint(cm, getAnnotationHints);
}, },
"Ctrl-Space": "autocomplete" data: function (params) {
} var postData = {};
postData.requestMethod = "GET";
postData.requestURL = "/api/device-mgt/v1.0/users/search/usernames?filter=" + params.term;
postData.requestPayload = null;
return JSON.stringify(postData);
},
processResults: function (data) {
var newData = [];
$.each(data, function (index, value) {
value.id = value.username;
newData.push(value);
});
return {
results: newData
};
},
cache: true
},
escapeMarkup: function (markup) {
return markup;
}, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
}); });
$("#users-input").select2({ $("#loading-content").remove();
multiple: true, $(".policy-platform").removeClass("hidden");
tags: true,
ajax: {
url: window.location.origin + "/devicemgt/api/invoker/execute/",
method: "POST",
dataType: 'json',
delay: 250,
id: function (user) {
return user.username;
},
data: function (params) {
var postData = {};
postData.actionMethod = "GET";
postData.actionUrl = "/devicemgt_admin/users";
postData.actionPayload = JSON.stringify({
q: params.term, // search term
page: params.page
});
return JSON.stringify(postData);
},
processResults: function (data, page) {
var newData = [];
$.each(data.responseContent, function (index, value) {
value.id = value.username;
newData.push(value);
});
return {
results: newData
};
},
cache: true
},
escapeMarkup: function (markup) {
return markup;
}, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
$("#groups-input").select2({
multiple: true,
tags: true,
ajax: {
url: window.location.origin + "/devicemgt/api/invoker/execute/",
method: "POST",
dataType: 'json',
delay: 250,
id: function (group) {
return group.name;
},
data: function (params) {
var postData = {};
postData.actionMethod = "GET";
var username = $("#platform").data("username");
postData.actionUrl = "/devicemgt_admin/groups/user/" + username +
"/search?groupName=" + params.term;
return JSON.stringify(postData);
},
processResults: function (data, page) {
var newData = [];
$.each(data, function (index, value) {
value.id = value.name;
newData.push(value);
});
return {
results: newData
};
},
cache: true
},
escapeMarkup: function (markup) {
return markup;
}, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatGroupRepo, // omitted for brevity, see the source of this page
templateSelection: formatGroupRepoSelection // omitted for brevity, see the source of this page
});
// Adding initial state of wizard-steps. // Adding initial state of wizard-steps.
$("#policy-profile-wizard-steps").html($(".wr-steps").html()); $("#policy-platform-wizard-steps").html($(".wr-steps").html());
policy["platform"] = $("#platform").data("platform");
policy["platformId"] = $("#platform").data("platform-id");
deviceTypeLabel = $("#platform").data("platform-label");
// updating next-page wizard title with selected platform
$("#policy-profile-page-wizard-title").text("ADD " + deviceTypeLabel + " POLICY");
$("select.select2[multiple=multiple]").select2({ $("select.select2[multiple=multiple]").select2({
"tags": true "tags": false
}); });
$("#users-select-field").hide(); $("#users-select-field").hide();
$("#groups-select-field").hide();
$("#user-roles-select-field").show(); $("#user-roles-select-field").show();
$("input[type='radio'].select-users-radio").change(function () { $("input[type='radio'].select-users-radio").change(function () {
if ($("#user-roles-radio-btn").is(":checked")) {
$("#user-roles-select-field").show();
$("#users-select-field").hide();
$("#groups-select-field").hide();
}
if ($("#users-radio-btn").is(":checked")) { if ($("#users-radio-btn").is(":checked")) {
$("#user-roles-select-field").hide(); $("#user-roles-select-field").hide();
$("#users-select-field").show(); $("#users-select-field").show();
$("#groups-select-field").hide();
} }
if ($("#groups-radio-btn").is(":checked")) { if ($("#user-roles-radio-btn").is(":checked")) {
$("#user-roles-select-field").hide();
$("#users-select-field").hide(); $("#users-select-field").hide();
$("#groups-select-field").show(); $("#user-roles-select-field").show();
} }
}); });
// Support for special input type "ANY" on user(s) & user-role(s) selection // Support for special input type "ANY" on user(s) & user-role(s) selection
$("#user-roles-input").select2({ $("#user-roles-input").select2({
"tags": true "tags": false
}).on("select2:select", function (e) { }).on("select2:select", function (e) {
if (e.params.data.id == "ANY") { if (e.params.data.id == "ANY") {
$(this).val("ANY").trigger("change"); $(this).val("ANY").trigger("change");
@ -522,152 +467,7 @@ $(document).ready(function () {
} }
}); });
// Maintains an array of configured features of the profile //Policy wizard stepper
var advanceOperations = ".wr-advance-operations";
$(advanceOperations).on("click", ".wr-input-control.switch", function (event) {
var operationCode = $(this).parents(".operation-data").data("operation-code");
var operation = $(this).parents(".operation-data").data("operation");
var operationDataWrapper = $(this).data("target");
// prevents event bubbling by figuring out what element it's being called from.
if (event.target.tagName == "INPUT") {
var featureConfiguredIcon;
if ($("input[type='checkbox']", this).is(":checked")) {
configuredOperations.push(operationCode);
// when a feature is enabled, if "zero-configured-features" msg is available, hide that.
var zeroConfiguredOperationsErrorMsg = "#policy-profile-main-error-msg";
if (!$(zeroConfiguredOperationsErrorMsg).hasClass("hidden")) {
$(zeroConfiguredOperationsErrorMsg).addClass("hidden");
}
// add configured-state-icon to the feature
featureConfiguredIcon = "#" + operation + "-configured";
if ($(featureConfiguredIcon).hasClass("hidden")) {
$(featureConfiguredIcon).removeClass("hidden");
}
} else {
//splicing the array if operation is present.
var index = $.inArray(operationCode, configuredOperations);
if (index != -1) {
configuredOperations.splice(index, 1);
}
// when a feature is disabled, clearing all its current configured, error or success states
var subErrorMsgWrapper = "#" + operation + "-feature-error-msg";
var subErrorIcon = "#" + operation + "-error";
var subOkIcon = "#" + operation + "-ok";
featureConfiguredIcon = "#" + operation + "-configured";
if (!$(subErrorMsgWrapper).hasClass("hidden")) {
$(subErrorMsgWrapper).addClass("hidden");
}
if (!$(subErrorIcon).hasClass("hidden")) {
$(subErrorIcon).addClass("hidden");
}
if (!$(subOkIcon).hasClass("hidden")) {
$(subOkIcon).addClass("hidden");
}
if (!$(featureConfiguredIcon).hasClass("hidden")) {
$(featureConfiguredIcon).addClass("hidden");
}
// reinitializing input fields into the defaults
$(operationDataWrapper + " input").each(
function () {
if ($(this).is("input:text")) {
$(this).val($(this).data("default"));
} else if ($(this).is("input:password")) {
$(this).val("");
} else if ($(this).is("input:checkbox")) {
$(this).prop("checked", $(this).data("default"));
// if this checkbox is the parent input of a grouped-input
if ($(this).hasClass("parent-input")) {
var groupedInput = $(this).parent().parent().parent();
updateGroupedInputVisibility(groupedInput);
}
}
}
);
// reinitializing select fields into the defaults
$(operationDataWrapper + " select").each(
function () {
var defaultOption = $(this).data("default");
$("option:eq(" + defaultOption + ")", this).prop("selected", "selected");
}
);
// collapsing expanded-panes (upon the selection of html-select-options) if any
$(operationDataWrapper + " .expanded").each(
function () {
if ($(this).hasClass("expanded")) {
$(this).removeClass("expanded");
}
$(this).slideUp();
}
);
// removing all entries of grid-input elements if exist
$(operationDataWrapper + " .grouped-array-input").each(
function () {
var gridInputs = $(this).find("[data-add-form-clone]");
if (gridInputs.length > 0) {
gridInputs.remove();
}
var helpTexts = $(this).find("[data-help-text=add-form]");
if (helpTexts.length > 0) {
helpTexts.show();
}
}
);
}
}
});
// adding support for cloning multiple profiles per feature with cloneable class definitions
$(advanceOperations).on("click", ".multi-view.add.enabled", function () {
// get a copy of .cloneable and create new .cloned div element
var cloned = "<div class='cloned'><hr>" + $(".cloneable", $(this).parent().parent()).html() + "</div>";
// append newly created .cloned div element to panel-body
$(this).parent().parent().append(cloned);
// enable remove action of newly cloned div element
$(".cloned", $(this).parent().parent()).each(
function () {
if ($(".multi-view.remove", this).hasClass("disabled")) {
$(".multi-view.remove", this).removeClass("disabled");
}
if (!$(".multi-view.remove", this).hasClass("enabled")) {
$(".multi-view.remove", this).addClass("enabled");
}
}
);
});
$(advanceOperations).on("click", ".multi-view.remove.enabled", function () {
$(this).parent().remove();
});
// enabling or disabling grouped-input based on the status of a parent check-box
$(advanceOperations).on("click", ".grouped-input", function () {
updateGroupedInputVisibility(this);
});
// add form entry click function for grid inputs
$(advanceOperations).on("click", "[data-click-event=add-form]", function () {
var addFormContainer = $("[data-add-form-container=" + $(this).attr("href") + "]");
var clonedForm = $("[data-add-form=" + $(this).attr("href") + "]").clone().
find("[data-add-form-element=clone]").attr("data-add-form-clone", $(this).attr("href"));
// adding class .child-input to capture text-input-array-values
$("input, select", clonedForm).addClass("child-input");
$(addFormContainer).append(clonedForm);
setId(addFormContainer);
showHideHelpText(addFormContainer);
});
// remove form entry click function for grid inputs
$(advanceOperations).on("click", "[data-click-event=remove-form]", function () {
var addFormContainer = $("[data-add-form-container=" + $(this).attr("href") + "]");
$(this).closest("[data-add-form-element=clone]").remove();
setId(addFormContainer);
showHideHelpText(addFormContainer);
});
$(".wizard-stepper").click(function () { $(".wizard-stepper").click(function () {
// button clicked here can be either a continue button or a back button. // button clicked here can be either a continue button or a back button.
var currentStep = $(this).data("current"); var currentStep = $(this).data("current");
@ -685,11 +485,11 @@ $(document).ready(function () {
// remove if there are any visible error-messages. // remove if there are any visible error-messages.
var errorMsgWrappers = ".alert.alert-danger"; var errorMsgWrappers = ".alert.alert-danger";
$(errorMsgWrappers).each( $(errorMsgWrappers).each(
function () { function () {
if (!$(this).hasClass("hidden")) { if (!$(this).hasClass("hidden")) {
$(this).addClass("hidden"); $(this).addClass("hidden");
}
} }
}
); );
var nextStep = $(this).data("next"); var nextStep = $(this).data("next");
@ -728,16 +528,7 @@ $(document).ready(function () {
// hiding current section of the wizard and showing next section. // hiding current section of the wizard and showing next section.
$("." + currentStep).addClass("hidden"); $("." + currentStep).addClass("hidden");
if (nextStep !== "policy-message") { $("." + nextStep).removeClass("hidden");
$("." + nextStep).removeClass("hidden");
}
} }
}); });
}); });
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, " "));
}

@ -1,47 +1,13 @@
{{#zone "topCss"}} <span id="platform" class="hidden" data-platform="{{type.name}}" data-platform-label="{{type.label}}"
{{css "css/codemirror.css"}} data-username="{{username}}"></span>
{{/zone}}
<span id="platform" class="hidden" data-platform="{{type.name}}" data-platform-id="{{type.id}}"
data-platform-label="{{type.label}}" data-username="{{username}}"></span>
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="wr-steps hidden">
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-platform">
<div class="wiz-no">1</div>
<div class="wiz-lbl hidden-xs"><span>Select a platform</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz itm-wiz-current" data-step="policy-profile">
<div class="wiz-no">2</div>
<div class="wiz-lbl hidden-xs"><span>Configure profile</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-criteria">
<div class="wiz-no">3</div>
<div class="wiz-lbl hidden-xs"><span>Assign</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-naming">
<div class="wiz-no">4</div>
<div class="wiz-lbl hidden-xs"><span>Publish to devices</span></div>
</div>
<br class="c-both"/>
</div>
</div>
<div class="container col-centered wr-content policy-message hidden"> <div class="container col-centered wr-content policy-message hidden">
<div class="wr-form"> <div class="wr-form">
<h1 id="policy-message-page-wizard-title" class="page-sub-title">Policy creation is <h1 id="policy-message-page-wizard-title" class="page-sub-title">Policy creation is
successful.</h1> successful.</h1>
<br>Please click <b>"Add Another Policy"</b>, if you wish to add another policy or <br>Please click <b>"Add Another Policy"</b>, if you wish to add another policy or
click click
<b>"View policy list"</b> to complete the process and go back to the policy list. <b>"View policy list"</b> to complete the process and go back to the policy list.
<hr> <hr>
<button class="wr-btn wizard-stepper" data-current="policy-message" <button class="wr-btn wizard-stepper" data-current="policy-message"
@ -247,18 +213,11 @@
<div class="col-lg-12"> <div class="col-lg-12">
<h4>Step 2: Configure profile</h4> <h4>Step 2: Configure profile</h4>
<br> <br>
<label class="wr-input-label"> <label class="wr-input-label">
Set device specific configuration instructions Set device specific configuration instructions
</label> </label>
<div class="wr-advance-operations"> <div class="wr-advance-operations">
<div class="wr-input-control"> {{unit "cdmf.unit.device.type.generic.policy-wizard"}}
<div class="cus-col-100">
<textarea id="policy-definition-input" placeholder="Enter the policy"
style="width: 100%;" required></textarea>
</div>
<br class="c-both"/>
</div>
</div> </div>
<div class="wr-input-control wr-btn-grp"> <div class="wr-input-control wr-btn-grp">
<a href="javascript:window.history.back()" <a href="javascript:window.history.back()"
@ -281,7 +240,5 @@
</div> </div>
</div> </div>
{{#zone "bottomJs"}} {{#zone "bottomJs"}}
{{js "js/codemirror.js"}}
{{js "js/sql.js"}}
{{js "js/policy-create.js"}} {{js "js/policy-create.js"}}
{{/zone}} {{/zone}}

@ -17,7 +17,7 @@
*/ */
function onRequest(context) { function onRequest(context) {
//var log = new Log("wizard.js"); // var log = new Log("wizard.js");
var constants = require("/app/modules/constants.js"); var constants = require("/app/modules/constants.js");
var DTYPE_CONF_DEVICE_TYPE_KEY = "deviceType"; var DTYPE_CONF_DEVICE_TYPE_KEY = "deviceType";
var DTYPE_CONF_DEVICE_TYPE_LABEL_KEY = "label"; var DTYPE_CONF_DEVICE_TYPE_LABEL_KEY = "label";
@ -32,15 +32,11 @@ function onRequest(context) {
var deviceType = context.uriParams.deviceType; var deviceType = context.uriParams.deviceType;
var typesListResponse = userModule.getPlatforms(); var typesListResponse = userModule.getPlatforms();
if (typesListResponse["status"] == "success") { if (typesListResponse["status"] == "success") {
for (var type in typesListResponse["content"]) { wizardPage["type"] = {};
if (deviceType == typesListResponse["content"][type]["name"]) { for (var type in typesListResponse["content"]["deviceTypes"]) {
wizardPage["type"] = typesListResponse["content"][type]; if (deviceType == typesListResponse["content"]["deviceTypes"][type]) {
var deviceTypeLabel = deviceType; wizardPage["type"]["name"] = deviceType;
var configs = utility.getDeviceTypeConfig(deviceType); wizardPage["type"]["label"] = deviceType;
if (configs && configs[DTYPE_CONF_DEVICE_TYPE_KEY][DTYPE_CONF_DEVICE_TYPE_LABEL_KEY]) {
deviceTypeLabel = configs[DTYPE_CONF_DEVICE_TYPE_KEY][DTYPE_CONF_DEVICE_TYPE_LABEL_KEY];
}
wizardPage["type"]["label"] = deviceTypeLabel;
} }
} }
} }

Loading…
Cancel
Save