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 ===================================================================
28 background-color: #dddd;
32 background-color: #dddd;
41 .fileUpload input.upload {
50 filter: alpha(opacity = 0);
55 display: inline-block;
71 vertical-align: middle;
81 background-color: #f2bfab;
92 background-color: #f5f5f5;
93 padding: 15px 5px 0 5px;
96 .form-group.clearfix {
97 display: -webkit-flex;
109 padding: 2px 2px 2px 30px;
120 border-bottom: 1px solid #ddd;
121 border-collapse: collapse;
131 #policyTable tr.highlight {
132 background-color: #f5f5f5;
144 <script type="text/javascript">
145 function disablefile() {
147 document.getElementById("fileUpload").disabled = true;
151 function disableSVN() {
152 var selectLength = document.querySelectorAll(".disabled-block-container .tab-close-popup");
153 if(selectLength && selectLength.length>0){
154 for(var i = 0; i< selectLength.length ; i++){
155 selectLength[i].disabled = true;
159 document.getElementById("schemaLocation").disabled = true;
160 document.getElementById("userID").disabled = true;
161 document.getElementById("password").disabled = true;
167 <div attribute-test="policywindowproperties" id="configure-widgets"
168 class="disabled-block-container">
169 <div attribute-test="policywindowpropertiesh" class="modal-header">
170 <button type="button" class="close" ng-click="close(false)"
171 aria-hidden="true" style="margin-top: -3px">×</button>
172 <h4>Operational Policy</h4>
176 <div class="modal-body">
177 <div attribute-test="policywindowpropertiesb" class="modal-body row">
179 <div class="leftPolicyPanel">
180 <div class="panel panel-default">
181 <i class="glyphicon glyphicon-search modelSearchBox"></i> <input
182 type="text" id="policySearch" onkeyup="searchPolicyList()"
183 placeholder="Search ...">
184 <div id="policyTableHolder">
185 <table id="policyTable"></table>
188 <div style="float: left">
189 <button type="button" id="createNewPolicy" class="btn btn-sm">New
193 <div style="float: right">
194 <button type="button" id="deletePolicy"
195 class="btn btn-sm glyphicon glyphicon-trash" disabled></button>
198 <div id="repeatIdError" class="idError">Error: This Policy
199 name is already taken.</div>
200 <div id="newIdError" class="idError">Error: Please rename your
202 <div id="spaceError" class="idError">Error: Spaces are not
203 allowed in the ID.</div>
206 <div class="panel panel-default col-sm-9 policyPanel"
207 style="display: none;">
208 <form id="Timeoutform" class="form-horizontal">
210 <div class="form-group clearfix row">
211 <label class="col-sm-2">Name</label>
212 <div class="col-sm-3" style="padding: 0px;">
213 <input type="text" id="pname" name="pname" maxlength="48"
214 placeholder="Enter Unique Name" class="form-control">
217 <label class="col-sm-1">ID</label>
218 <div class="col-sm-1" style="padding: 0px;">
219 <input onkeydown="return false;" type="text" id="pid" name="pid"
220 class="form-control" readonly>
223 <label for="userID" class="col-sm-3"
224 style="padding-left: 5px; padding-right: 10px;">Overall
226 <div class="col-sm-2" style="padding-left: 0px;">
227 <input type="text" maxlength="10"
228 onkeypress="return isNumberKey(event)" class="form-control"
229 id="timeout" name="timeout">
234 <div class="panel-heading" style="background-color: white;">
235 <ul id="nav_Tabs" class="nav nav-tabs">
236 <li class><a id="add_one_more" href="#desc_tab"><span
237 class="glyphicon glyphicon-plus" aria-hidden="true"></span></a></li>
240 <div class="panel-body">
241 <div class="tab-content">
242 <div id="properties_tab" class="tab-pane fade in active"></div>
247 <span id="formSpan" style="display: none">
248 <form class="saveProps" class="form-horizontal">
250 <div class="form-group clearfix">
251 <label class="col-sm-4 control-label" for="recipe">Recipe</label>
252 <div class="col-sm-8">
253 <select class="form-control" name="recipe" id="recipe"
254 enableFilter="true"></select>
257 <div class="form-group clearfix">
258 <label for="maxRetries" class="col-sm-4 control-label">
260 <div class="col-sm-8">
261 <input type="text" maxlength="5" class="form-control"
262 id="maxRetries" onkeypress="return isNumberKey(event)"
263 name="maxRetries"> </input>
266 <div class="form-group clearfix">
267 <label for="retryTimeLimit" class="col-sm-4 control-label">
268 Retry Time Limit</label>
269 <div class="col-sm-8">
270 <input type="text" maxlength="5" class="form-control"
271 id="retryTimeLimit" onkeypress="return isNumberKey(event)"
272 name="retryTimeLimit"></input>
275 <div style="display: none;" class="form-group clearfix">
276 <label for="_id" class="col-sm-4 control-label"> PolicyID</label>
277 <div class="col-sm-8">
278 <input type="text" onkeydown="return false;"
279 class="form-control" id="_id" name="_id" value=""></input>
282 <div class="form-group clearfix">
283 <label for="parentPolicy" class="col-sm-4 control-label">
284 Parent Policy</label>
285 <div class="col-sm-8">
286 <select class="form-control" id="parentPolicy"
287 name="parentPolicy" enableFilter="true"><option
288 value=""></option></select>
291 <div class="form-group clearfix">
292 <label for="parentPolicyConditions"
293 class="col-sm-4 control-label"> Parent Policy Conditions</label>
294 <div class="col-sm-8">
295 <select class="form-control" id="parentPolicyConditions"
296 name="parentPolicyConditions" multiple></select>
299 <div class="form-group clearfix">
301 <label for="actor" class="col-sm-4 control-label"> Actor</label>
302 <div class="col-sm-8">
303 <select class="form-control" id="actor" name="actor"></select>
306 <label for="payload" class="col-sm-4 control-label">
308 <div class="col-sm-8">
309 <textarea class="form-control" id="recipeInput"
310 name=recipeInput></textarea >
313 <div class="form-group clearfix">
314 <label for="targetType" class="col-sm-4 control-label">
316 <div class="col-sm-8">
317 <select class="form-control" name="recipeLevel" id="recipeLevel">
321 <label for="targetResourceId" class="col-sm-4 control-label">
322 Target ResourceId</label>
323 <div class="col-sm-8">
324 <select class="form-control" name="targetResourceId"
325 id="targetResourceId" enableFilter="true"
326 onchange="changeTargetResourceIdOther();">
327 <option value=""></option>
328 <option value="Other:">Other:</option>
331 <input type="text" style="display: none" class="form-control"
332 id="targetResourceIdOther" name="targetResourceIdOther" value=""></input>
340 <div attribute-test="policywindowpropertiesf" class="modal-footer">
341 <!--<button ng-click="reset()" class="btn btn-primary" style="float:left">Reset</button>-->
342 <button id="savePropsBtn" class="btn btn-primary">Close</button>
343 <button ng-click="close(true)" id="close_button"
344 class="btn btn-primary">Cancel</button>
349 function initTargetResourceId() {
350 // Set all the Resource Invariant UUID in the target resource ID list (+Empty and other)
351 Object.keys(vf_Services["shared"]["byVf"]).forEach(function(key){
352 $('#targetResourceId').append($('<option></option>').val(key).html(key));
356 function changeTargetResourceIdOther() {
357 if ($("#targetResourceId").val()==="Other:") {
358 $("#targetResourceIdOther").show();
360 $("#targetResourceIdOther").hide();
361 $("#targetResourceIdOther").val("");
364 //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
365 // css attribute display:none
366 $("#add_one_more").click(function(event) {
367 event.preventDefault();
368 var num = add_one_more();
371 loadPropertyWindow("policy")
373 // by default, parentPolicyConditions is disabled
374 //$("#parentPolicyConditions").prop('disabled', 'disabled');
381 //Grab saved values for dropdowns
382 var obj = elementMap[lastElementSelected];
384 if (!($.isEmptyObject(obj))){
385 allPolicies = jQuery.extend({}, obj);
386 for (var x in allPolicies){
387 $("#policyTable").prepend("<tr><td>"+x+"</td></tr>");
388 if (allPolicies[x][1]['value']){
389 allPolIds.push(parseInt(allPolicies[x][1]['value']));
395 //load recipes for a chosen policy
396 function disperseConfig(policyObj, id){
398 //remove old gui forms
399 for (var i=1; i<($(".formId").length + 1); i++){
400 $("#go_properties_tab"+i).parent().remove();
402 $(".formId").remove();
404 if (policyObj !== undefined) {
405 var el = policyObj[id][3]['policyConfigurations']
406 for (var i = 0; i < el.length; i++) {
408 var num = add_one_more();
410 for (var j = 0; j < el[i].length; j++) {
411 if(el[i][j].hasOwnProperty("name")){
412 $("#formId" + num + " #" + el[i][j].name).val(
414 if(el[i][j].name==="_id")
415 policy_ids["#formId" + num]=el[i][j].value
416 if(el[i][j].name==='parentPolicy')
417 parent_policy[num]=el[i][j].value
418 if(el[i][j].name==='recipe' && el[i][j].value.toString()!==''){
419 $("#go_properties_tab"+num).text(el[i][j].value)
421 if(el[i][j].name==="targetResourceIdOther" && el[i][j].value.toString()!=='') {
422 // Add the entry and set it
423 $('#targetResourceId').append($('<option></option>').val($('#targetResourceIdOther').val()).html($('#targetResourceIdOther').val()));
424 $('#targetResourceId').val($('#targetResourceIdOther').val());
431 //Adding all the ids for parent policy options
432 for(var i=1;i<=$(".formId").length;i++){
433 for(k in policy_ids){
434 if($("#formId"+i+" #_id").val()!==policy_ids[k].toString() && $(k+" #recipe").val()!==undefined && $(k+" #recipe").val()!==""){
435 $("#formId"+i+" #parentPolicy").append("<option value=\""+policy_ids[k]+"\">" +$(k+" #recipe").val()+"</option>");
440 for(k in parent_policy){
441 $("#formId"+k+" #parentPolicy").val(parent_policy[k]);
442 if($("#formId"+k+" #parentPolicy").val() ==""){
443 $("#formId" +k+ " #parentPolicyConditions").multiselect("disable");
445 $("#formId" +k+ " #parentPolicyConditions").multiselect("enable");
447 // force the change event
448 $("#formId"+k+" #parentPolicy").change();
451 // Now load all component with the right value defined in policyObj JSON
452 for (headInd in policyObj[id]){
453 if (!(policyObj[id][headInd].hasOwnProperty("policyConfigurations"))){
454 $("#" + policyObj[id][headInd].name).val(policyObj[id][headInd].value);
462 $('select[multiple] option').each(function() {
463 var input = $('input[value="' + $(this).val() + '"]');
464 input.prop('disabled', true);
465 input.parent('li').addClass('disabled');
467 $('input[value="multiselect-all"]').prop('disabled', true).parent('li').addClass('disabled');
472 function addSelectListen(count) {
473 var onSelectChange = function() {
474 var opselected = this.selectedOptions[0].text;
476 if (this.id == "recipe"){
478 var polCount = $(this).closest("[id^='formId']").attr("id").substring(6);
479 $(this).closest(".policyPanel").find("#go_properties_tab"+polCount).text(opselected);
481 $(this).closest("[id^='go_properties_tab']").text("Policy");
485 if (this.id=="parentPolicy"){
486 var ppCond = $(this).closest("[id^='formId']").find("#parentPolicyConditions");
488 ppCond.multiselect("clearSelection");
489 ppCond.multiselect("disable");
491 ppCond.multiselect("enable");
495 $("#formId"+count+" select").each( function () {
496 this.change = onSelectChange;
501 //This is ensure there are no repeated keys in the map
502 function noRepeats(form) {
503 //triggered per policy.
505 for (var i = 0; i < form.length; i++) {
506 if (select[form[i].name] === undefined)
507 select[form[i].name] = []
508 select[form[i].name].push(form[i].value);
520 $("#savePropsBtn").click(function(event) {
521 if($("#targetResourceIdOther").is(":visible")) {
522 $('#targetResourceId').append($('<option></option>').val($("#targetResourceIdOther").val()).html($("#targetResourceIdOther").val()))
523 $("#targetResourceId").val($("#targetResourceIdOther").val());
525 $(".idError").hide();
526 if ($("#policyTable .highlight td").html() !== $("#pname").val()){
528 if ($.inArray($("#pname").val(), Object.keys(allPolicies)) > -1){
529 $("#repeatIdError").show();
531 } else { //not repeated
532 delete allPolicies[$("#policyTable .highlight td").html()];
535 if ($("#pname").val().trim() == "New_Policy"){
536 $("#newIdError").show();
541 /* if ($("#policyTable .highlight").length > 0){
542 saveLastPolicyLocally($("#policyTable .highlight").attr("id"));
546 //Removes outdated (deleted) policies by checking against left menu
547 var finalSaveList = {};
548 $("#policyTable td").each(function(){
549 var tableVal = $(this).text();
550 if (tableVal in allPolicies){
551 finalSaveList[tableVal] = allPolicies[tableVal];
555 saveProperties(finalSaveList);
556 $("#close_button").click();
559 function add_one_more() {
560 $("#nav_Tabs li").removeClass("active");
562 //FormSpan contains a block of the form that is not being displayed. We will create clones of that and add them to tabs
563 var form = $($("#formSpan").children()[0]).clone()
565 //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
566 if ($(".formId").length > 0) {
568 var s = $(".formId");
569 for (var i = 0; i < s.length; i++) {
570 if (parseInt($(s[i]).attr("id").substring(6)) > greatest) {
571 greatest = parseInt($(s[i]).attr("id").substring(6))
574 count = greatest + 1;
575 $("#properties_tab").append(
576 ('<span class="formId" id="formId'+count+'"></span>'));
579 $("#properties_tab").append(
580 '<span class="formId" id="formId1"></span>');
583 //$(form).find("#policyName").val("Recipe "+makid(2))
584 //TODO change up how we auto assign policyName. There could be the case where we do this and it will have repeats
585 //alert($(form).find("#_id").val())
586 //policyNameChangeListener(form)
590 ' <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>');
591 $("#formId" + count).append(form);
592 $(".formId").not($("#formId" + count)).css("display", "none")
595 addSelectListen(count);
596 // This is for when the process is not loading from map but being created
599 $(form).find("#_id").val(l)
600 policy_ids["#formId" + count]=l
603 for(var i=1;i<=greatestIdNum();i++){
604 if($("#formId"+i).length>0){
605 answers["#formId"+i+" #parentPolicy"]=$("#formId"+i+" #parentPolicy").val();
606 $("#formId"+i+" #parentPolicy").empty();
608 for(k in policy_ids){
609 if(($("#formId"+i+" #_id").val()!==policy_ids[k].toString()) && $(k+" #recipe").val()!==undefined && $(k+" #recipe").val()!==""){
610 $("#formId"+i+" #parentPolicy").append("<option value='"+policy_ids[k]+"'>"+$(k+" #recipe").val()+"</option>")
613 $("#formId"+i+" #parentPolicy").prepend("<option value=''></option>")
617 $("#formId"+count+" #parentPolicyConditions").multiselect("disable");
619 //re-populate parent policy with chosen options
628 function add_new_policy(issueNewNames) {
629 //remove old gui forms
630 for (var i=1; i<($(".formId").length + 1); i++){
631 $("#go_properties_tab"+i).parent().remove();
633 $(".formId").remove();
636 //$("#pname").val("0");
637 $("#pname").val("New_Policy");
638 $("#timeout").val(defaults_props.policy.timeout);
640 $("#add_one_more").click();
643 function addCustListen(count) {
644 $('#go_properties_tab' + count).click(function(event) {
645 $("#nav_Tabs li").removeClass("active");
646 $(this).parent().addClass("active");
647 $("#formId" + count).css("display", "")
648 $(".formId").not($("#formId" + count)).css("display", "none")
651 $('#tab_close' + count).click(function(event) {
652 if(document.getElementById("timeout").disabled){
655 $(this).parent().remove();
656 for(var i=1;i<=greatestIdNum();i++){
657 if( $("#formId"+i).length>0){
659 if( $("#formId"+i+" #parentPolicy").val()===$("#formId"+count+" #_id").val().toString())
660 $("#formId"+i+" #parentPolicy").val("")
661 $("#formId"+i+" #parentPolicy option[value='"+$("#formId"+count+" #_id").val().toString()+"']").remove();
665 delete policy_ids["#formId" + count + " #_id"]
666 $("#formId" + count).remove();
671 function greatestIdNum() {
673 var s = $(".formId");
674 for (var i = 0; i < s.length; i++) {
675 if (parseInt($(s[i]).attr("id").substring(6)) > greatest) {
676 greatest = parseInt($(s[i]).attr("id").substring(6))
682 //Generate random id for each policy
683 //Also made sure ids couldnt be repeated
684 function makeid(num) {
687 var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
690 for (var i = 0; i < 7; i++)
691 text += possible.charAt(Math.floor(Math.random()
693 var hasValue = false;
694 for (k in policy_ids) {
695 if (text === policy_ids[k])
704 var ParentPolicy = function(id, name) {
709 //Policy table search filter
710 function searchPolicyList() {
711 var search = document.getElementById("policySearch");
712 var row = document.getElementsByTagName("td");
713 for (var i = 0; i < row.length; i++) {
714 if (row[i].innerHTML.toUpperCase().indexOf(
715 search.value.toUpperCase()) > -1) {
716 row[i].style.display = "";
718 row[i].style.display = "none";
723 function saveLastPolicyLocally(lastPolicyId) {
726 var properties = $(".saveProps").not("#formSpan .saveProps");
727 var timeoutForm = $("#Timeoutform").serializeArray();
729 for (var i = 0; i < timeoutForm.length; i++) {
730 polForm.push(timeoutForm[i]);
734 d["policyConfigurations"] = [];
735 for (var i = 0; i < properties.length; i++) {
736 var ser = $(properties[i]).serializeArray();
737 var s = noRepeats(ser)
738 d["policyConfigurations"].push(s);
741 allPolicies[lastPolicyId] = polForm;
744 function getNextId(){
747 if ((Math.min.apply(Math, allPolIds) == 0)
748 && (allPolIds.length > 0)) {
750 for (var i = 1; i < allPolIds.length; i++) {
751 if ((allPolIds[i] - allPolIds[i - 1]) != 1) {
752 newPolId = (allPolIds[i - 1] + 1);
757 newPolId = (Math.max.apply(Math, allPolIds)) + 1;
762 allPolIds.push(newPolId);
763 $("#pid").val(newPolId);
766 $("#deletePolicy").on('click', function() {
767 $(".idError").hide();
769 allPolIds.splice((allPolIds.indexOf(parseInt($("#pid").val()))),1);
772 var deleteId = $("#policyTable .highlight td").html();
773 delete allPolicies[deleteId];
774 $("#policyTable .highlight").remove();
779 $('#policyTable').on('click', 'tr', function(event) {
780 $(".idError").hide();
782 if ($("#policyTable .highlight td").html() !== $("#pname").val()){
784 if ($.inArray($("#pname").val(), Object.keys(allPolicies)) > -1){
785 $("#repeatIdError").show();
787 } else { //not repeated
788 $("#repeatIdError").hide();
789 delete allPolicies[$("#policyTable .highlight td").html()];
792 //if (parseInt($("#pname").val()) == 0){
793 if ($("#pname").val().trim() == "New_Policy"){
794 $("#newIdError").show();
800 if ($("#policyTable .highlight").length == 0){
804 $(this).addClass('highlight').siblings().removeClass('highlight');
805 disperseConfig(allPolicies, $(this).find("td").html());
808 $('#createNewPolicy').on('click', function(){
809 $(".idError").hide();
811 if ($("#policyTable .highlight td").html() !== $("#pname").val()){
813 if ($.inArray($("#pname").val(), Object.keys(allPolicies)) > -1){
814 $("#repeatIdError").show();
816 } else { //not repeated
817 $("#repeatIdError").hide();
818 delete allPolicies[$("#policyTable .highlight td").html()];
821 //if (parseInt($("#pname").val()) == 0){
822 if ($("#pname").val().trim() == "New_Policy"){
823 $("#newIdError").show();
828 if (("#policyTable .highlight").length > 0){
829 $('#policyTable tr.highlight').removeClass('highlight');
831 $("#policyTable").prepend("<tr class='highlight'><td>New_Policy</td></tr>");
836 $('#pname').on('keypress', function(e){
837 /* var newVal = $(this).val() + String.fromCharCode(e.which);
838 if ((newVal>99) || (($(this).val().length>2) && e.keyCode != 46 && e.keyCode !=8)){
841 if (e.keyCode == 32){
842 $("#spaceError").show();
847 function isNumberKey(event){
848 var charCode = (event.which) ? event.which : event.keyCode
849 if (charCode > 31 && (charCode < 48 || charCode > 57)){
855 function startNextItem() {
856 //save last item before transitioning
857 var lastItem = $("#policyTable .highlight");
858 if (lastItem.length > 0) {
859 saveLastPolicyLocally($("#pname").val());
860 //lastItem.attr("id", $("#pname").val());
861 lastItem.find("td").html($("#pname").val());
867 if ($("#deletePolicy").prop("disabled")) {
868 $("#deletePolicy").prop("disabled", false);
873 initTargetResourceId();
874 //load metrics dropdown
875 if (elementMap["global"]){
876 for (var i = 0; i < (elementMap["global"].length); i++){
877 if ((elementMap["global"][i]["name"]) == "actionSet"){
878 var asSel = elementMap["global"][i]["value"];
879 if (asSel == "vnfRecipe"){
880 if (vf_Services["policy"][asSel]){
881 $.each((vf_Services["policy"][asSel]), function(val, text) {
883 $('<option></option>').val(val).html(text)
893 //Show table panel only
894 function expandTable() {
895 $(".policyPanel").css("display", "none");
896 $(".leftPolicyPanel").removeClass("col-sm-3");
897 $(".modelSearchBox").css("padding", "25px 12px");
898 if (!($("#deletePolicy").prop("disabled"))) {
899 $("#deletePolicy").prop("disabled", true);
904 function collapseTable() {
905 $(".leftPolicyPanel").addClass("col-sm-3");
906 $(".modelSearchBox").css("padding", "10px 12px");
907 $(".policyPanel").css("display", "unset");