2 ============LICENSE_START=======================================================
4 ================================================================================
5 Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
7 ================================================================================
8 Licensed under the Apache License, Version 2.0 (the "License");
9 you may not use this file except in compliance with the License.
10 You may obtain a copy of the License at
12 http://www.apache.org/licenses/LICENSE-2.0
14 Unless required by applicable law or agreed to in writing, software
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
19 ============LICENSE_END============================================
20 ===================================================================
27 background-color: #dddd;
32 vertical-align: middle;
47 background-color: #f5f5f5;
48 padding: 15px 5px 0 5px;
51 .form-group.clearfix {
52 display: -webkit-flex;
67 border-bottom: 1px solid #ddd;
68 border-collapse: collapse;
78 #policyTable tr.highlight {
79 background-color: #f5f5f5;
92 <div attribute-test="policywindowproperties" id="configure-widgets"
93 class="disabled-block-container">
94 <div attribute-test="policywindowpropertiesh" class="modal-header">
95 <button type="button" class="close" ng-click="close(false)"
96 aria-hidden="true" style="margin-top: -3px">×</button>
97 <h4>Operational Policy</h4>
101 <div class="modal-body">
102 <div attribute-test="policywindowpropertiesb" class="modal-body row">
103 <div class="leftPolicyPanel" style="display: none;">
104 <div class="panel panel-default">
105 <div id="policyTableHolder">
106 <table id="policyTable"></table>
110 <div id="spaceError" class="idError">Error: Spaces are not
111 allowed in the ID.</div>
113 <div class="panel panel-default col-sm-9 policyPanel">
114 <form id="Timeoutform" class="form-horizontal">
116 <div class="form-group clearfix row">
117 <label class="col-sm-2">Name</label>
118 <div class="col-sm-3" style="padding: 0px;">
119 <input type="text" id="pname" name="pname" maxlength="48"
120 placeholder="Enter Unique Name" class="form-control">
123 <label class="col-sm-1">ID</label>
124 <div class="col-sm-1" style="padding: 0px;">
125 <input onkeydown="return false;" type="text" id="pid" name="pid"
126 class="form-control" readonly>
129 <label for="userID" class="col-sm-3"
130 style="padding-left: 5px; padding-right: 10px;">Overall
132 <div class="col-sm-2" style="padding-left: 0px;">
133 <input type="text" maxlength="10"
134 onkeypress="return isNumberKey(event)" class="form-control"
135 id="timeout" name="timeout">
140 <div class="panel-heading" style="background-color: white;">
141 <ul id="nav_Tabs" class="nav nav-tabs">
142 <li class><a id="add_one_more" href="#desc_tab"><span
143 class="glyphicon glyphicon-plus" aria-hidden="true"></span></a></li>
146 <div class="panel-body">
147 <div class="tab-content">
148 <div id="properties_tab" class="tab-pane fade in active"></div>
153 <span id="formSpan" style="display: none">
154 <form class="saveProps" class="form-horizontal">
156 <div class="form-group clearfix">
157 <label class="col-sm-4 control-label" for="recipe">Recipe</label>
158 <div class="col-sm-8">
159 <select class="form-control" name="recipe" id="recipe"
160 enableFilter="true"></select>
163 <div class="form-group clearfix">
164 <label for="maxRetries" class="col-sm-4 control-label">
166 <div class="col-sm-8">
167 <input type="text" maxlength="5" class="form-control"
168 id="maxRetries" onkeypress="return isNumberKey(event)"
169 name="maxRetries"> </input>
172 <div class="form-group clearfix">
173 <label for="retryTimeLimit" class="col-sm-4 control-label">
174 Retry Time Limit</label>
175 <div class="col-sm-8">
176 <input type="text" maxlength="5" class="form-control"
177 id="retryTimeLimit" onkeypress="return isNumberKey(event)"
178 name="retryTimeLimit"></input>
181 <div style="display: none;" class="form-group clearfix">
182 <label for="_id" class="col-sm-4 control-label"> PolicyID</label>
183 <div class="col-sm-8">
184 <input type="text" onkeydown="return false;"
185 class="form-control" id="_id" name="_id" value=""></input>
188 <div class="form-group clearfix">
189 <label for="parentPolicy" class="col-sm-4 control-label">
190 Parent Policy</label>
191 <div class="col-sm-8">
192 <select class="form-control" id="parentPolicy"
193 name="parentPolicy" enableFilter="true"><option
194 value=""></option></select>
197 <div class="form-group clearfix">
198 <label for="parentPolicyConditions"
199 class="col-sm-4 control-label"> Parent Policy Conditions</label>
200 <div class="col-sm-8">
201 <select class="form-control" id="parentPolicyConditions"
202 name="parentPolicyConditions" multiple></select>
205 <div class="form-group clearfix">
207 <label for="actor" class="col-sm-4 control-label"> Actor</label>
208 <div class="col-sm-8">
209 <select class="form-control" id="actor" name="actor"></select>
212 <label for="payload" class="col-sm-4 control-label">
213 Payload (YAML)</label>
214 <div class="col-sm-8">
215 <textarea class="form-control" id="recipePayload" name=recipePayload></textarea>
218 <div class="form-group clearfix">
219 <label for="targetType" class="col-sm-4 control-label">
221 <div class="col-sm-8">
222 <select class="form-control" name="recipeLevel" id="recipeLevel">
226 <label for="targetResourceId" class="col-sm-4 control-label">
227 Target ResourceId</label>
228 <div class="col-sm-8">
229 <select class="form-control" name="targetResourceId"
230 id="targetResourceId" enableFilter="true"
231 onchange="changeTargetResourceIdOther();">
232 <option value=""></option>
233 <option value="Other:">Other:</option>
236 <input type="text" style="display: none" class="form-control"
237 id="targetResourceIdOther" name="targetResourceIdOther" value=""></input>
239 <div style="border: 2px dotted gray;">
240 <div class="form-group clearfix">
241 <label for="enableGuardPolicy" class="col-sm-4 control-label">
242 Enable Guard Policy</label>
243 <div class="col-sm-8">
244 <input type="checkbox" class="form-control"
245 name="enableGuardPolicy" id="enableGuardPolicy">
247 <div class="col-sm-8">
248 <label for="guardPolicyType" class="col-sm-4 control-label">
249 Guard Policy Type</label> <select class="form-control"
250 name="guardPolicyType" id="guardPolicyType"
251 onchange="changeGuardPolicyType();">
252 <option value="GUARD_MIN_MAX">MinMax</option>
253 <option value="GUARD_YAML">FrequencyLimiter</option>
256 <label for="guardTargets" class="col-sm-4 control-label">Guard
258 <div class="col-sm-8">
259 <input class="form-control" name="guardTargets"
264 <div class="form-group clearfix" id="minMaxGuardPolicyDiv">
265 <label for="minGuard" class="col-sm-4 control-label">
267 <div class="col-sm-8">
268 <input class="form-control" name="minGuard" id="minGuard" />
270 <label for="maxGuard" class="col-sm-4 control-label">
272 <div class="col-sm-8">
273 <input class="form-control" name="maxGuard" id="maxGuard" />
276 <div class="form-group clearfix"
277 id="frequencyLimiterGuardPolicyDiv" style="display: none">
278 <label for="limitGuard" class="col-sm-4 control-label">Limit</label>
279 <div class="col-sm-8">
280 <input class="form-control" name="limitGuard" id="limitGuard" />
282 <div class="col-sm-8">
283 <select class="form-control" name="timeUnitsGuard"
284 id="timeUnitsGuard" /> <label for="timeWindowGuard"
285 class="col-sm-4 control-label">Time Window</label>
287 <div class="col-sm-8">
288 <input class="form-control" name="timeWindowGuard"
289 id="timeWindowGuard" />
292 <div class="form-group clearfix">
293 <label for="guardActiveStart" class="col-sm-4 control-label">
294 Guard Active Start</label>
295 <div class="col-sm-8">
296 <input class="form-control" name="guardActiveStart"
297 id="guardActiveStart" />
299 <label for="guardActiveEnd" class="col-sm-4 control-label">
300 Guard Active End</label>
301 <div class="col-sm-8">
302 <input class="form-control" name="guardActiveEnd"
303 id="guardActiveEnd" />
313 <div attribute-test="policywindowpropertiesf" class="modal-footer">
314 <!--<button ng-click="reset()" class="btn btn-primary" style="float:left">Reset</button>-->
315 <button id="savePropsBtn" class="btn btn-primary">Close</button>
316 <button ng-click="close(true)" id="close_button"
317 class="btn btn-primary">Cancel</button>
321 function getAllFormId() {
322 return Array.from(document.getElementsByClassName("formId"));
325 function searchActiveFormId() {
326 var formArray = getAllFormId();
327 for (var i=0, max=formArray.length; i < max; i++) {
329 console.log("Search active FormId, current element "+formArray[i].id);
330 if (formArray[i].style.display !== "none") {
331 console.log("Active form is:"+formArray[i].id);
335 console.log("No active formId found !");
338 function initTargetResourceId() {
339 if (vf_Services !== null && vf_Services !== undefined) {
340 // Set all the Resource Invariant UUID in the target resource ID list (+Empty and other)
341 Object.keys(vf_Services["shared"]["byVf"]).forEach(function(key) {
342 $("#targetResourceId").append($('<option></option>').val(key).html(key));
347 function changeTargetResourceIdOther() {
348 var formItemActive = searchActiveFormId();
349 if ($("#"+formItemActive.id+" #targetResourceId").val()==="Other:") {
350 $("#"+formItemActive.id+" #targetResourceIdOther").show();
352 $("#"+formItemActive.id+" #targetResourceIdOther").hide();
353 $("#"+formItemActive.id+" #targetResourceIdOther").val("");
357 function changeGuardPolicyType() {
358 var formItemActive = searchActiveFormId();
359 if ($("#"+formItemActive.id+" #guardPolicyType").val()==="GUARD_MIN_MAX") {
360 $("#"+formItemActive.id+" #minMaxGuardPolicyDiv").show();
361 $("#"+formItemActive.id+" #frequencyLimiterGuardPolicyDiv").hide();
362 } else if ($("#"+formItemActive.id+" #guardPolicyType").val()==="GUARD_YAML") {
363 $("#"+formItemActive.id+" #minMaxGuardPolicyDiv").hide();
364 $("#"+formItemActive.id+" #frequencyLimiterGuardPolicyDiv").show();
367 //Basically this method will add a new form. All forms share the same class. When you want one form to show(active form) the other forms get the
368 // css attribute display:none
369 $("#add_one_more").click(function(event) {
370 console.log("add one more");
371 event.preventDefault();
372 var num = add_one_more();
375 loadPropertyWindow("policy")
377 // by default, parentPolicyConditions is disabled
378 //$("#parentPolicyConditions").prop('disabled', 'disabled');
385 //Grab saved values for dropdowns
386 var obj = elementMap[lastElementSelected];
388 console.log("lastElementSelected :"+ lastElementSelected);
389 if (!($.isEmptyObject(obj))){
390 allPolicies = jQuery.extend({}, obj);
391 for (var x in allPolicies){
392 $("#policyTable").prepend("<tr><td>"+x+"</td></tr>");
393 if (allPolicies[x][1]['value']){
394 allPolIds.push(parseInt(allPolicies[x][1]['value']));
396 console.log("policies found :"+ x);
401 if (loadPolicy !== undefined && loadPolicy !== null) {
403 console.log("load properties");
404 disperseConfig(allPolicies,loadPolicy);
406 console.log("create new policy");
410 //load recipes for a chosen policy
411 function disperseConfig(policyObj, id){
412 console.log("disperseConfig with id:" + id);
414 //remove old gui forms
415 for (var i=1; i<($(".formId").length + 1); i++){
416 $("#go_properties_tab"+i).parent().remove();
418 $(".formId").remove();
420 if (policyObj !== undefined && policyObj[id] !== undefined) {
421 var el = policyObj[id][3]['policyConfigurations']
422 for (var i = 0; i < el.length; i++) {
424 var num = add_one_more();
425 console.log("number is=:" + num);
427 for (var j = 0; j < el[i].length; j++) {
428 if(el[i][j].hasOwnProperty("name")){
429 $("#formId" + num + " #" + el[i][j].name).val(
431 if(el[i][j].name==="_id") {
432 console.log("formId num:" + num + "; value is:" + el[i][j].value);
433 policy_ids["#formId" + num]=el[i][j].value
435 if(el[i][j].name==='parentPolicy')
436 parent_policy[num]=el[i][j].value
437 if(el[i][j].name==='recipe' && el[i][j].value.toString()!==''){
438 $("#go_properties_tab"+num).text(el[i][j].value)
440 if(el[i][j].name==="targetResourceIdOther" && el[i][j].value.toString()!=='') {
441 // Add the entry and set it
442 $("#formId" + num + " #targetResourceId").append($('<option></option>').val($("#formId" + num + " #targetResourceIdOther").val()).html($("#formId" + num + " #targetResourceIdOther").val()));
443 $("#formId" + num + " #targetResourceId").val($("#formId" + num + " #targetResourceIdOther").val());
445 changeGuardPolicyType();
450 //Adding all the ids for parent policy options
451 for(var i=1;i<=$(".formId").length;i++){
452 for(k in policy_ids){
453 if($("#formId"+i+" #_id").val()!==policy_ids[k].toString() && $(k+" #recipe").val()!==undefined && $(k+" #recipe").val()!==""){
454 $("#formId"+i+" #parentPolicy").append("<option value=\""+policy_ids[k]+"\">" +$(k+" #recipe").val()+"</option>");
459 for(k in parent_policy){
460 $("#formId"+k+" #parentPolicy").val(parent_policy[k]);
461 if($("#formId"+k+" #parentPolicy").val() ==""){
462 $("#formId" +k+ " #parentPolicyConditions").multiselect("disable");
464 $("#formId" +k+ " #parentPolicyConditions").multiselect("enable");
466 // force the change event
467 $("#formId"+k+" #parentPolicy").change();
470 // Now load all component with the right value defined in policyObj JSON
471 for (headInd in policyObj[id]){
472 if (!(policyObj[id][headInd].hasOwnProperty("policyConfigurations"))){
473 $("#" + policyObj[id][headInd].name).val(policyObj[id][headInd].value);
481 $('select[multiple] option').each(function() {
482 var input = $('input[value="' + $(this).val() + '"]');
483 input.prop('disabled', true);
484 input.parent('li').addClass('disabled');
486 $('input[value="multiselect-all"]').prop('disabled', true).parent('li').addClass('disabled');
491 function addSelectListen(count) {
492 var onSelectChange = function() {
493 var opselected = this.selectedOptions[0].text;
495 if (this.id == "recipe"){
497 var polCount = $(this).closest("[id^='formId']").attr("id").substring(6);
498 $(this).closest(".policyPanel").find("#go_properties_tab"+polCount).text(opselected);
500 $(this).closest("[id^='go_properties_tab']").text("Policy");
504 if (this.id=="parentPolicy"){
505 var ppCond = $(this).closest("[id^='formId']").find("#parentPolicyConditions");
507 ppCond.multiselect("clearSelection");
508 ppCond.multiselect("disable");
510 ppCond.multiselect("enable");
514 $("#formId"+count+" select").each( function () {
515 this.change = onSelectChange;
520 //This is ensure there are no repeated keys in the map
521 function noRepeats(form) {
522 //triggered per policy.
524 for (var i = 0; i < form.length; i++) {
525 if (select[form[i].name] === undefined)
526 select[form[i].name] = []
527 select[form[i].name].push(form[i].value);
539 $("#savePropsBtn").click(function(event) {
540 console.log("save properties triggered");
541 if($("#targetResourceIdOther").is(":visible")) {
542 $('#targetResourceId').append($('<option></option>').val($("#targetResourceIdOther").val()).html($("#targetResourceIdOther").val()))
543 $("#targetResourceId").val($("#targetResourceIdOther").val());
545 $(".idError").hide();
547 console.log("save properties triggered2");
549 /* if ($("#policyTable .highlight").length > 0){
550 saveLastPolicyLocally($("#policyTable .highlight").attr("id"));
554 //Removes outdated (deleted) policies by checking against left menu
555 console.log("get all policies");
556 var finalSaveList = {};
557 $("#policyTable td").each(function(){
558 console.log("enter policy table each loop");
559 var tableVal = $(this).text();
560 if (tableVal in allPolicies){
561 finalSaveList[tableVal] = allPolicies[tableVal];
563 console.log("save properties; add tableVal to policies: "+ tableVal);
566 saveProperties(finalSaveList);
567 $("#close_button").click();
570 function add_one_more() {
571 $("#nav_Tabs li").removeClass("active");
573 //FormSpan contains a block of the form that is not being displayed. We will create clones of that and add them to tabs
574 var form = $($("#formSpan").children()[0]).clone()
576 //Each new tab will have the formId class attached to it. This way we can track how many forms we currently have out there and assign listeners to them
577 if ($(".formId").length > 0) {
579 var s = $(".formId");
580 for (var i = 0; i < s.length; i++) {
581 if (parseInt($(s[i]).attr("id").substring(6)) > greatest) {
582 greatest = parseInt($(s[i]).attr("id").substring(6))
585 count = greatest + 1;
586 $("#properties_tab").append(
587 ('<span class="formId" id="formId'+count+'"></span>'));
590 $("#properties_tab").append(
591 '<span class="formId" id="formId1"></span>');
594 //$(form).find("#policyName").val("Recipe "+makid(2))
595 //TODO change up how we auto assign policyName. There could be the case where we do this and it will have repeats
596 //alert($(form).find("#_id").val())
597 //policyNameChangeListener(form)
601 ' <li class="active"><a id="go_properties_tab'+count+'">Policy</a><button id="tab_close'+count+'" type="button" class="close tab-close-popup" aria-hidden="true" style="margin-top: -30px;margin-right: 5px">×</button></li>');
602 $("#formId" + count).append(form);
603 $(".formId").not($("#formId" + count)).css("display", "none")
606 addSelectListen(count);
607 // This is for when the process is not loading from map but being created
610 $(form).find("#_id").val(l)
611 policy_ids["#formId" + count]=l
614 for(var i=1;i<=greatestIdNum();i++){
615 if($("#formId"+i).length>0){
616 answers["#formId"+i+" #parentPolicy"]=$("#formId"+i+" #parentPolicy").val();
617 $("#formId"+i+" #parentPolicy").empty();
619 for(k in policy_ids){
620 if(($("#formId"+i+" #_id").val()!==policy_ids[k].toString()) && $(k+" #recipe").val()!==undefined && $(k+" #recipe").val()!==""){
621 $("#formId"+i+" #parentPolicy").append("<option value='"+policy_ids[k]+"'>"+$(k+" #recipe").val()+"</option>")
624 $("#formId"+i+" #parentPolicy").prepend("<option value=''></option>")
628 $("#formId"+count+" #parentPolicyConditions").multiselect("disable");
630 //re-populate parent policy with chosen options
641 function addCustListen(count) {
642 $('#go_properties_tab' + count).click(function(event) {
643 $("#nav_Tabs li").removeClass("active");
644 $(this).parent().addClass("active");
645 $("#formId" + count).css("display", "")
646 $(".formId").not($("#formId" + count)).css("display", "none")
649 $('#tab_close' + count).click(function(event) {
650 if(document.getElementById("timeout").disabled){
653 $(this).parent().remove();
654 for(var i=1;i<=greatestIdNum();i++){
655 if( $("#formId"+i).length>0){
657 if( $("#formId"+i+" #parentPolicy").val()===$("#formId"+count+" #_id").val().toString())
658 $("#formId"+i+" #parentPolicy").val("")
659 $("#formId"+i+" #parentPolicy option[value='"+$("#formId"+count+" #_id").val().toString()+"']").remove();
663 delete policy_ids["#formId" + count + " #_id"]
664 $("#formId" + count).remove();
669 function greatestIdNum() {
671 var s = $(".formId");
672 for (var i = 0; i < s.length; i++) {
673 if (parseInt($(s[i]).attr("id").substring(6)) > greatest) {
674 greatest = parseInt($(s[i]).attr("id").substring(6))
680 //Generate random id for each policy
681 //Also made sure ids couldnt be repeated
682 function makeid(num) {
685 var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
688 for (var i = 0; i < 7; i++)
689 text += possible.charAt(Math.floor(Math.random()
691 var hasValue = false;
692 for (k in policy_ids) {
693 if (text === policy_ids[k])
702 var ParentPolicy = function(id, name) {
707 function saveLastPolicyLocally(lastPolicyId) {
708 console.log("last policy id is:" + lastPolicyId);
711 var properties = $(".saveProps").not("#formSpan .saveProps");
712 var timeoutForm = $("#Timeoutform").serializeArray();
714 for (var i = 0; i < timeoutForm.length; i++) {
715 polForm.push(timeoutForm[i]);
719 d["policyConfigurations"] = [];
720 for (var i = 0; i < properties.length; i++) {
721 var ser = $(properties[i]).serializeArray();
722 var s = noRepeats(ser)
723 d["policyConfigurations"].push(s);
727 for (var x in allPolicies){
728 if (x !== lastPolicyId) {
729 delete allPolicies[x];
730 console.log("remove old policy"+ x);
734 allPolicies[lastPolicyId] = polForm;
737 $('#policyTable').on('click', 'tr', function(event) {
739 console.log("click on policyTable");
740 $(".idError").hide();
745 $(this).addClass('highlight').siblings().removeClass('highlight');
746 disperseConfig(allPolicies, $(this).find("td").html());
750 $('#pname').on('keypress', function(e){
751 /* var newVal = $(this).val() + String.fromCharCode(e.which);
752 if ((newVal>99) || (($(this).val().length>2) && e.keyCode != 46 && e.keyCode !=8)){
755 if (e.keyCode == 32){
756 $("#spaceError").show();
761 function isNumberKey(event){
762 var charCode = (event.which) ? event.which : event.keyCode
763 if (charCode > 31 && (charCode < 48 || charCode > 57)){
769 function startNextItem() {
770 console.log("start next Item");
771 //save last item before transitioning
772 var lastItem = $("#policyTable .highlight");
773 if (lastItem.length > 0) {
774 console.log("start next Item length > 0");
775 saveLastPolicyLocally($("#pname").val());
776 //lastItem.attr("id", $("#pname").val());
777 lastItem.find("td").html($("#pname").val());
781 function add_new_policy(issueNewNames) {
782 //remove old gui forms
783 for (var i=1; i<($(".formId").length + 1); i++){
784 $("#go_properties_tab"+i).parent().remove();
786 $(".formId").remove();
789 //$("#pname").val("0");
790 $("#pname").val("New_Policy");
791 $("#timeout").val(defaults_props.policy.timeout);
793 $("#add_one_more").click();
798 if (("#policyTable .highlight").length > 0){
799 $('#policyTable tr.highlight').removeClass('highlight');
801 $("#policyTable").prepend("<tr class='highlight'><td>New_Policy</td></tr>");
806 initTargetResourceId();
808 //load metrics dropdown
809 if (elementMap["global"]) {
810 for (var i = 0; i < (elementMap["global"].length); i++){
811 if ((elementMap["global"][i]["name"]) == "actionSet"){
812 var asSel = elementMap["global"][i]["value"];
813 if (asSel == "vnfRecipe" && vf_Services !== null && vf_Services !== undefined){
814 if (vf_Services["policy"][asSel]){
815 $.each((vf_Services["policy"][asSel]), function(val, text) {
817 $('<option></option>').val(val).html(text)