2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
23 app.controller("aaiSubscriberController", [ "COMPONENT", "DataService", "PropertyService", "$scope", "$http", "$timeout", "$location", "$log", "$route", "UtilityService", "vidService",
24 function(COMPONENT, DataService, PropertyService, $scope, $http, $timeout, $location, $log, $route, UtilityService, vidService) {
26 $scope.showVnfDetails = function(vnf) {
27 console.log("showVnfDetails");
28 DataService.setVnfInstanceId("VNF_INSTANCE_ID_12345");
30 .setInventoryItem(aaiResult["inventory-response-items"]["inventory-response-item"][0]);
32 $scope.$broadcast("showComponentDetails", {
33 componentId : COMPONENT.VNF,
34 callbackFunction : callbackFunction
37 $scope.popup = new Object();
40 $scope.isPopupVisible = false;
41 $scope.defaultBaseUrl = "";
42 $scope.responseTimeoutMsec = 60000;
44 $scope.serviceTypes=[ "Select a service type" ];
45 $scope.defaultSubscriberName=[ "Select a subscriber name" ];
47 var callbackFunction = function(response) {
51 $scope.getSubs = function() {
52 $scope.status = "Fetching subscriber list from A&AI...";
54 $http.get( PropertyService.getAaiBaseUrl() + "/aai_get_full_subscribers" + '?r=' + Math.random(), {
57 timeout: $scope.responseTimeoutMsec
58 }).then($scope.handleInitialResponse)
59 ["catch"]($scope.handleServerError);
60 var serviceIdList = [];
61 $http.get(PropertyService.getAaiBaseUrl() + "/aai_get_services" + '?r=' + Math.random(), {
63 timeout: $scope.responseTimeoutMsec
64 }).then(function(response) {
65 angular.forEach(response.data, function(value, key) {
66 angular.forEach(value, function(subVal, key) {
67 var newVal = { "id" : subVal["service-id"], "description" : subVal["service-description"] };
68 serviceIdList.push(newVal);
69 DataService.setServiceIdList(serviceIdList);
75 $scope.refreshSubs = function() {
76 $scope.status = "Fetching subscriber list from A&AI...";
78 $http.get(PropertyService.getAaiBaseUrl() + "/aai_refresh_full_subscribers" + '?r=' + Math.random(), {
81 timeout: $scope.responseTimeoutMsec
82 }).then($scope.handleInitialResponse)
83 ["catch"]($scope.handleServerError);
86 $scope.getSubDetails = function(request) {
89 $scope.selectedSubscriber = $location.search().selectedSubscriber;
90 $scope.selectedServiceInstance = $location.search().selectedServiceInstance;
91 $scope.status = "Fetching subscriber details from A&AI for " + $scope.selectedSubscriber;
92 $http.get(PropertyService.getAaiBaseUrl() + "/aai_sub_details/" + $scope.selectedSubscriber + '?r=' + Math.random(), {
95 timeout: $scope.responseTimeoutMsec
96 }).then(function(response) {
97 $scope.subscriber = response.data;
98 $scope.selectedSubscriberName = $scope.subscriber["subscriber-name"];
100 $scope.displayData= [];
101 if ($scope.subscriber["service-subscriptions"] != null) {
102 angular.forEach($scope.subscriber["service-subscriptions"]["service-subscription"], function(serviceSubscription, key) {
103 $scope.serviceInstanceId = [];
104 if (serviceSubscription["service-type"] != null) {
105 $scope.serviceType = serviceSubscription["service-type"];
107 $scope.serviceType = "No Service Subscription Found";
109 if (serviceSubscription["service-instances"] != null) {
110 angular.forEach(serviceSubscription["service-instances"]["service-instance"], function(instValue, instKey) {
111 // put them together, i guess
112 var inst = { "serviceInstanceId": instValue["service-instance-id"],
113 "personaModelId": instValue["persona-model-id"],
114 "personaModelVersion": instValue["persona-model-version"],
115 "serviceInstanceName": instValue["service-instance-name"]
117 if ($scope.selectedServiceInstance != null) {
118 if (instValue["service-instance-id"] == $scope.selectedServiceInstance) {
119 $scope.serviceInstanceId.push(inst);
122 $scope.serviceInstanceId.push(inst);
126 if ($scope.serviceInstanceId == []) {
127 $scope.serviceInstanceId = [ "No Service Instance Found" ];
130 angular.forEach($scope.serviceInstanceId, function(subVal, subKey) {
131 $scope.displayData.push({
132 globalCustomerId : $scope.selectedSubscriber,
133 subscriberName : $scope.selectedSubscriberName,
134 serviceType : $scope.serviceType,
135 serviceInstanceId : subVal.serviceInstanceId,
136 personaModelId : subVal.personaModelId,
137 personaModelVersion : subVal.personaModelVersion,
138 serviceInstanceName : subVal.serviceInstanceName
143 $scope.displayData.push({
144 globalCustomerId : $scope.selectedSubscriber,
145 subscriberName : $scope.selectedSubscriberName,
146 serviceType : "No Service Subscription Found",
147 serviceInstanceId : "No Service Instance Found"
150 $scope.viewPerPage=10;
151 $scope.totalPage=$scope.displayData.length/$scope.viewPerPage;
152 $scope.scrollViewPerPage=2;
153 $scope.currentPage=1;
154 $scope.searchCategory;
155 $scope.searchString="";
156 $scope.currentPageNum=1;
157 $scope.defaultSort="subscriberName"
158 $scope.setProgress(100); // done
159 $scope.status = "Done";
160 $scope.isSpinnerVisible = false;
165 $scope.$on("deleteInstance", function(event, request) {
166 // $log.debug("deleteInstance: request:");
167 // $log.debug(request);
169 // Use this line instead of the subsequent $http.post to change from POST to DELETE
170 // $http["delete"]($scope.baseUrl + request.url,{timeout: $scope.responseTimeoutMsec}).then($scope.requestOkay
171 $http.post($scope.baseUrl + request.url, {
172 requestDetails: request.requestDetails
174 timeout: $scope.responseTimeoutMsec
175 }).then($scope.handleInitialResponse)
176 ["catch"]($scope.handleServerError);
179 $scope.init = function() {
181 //PropertyService.setAaiBaseUrl("testaai");
182 //PropertyService.setAsdcBaseUrl("testasdc");
184 // takes a default value, retrieves the prop value from the file system and sets it
185 var msecs = PropertyService.retrieveMsoMaxPollingIntervalMsec(1000);
186 PropertyService.setMsoMaxPollingIntervalMsec(msecs);
188 // takes a default value, retrieves the prop value from the file system and sets it
189 var polls = PropertyService.retrieveMsoMaxPolls(7);
190 PropertyService.setMsoMaxPolls(polls);
192 //PropertyService.setMsoBaseUrl("testmso");
193 PropertyService.setServerResponseTimeoutMsec(10000);
196 * Common parameters that would typically be set when the page is
197 * displayed for a specific service instance id.
200 // DataService.setSubscriberName("Mobility");
201 // DataService.setGlobalCustomerId("CUSTID12345")
202 // DataService.setServiceType("Mobility Type 1");
203 // DataService.setServiceName("Mobility Service 1");
204 // DataService.setServiceInstanceId("mmsc-test-service-instance");
206 $scope.baseUrl = $scope.defaultBaseUrl;
208 $scope.isSpinnerVisible = true;
209 $scope.isProgressVisible = true;
210 $scope.isPopupVisible = true;
211 $scope.requestId = "";
213 $scope.pollAttempts = 0;
215 $scope.enableCloseButton(false);
216 $scope.resetProgress();
217 $scope.setProgress(2); // Show "a little" progress
220 $scope.getComponentList = function(event, request) {
222 $scope.isSpinnerVisible = true;
223 $scope.isProgressVisible = true;
224 $scope.isPopupVisible = true;
225 $scope.requestId = "";
227 $scope.pollAttempts = 0;
230 $scope.resetProgress();
231 $scope.setProgress(2); // Show "a little" progress
233 //subscriberId=jimmy-testing&serviceType=gamma-01%2F1&serviceInstanceId=jimmy2-01%2F01%2F%2F01
234 $scope.globalCustomerId = $location.search().subscriberId;
235 $scope.serviceType = $location.search().serviceType;
236 $scope.serviceInstanceId = $location.search().serviceInstanceId;
238 //$scope.getAsdcModel($location.search().modelUuid);
240 // this should be in a config file?
241 $scope.namedQueryId = "ed0a0f5b-cf79-4784-88b2-911cd726cd3d";
242 $scope.url = PropertyService.getAaiBaseUrl() + "/aai_sub_viewedit" +
243 "/" + encodeURIComponent($scope.namedQueryId) +
244 "/" + encodeURIComponent($scope.globalCustomerId) +
245 "/" + encodeURIComponent($scope.serviceType) +
246 "/" + encodeURIComponent($scope.serviceInstanceId) + '?r=' + Math.random();
248 $scope.status = "Fetching service instance data from A&AI for service-instance-id=" + $scope.serviceInstanceId;
249 $http.get($scope.url, {
251 timeout: $scope.responseTimeoutMsec
252 }).then($scope.handleInitialResponseInventoryItems)
253 ["catch"]($scope.handleServerError);
256 $scope.handleServerError = function(response, status) {
257 alert(response.statusText);
260 $scope.getAsdcModel = function(disData) {
261 $http.get(PropertyService.getAaiBaseUrl() + '/rest/models/services')
262 .then(function successCallback(response) {
264 var lastVersion = -1;
265 angular.forEach(response.data, function(model, key) {
266 if (angular.equals(model.invariantUUID,disData.personaModelId)) {
267 if (model.version > lastVersion) {
268 lastVersion = model.version;
276 console.log("aaiSubscriber getAsdcModel - No matching model found matching the persona Model Id = " + disData.personaModelId);
281 $http.get(PropertyService.getAaiBaseUrl() + '/rest/models/services/' + myUuid)
282 .then(function successCallback(response2) {
283 vidService.setModel(response2.data);
284 window.location.href = "#/instantiate?subscriberId=" + disData.globalCustomerId + "&serviceType=" + disData.serviceType + "&serviceInstanceId=" + disData.serviceInstanceId;
285 console.log("aaiSubscriber getAsdcModel DONE!!!!");
288 }, function errorCallback(response) {
293 $scope.getTenants = function(globalCustomerId) {
294 $http.get(PropertyService.getAaiBaseUrl() + '/aai_get_tenants' + globalCustomerId + '?r=' + Math.random())
295 .then(function successCallback(response) {
296 return response.data;
297 //$location.path("/instantiate");
298 }, function errorCallback(response) {
303 $scope.handleInitialResponseInventoryItems = function(response) {
304 // $log.debug("handleInitialResponse: response contents:");
305 // $log.debug(response);
308 if (response.status < 200 || response.status > 202) {
309 $scope.handleServerError(response, response.status);
313 $scope.inventoryResponseItemList = response.data["inventory-response-item"]; // get data from json
314 console.log($scope.inventoryResponseItemList.toString());
316 $scope.displayData = [];
319 $scope.counter = 100;
321 angular.forEach($scope.inventoryResponseItemList, function(inventoryResponseItem, key) {
323 $scope.inventoryResponseItem = inventoryResponseItem;
325 $scope.serviceInstanceToCustomer = DataService.getServiceInstanceToCustomer();
326 var subscriberName = "";
327 angular.forEach($scope.serviceInstanceToCustomer, function(servInst, key2) {
328 if (servInst.serviceInstanceId === $scope.serviceInstanceId) {
329 subscriberName = servInst.subscriberName;
332 $scope.service.instance = {
333 "name": $scope.inventoryResponseItem["service-instance"]["service-instance-name"],
334 "serviceInstanceId": $scope.serviceInstanceId,
335 "serviceType": $scope.serviceType,
336 "globalCustomerId": $scope.globalCustomerId,
337 "subscriberName": subscriberName,
338 "id": $scope.serviceInstanceId,
342 "description": "This variable is 'a'",
343 "default": "A default"
347 "description": "This variable is 'b'",
348 "default": "B default"
351 "object": $scope.inventoryResponseItem["service-instance"],
356 if (inventoryResponseItem["inventory-response-items"] != null) {
358 angular.forEach(inventoryResponseItem["inventory-response-items"]["inventory-response-item"], function(subInventoryResponseItem, key) {
359 // i expect to find vnfs now
361 if (subInventoryResponseItem["l3-network"] != null) {
362 var l3NetworkObject = subInventoryResponseItem["l3-network"];
363 var l3Network = { "id": $scope.counter++,
364 "name": l3NetworkObject["network-name"],
365 "itemType": "l3-network",
366 "nodeId": l3NetworkObject["network-id"],
367 "nodeType": l3NetworkObject["network-type"],
368 "nodeStatus": l3NetworkObject["orchestration-status"],
369 "object": l3NetworkObject,
372 $scope.service.instance["networks"].push(l3Network);
375 if (subInventoryResponseItem["generic-vnf"] != null) {
376 var genericVnfObject = subInventoryResponseItem["generic-vnf"];
379 "name": genericVnfObject["vnf-name"],
380 "id": $scope.counter++,
382 "nodeType": genericVnfObject["vnf-type"],
383 "nodeId": genericVnfObject["vnf-id"],
384 "nodeStatus": genericVnfObject["orchestration-status"],
385 "object": genericVnfObject,
388 "availableVolumeGroups": []
390 $scope.service.instance["vnfs"].push(genericVnf);
392 // look for volume-groups
393 if (subInventoryResponseItem["inventory-response-items"] != null) {
394 angular.forEach(subInventoryResponseItem["inventory-response-items"]["inventory-response-item"], function(vfmodules, key) {
396 if (vfmodules["volume-group"] != null) {
397 var volumeGroupObject = vfmodules["volume-group"];
398 var volumeGroup = { "id": $scope.counter++,
399 "name": volumeGroupObject["volume-group-name"],
400 "itemType": "volume-group",
401 "nodeId": volumeGroupObject["volume-group-id"],
402 "nodeType": volumeGroupObject["vnf-type"],
403 "nodeStatus": volumeGroupObject["orchestration-status"],
404 "object": volumeGroupObject,
407 genericVnf["volumeGroups"].push(volumeGroup);
408 genericVnf["availableVolumeGroups"].push(volumeGroup);
412 // now we've loaded up the availableVolumeGroups, we can use it
413 if (subInventoryResponseItem["inventory-response-items"] != null) {
414 angular.forEach(subInventoryResponseItem["inventory-response-items"]["inventory-response-item"], function(vfmodules, key) {
416 if (vfmodules["vf-module"] != null) {
417 var vfModuleObject = vfmodules["vf-module"];
418 var vfModule = { "id": $scope.counter++,
419 "name": vfModuleObject["vf-module-name"],
420 "itemType": "vf-module",
421 "nodeType": "vf-module",
422 "nodeStatus": vfModuleObject["orchestration-status"],
424 "object": vfModuleObject,
427 genericVnf["vfModules"].push(vfModule);
428 if (vfmodules["inventory-response-items"] != null) {
429 angular.forEach(vfmodules["inventory-response-items"]["inventory-response-item"], function(networks, key) {
430 if (networks["l3-network"] != null) {
431 var l3NetworkObject = networks["l3-network"];
432 var l3Network = { "id": $scope.counter++,
433 "name": l3NetworkObject["network-name"],
434 "itemType": "l3-network",
435 "nodeId": l3NetworkObject["network-id"],
436 "nodeType": l3NetworkObject["network-type"],
437 "nodeStatus": l3NetworkObject["orchestration-status"],
438 "object": l3NetworkObject,
441 vfModule["networks"].push(l3Network);
443 if (networks["volume-group"] != null) {
444 var volumeGroupObject = networks["volume-group"];
446 var volumeGroup = { "id": $scope.counter++,
447 "name": volumeGroupObject["volume-group-name"],
448 "itemType": "volume-group",
449 "nodeId": volumeGroupObject["volume-group-id"],
450 "nodeType": volumeGroupObject["vnf-type"],
451 "nodeStatus": volumeGroupObject["orchestration-status"],
452 "object": volumeGroupObject,
455 var tmpVolGroup = [];
457 angular.forEach(genericVnf["availableVolumeGroups"], function(avgroup, key) {
458 if (avgroup.name != volumeGroup.name) {
459 tmpVolGroup.push(avgroup);
463 genericVnf["availableVolumeGroups"] = tmpVolGroup;
465 vfModule["volumeGroups"].push(volumeGroup);
478 $scope.setProgress(100); // done
479 $scope.status = "Done";
480 $scope.isSpinnerVisible = false;
481 console.log("HERE!!!");
487 $scope.handleInitialResponse = function(response) {
489 $scope.enableCloseButton(true);
490 $scope.updateLog(response);
491 if (response.data.status < 200 || response.data.status > 202) {
492 $scope.showError("MSO failure - see log below for details")
496 $scope.setProgress(100); // done
497 $scope.status = "Done";
498 $scope.isSpinnerVisible = false;
500 $scope.customer = response.data.customer; // get data from json
502 $scope.customerList = [];
504 $scope.serviceInstanceToCustomer = [];
505 //$scope.serviceIdList = [];
506 angular.forEach($scope.customer, function(subVal, subKey) {
507 var cust = { "globalCustomerId": subVal["global-customer-id"], "subscriberName": subVal["subscriber-name"] };
508 $scope.customerList.push(cust);
509 if (subVal["service-subscriptions"] != null) {
512 angular.forEach(subVal["service-subscriptions"]["service-subscription"], function(serviceSubscription, key) {
513 $scope.serviceInstanceId = [];
514 if (serviceSubscription["service-type"] != null) {
515 // var newVal = { "id" : serviceSubscription["service-type"], "description" : serviceSubscription["service-type"] };
516 // if ($scope.serviceIdList.indexOf(newVal) == -1) {
517 // $scope.serviceIdList.push(newVal);
519 $scope.serviceType = serviceSubscription["service-type"];
521 $scope.serviceType = "No Service Subscription Found";
523 if (serviceSubscription["service-instances"] != null) {
524 angular.forEach(serviceSubscription["service-instances"]["service-instance"], function(instValue, instKey) {
525 var foo = { "serviceInstanceId": instValue["service-instance-id"],
526 "globalCustomerId": subVal["global-customer-id"],
527 "subscriberName": subVal["subscriber-name"] };
528 $scope.serviceInstanceToCustomer.push(foo);
534 // DataService.setServiceIdList($scope.serviceIdList);
535 DataService.setServiceInstanceToCustomer($scope.serviceInstanceToCustomer);
537 $scope.showContentError(error);
541 $scope.autoGetSubs = function() {
543 * Optionally comment in / out one of these method calls (or add a similar
544 * entry) to auto-invoke an entry when the test screen is redrawn.
550 $scope.pollStatus = function () {
552 * The "?r=" argument overrides caching. This was needed for Internet Explorer 11.
554 * Ideally this should NOT be needed and appears to be an Angular bug.
556 $http.get($scope.baseUrl + "mso_get_orch_req/" + $scope.requestId + "?r=" + Math.random(), {
557 cache: false, // This alternative did NOT seem to disable caching but was retained as a reference
558 timeout: $scope.responseTimeoutMsec
559 }).then($scope.handlePollResponse)
560 ["catch"]($scope.handleServerError);
563 $scope.handlePollResponse = function(response) {
565 // $log.debug("handlePollResponse: response contents:");
566 // $log.debug(response);
567 $scope.updateLog(response);
569 if (response.data.status < 200 || response.data.status > 202) {
570 $scope.showError("MSO failure - see log below for details")
574 // UtilityService.checkUndefined("request", response.data.entity.request);
575 // UtilityService.checkUndefined("requestStatus", response.data.entity.request.requestStatus);
577 // $scope.setProgress(response.data.entity.request.requestStatus.percentProgress);
579 // var requestState = response.data.entity.request.requestStatus.requestState;
580 // if (requestState == "InProgress") {
581 // requestState = "In Progress";
583 // var statusMessage = response.data.entity.request.requestStatus.statusMessage;
584 // if (UtilityService.hasContents(statusMessage)) {
585 // $scope.status = requestState + " - " + statusMessage;
587 // $scope.status = requestState;
589 // if (requestState == "Complete") {
590 // $scope.isSpinnerVisible = false;
593 // if (requestState == "Failure") {
594 // $scope.showError("MSO failure - see log below for details")
597 // if (++$scope.pollAttempts > $scope.properties.msoMaxPolls) {
598 // $scope.showError("Maximum number of poll attempts exceeded");
600 // $scope.timer = $timeout($scope.pollStatus, $scope.properties.msoMaxPollingIntervalMsec);
603 $scope.showContentError(error);
607 $scope.updateLog = function(response) {
608 // $scope.log = UtilityService.getCurrentTime() + " HTTP Status: " +
609 // UtilityService.getHttpStatusText(response.data.status) + "\n" +
610 // angular.toJson(response.data.entity, true) + "\n\n" + $scope.log;
611 // UtilityService.checkUndefined("entity", response.data.entity);
612 // UtilityService.checkUndefined("status", response.data.status);
615 $scope.handleServerError = function(response, status) {
616 $scope.enableCloseButton(true);
617 var message = UtilityService.getHttpErrorMessage(response);
619 message = " (" + message + ")";
621 $scope.showError("System failure" + message);
624 $scope.showContentError = function(message) {
625 // $log.debug(message);
626 console.log(message);
627 if (UtilityService.hasContents(message)) {
628 $scope.showError("System failure (" + message + ")");
630 $scope.showError("System failure");
634 $scope.showError = function(message) {
635 $scope.isSpinnerVisible = false;
636 $scope.isProgressVisible = false;
637 $scope.error = message;
638 $scope.status = "Error";
641 $scope.close = function() {
642 if ($scope.timer != undefined) {
643 $timeout.cancel($scope.timer);
645 $scope.isPopupVisible = false;
651 * Consider converting the progress bar mechanism, the disabled button handling
652 * and the following methods to generic Angular directive(s) and/or approach.
655 $scope.enableCloseButton = function(isEnabled) {
656 var selector = "div[ng-controller=msoCommitController] button";
658 $scope.isCloseEnabled = isEnabled;
661 $(selector).addClass("button--primary").removeClass("button--inactive").attr("btn-type", "primary");
663 $(selector).removeClass("button--primary").addClass("button--inactive").attr("btn-type", "disabled");
667 $scope.resetProgress = function() {
668 $scope.percentProgress = 0;
669 $scope.progressClass = "progress-bar progress-bar-info";
672 $scope.setProgress = function(percentProgress) {
673 percentProgress = parseInt(percentProgress);
674 if (percentProgress >= 100) {
675 $scope.progressClass = "progress-bar progress-bar-success";
678 if (percentProgress < $scope.percentProgress) {
682 $scope.percentProgress = percentProgress;
683 $scope.progressWidth = {width: percentProgress + "%"};
684 if (percentProgress >= 5) {
685 $scope.progressText = percentProgress + " %";
687 // Hidden since color combination is barely visible when progress portion is narrow.
688 $scope.progressText = "";
692 $scope.reloadRoute = function() {
696 $scope.prevPage = function() {
697 $scope.currentPage--;
700 $scope.nextPage = function() {
701 $scope.currentPage++;
703 $scope.getSubscriberDet = function(selectedCustomer,selectedServiceInstance){
704 if (selectedCustomer != null) {
705 window.location.href = '#/instances/subdetails?selectedSubscriber=' + selectedCustomer;
706 } else if (selectedServiceInstance != null) {
707 selectedServiceInstance.trim();
708 var serviceInstanceToCustomer = $scope.serviceInstanceToCustomer;
710 angular.forEach(serviceInstanceToCustomer, function(inst, key) {
711 if (inst.serviceInstanceId == selectedServiceInstance) {
714 window.location.href = '#/instances/subdetails?selectedSubscriber=' + inst.globalCustomerId + '&selectedServiceInstance=' + selectedServiceInstance;
718 alert("That service instance does not exist. Please try again.");
721 alert("Please select a subscriber or enter a service instance");
728 app.controller('TreeCtrl', ['$scope', function ($scope) {
729 $scope.remove = function (scope) {
733 $scope.toggle = function (scope) {
737 $scope.moveLastToTheBeginning = function () {
738 var a = $scope.data.pop();
739 $scope.data.splice(0, 0, a);
742 $scope.newSubItem = function (scope) {
743 var nodeData = scope.$modelValue;
744 nodeData.nodes.push({
745 id: nodeData.id * 10 + nodeData.nodes.length,
746 title: nodeData.title + '.' + (nodeData.nodes.length + 1),
751 $scope.collapseAll = function () {
752 $scope.$broadcast('angular-ui-tree:collapse-all');
755 $scope.expandAll = function () {
756 $scope.$broadcast('angular-ui-tree:expand-all');