diff options
Diffstat (limited to 'vid/src/main/webapp/app/vid/scripts')
48 files changed, 9004 insertions, 0 deletions
diff --git a/vid/src/main/webapp/app/vid/scripts/angular-ui-tree.js b/vid/src/main/webapp/app/vid/scripts/angular-ui-tree.js new file mode 100644 index 000000000..a7e8cf494 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/angular-ui-tree.js @@ -0,0 +1,1636 @@ +/** + * @license Angular UI Tree v2.17.0 + * (c) 2010-2016. https://github.com/angular-ui-tree/angular-ui-tree + * License: MIT + */ +(function () { + 'use strict'; + + angular.module('ui.tree', []) + .constant('treeConfig', { + treeClass: 'angular-ui-tree', + emptyTreeClass: 'angular-ui-tree-empty', + hiddenClass: 'angular-ui-tree-hidden', + nodesClass: 'angular-ui-tree-nodes', + nodeClass: 'angular-ui-tree-node', + handleClass: 'angular-ui-tree-handle', + placeholderClass: 'angular-ui-tree-placeholder', + dragClass: 'angular-ui-tree-drag', + dragThreshold: 3, + levelThreshold: 30, + defaultCollapsed: false + }); + +})(); + +(function () { + 'use strict'; + + angular.module('ui.tree') + + .controller('TreeHandleController', ['$scope', '$element', + function ($scope, $element) { + this.scope = $scope; + + $scope.$element = $element; + $scope.$nodeScope = null; + $scope.$type = 'uiTreeHandle'; + + } + ]); +})(); + +(function () { + 'use strict'; + + angular.module('ui.tree') + .controller('TreeNodeController', ['$scope', '$element', + function ($scope, $element) { + this.scope = $scope; + + $scope.$element = $element; + $scope.$modelValue = null; // Model value for node; + $scope.$parentNodeScope = null; // uiTreeNode Scope of parent node; + $scope.$childNodesScope = null; // uiTreeNodes Scope of child nodes. + $scope.$parentNodesScope = null; // uiTreeNodes Scope of parent nodes. + $scope.$treeScope = null; // uiTree scope + $scope.$handleScope = null; // it's handle scope + $scope.$type = 'uiTreeNode'; + $scope.$$allowNodeDrop = false; + $scope.collapsed = false; + $scope.expandOnHover = false; + + $scope.init = function (controllersArr) { + var treeNodesCtrl = controllersArr[0]; + $scope.$treeScope = controllersArr[1] ? controllersArr[1].scope : null; + + // find the scope of it's parent node + $scope.$parentNodeScope = treeNodesCtrl.scope.$nodeScope; + // modelValue for current node + $scope.$modelValue = treeNodesCtrl.scope.$modelValue[$scope.$index]; + $scope.$parentNodesScope = treeNodesCtrl.scope; + treeNodesCtrl.scope.initSubNode($scope); // init sub nodes + + $element.on('$destroy', function () { + treeNodesCtrl.scope.destroySubNode($scope); // destroy sub nodes + }); + }; + + $scope.index = function () { + return $scope.$parentNodesScope.$modelValue.indexOf($scope.$modelValue); + }; + + $scope.dragEnabled = function () { + return !($scope.$treeScope && !$scope.$treeScope.dragEnabled); + }; + + $scope.isSibling = function (targetNode) { + return $scope.$parentNodesScope == targetNode.$parentNodesScope; + }; + + $scope.isChild = function (targetNode) { + var nodes = $scope.childNodes(); + return nodes && nodes.indexOf(targetNode) > -1; + }; + + $scope.prev = function () { + var index = $scope.index(); + if (index > 0) { + return $scope.siblings()[index - 1]; + } + return null; + }; + + $scope.siblings = function () { + return $scope.$parentNodesScope.childNodes(); + }; + + $scope.childNodesCount = function () { + return $scope.childNodes() ? $scope.childNodes().length : 0; + }; + + $scope.hasChild = function () { + return $scope.childNodesCount() > 0; + }; + + $scope.childNodes = function () { + return $scope.$childNodesScope && $scope.$childNodesScope.$modelValue ? + $scope.$childNodesScope.childNodes() : + null; + }; + + $scope.accept = function (sourceNode, destIndex) { + return $scope.$childNodesScope && + $scope.$childNodesScope.$modelValue && + $scope.$childNodesScope.accept(sourceNode, destIndex); + }; + + $scope.remove = function () { + return $scope.$parentNodesScope.removeNode($scope); + }; + + $scope.toggle = function () { + $scope.collapsed = !$scope.collapsed; + $scope.$treeScope.$callbacks.toggle($scope.collapsed, $scope); + }; + + $scope.collapse = function () { + $scope.collapsed = true; + }; + + $scope.expand = function () { + $scope.collapsed = false; + }; + + $scope.depth = function () { + var parentNode = $scope.$parentNodeScope; + if (parentNode) { + return parentNode.depth() + 1; + } + return 1; + }; + + /** + * Returns the depth of the deepest subtree under this node + * @param scope a TreeNodesController scope object + * @returns Depth of all nodes *beneath* this node. If scope belongs to a leaf node, the + * result is 0 (it has no subtree). + */ + function countSubTreeDepth(scope) { + var thisLevelDepth = 0, + childNodes = scope.childNodes(), + childNode, + childDepth, + i; + if (!childNodes || childNodes.length === 0) { + return 0; + } + for (i = childNodes.length - 1; i >= 0 ; i--) { + childNode = childNodes[i], + childDepth = 1 + countSubTreeDepth(childNode); + thisLevelDepth = Math.max(thisLevelDepth, childDepth); + } + return thisLevelDepth; + } + + $scope.maxSubDepth = function () { + return $scope.$childNodesScope ? countSubTreeDepth($scope.$childNodesScope) : 0; + }; + } + ]); +})(); + +(function () { + 'use strict'; + + angular.module('ui.tree') + + .controller('TreeNodesController', ['$scope', '$element', + function ($scope, $element) { + this.scope = $scope; + + $scope.$element = $element; + $scope.$modelValue = null; + $scope.$nodeScope = null; // the scope of node which the nodes belongs to + $scope.$treeScope = null; + $scope.$type = 'uiTreeNodes'; + $scope.$nodesMap = {}; + + $scope.nodropEnabled = false; + $scope.maxDepth = 0; + $scope.cloneEnabled = false; + + $scope.initSubNode = function (subNode) { + if (!subNode.$modelValue) { + return null; + } + $scope.$nodesMap[subNode.$modelValue.$$hashKey] = subNode; + }; + + $scope.destroySubNode = function (subNode) { + if (!subNode.$modelValue) { + return null; + } + $scope.$nodesMap[subNode.$modelValue.$$hashKey] = null; + }; + + $scope.accept = function (sourceNode, destIndex) { + return $scope.$treeScope.$callbacks.accept(sourceNode, $scope, destIndex); + }; + + $scope.beforeDrag = function (sourceNode) { + return $scope.$treeScope.$callbacks.beforeDrag(sourceNode); + }; + + $scope.isParent = function (node) { + return node.$parentNodesScope == $scope; + }; + + $scope.hasChild = function () { + return $scope.$modelValue.length > 0; + }; + + $scope.safeApply = function (fn) { + var phase = this.$root.$$phase; + if (phase == '$apply' || phase == '$digest') { + if (fn && (typeof (fn) === 'function')) { + fn(); + } + } else { + this.$apply(fn); + } + }; + + $scope.removeNode = function (node) { + var index = $scope.$modelValue.indexOf(node.$modelValue); + if (index > -1) { + $scope.safeApply(function () { + $scope.$modelValue.splice(index, 1)[0]; + }); + return $scope.$treeScope.$callbacks.removed(node); + } + return null; + }; + + $scope.insertNode = function (index, nodeData) { + $scope.safeApply(function () { + $scope.$modelValue.splice(index, 0, nodeData); + }); + }; + + $scope.childNodes = function () { + var i, nodes = []; + if ($scope.$modelValue) { + for (i = 0; i < $scope.$modelValue.length; i++) { + nodes.push($scope.$nodesMap[$scope.$modelValue[i].$$hashKey]); + } + } + return nodes; + }; + + $scope.depth = function () { + if ($scope.$nodeScope) { + return $scope.$nodeScope.depth(); + } + return 0; // if it has no $nodeScope, it's root + }; + + // check if depth limit has reached + $scope.outOfDepth = function (sourceNode) { + var maxDepth = $scope.maxDepth || $scope.$treeScope.maxDepth; + if (maxDepth > 0) { + return $scope.depth() + sourceNode.maxSubDepth() + 1 > maxDepth; + } + return false; + }; + + } + ]); +})(); + +(function () { + 'use strict'; + + angular.module('ui.tree') + + .controller('TreeController', ['$scope', '$element', + function ($scope, $element) { + this.scope = $scope; + + $scope.$element = $element; + $scope.$nodesScope = null; // root nodes + $scope.$type = 'uiTree'; + $scope.$emptyElm = null; + $scope.$callbacks = null; + + $scope.dragEnabled = true; + $scope.emptyPlaceholderEnabled = true; + $scope.maxDepth = 0; + $scope.dragDelay = 0; + $scope.cloneEnabled = false; + $scope.nodropEnabled = false; + + // Check if it's a empty tree + $scope.isEmpty = function () { + return ($scope.$nodesScope && $scope.$nodesScope.$modelValue + && $scope.$nodesScope.$modelValue.length === 0); + }; + + // add placeholder to empty tree + $scope.place = function (placeElm) { + $scope.$nodesScope.$element.append(placeElm); + $scope.$emptyElm.remove(); + }; + + this.resetEmptyElement = function () { + if ((!$scope.$nodesScope.$modelValue || $scope.$nodesScope.$modelValue.length === 0) && + $scope.emptyPlaceholderEnabled) { + $element.append($scope.$emptyElm); + } else { + $scope.$emptyElm.remove(); + } + }; + + $scope.resetEmptyElement = this.resetEmptyElement; + } + ]); +})(); + +(function () { + 'use strict'; + + angular.module('ui.tree') + .directive('uiTree', ['treeConfig', '$window', + function (treeConfig, $window) { + return { + restrict: 'A', + scope: true, + controller: 'TreeController', + link: function (scope, element, attrs, ctrl) { + var callbacks = { + accept: null, + beforeDrag: null + }, + config = {}, + tdElm, + $trElm, + emptyElmColspan; + + angular.extend(config, treeConfig); + if (config.treeClass) { + element.addClass(config.treeClass); + } + + if (element.prop('tagName').toLowerCase() === 'table') { + scope.$emptyElm = angular.element($window.document.createElement('tr')); + $trElm = element.find('tr'); + // If we can find a tr, then we can use its td children as the empty element colspan. + if ($trElm.length > 0) { + emptyElmColspan = angular.element($trElm).children().length; + } else { + // If not, by setting a huge colspan we make sure it takes full width. + emptyElmColspan = 1000000; + } + tdElm = angular.element($window.document.createElement('td')) + .attr('colspan', emptyElmColspan); + scope.$emptyElm.append(tdElm); + } else { + scope.$emptyElm = angular.element($window.document.createElement('div')); + } + + if (config.emptyTreeClass) { + scope.$emptyElm.addClass(config.emptyTreeClass); + } + + scope.$watch('$nodesScope.$modelValue.length', function (val) { + if (!angular.isNumber(val)) { + return; + } + + ctrl.resetEmptyElement(); + }, true); + + scope.$watch(attrs.dragEnabled, function (val) { + if ((typeof val) == 'boolean') { + scope.dragEnabled = val; + } + }); + + scope.$watch(attrs.emptyPlaceholderEnabled, function (val) { + if ((typeof val) == 'boolean') { + scope.emptyPlaceholderEnabled = val; + ctrl.resetEmptyElement(); + } + }); + + scope.$watch(attrs.nodropEnabled, function (val) { + if ((typeof val) == 'boolean') { + scope.nodropEnabled = val; + } + }); + + scope.$watch(attrs.cloneEnabled, function (val) { + if ((typeof val) == 'boolean') { + scope.cloneEnabled = val; + } + }); + + scope.$watch(attrs.maxDepth, function (val) { + if ((typeof val) == 'number') { + scope.maxDepth = val; + } + }); + + scope.$watch(attrs.dragDelay, function (val) { + if ((typeof val) == 'number') { + scope.dragDelay = val; + } + }); + + /** + * Callback checks if the destination node can accept the dragged node. + * By default, ui-tree will check that 'data-nodrop-enabled' is not set for the + * destination ui-tree-nodes, and that the 'max-depth' attribute will not be exceeded + * if it is set on the ui-tree or ui-tree-nodes. + * This callback can be overridden, but callers must manually enforce nodrop and max-depth + * themselves if they need those to be enforced. + * @param sourceNodeScope Scope of the ui-tree-node being dragged + * @param destNodesScope Scope of the ui-tree-nodes where the node is hovering + * @param destIndex Index in the destination nodes array where the source node will drop + * @returns {boolean} True if the node is permitted to be dropped here + */ + callbacks.accept = function (sourceNodeScope, destNodesScope, destIndex) { + return !(destNodesScope.nodropEnabled || destNodesScope.$treeScope.nodropEnabled || destNodesScope.outOfDepth(sourceNodeScope)); + }; + + callbacks.beforeDrag = function (sourceNodeScope) { + return true; + }; + + callbacks.expandTimeoutStart = function() + { + + }; + + callbacks.expandTimeoutCancel = function() + { + + }; + + callbacks.expandTimeoutEnd = function() + { + + }; + + callbacks.removed = function (node) { + + }; + + /** + * Callback is fired when a node is successfully dropped in a new location + * @param event + */ + callbacks.dropped = function (event) { + + }; + + /** + * Callback is fired each time the user starts dragging a node + * @param event + */ + callbacks.dragStart = function (event) { + + }; + + /** + * Callback is fired each time a dragged node is moved with the mouse/touch. + * @param event + */ + callbacks.dragMove = function (event) { + + }; + + /** + * Callback is fired when the tree exits drag mode. If the user dropped a node, the drop may have been + * accepted or reverted. + * @param event + */ + callbacks.dragStop = function (event) { + + }; + + /** + * Callback is fired when a user drops a node (but prior to processing the drop action) + * beforeDrop can return a Promise, truthy, or falsy (returning nothing is falsy). + * If it returns falsy, or a resolve Promise, the node move is accepted + * If it returns truthy, or a rejected Promise, the node move is reverted + * @param event + * @returns {Boolean|Promise} Truthy (or rejected Promise) to cancel node move; falsy (or resolved promise) + */ + callbacks.beforeDrop = function (event) { + + }; + + /** + * Callback is fired when a user toggles node (but after processing the toggle action) + * @param sourceNodeScope + * @param collapsed + */ + callbacks.toggle = function (collapsed, sourceNodeScope) { + + }; + + scope.$watch(attrs.uiTree, function (newVal, oldVal) { + angular.forEach(newVal, function (value, key) { + if (callbacks[key]) { + if (typeof value === 'function') { + callbacks[key] = value; + } + } + }); + + scope.$callbacks = callbacks; + }, true); + + + } + }; + } + ]); +})(); + +(function () { + 'use strict'; + + angular.module('ui.tree') + .directive('uiTreeHandle', ['treeConfig', + function (treeConfig) { + return { + require: '^uiTreeNode', + restrict: 'A', + scope: true, + controller: 'TreeHandleController', + link: function (scope, element, attrs, treeNodeCtrl) { + var config = {}; + angular.extend(config, treeConfig); + if (config.handleClass) { + element.addClass(config.handleClass); + } + // connect with the tree node. + if (scope != treeNodeCtrl.scope) { + scope.$nodeScope = treeNodeCtrl.scope; + treeNodeCtrl.scope.$handleScope = scope; + } + } + }; + } + ]); +})(); + +(function () { + 'use strict'; + + angular.module('ui.tree') + + .directive('uiTreeNode', ['treeConfig', 'UiTreeHelper', '$window', '$document', '$timeout', '$q', + function (treeConfig, UiTreeHelper, $window, $document, $timeout, $q) { + return { + require: ['^uiTreeNodes', '^uiTree'], + restrict: 'A', + controller: 'TreeNodeController', + link: function (scope, element, attrs, controllersArr) { + // todo startPos is unused + var config = {}, + hasTouch = 'ontouchstart' in window, + startPos, firstMoving, dragInfo, pos, + placeElm, hiddenPlaceElm, dragElm, + treeScope = null, + elements, // As a parameter for callbacks + dragDelaying = true, + dragStarted = false, + dragTimer = null, + body = document.body, + html = document.documentElement, + document_height, + document_width, + dragStart, + tagName, + dragMove, + dragEnd, + dragStartEvent, + dragMoveEvent, + dragEndEvent, + dragCancelEvent, + dragDelay, + bindDragStartEvents, + bindDragMoveEvents, + unbindDragMoveEvents, + keydownHandler, + outOfBounds, + isHandleChild, + el; + + angular.extend(config, treeConfig); + if (config.nodeClass) { + element.addClass(config.nodeClass); + } + scope.init(controllersArr); + + scope.collapsed = !!UiTreeHelper.getNodeAttribute(scope, 'collapsed') || treeConfig.defaultCollapsed; + scope.expandOnHover = !!UiTreeHelper.getNodeAttribute(scope, 'expandOnHover'); + scope.sourceOnly = scope.nodropEnabled || scope.$treeScope.nodropEnabled; + + scope.$watch(attrs.collapsed, function (val) { + if ((typeof val) == 'boolean') { + scope.collapsed = val; + } + }); + + scope.$watch('collapsed', function (val) { + UiTreeHelper.setNodeAttribute(scope, 'collapsed', val); + attrs.$set('collapsed', val); + }); + + scope.$watch(attrs.expandOnHover, function(val) { + if ((typeof val) == 'boolean') { + scope.expandOnHover = val; + } + }); + + scope.$watch('expandOnHover', function (val) { + UiTreeHelper.setNodeAttribute(scope, 'expandOnHover', val); + attrs.$set('expandOnHover', val); + }); + + scope.$on('angular-ui-tree:collapse-all', function () { + scope.collapsed = true; + }); + + scope.$on('angular-ui-tree:expand-all', function () { + scope.collapsed = false; + }); + + /** + * Called when the user has grabbed a node and started dragging it + * @param e + */ + dragStart = function (e) { + // disable right click + if (!hasTouch && (e.button === 2 || e.which === 3)) { + return; + } + + // event has already fired in other scope + if (e.uiTreeDragging || (e.originalEvent && e.originalEvent.uiTreeDragging)) { + return; + } + + // the node being dragged + var eventElm = angular.element(e.target), + isHandleChild, cloneElm, eventElmTagName, tagName, + eventObj, tdElm, hStyle, + isTreeNode, + isTreeNodeHandle; + + // if the target element is a child element of a ui-tree-handle, + // use the containing handle element as target element + isHandleChild = UiTreeHelper.treeNodeHandlerContainerOfElement(eventElm); + if (isHandleChild) { + eventElm = angular.element(isHandleChild); + } + + cloneElm = element.clone(); + isTreeNode = UiTreeHelper.elementIsTreeNode(eventElm); + isTreeNodeHandle = UiTreeHelper.elementIsTreeNodeHandle(eventElm); + + if (!isTreeNode && !isTreeNodeHandle) { + return; + } + + if (isTreeNode && UiTreeHelper.elementContainsTreeNodeHandler(eventElm)) { + return; + } + + eventElmTagName = eventElm.prop('tagName').toLowerCase(); + if (eventElmTagName == 'input' || + eventElmTagName == 'textarea' || + eventElmTagName == 'button' || + eventElmTagName == 'select') { // if it's a input or button, ignore it + return; + } + + // check if it or it's parents has a 'data-nodrag' attribute + el = angular.element(e.target); + while (el && el[0] && el[0] !== element) { + if (UiTreeHelper.nodrag(el)) { // if the node mark as `nodrag`, DONOT drag it. + return; + } + el = el.parent(); + } + + if (!scope.beforeDrag(scope)) { + return; + } + + e.uiTreeDragging = true; // stop event bubbling + if (e.originalEvent) { + e.originalEvent.uiTreeDragging = true; + } + e.preventDefault(); + eventObj = UiTreeHelper.eventObj(e); + + firstMoving = true; + dragInfo = UiTreeHelper.dragInfo(scope); + + tagName = element.prop('tagName'); + + if (tagName.toLowerCase() === 'tr') { + placeElm = angular.element($window.document.createElement(tagName)); + tdElm = angular.element($window.document.createElement('td')) + .addClass(config.placeholderClass) + .attr('colspan', element[0].children.length); + placeElm.append(tdElm); + } else { + placeElm = angular.element($window.document.createElement(tagName)) + .addClass(config.placeholderClass); + } + hiddenPlaceElm = angular.element($window.document.createElement(tagName)); + if (config.hiddenClass) { + hiddenPlaceElm.addClass(config.hiddenClass); + } + + pos = UiTreeHelper.positionStarted(eventObj, element); + placeElm.css('height', UiTreeHelper.height(element) + 'px'); + + dragElm = angular.element($window.document.createElement(scope.$parentNodesScope.$element.prop('tagName'))) + .addClass(scope.$parentNodesScope.$element.attr('class')).addClass(config.dragClass); + dragElm.css('width', UiTreeHelper.width(element) + 'px'); + dragElm.css('z-index', 9999); + + // Prevents cursor to change rapidly in Opera 12.16 and IE when dragging an element + hStyle = (element[0].querySelector('.angular-ui-tree-handle') || element[0]).currentStyle; + if (hStyle) { + document.body.setAttribute('ui-tree-cursor', $document.find('body').css('cursor') || ''); + $document.find('body').css({'cursor': hStyle.cursor + '!important'}); + } + + if (scope.sourceOnly) { + placeElm.css('display', 'none'); + } + element.after(placeElm); + element.after(hiddenPlaceElm); + if (dragInfo.isClone() && scope.sourceOnly) { + dragElm.append(cloneElm); + } else { + dragElm.append(element); + } + + $document.find('body').append(dragElm); + + dragElm.css({ + 'left': eventObj.pageX - pos.offsetX + 'px', + 'top': eventObj.pageY - pos.offsetY + 'px' + }); + elements = { + placeholder: placeElm, + dragging: dragElm + }; + + bindDragMoveEvents(); + // Fire dragStart callback + scope.$apply(function () { + scope.$treeScope.$callbacks.dragStart(dragInfo.eventArgs(elements, pos)); + }); + + document_height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight); + document_width = Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth); + }; + + dragMove = function (e) { + var eventObj = UiTreeHelper.eventObj(e), + prev, + next, + leftElmPos, + topElmPos, + top_scroll, + bottom_scroll, + target, + decrease, + targetX, + targetY, + displayElm, + targetNode, + targetElm, + isEmpty, + scrollDownBy, + targetOffset, + targetBefore; + + if (dragElm) { + e.preventDefault(); + + if ($window.getSelection) { + $window.getSelection().removeAllRanges(); + } else if ($window.document.selection) { + $window.document.selection.empty(); + } + + leftElmPos = eventObj.pageX - pos.offsetX; + topElmPos = eventObj.pageY - pos.offsetY; + + //dragElm can't leave the screen on the left + if (leftElmPos < 0) { + leftElmPos = 0; + } + + //dragElm can't leave the screen on the top + if (topElmPos < 0) { + topElmPos = 0; + } + + //dragElm can't leave the screen on the bottom + if ((topElmPos + 10) > document_height) { + topElmPos = document_height - 10; + } + + //dragElm can't leave the screen on the right + if ((leftElmPos + 10) > document_width) { + leftElmPos = document_width - 10; + } + + dragElm.css({ + 'left': leftElmPos + 'px', + 'top': topElmPos + 'px' + }); + + top_scroll = window.pageYOffset || $window.document.documentElement.scrollTop; + bottom_scroll = top_scroll + (window.innerHeight || $window.document.clientHeight || $window.document.clientHeight); + + // to scroll down if cursor y-position is greater than the bottom position the vertical scroll + if (bottom_scroll < eventObj.pageY && bottom_scroll < document_height) { + scrollDownBy = Math.min(document_height - bottom_scroll, 10); + window.scrollBy(0, scrollDownBy); + } + + // to scroll top if cursor y-position is less than the top position the vertical scroll + if (top_scroll > eventObj.pageY) { + window.scrollBy(0, -10); + } + + UiTreeHelper.positionMoved(e, pos, firstMoving); + if (firstMoving) { + firstMoving = false; + return; + } + + // check if add it as a child node first + // todo decrease is unused + decrease = (UiTreeHelper.offset(dragElm).left - UiTreeHelper.offset(placeElm).left) >= config.threshold; + + targetX = eventObj.pageX - ($window.pageXOffset || + $window.document.body.scrollLeft || + $window.document.documentElement.scrollLeft) - + ($window.document.documentElement.clientLeft || 0); + + targetY = eventObj.pageY - ($window.pageYOffset || + $window.document.body.scrollTop || + $window.document.documentElement.scrollTop) - + ($window.document.documentElement.clientTop || 0); + + // Select the drag target. Because IE does not support CSS 'pointer-events: none', it will always + // pick the drag element itself as the target. To prevent this, we hide the drag element while + // selecting the target. + if (angular.isFunction(dragElm.hide)) { + dragElm.hide(); + } else { + displayElm = dragElm[0].style.display; + dragElm[0].style.display = 'none'; + } + + // when using elementFromPoint() inside an iframe, you have to call + // elementFromPoint() twice to make sure IE8 returns the correct value + $window.document.elementFromPoint(targetX, targetY); + + targetElm = angular.element($window.document.elementFromPoint(targetX, targetY)); + + // if the target element is a child element of a ui-tree-handle, + // use the containing handle element as target element + isHandleChild = UiTreeHelper.treeNodeHandlerContainerOfElement(targetElm); + if (isHandleChild) { + targetElm = angular.element(isHandleChild); + } + + if (angular.isFunction(dragElm.show)) { + dragElm.show(); + } else { + dragElm[0].style.display = displayElm; + } + + outOfBounds = !UiTreeHelper.elementIsTreeNodeHandle(targetElm) && + !UiTreeHelper.elementIsTreeNode(targetElm) && + !UiTreeHelper.elementIsTreeNodes(targetElm) && + !UiTreeHelper.elementIsTree(targetElm) && + !UiTreeHelper.elementIsPlaceholder(targetElm); + + // Detect out of bounds condition, update drop target display, and prevent drop + if (outOfBounds) { + + // Remove the placeholder + placeElm.remove(); + + // If the target was an empty tree, replace the empty element placeholder + if (treeScope) { + treeScope.resetEmptyElement(); + treeScope = null; + } + } + + // move horizontal + if (pos.dirAx && pos.distAxX >= config.levelThreshold) { + pos.distAxX = 0; + + // increase horizontal level if previous sibling exists and is not collapsed + if (pos.distX > 0) { + prev = dragInfo.prev(); + if (prev && !prev.collapsed + && prev.accept(scope, prev.childNodesCount())) { + prev.$childNodesScope.$element.append(placeElm); + dragInfo.moveTo(prev.$childNodesScope, prev.childNodes(), prev.childNodesCount()); + } + } + + // decrease horizontal level + if (pos.distX < 0) { + // we can't decrease a level if an item preceeds the current one + next = dragInfo.next(); + if (!next) { + target = dragInfo.parentNode(); // As a sibling of it's parent node + if (target + && target.$parentNodesScope.accept(scope, target.index() + 1)) { + target.$element.after(placeElm); + dragInfo.moveTo(target.$parentNodesScope, target.siblings(), target.index() + 1); + } + } + } + } + + // move vertical + if (!pos.dirAx) { + if (UiTreeHelper.elementIsTree(targetElm)) { + targetNode = targetElm.controller('uiTree').scope; + } else if (UiTreeHelper.elementIsTreeNodeHandle(targetElm)) { + targetNode = targetElm.controller('uiTreeHandle').scope; + } else if (UiTreeHelper.elementIsTreeNode(targetElm)) { + targetNode = targetElm.controller('uiTreeNode').scope; + } else if (UiTreeHelper.elementIsTreeNodes(targetElm)) { + targetNode = targetElm.controller('uiTreeNodes').scope; + } else if (UiTreeHelper.elementIsPlaceholder(targetElm)) { + targetNode = targetElm.controller('uiTreeNodes').scope; + } else if (targetElm.controller('uiTreeNode')) { + // is a child element of a node + targetNode = targetElm.controller('uiTreeNode').scope; + } + + // check it's new position + isEmpty = false; + if (!targetNode) { + return; + } + + // Show the placeholder if it was hidden for nodrop-enabled and this is a new tree + if (targetNode.$treeScope && !targetNode.$parent.nodropEnabled && !targetNode.$treeScope.nodropEnabled) { + placeElm.css('display', ''); + } + + if (targetNode.$type == 'uiTree' && targetNode.dragEnabled) { + isEmpty = targetNode.isEmpty(); // Check if it's empty tree + } + + if (targetNode.$type == 'uiTreeHandle') { + targetNode = targetNode.$nodeScope; + } + + if (targetNode.$type != 'uiTreeNode' + && !isEmpty) { // Check if it is a uiTreeNode or it's an empty tree + return; + } + + // if placeholder move from empty tree, reset it. + if (treeScope && placeElm.parent()[0] != treeScope.$element[0]) { + treeScope.resetEmptyElement(); + treeScope = null; + } + + if (isEmpty) { // it's an empty tree + treeScope = targetNode; + if (targetNode.$nodesScope.accept(scope, 0)) { + targetNode.place(placeElm); + dragInfo.moveTo(targetNode.$nodesScope, targetNode.$nodesScope.childNodes(), 0); + } + } else if (targetNode.dragEnabled()) { // drag enabled + if (angular.isDefined(scope.expandTimeoutOn) && scope.expandTimeoutOn !== targetNode.id) { + $timeout.cancel(scope.expandTimeout); + delete scope.expandTimeout; + delete scope.expandTimeoutOn; + + scope.$callbacks.expandTimeoutCancel(); + } + + if (targetNode.collapsed) { + if (scope.expandOnHover === true || (angular.isNumber(scope.expandOnHover) && scope.expandOnHover === 0)) { + targetNode.collapsed = false; + } else if (scope.expandOnHover !== false && angular.isNumber(scope.expandOnHover) && scope.expandOnHover > 0) { + if (angular.isUndefined(scope.expandTimeoutOn)) { + scope.expandTimeoutOn = targetNode.$id; + + scope.$callbacks.expandTimeoutStart(); + scope.expandTimeout = $timeout(function() + { + scope.$callbacks.expandTimeoutEnd(); + targetNode.collapsed = false; + }, scope.expandOnHover); + } + } + } + + targetElm = targetNode.$element; // Get the element of ui-tree-node + targetOffset = UiTreeHelper.offset(targetElm); + targetBefore = targetNode.horizontal ? eventObj.pageX < (targetOffset.left + UiTreeHelper.width(targetElm) / 2) + : eventObj.pageY < (targetOffset.top + UiTreeHelper.height(targetElm) / 2); + + if (targetNode.$parentNodesScope.accept(scope, targetNode.index())) { + if (targetBefore) { + targetElm[0].parentNode.insertBefore(placeElm[0], targetElm[0]); + dragInfo.moveTo(targetNode.$parentNodesScope, targetNode.siblings(), targetNode.index()); + } else { + targetElm.after(placeElm); + dragInfo.moveTo(targetNode.$parentNodesScope, targetNode.siblings(), targetNode.index() + 1); + } + } else if (!targetBefore && targetNode.accept(scope, targetNode.childNodesCount())) { // we have to check if it can add the dragging node as a child + targetNode.$childNodesScope.$element.append(placeElm); + dragInfo.moveTo(targetNode.$childNodesScope, targetNode.childNodes(), targetNode.childNodesCount()); + } else { + outOfBounds = true; + } + } + } + + scope.$apply(function () { + scope.$treeScope.$callbacks.dragMove(dragInfo.eventArgs(elements, pos)); + }); + } + }; + + dragEnd = function (e) { + var dragEventArgs = dragInfo.eventArgs(elements, pos); + e.preventDefault(); + unbindDragMoveEvents(); + + $timeout.cancel(scope.expandTimeout); + + scope.$treeScope.$apply(function () { + $q.when(scope.$treeScope.$callbacks.beforeDrop(dragEventArgs)) + // promise resolved (or callback didn't return false) + .then(function (allowDrop) { + if (allowDrop !== false && scope.$$allowNodeDrop && !outOfBounds) { // node drop accepted) + dragInfo.apply(); + // fire the dropped callback only if the move was successful + scope.$treeScope.$callbacks.dropped(dragEventArgs); + } else { // drop canceled - revert the node to its original position + bindDragStartEvents(); + } + }) + // promise rejected - revert the node to its original position + .catch(function () { + bindDragStartEvents(); + }) + .finally(function () { + hiddenPlaceElm.replaceWith(scope.$element); + placeElm.remove(); + + if (dragElm) { // drag element is attached to the mouse pointer + dragElm.remove(); + dragElm = null; + } + scope.$treeScope.$callbacks.dragStop(dragEventArgs); + scope.$$allowNodeDrop = false; + dragInfo = null; + + // Restore cursor in Opera 12.16 and IE + var oldCur = document.body.getAttribute('ui-tree-cursor'); + if (oldCur !== null) { + $document.find('body').css({'cursor': oldCur}); + document.body.removeAttribute('ui-tree-cursor'); + } + }); + }); + }; + + dragStartEvent = function (e) { + if (scope.dragEnabled()) { + dragStart(e); + } + }; + + dragMoveEvent = function (e) { + dragMove(e); + }; + + dragEndEvent = function (e) { + scope.$$allowNodeDrop = true; + dragEnd(e); + }; + + dragCancelEvent = function (e) { + dragEnd(e); + }; + + dragDelay = (function () { + var to; + + return { + exec: function (fn, ms) { + if (!ms) { + ms = 0; + } + this.cancel(); + to = $timeout(fn, ms); + }, + cancel: function () { + $timeout.cancel(to); + } + }; + })(); + + /** + * Binds the mouse/touch events to enable drag start for this node + */ + bindDragStartEvents = function () { + element.bind('touchstart mousedown', function (e) { + dragDelay.exec(function () { + dragStartEvent(e); + }, scope.dragDelay || 0); + }); + element.bind('touchend touchcancel mouseup', function () { + dragDelay.cancel(); + }); + }; + bindDragStartEvents(); + + /** + * Binds mouse/touch events that handle moving/dropping this dragged node + */ + bindDragMoveEvents = function () { + angular.element($document).bind('touchend', dragEndEvent); + angular.element($document).bind('touchcancel', dragEndEvent); + angular.element($document).bind('touchmove', dragMoveEvent); + angular.element($document).bind('mouseup', dragEndEvent); + angular.element($document).bind('mousemove', dragMoveEvent); + angular.element($document).bind('mouseleave', dragCancelEvent); + }; + + /** + * Unbinds mouse/touch events that handle moving/dropping this dragged node + */ + unbindDragMoveEvents = function () { + angular.element($document).unbind('touchend', dragEndEvent); + angular.element($document).unbind('touchcancel', dragEndEvent); + angular.element($document).unbind('touchmove', dragMoveEvent); + angular.element($document).unbind('mouseup', dragEndEvent); + angular.element($document).unbind('mousemove', dragMoveEvent); + angular.element($document).unbind('mouseleave', dragCancelEvent); + }; + + keydownHandler = function (e) { + if (e.keyCode == 27) { + scope.$$allowNodeDrop = false; + dragEnd(e); + } + }; + + angular.element($window.document).bind('keydown', keydownHandler); + + //unbind handler that retains scope + scope.$on('$destroy', function () { + angular.element($window.document).unbind('keydown', keydownHandler); + }); + } + }; + } + ]); + +})(); + +(function () { + 'use strict'; + + angular.module('ui.tree') + .directive('uiTreeNodes', ['treeConfig', '$window', + function (treeConfig) { + return { + require: ['ngModel', '?^uiTreeNode', '^uiTree'], + restrict: 'A', + scope: true, + controller: 'TreeNodesController', + link: function (scope, element, attrs, controllersArr) { + + var config = {}, + ngModel = controllersArr[0], + treeNodeCtrl = controllersArr[1], + treeCtrl = controllersArr[2]; + + angular.extend(config, treeConfig); + if (config.nodesClass) { + element.addClass(config.nodesClass); + } + + if (treeNodeCtrl) { + treeNodeCtrl.scope.$childNodesScope = scope; + scope.$nodeScope = treeNodeCtrl.scope; + } else { + // find the root nodes if there is no parent node and have a parent ui-tree + treeCtrl.scope.$nodesScope = scope; + } + scope.$treeScope = treeCtrl.scope; + + if (ngModel) { + ngModel.$render = function () { + scope.$modelValue = ngModel.$modelValue; + }; + } + + scope.$watch(function () { + return attrs.maxDepth; + }, function (val) { + if ((typeof val) == 'number') { + scope.maxDepth = val; + } + }); + + scope.$watch(function () { + return attrs.nodropEnabled; + }, function (newVal) { + if ((typeof newVal) != 'undefined') { + scope.nodropEnabled = true; + } + }, true); + + attrs.$observe('horizontal', function (val) { + scope.horizontal = ((typeof val) != 'undefined'); + }); + + } + }; + } + ]); +})(); + +(function () { + 'use strict'; + + angular.module('ui.tree') + + /** + * @ngdoc service + * @name ui.tree.service:UiTreeHelper + * @requires ng.$document + * @requires ng.$window + * + * @description + * angular-ui-tree. + */ + .factory('UiTreeHelper', ['$document', '$window', 'treeConfig', + function ($document, $window, treeConfig) { + return { + + /** + * A hashtable used to storage data of nodes + * @type {Object} + */ + nodesData: {}, + + setNodeAttribute: function (scope, attrName, val) { + if (!scope.$modelValue) { + return null; + } + var data = this.nodesData[scope.$modelValue.$$hashKey]; + if (!data) { + data = {}; + this.nodesData[scope.$modelValue.$$hashKey] = data; + } + data[attrName] = val; + }, + + getNodeAttribute: function (scope, attrName) { + if (!scope.$modelValue) { + return null; + } + var data = this.nodesData[scope.$modelValue.$$hashKey]; + if (data) { + return data[attrName]; + } + return null; + }, + + /** + * @ngdoc method + * @methodOf ui.tree.service:$nodrag + * @param {Object} targetElm angular element + * @return {Bool} check if the node can be dragged. + */ + nodrag: function (targetElm) { + if (typeof targetElm.attr('data-nodrag') != 'undefined') { + return targetElm.attr('data-nodrag') !== 'false'; + } + return false; + }, + + /** + * get the event object for touches + * @param {[type]} e [description] + * @return {[type]} [description] + */ + eventObj: function (e) { + var obj = e; + if (e.targetTouches !== undefined) { + obj = e.targetTouches.item(0); + } else if (e.originalEvent !== undefined && e.originalEvent.targetTouches !== undefined) { + obj = e.originalEvent.targetTouches.item(0); + } + return obj; + }, + + dragInfo: function (node) { + return { + source: node, + sourceInfo: { + cloneModel: node.$treeScope.cloneEnabled === true ? angular.copy(node.$modelValue) : undefined, + nodeScope: node, + index: node.index(), + nodesScope: node.$parentNodesScope + }, + index: node.index(), + siblings: node.siblings().slice(0), + parent: node.$parentNodesScope, + + // Move the node to a new position + moveTo: function (parent, siblings, index) { + this.parent = parent; + this.siblings = siblings.slice(0); + + // If source node is in the target nodes + var i = this.siblings.indexOf(this.source); + if (i > -1) { + this.siblings.splice(i, 1); + if (this.source.index() < index) { + index--; + } + } + + this.siblings.splice(index, 0, this.source); + this.index = index; + }, + + parentNode: function () { + return this.parent.$nodeScope; + }, + + prev: function () { + if (this.index > 0) { + return this.siblings[this.index - 1]; + } + + return null; + }, + + next: function () { + if (this.index < this.siblings.length - 1) { + return this.siblings[this.index + 1]; + } + + return null; + }, + + isClone: function () { + return this.source.$treeScope.cloneEnabled === true; + }, + + clonedNode: function (node) { + return angular.copy(node); + }, + + isDirty: function () { + return this.source.$parentNodesScope != this.parent || + this.source.index() != this.index; + }, + + isForeign: function () { + return this.source.$treeScope !== this.parent.$treeScope; + }, + + eventArgs: function (elements, pos) { + return { + source: this.sourceInfo, + dest: { + index: this.index, + nodesScope: this.parent + }, + elements: elements, + pos: pos + }; + }, + + apply: function () { + + var nodeData = this.source.$modelValue; + + // nodrop enabled on tree or parent + if (this.parent.nodropEnabled || this.parent.$treeScope.nodropEnabled) { + return; + } + + // node was dropped in the same place - do nothing + if (!this.isDirty()) { + return; + } + + // cloneEnabled and cross-tree so copy and do not remove from source + if (this.isClone() && this.isForeign()) { + this.parent.insertNode(this.index, this.sourceInfo.cloneModel); + } else { // Any other case, remove and reinsert + this.source.remove(); + this.parent.insertNode(this.index, nodeData); + } + } + }; + }, + + /** + * @ngdoc method + * @name ui.tree#height + * @methodOf ui.tree.service:UiTreeHelper + * + * @description + * Get the height of an element. + * + * @param {Object} element Angular element. + * @returns {String} Height + */ + height: function (element) { + return element.prop('scrollHeight'); + }, + + /** + * @ngdoc method + * @name ui.tree#width + * @methodOf ui.tree.service:UiTreeHelper + * + * @description + * Get the width of an element. + * + * @param {Object} element Angular element. + * @returns {String} Width + */ + width: function (element) { + return element.prop('scrollWidth'); + }, + + /** + * @ngdoc method + * @name ui.tree#offset + * @methodOf ui.nestedSortable.service:UiTreeHelper + * + * @description + * Get the offset values of an element. + * + * @param {Object} element Angular element. + * @returns {Object} Object with properties width, height, top and left + */ + offset: function (element) { + var boundingClientRect = element[0].getBoundingClientRect(); + + return { + width: element.prop('offsetWidth'), + height: element.prop('offsetHeight'), + top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft) + }; + }, + + /** + * @ngdoc method + * @name ui.tree#positionStarted + * @methodOf ui.tree.service:UiTreeHelper + * + * @description + * Get the start position of the target element according to the provided event properties. + * + * @param {Object} e Event + * @param {Object} target Target element + * @returns {Object} Object with properties offsetX, offsetY, startX, startY, nowX and dirX. + */ + positionStarted: function (e, target) { + var pos = {}, + pageX = e.pageX, + pageY = e.pageY; + + if (e.originalEvent && e.originalEvent.touches && (e.originalEvent.touches.length > 0)) { + pageX = e.originalEvent.touches[0].pageX; + pageY = e.originalEvent.touches[0].pageY; + } + pos.offsetX = pageX - this.offset(target).left; + pos.offsetY = pageY - this.offset(target).top; + pos.startX = pos.lastX = pageX; + pos.startY = pos.lastY = pageY; + pos.nowX = pos.nowY = pos.distX = pos.distY = pos.dirAx = 0; + pos.dirX = pos.dirY = pos.lastDirX = pos.lastDirY = pos.distAxX = pos.distAxY = 0; + return pos; + }, + + positionMoved: function (e, pos, firstMoving) { + var pageX = e.pageX, + pageY = e.pageY, + newAx; + if (e.originalEvent && e.originalEvent.touches && (e.originalEvent.touches.length > 0)) { + pageX = e.originalEvent.touches[0].pageX; + pageY = e.originalEvent.touches[0].pageY; + } + // mouse position last events + pos.lastX = pos.nowX; + pos.lastY = pos.nowY; + + // mouse position this events + pos.nowX = pageX; + pos.nowY = pageY; + + // distance mouse moved between events + pos.distX = pos.nowX - pos.lastX; + pos.distY = pos.nowY - pos.lastY; + + // direction mouse was moving + pos.lastDirX = pos.dirX; + pos.lastDirY = pos.dirY; + + // direction mouse is now moving (on both axis) + pos.dirX = pos.distX === 0 ? 0 : pos.distX > 0 ? 1 : -1; + pos.dirY = pos.distY === 0 ? 0 : pos.distY > 0 ? 1 : -1; + + // axis mouse is now moving on + newAx = Math.abs(pos.distX) > Math.abs(pos.distY) ? 1 : 0; + + // do nothing on first move + if (firstMoving) { + pos.dirAx = newAx; + pos.moving = true; + return; + } + + // calc distance moved on this axis (and direction) + if (pos.dirAx !== newAx) { + pos.distAxX = 0; + pos.distAxY = 0; + } else { + pos.distAxX += Math.abs(pos.distX); + if (pos.dirX !== 0 && pos.dirX !== pos.lastDirX) { + pos.distAxX = 0; + } + + pos.distAxY += Math.abs(pos.distY); + if (pos.dirY !== 0 && pos.dirY !== pos.lastDirY) { + pos.distAxY = 0; + } + } + + pos.dirAx = newAx; + }, + + elementIsTreeNode: function (element) { + return typeof element.attr('ui-tree-node') !== 'undefined'; + }, + + elementIsTreeNodeHandle: function (element) { + return typeof element.attr('ui-tree-handle') !== 'undefined'; + }, + elementIsTree: function (element) { + return typeof element.attr('ui-tree') !== 'undefined'; + }, + elementIsTreeNodes: function (element) { + return typeof element.attr('ui-tree-nodes') !== 'undefined'; + }, + elementIsPlaceholder: function (element) { + return element.hasClass(treeConfig.placeholderClass); + }, + elementContainsTreeNodeHandler: function (element) { + return element[0].querySelectorAll('[ui-tree-handle]').length >= 1; + }, + treeNodeHandlerContainerOfElement: function (element) { + return findFirstParentElementWithAttribute('ui-tree-handle', element[0]); + } + }; + } + ]); + + // TODO: optimize this loop + function findFirstParentElementWithAttribute(attributeName, childObj) { + // undefined if the mouse leaves the browser window + if (childObj === undefined) { + return null; + } + var testObj = childObj.parentNode, + count = 1, + // check for setAttribute due to exception thrown by Firefox when a node is dragged outside the browser window + res = (typeof testObj.setAttribute === 'function' && testObj.hasAttribute(attributeName)) ? testObj : null; + while (testObj && typeof testObj.setAttribute === 'function' && !testObj.hasAttribute(attributeName)) { + testObj = testObj.parentNode; + res = testObj; + if (testObj === document.documentElement) { + res = null; + break; + } + count++; + } + + return res; + } + +})(); diff --git a/vid/src/main/webapp/app/vid/scripts/constants/componentConstants.js b/vid/src/main/webapp/app/vid/scripts/constants/componentConstants.js new file mode 100644 index 000000000..b2a9f0a53 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/constants/componentConstants.js @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +app.constant("COMPONENT", (function() { + return { + NETWORK : "network", + SERVICE : "service", + VF_MODULE : "vfModule", + VNF : "vnf", + VOLUME_GROUP : "volumeGroup", + FULL_NAME_MAP : { + "persona-model-id" : "Model ID", + "persona-model-version" : "Model Version" + }, + PARTIAL_NAME_MAP : { + "id" : "ID", + "uuid" : "UUID", + "vfmodule" : "VF Module", + "vnf" : "VNF", + "volumegroup" : "Volume Group" + } + }; +})()) diff --git a/vid/src/main/webapp/app/vid/scripts/constants/fieldConstants.js b/vid/src/main/webapp/app/vid/scripts/constants/fieldConstants.js new file mode 100644 index 000000000..4663ee821 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/constants/fieldConstants.js @@ -0,0 +1,182 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +app.factory("FIELD", [ "PARAMETER", function(PARAMETER) { + + /* + * ID values are typically used internally. + */ + var ID = { + AVAILABLE_VOLUME_GROUP : "availableVolumeGroup", + INSTANCE_NAME : "instanceName", + LCP_REGION : "lcpRegion", + LCP_REGION_TEXT : "lcpRegionText", + PRODUCT_FAMILY : "productFamily", + SERVICE_TYPE : "serviceType", + SUBSCRIBER_NAME : "subscriberName", + SUPPRESS_ROLLBACK : "suppressRollback", + TENANT : "tenant" + }; + + var KEY = { + LCP_REGION_TEXT : "DEFAULTREGION" + }; + + /* + * NAME values are displayed on GUI pages. + */ + var NAME = { + AVAILABLE_VOLUME_GROUP : "Available Volume Group", + INSTANCE_NAME : "Instance Name", + CUSTOMER_ID : "Customer ID", + LCP_REGION : "LCP Region", + LCP_REGION_TEXT : "AIC 2.5 Region", + MODEL_INVARIANT_UUID: "Model Invariant UUID", + MODEL_NAME: "Model Name", + MODEL_VERSION: "Model Version", + MODEL_UUID: "Model UUID", + PRODUCT_FAMILY : "Product Family", + RESOURCE_DESCRIPTION : "Resource Description", + RESOURCE_NAME : "Resource Name", + SERVICE_CATEGORY : "Service Category", + SERVICE_DESCRIPTION : "Service Description", + SERVICE_INSTANCE_ID : "Service Instance ID", + SERVICE_INSTANCE_NAME : "Service Instance Name", + SERVICE_INVARIANT_UUID : "Service Invariant UUID", + SERVICE_NAME : "Service Name", + SERVICE_TYPE : "Service Type", + SERVICE_UUID : "Service UUID", + SERVICE_VERSION : "Service Version", + SUBSCRIBER_NAME : "Subscriber Name", + SUPPRESS_ROLLBACK : "Suppress Rollback on Failure", + TENANT : "Tenant", + USER_SERVICE_INSTANCE_NAME : "User Service Instance Name", + VF_MODULE_DESCRIPTION : "VF Module Description", + VF_MODULE_LABEL : "VF Module Label", + VF_MODULE_TYPE : "VF Module Type" + }; + + /* + * PROMPT values are initial values displayed in select lists. + */ + var PROMPT = { + AVAILABLE_VOLUME_GROUP : "Select Volume Group", + LCP_REGION : "Select LCP Region", + PRODUCT_FAMILY : "Select Product Family", + SERVICE_TYPE : "Select Service Type", + SUBSCRIBER_NAME : "Select Subscriber Name", + TENANT : "Select Tenant Name" + }; + + /* + * PARAMETER values indicate field configurations that are provided to + * parameter block directives. + */ + + var PARAMETER = { + AVAILABLE_VOLUME_GROUP : { + name : NAME.AVAILABLE_VOLUME_GROUP, + id : ID.AVAILABLE_VOLUME_GROUP, + type : PARAMETER.SELECT, + prompt : PROMPT.AVAILABLE_VOLUME_GROUP, + isRequired : true + }, + INSTANCE_NAME : { + name : NAME.INSTANCE_NAME, + id : ID.INSTANCE_NAME, + isRequired : true + }, + LCP_REGION : { + name : NAME.LCP_REGION, + id : ID.LCP_REGION, + type : PARAMETER.SELECT, + prompt : PROMPT.LCP_REGION, + isRequired : true + }, + LCP_REGION_TEXT_HIDDEN : { + id : ID.LCP_REGION_TEXT, + isVisible : false + }, + LCP_REGION_TEXT_VISIBLE : { + name : NAME.LCP_REGION_TEXT, + id : ID.LCP_REGION_TEXT, + isRequired : true, + isVisible : true + }, + PRODUCT_FAMILY : { + name : NAME.PRODUCT_FAMILY, + id : ID.PRODUCT_FAMILY, + type : PARAMETER.SELECT, + prompt : PROMPT.PRODUCT_FAMILY, + isRequired : true + }, + SERVICE_TYPE : { + name : NAME.SERVICE_TYPE, + id : ID.SERVICE_TYPE, + type : PARAMETER.SELECT, + prompt : PROMPT.SERVICE_TYPE, + isRequired : true + }, + SERVICE_TYPE_DISABLED : { + name : NAME.SERVICE_TYPE, + id : ID.SERVICE_TYPE, + type : PARAMETER.SELECT, + isEnabled : false, + isRequired : true + }, + SUPPRESS_ROLLBACK : { + name : NAME.SUPPRESS_ROLLBACK, + id : ID.SUPPRESS_ROLLBACK, + type : PARAMETER.BOOLEAN, + value : false + }, + SUBSCRIBER_NAME : { + name : NAME.SUBSCRIBER_NAME, + id : ID.SUBSCRIBER_NAME, + type : PARAMETER.SELECT, + prompt : PROMPT.SUBSCRIBER_NAME, + isRequired : true + }, + TENANT_DISABLED : { + name : NAME.TENANT, + id : ID.TENANT, + type : PARAMETER.SELECT, + isEnabled : false, + isRequired : true + }, + TENANT_ENABLED : { + name : NAME.TENANT, + id : ID.TENANT, + type : PARAMETER.SELECT, + isEnabled : true, + prompt : PROMPT.TENANT, + isRequired : true + } + }; + + return { + ID : ID, + KEY : KEY, + NAME : NAME, + PARAMETER : PARAMETER + } +} ]); diff --git a/vid/src/main/webapp/app/vid/scripts/constants/parameterConstants.js b/vid/src/main/webapp/app/vid/scripts/constants/parameterConstants.js new file mode 100644 index 000000000..466d188dc --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/constants/parameterConstants.js @@ -0,0 +1,29 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +app.constant("PARAMETER", (function() { + return { + BOOLEAN : "boolean", + SELECT : "select", + STRING : "string" + }; +})()) diff --git a/vid/src/main/webapp/app/vid/scripts/controller/InstantiationController.js b/vid/src/main/webapp/app/vid/scripts/controller/InstantiationController.js new file mode 100644 index 000000000..fb9baa4b8 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/InstantiationController.js @@ -0,0 +1,1028 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +/** + * The Instantiation (or View/Edit) Controller controls the instantiation/removal of + * deployable objects (Services, VNFs, VF-Modules, Networks, and Volume-Groups) + */ +(function () { + "use strict"; + + app.requires.push('ui.tree'); + + app.controller("InstantiationController", function ($scope, $route, $location, $timeout, COMPONENT, DataService, PropertyService, UtilityService, $http, vidService) { + + $scope.popup = new Object(); + $scope.defaultBaseUrl = ""; + $scope.responseTimeoutMsec = 60000; + $scope.properties = UtilityService.getProperties(); + $scope.init = function() { + + /* + * These 2 statements should be included in non-test code. + */ + // takes a default value, retrieves the prop value from the file system and sets it + var msecs = PropertyService.retrieveMsoMaxPollingIntervalMsec(1000); + PropertyService.setMsoMaxPollingIntervalMsec(msecs); + + // takes a default value, retrieves the prop value from the file system and sets it + var polls = PropertyService.retrieveMsoMaxPolls(7); + PropertyService.setMsoMaxPolls(polls); + + //PropertyService.setMsoBaseUrl("testmso"); + PropertyService.setServerResponseTimeoutMsec(10000); + + /* + * Common parameters that shows an example of how the view edit screen + * is expected to pass some common service instance values to the + * popups. + */ + +// DataService.setSubscriberName("Mobility"); +// DataService.setGlobalCustomerId("CUSTID12345") +// DataService.setServiceType("Mobility Type 1"); +// DataService.setServiceInstanceName("Example Service Instance Name"); +// DataService.setServiceName("Mobility Service 1"); +// DataService.setServiceInstanceId("mmsc-test-service-instance"); +// DataService.setServiceUuid("XXXX-YYYY-ZZZZ"); +// DataService.setUserServiceInstanceName("USER_SERVICE_INSTANCE_NAME"); + } + + //PropertyService.setMsoBaseUrl("testmso"); + + $scope.convertModel = function(asdcModel) { + + if (!asdcModel) return undefined; + + var convertedAsdcModel = { + "service": asdcModel.service, + "networks": {}, + "vnfs": {} + }; + + for (var networkUuid in asdcModel.networks) { + var networkModel = asdcModel.networks[networkUuid]; + convertedAsdcModel.networks[networkModel.invariantUuid] = {}; + convertedAsdcModel.networks[networkModel.invariantUuid][networkModel.version] = networkModel; + } + + for (var vnfUuid in asdcModel.vnfs) { + var vnfModel = asdcModel.vnfs[vnfUuid]; + convertedAsdcModel.vnfs[vnfModel.invariantUuid] = {}; + convertedAsdcModel.vnfs[vnfModel.invariantUuid][vnfModel.version] = { + "uuid": vnfModel.uuid, + "invariantUuid": vnfModel.invariantUuid, + "version": vnfModel.version, + "name": vnfModel.name, + "modelCustomizationName": vnfModel.modelCustomizationName, + "inputs": "", + "description": vnfModel.description, + "vfModules": {}, + "volumeGroups": {} + } + + for (var vfModuleUuid in asdcModel.vnfs[vnfUuid].vfModules) { + var vfModuleModel = asdcModel.vnfs[vnfUuid].vfModules[vfModuleUuid]; + convertedAsdcModel.vnfs[vnfModel.invariantUuid][vnfModel.version].vfModules[vfModuleModel.invariantUuid] = {}; + convertedAsdcModel.vnfs[vnfModel.invariantUuid][vnfModel.version].vfModules[vfModuleModel.invariantUuid][vfModuleModel.version] = vfModuleModel; + } + + for (var volumeGroupUuid in asdcModel.vnfs[vnfUuid].volumeGroups) { + var volumeGroupModel = asdcModel.vnfs[vnfUuid].volumeGroups[volumeGroupUuid]; + convertedAsdcModel.vnfs[vnfModel.invariantUuid][vnfModel.version].volumeGroups[volumeGroupModel.invariantUuid] = {}; + convertedAsdcModel.vnfs[vnfModel.invariantUuid][vnfModel.version].volumeGroups[volumeGroupModel.invariantUuid][volumeGroupModel.version] = volumeGroupModel; + } + } + console.log ("convertedAsdcModel: "); console.log (JSON.stringify ( convertedAsdcModel, null, 4 ) ); + return convertedAsdcModel; + }; + + $scope.service = { + "model": vidService.getModel(), + "modelByInvariantUuid": $scope.convertModel(vidService.getModel()), + "instance": vidService.getInstance() + }; + + $scope.deleteNetwork = function(serviceObject, network) { + + console.log("Removing Network " + network.name); + + //Send delete network request to MSO + + //var networks = this.service.instance.networks; + + //networks.splice(networks.indexOf(network), 1); + + //Retrieve updated data from A&AI + var serviceInstance = serviceObject.object; + + DataService.setInventoryItem(network); + DataService.setModelInfo(COMPONENT.NETWORK, $scope.service.model); + + DataService.setSubscriberName(serviceObject['subscriberName']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceInstance['service-instance-id']); + + DataService.setGlobalCustomerId(serviceObject['globalCustomerId']); + DataService.setServiceInstanceName($scope.service.instance.name); + + //DataService.setServiceName($scope.service.model.name); + + //DataService.setServiceUuid("XXXX-YYYY-ZZZZ"); + //DataService.setUserServiceInstanceName("USER_SERVICE_INSTANCE_NAME"); + + $scope.$broadcast("deleteComponent", { + componentId : COMPONENT.NETWORK, + callbackFunction : deleteCallbackFunction + }); + }; + + $scope.deleteService = function(serviceObject) { + + var serviceInstance = serviceObject.object; + + console.log("Removing Service " + $scope.service.instance.name); + + DataService.setInventoryItem(serviceInstance); + //DataService.setModelInfo(COMPONENT.SERVICE, $scope.service.model); + + DataService.setModelInfo(COMPONENT.SERVICE, { + "modelInvariantId": $scope.service.model.service.invariantUuid, + "modelVersion": $scope.service.model.service.version, + "modelNameVersionId": $scope.service.model.service.uuid, + "modelCustomizationName": "", + "modelName": $scope.service.model.service.name, + "inputs": "" + }); + + DataService.setSubscriberName(serviceObject['subscriberName']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceInstance['service-instance-id']); + + DataService.setGlobalCustomerId(serviceObject['globalCustomerId']); + DataService.setServiceInstanceName($scope.service.instance.name); + + DataService.setServiceName($scope.service.model.service.name); + + DataService.setServiceUuid($scope.service.model.service.uuid); + //DataService.setUserServiceInstanceName("USER_SERVICE_INSTANCE_NAME"); + + $scope.$broadcast("deleteComponent", { + componentId : COMPONENT.SERVICE, + callbackFunction : deleteServiceInstanceCallbackFunction + }); + + }; + + $scope.deleteVfModule = function(serviceObject, vfModule, vnf) { + + console.log("Removing VF-Module " + vfModule.name); + + var serviceInstance = serviceObject.object; + + DataService.setInventoryItem(vfModule.object); + + var svcModel = $scope.service.modelByInvariantUuid; + var vnfModelInvariantUuid = vnf.object["persona-model-id"]; + var vnfModelVersion = vnf.object["persona-model-version"]; + if (svcModel != null && vnfModelInvariantUuid != null && vnfModelVersion != null ) + { + if ( ( UtilityService.hasContents(svcModel.vnfs) && UtilityService.hasContents(svcModel.vnfs[vnfModelInvariantUuid] ) ) && + ( UtilityService.hasContents(svcModel.vnfs[vnfModelInvariantUuid][vnfModelVersion] ) ) ) { + var vnfModel = svcModel.vnfs[vnfModelInvariantUuid][vnfModelVersion]; + + // volume groups don't have persona-model-id/version in a&ai. + // Their persona-model-id/version is the one for the associated vfModule + + var vfModuleInvariantUuid = vfModule.object["persona-model-id"]; + var vfModuleModelVersion = vfModule.object["persona-model-version"]; + + if ( UtilityService.hasContents(vnfModel) && UtilityService.hasContents(vnfModel.vfModules) && UtilityService.hasContents(vfModuleInvariantUuid) && UtilityService.hasContents(vfModuleModelVersion) ) + { + var vfModelGroupModel = vnfModel.vfModules[vfModuleInvariantUuid][vfModuleModelVersion]; + + var vfModeluuid = vfModelGroupModel.uuid; + if (vfModeluuid == null) + vfModeluuid = ""; + + var vnfModelCustomizationName = vnfModel.modelCustomizationName; + if (vnfModelCustomizationName == null) + vnfModelCustomizationName = ""; + + var vfModelName = vfModelGroupModel.name; + if (vfModelName == null) + vfModelName = ""; + + var vfModelVersionID = vfModule.object['vf-module-id']; + if (vfModelVersionID == null) + vfModelVersionID = ""; + + DataService.setModelInfo(COMPONENT.VF_MODULE, { + "modelInvariantId": vfModuleInvariantUuid, + "modelVersion": vfModuleModelVersion, + "modelNameVersionId": vfModeluuid, + "modelCustomizationName": vnfModelCustomizationName, + "modelName": vfModelName, + "inputs": "" + }); + + DataService.setVnfInstanceId(vnf.object['vnf-id']); + DataService.setVfModuleInstanceId(vfModelVersionID); + + DataService.setSubscriberName(serviceObject['subscriberName']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceInstance['service-instance-id']); + + DataService.setGlobalCustomerId(serviceObject['globalCustomerId']); + DataService.setServiceInstanceName($scope.service.instance.name); + + DataService.setServiceName($scope.service.model.service.name); + + DataService.setServiceUuid($scope.service.model.service.uuid); + //DataService.setUserServiceInstanceName("USER_SERVICE_INSTANCE_NAME"); + + $scope.$broadcast("deleteComponent", { + componentId : COMPONENT.VF_MODULE, + callbackFunction : deleteCallbackFunction + }); + + return; + } + + } + } + + console.log("Removing VNF " + vnf.name + " could not proceed due to missing ASDC model information."); + + + //Retrieve updated data from A&AI + }; + + $scope.deleteVnf = function(serviceObject, vnf) { + + console.log("Removing VNF " + vnf.name); + + var serviceInstance = serviceObject.object; + + DataService.setInventoryItem(vnf.object); + + var vnftype = vnf.object['vnf-type']; + if (vnftype == null) + vnftype = ""; + else + { + var n = vnftype.search("/"); + if (n >= 0) + vnftype = vnftype.substring(n+1); + } + + + var svcModel = $scope.service.modelByInvariantUuid; + var vnfModelInvariantUuid = vnf.object["persona-model-id"]; + var vnfModelVersion = vnf.object["persona-model-version"]; + if (svcModel != null && vnfModelInvariantUuid != null && vnfModelVersion != null ) + { + + console.log ( "vnf models: "); console.log ( JSON.stringify ($scope.service.modelByInvariantUuid.vnfs, null, 4) ); + + var vnfModel = $scope.service.modelByInvariantUuid.vnfs[vnfModelInvariantUuid][vnfModelVersion]; + if (vnfModel == null) + { + DataService.setModelInfo(COMPONENT.VNF, { + "modelInvariantId": vnfModelInvariantUuid, + "modelVersion": vnfModelVersion, + "modelNameVersionId": "", + "modelCustomizationName": vnftype, + "modelName": "", + "inputs": "" + }); + } + else + { + DataService.setModelInfo(COMPONENT.VNF, { + "modelInvariantId": vnfModelInvariantUuid, + "modelVersion": vnfModelVersion, + "modelNameVersionId": vnfModel.uuid, + "modelCustomizationName": vnftype, + "modelName": vnfModel.name, + "inputs": "" + }); + } + } + else + { + console.log("Removing VNF name = " + vnf.name + " didn't get the correponding model details so sending empty model values to MSO!"); + DataService.setModelInfo(COMPONENT.VNF, { + "modelInvariantId": "", + "modelVersion": "", + "modelNameVersionId": "", + "modelCustomizationName": vnftype, + "modelName": "", + "inputs": "" + }); + } + + DataService.setVnfInstanceId(vnf.object['vnf-id']); + + DataService.setSubscriberName(serviceObject['subscriberName']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceInstance['service-instance-id']); + + DataService.setGlobalCustomerId(serviceObject['globalCustomerId']); + DataService.setServiceInstanceName($scope.service.instance.name); + + DataService.setServiceName($scope.service.model.service.name); + + DataService.setServiceUuid($scope.service.model.service.uuid); + //DataService.setUserServiceInstanceName("USER_SERVICE_INSTANCE_NAME"); + + $scope.$broadcast("deleteComponent", { + componentId : COMPONENT.VNF, + callbackFunction : deleteCallbackFunction + }); + + }; + + /* + $scope.deleteVnf = function(serviceObject, vnf) { + + console.log("Removing VNF " + vnf.name); + + //Send delete VF-Module request to MSO + + var svcModel = $scope.service.modelByInvariantUuid; + var vnfModelInvariantUuid = vnf.object["persona-model-id"]; + var vnfModelVersion = vnf.object["persona-model-version"]; + console.log ( "vnf models: "); console.log ( JSON.stringify ($scope.service.modelByInvariantUuid.vnfs, null, 4) ); + + DataService.setInventoryItem(vnf); + + var vnfModel = $scope.service.modelByInvariantUuid.vnfs[vnfModelInvariantUuid][vnfModelVersion]; + + DataService.setModelInfo(COMPONENT.VNF, { + "modelInvariantId": vnfModelInvariantUuid, + "modelVersion": vnfModelVersion, + "modelNameVersionId": vnfModel.uuid, + "modelCustomizationName": vnfModel.modelCustomizationName, + "modelName": vnfModel.name, + "inputs": vnfModel.inputs + }); + + DataService.setSubscriberName(serviceObject['globalCustomerId']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceObject['service-instance-id']); + + DataService.setGlobalCustomerId(serviceObject['globalCustomerId']); + DataService.setServiceInstanceName($scope.service.instance.name); + + DataService.setServiceName(vnf.name); + + DataService.setServiceUuid($scope.service.model.service.uuid); + //DataService.setUserServiceInstanceName("USER_SERVICE_INSTANCE_NAME"); + + $scope.$broadcast("deleteComponent", { + componentId : COMPONENT.VNF, + callbackFunction : deleteCallbackFunction + }); + + //var vnfs = this.service.instance.vnfs; + + //vnfs.splice(vnfs.indexOf(vnf), 1); + + //Retrieve updated data from A&AI + };*/ + + $scope.deleteVolumeGroup = function(serviceObject, vnf, vfModule, volumeGroup) { + + console.log("Removing Volume Group " + volumeGroup.name); + var haveModel = false; + var svcModel = $scope.service.modelByInvariantUuid; + + var vnfModelInvariantUuid = vnf.object["persona-model-id"]; + var vnfModelVersion = vnf.object["persona-model-version"]; + + if ( ( UtilityService.hasContents(vnfModelInvariantUuid) ) && (UtilityService.hasContents(vnfModelVersion) ) ) { + if ( UtilityService.hasContents(svcModel) && UtilityService.hasContents($scope.service.modelByInvariantUuid.vnfs) ) { + //console.log ( "vnf models "); console.log (JSON.stringify ($scope.service.modelByInvariantUuid.vnfs, null, 4) ); + if ( ( UtilityService.hasContents($scope.service.modelByInvariantUuid.vnfs[vnfModelInvariantUuid] ) ) && + ( UtilityService.hasContents($scope.service.modelByInvariantUuid.vnfs[vnfModelInvariantUuid][vnfModelVersion] ) ) ) { + var vnfModel = $scope.service.modelByInvariantUuid.vnfs[vnfModelInvariantUuid][vnfModelVersion]; + + // volume groups don't have persona-model-id/version in a&ai. + // Their persona-model-id/version is the one for the associated vfModule + + var vfModuleInvariantUuid = vfModule.object["persona-model-id"]; + var vfModuleModelVersion = vfModule.object["persona-model-version"]; + + if ( UtilityService.hasContents(vnfModel.volumeGroups) && UtilityService.hasContents(vfModuleInvariantUuid) && UtilityService.hasContents(vfModuleModelVersion) ) { + + if ( ( UtilityService.hasContents (vnfModel.volumeGroups[vfModuleInvariantUuid]) ) && + (UtilityService.hasContents (vnfModel.volumeGroups[vfModuleInvariantUuid][vfModuleModelVersion]) ) ) { + var volGroupModel = vnfModel.volumeGroups[vfModuleInvariantUuid][vfModuleModelVersion]; + + DataService.setModelInfo(COMPONENT.VOLUME_GROUP, { + "modelInvariantId": vfModuleInvariantUuid, + "modelVersion": vfModuleModelVersion, + "modelNameVersionId": volGroupModel.uuid, + "modelCustomizationName": vnfModel.modelCustomizationName, + "modelName": volGroupModel.name, + "inputs": "" + }); + haveModel = true; + + } + } + } + } + } + if ( !haveModel ) { + DataService.setModelInfo(COMPONENT.VOLUME_GROUP, { + "modelInvariantId": "", + "modelVersion": "", + "modelNameVersionId": "", + "modelCustomizationName": "", + "modelName": "", + "inputs": "" + }); + } + + var serviceInstance = serviceObject.object; + + DataService.setInventoryItem(volumeGroup.object); + + DataService.setSubscriberName(serviceObject['subscriberName']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceInstance['service-instance-id']); + + DataService.setGlobalCustomerId(serviceObject['globalCustomerId']); + DataService.setServiceInstanceName($scope.service.instance.name); + + DataService.setServiceName($scope.service.model.service.name); + + DataService.setServiceUuid($scope.service.model.service.uuid); + DataService.setVnfInstanceId(vnf.nodeId); + DataService.setVolumeGroupInstanceId(volumeGroup.nodeId); + + //DataService.setUserServiceInstanceName("USER_SERVICE_INSTANCE_NAME"); + + $scope.$broadcast("deleteComponent", { + componentId : COMPONENT.VOLUME_GROUP, + callbackFunction : deleteCallbackFunction + }); + }; + + $scope.deleteVnfVolumeGroup = function(serviceObject, vnf, volumeGroup) { + + console.log("Removing Volume Group " + volumeGroup.name); + var serviceInstance = serviceObject.object; + + DataService.setInventoryItem(volumeGroup.object); + + var svcModel = $scope.service.modelByInvariantUuid; + var vnfModelInvariantUuid = vnf.object["persona-model-id"]; + var vnfModelVersion = vnf.object["persona-model-version"]; + var vnfModel = null; + + var volGroupModelInvariantUuid = null; + var volGroupModelVersion = null; + + // send an empty model by default since model is not required for deletes + DataService.setModelInfo(COMPONENT.VOLUME_GROUP, {}); + + if ( (volumeGroup.object != null) && ( volumeGroup.object["persona-model-id"] != null ) && + (volumeGroup.object["persona-model-version"] != null) ) { + + volGroupModelInvariantUuid = volumeGroup.object["persona-model-id"]; + volGroupModelVersion = volumeGroup.object["persona-model-version"]; + + if (svcModel != null && vnfModelInvariantUuid != null && vnfModelVersion != null ) { + console.log ( "vnf models: "); console.log ( JSON.stringify ($scope.service.modelByInvariantUuid.vnfs, null, 4) ); + if ( ($scope.service.modelByInvariantUuid.vnfs[vnfModelInvariantUuid] != null) && + ($scope.service.modelByInvariantUuid.vnfs[vnfModelInvariantUuid][vnfModelVersion]) != null ) { + + vnfModel = $scope.service.modelByInvariantUuid.vnfs[vnfModelInvariantUuid][vnfModelVersion]; + if ( (vnfModel.volumeGroups != null) && ( vnfModel.volumeGroups[volGroupModelInvariantUuid] != null ) + && ( vnfModel.volumeGroups[volGroupModelInvariantUuid][volGroupModelVersion] != null ) ) { + + var volumeGroupModel = vnfModel.volumeGroups[volGroupModelInvariantUuid][volGroupModelVersion]; + + DataService.setModelInfo(COMPONENT.VOLUME_GROUP, { + "modelInvariantId": volumeGroupModel.invariantUuid, + "modelVersion": volumeGroupModel.version, + "modelNameVersionId": volumeGroupModel.uuid, + "modelName": volumeGroupModel.name, + "modelCustomizationName": volumeGroupModel.modelCustomizationName, + "inputs": "" + }); + } + } + } + } + + DataService.setVnfInstanceId(vnf.object['vnf-id']); + + DataService.setSubscriberName(serviceObject['subscriberName']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceInstance['service-instance-id']); + + DataService.setGlobalCustomerId(serviceObject['globalCustomerId']); + DataService.setServiceInstanceName($scope.service.instance.name); + + DataService.setServiceName($scope.service.model.service.name); + + DataService.setServiceUuid($scope.service.model.service.uuid); + DataService.setVnfInstanceId(vnf.nodeId); + DataService.setVolumeGroupInstanceId(volumeGroup.nodeId); + + //DataService.setUserServiceInstanceName("USER_SERVICE_INSTANCE_NAME"); + + $scope.$broadcast("deleteComponent", { + componentId : COMPONENT.VOLUME_GROUP, + callbackFunction : deleteCallbackFunction + }); + }; + + $scope.describeNetwork = function(serviceObject, networkObject) { + var serviceInstance = serviceObject.object; + var network = networkObject.object; + + //Display popup with additional network information + DataService.setNetworkInstanceId(network['network-id']); + DataService.setInventoryItem(network); + //DataService.setModelInfo(network['network-id'], network); + + DataService.setSubscriberName(serviceObject['subscriber-name']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceInstance['service-instance-id']); + + //DataService.setVnfInstanceId("Testing"); + $scope.$broadcast("showComponentDetails", { + componentId : COMPONENT.NETWORK + }); + }; + + // for service instance id - no need for this! + $scope.describeService = function(serviceObject) { + var serviceInstance = serviceObject.object; + + DataService.setInventoryItem(serviceInstance); + //DataService.setModelInfo(serviceInstance['service-instance-id'], serviceInstance); + + DataService.setSubscriberName(serviceObject['subscriberName']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceInstance['service-instance-id']); + + //Display popup with additional service information + $scope.$broadcast("showComponentDetails", { + componentId : COMPONENT.SERVICE + }); + + }; + + $scope.describeVfModule = function(serviceObject, vfModuleObject) { + var serviceInstance = serviceObject.object; + var vfModule = vfModuleObject.object; + + //Display popup with additional VF-Module information + DataService.setVfModuleInstanceId(vfModule['vf-module-id']); + DataService.setInventoryItem(vfModule); + //DataService.setModelInfo(vfModule['vf-module-id'], vfModule); + + DataService.setSubscriberName(serviceObject['subscriberName']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceInstance['service-instance-id']); + + $scope.$broadcast("showComponentDetails", { + componentId : COMPONENT.VF_MODULE + }); + }; + + $scope.describeVnf = function(serviceObject, vnfObject) { + var serviceInstance = serviceObject.object; + var vnf = vnfObject.object; + + //Display popup with additional VNF information + DataService.setVnfInstanceId(vnf['vnf-id']); + DataService.setInventoryItem(vnf); + //DataService.setModelInfo(vnf['vnf-id'], vnf); + + DataService.setSubscriberName(serviceObject['subscriberName']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceInstance['service-instance-id']); + + $scope.$broadcast("showComponentDetails", { + componentId : COMPONENT.VNF + }); + }; + + $scope.describeVolumeGroup = function(serviceObject, volumeGroupObject) { + var serviceInstance = serviceObject.object; + var volumeGroup = volumeGroupObject.object; + + DataService.setVolumeGroupInstanceId(volumeGroup['volume-group-id']); + DataService.setInventoryItem(volumeGroup); + DataService.setModelInfo(volumeGroup['volume-group-id'], volumeGroup); + + DataService.setSubscriberName(serviceObject['subscriberName']); + DataService.setServiceType(serviceObject['serviceType']); + DataService.setServiceInstanceId(serviceInstance['service-instance-id']); + + //Display popup with additional Volume Group information + //DataService.setVnfInstanceId("Testing"); + $scope.$broadcast("showComponentDetails", { + componentId : COMPONENT.VOLUME_GROUP + }); + }; + + $scope.addNetworkInstance = function(network) { + console.log("Unsupported in 1610: Adding Network instance of type " + network.name + " to service instance" + this.service.instance.name); + }; + + $scope.addVnfInstance = function(vnf) { + //console.log ("addVnfInstance invoked VNF="); console.log (JSON.stringify (vnf,null,4)); + + DataService.setSubscriberName($scope.service.instance.subscriberName); + DataService.setGlobalCustomerId($scope.service.instance.globalCustomerId); + DataService.setServiceType($scope.service.instance.serviceType); + DataService.setServiceInstanceName($scope.service.instance.name); + DataService.setServiceInstanceId($scope.service.instance.id); + DataService.setServiceName($scope.service.model.service.name); + + DataService.setModelInfo(COMPONENT.VNF, { + "modelType": "vnf", + "modelInvariantId": vnf.invariantUuid, + "modelVersion": vnf.version, + "modelNameVersionId": vnf.uuid, + "modelName": vnf.name, + "modelCustomizationName": vnf.modelCustomizationName, + "inputs": "" + }); + + DataService.setModelInstanceName($scope.service.model.service.name); + + DataService.setModelInfo(COMPONENT.SERVICE, { + "modelInvariantId": $scope.service.model.service.invariantUuid, + "modelVersion": $scope.service.model.service.version, + "modelNameVersionId": $scope.service.model.service.uuid, + "modelName": $scope.service.model.service.name, + "inputs": "" + }); + + $scope.$broadcast("createComponent", { + componentId : COMPONENT.VNF, + callbackFunction : createVnfCallbackFunction + }); + }; + + $scope.addVfModuleInstance = function(vnfInstance, vfModuleModel) { + + DataService.setSubscriberName($scope.service.instance.subscriberName); + DataService.setGlobalCustomerId($scope.service.instance.globalCustomerId); + DataService.setServiceType($scope.service.instance.serviceType); + DataService.setServiceInstanceName($scope.service.instance.name); + DataService.setServiceInstanceId($scope.service.instance.id); + DataService.setServiceName($scope.service.model.service.name); + + var vnfModelInvariantUuid = vnfInstance.object["persona-model-id"]; + var vnfModelVersion = vnfInstance.object["persona-model-version"]; + var vnfModel = $scope.service.modelByInvariantUuid.vnfs[vnfModelInvariantUuid][vnfModelVersion]; + + var availableVolumeGroupList = []; + angular.forEach(vnfInstance["availableVolumeGroups"], function(volumeGroupInstance, key) { + availableVolumeGroupList.push({"instance": volumeGroupInstance}); + }); + + if (vfModuleModel.volumeGroupAllowed) { + DataService.setAvailableVolumeGroupList(availableVolumeGroupList); + } + + DataService.setModelInfo(COMPONENT.SERVICE, { + "modelInvariantId": $scope.service.model.service.invariantUuid, + "modelVersion": $scope.service.model.service.version, + "modelNameVersionId": $scope.service.model.service.uuid, + "modelName": $scope.service.model.service.name, + "inputs": "" + }); + + DataService.setVnfInstanceId(vnfInstance.object["vnf-id"]); + + DataService.setModelInfo(COMPONENT.VNF, { + "modelInvariantId": vnfModel.invariantUuid, + "modelVersion": vnfModel.version, + "modelNameVersionId": vnfModel.uuid, + "modelName": vnfModel.name, + "modelCustomizationName": vnfModel.modelCustomizationName, + "inputs": "" + }); + + DataService.setModelInfo(COMPONENT.VF_MODULE, { + "modelInvariantId": vfModuleModel.invariantUuid, + "modelVersion": vfModuleModel.version, + "modelNameVersionId": vfModuleModel.uuid, + "modelName": vfModuleModel.name, + "inputs": "" + }); + + $scope.$broadcast("createComponent", { + componentId : COMPONENT.VF_MODULE, + callbackFunction : createVfModuleCallbackFunction + }); + + }; + + $scope.addVolumeGroupInstance = function(vnfInstance, volumeGroupModel) { + + DataService.setSubscriberName($scope.service.instance.subscriberName); + DataService.setGlobalCustomerId($scope.service.instance.globalCustomerId); + DataService.setServiceType($scope.service.instance.serviceType); + DataService.setServiceInstanceName($scope.service.instance.name); + DataService.setServiceInstanceId($scope.service.instance.id); + DataService.setServiceName($scope.service.model.service.name); + + DataService.setModelInfo(COMPONENT.SERVICE, { + "modelInvariantId": $scope.service.model.service.invariantUuid, + "modelVersion": $scope.service.model.service.version, + "modelNameVersionId": $scope.service.model.service.uuid, + "modelName": $scope.service.model.service.name, + "inputs": "" + }); + + DataService.setVnfInstanceId(vnfInstance.object["vnf-id"]); + + var vnfModelInvariantUuid = vnfInstance.object["persona-model-id"]; + var vnfModelVersion = vnfInstance.object["persona-model-version"]; + var vnfModel = $scope.service.modelByInvariantUuid.vnfs[vnfModelInvariantUuid][vnfModelVersion]; + + DataService.setModelInfo(COMPONENT.VNF, { + "modelInvariantId": vnfModel.invariantUuid, + "modelVersion": vnfModel.version, + "modelNameVersionId": vnfModel.uuid, + "modelName": vnfModel.name, + "modelCustomizationName": vnfModel.modelCustomizationName, + "inputs": "" + }); + + DataService.setModelInfo(COMPONENT.VOLUME_GROUP, { + "modelInvariantId": volumeGroupModel.invariantUuid, + "modelVersion": volumeGroupModel.version, + "modelNameVersionId": volumeGroupModel.uuid, + "modelName": volumeGroupModel.name, + "inputs": "" + }); + + $scope.$broadcast("createComponent", { + componentId : COMPONENT.VOLUME_GROUP, + callbackFunction : createVolumeGroupCallbackFunction + }); + }; + + $scope.attachVolumeGroupInstance = function(vfModuleInstance, volumeGroupInstance) { + + var vnfInstance = this.vnf; + var vnfModelInvariantUuid = vnfInstance.object["persona-model-id"]; + var vnfModelVersion = vnfInstance.object["persona-model-version"]; + var vnfModel = $scope.service.modelByInvariantUuid.vnfs[vnfModelInvariantUuid][vnfModelVersion]; + + var vfModuleModelInvariantUuid = vfModuleInstance.object["persona-model-id"]; + var vfModuleVersion = vfModuleInstance.object["persona-model-version"]; + var vfModuleModel = vnfModel.vfModules[vfModuleModelInvariantUuid][vfModuleVersion]; + + var volumeGroupModelInvariantUuid = volumeGroupInstance.object["persona-model-id"]; + var volumeGroupModelVersion = volumeGroupInstance.object["persona-model-version"]; + var volumeGroupModel = vnfModel.volumeGroups[volumeGroupModelInvariantUuid][volumeGroupModelVersion]; + + if (vfModuleModel.uuid != volumeGroupModel.uuid) alert("Cannot attach this volume group to this VF module (models do not match)"); + + DataService.setSubscriberName($scope.service.instance.subscriberName); + DataService.setGlobalCustomerId($scope.service.instance.globalCustomerId); + DataService.setServiceName($scope.service.model.name); + DataService.setServiceType($scope.service.instance.serviceType); + DataService.setServiceInstanceName($scope.service.instance.name); + DataService.setServiceInstanceId($scope.service.instance.id); + + DataService.setModelInfo(COMPONENT.SERVICE, { + "modelInvariantId": $scope.service.model.service.invariantUuid, + "modelVersion": $scope.service.model.service.version, + "modelNameVersionId": $scope.service.model.service.uuid, + "modelName": $scope.service.model.service.name, + "inputs": "" + }); + + DataService.setVnfInstanceId(vnfInstance.object["vnf-id"]); + + DataService.setModelInfo(COMPONENT.VNF, { + "modelInvariantId": vnfModel.invariantUuid, + "modelVersion": vnfModel.version, + "modelNameVersionId": vnfModel.uuid, + "modelName": vnfModel.name, + "modelCustomizationName": vnfModel.modelCustomizationName, + "inputs": "" + }); + + DataService.setModelInfo(COMPONENT.VOLUME_GROUP, { + "modelInvariantId": volumeGroupModel.invariantUuid, + "modelVersion": volumeGroupModel.version, + "modelNameVersionId": volumeGroupModel.uuid, + "modelName": volumeGroupModel.name, + "inputs": "" + }); + + $scope.$broadcast("createComponent", { + componentId : COMPONENT.VOLUME_GROUP, + callbackFunction : createVolumeGroupCallbackFunction + }); + /* + * Code to manipulate the angular ui-tree + var volumeGroups = this.vnf.volumeGroups; + volumeGroups.splice(volumeGroups.indexOf(volumeGroup), 1); + vfModule.volumeGroups.push(volumeGroup); + */ + }; + + $scope.resetProgress = function() { + $scope.percentProgress = 0; + $scope.progressClass = "progress-bar progress-bar-info"; + }; + + $scope.setProgress = function(percentProgress) { + percentProgress = parseInt(percentProgress); + if (percentProgress >= 100) { + $scope.progressClass = "progress-bar progress-bar-success"; + } + + if (percentProgress < $scope.percentProgress) { + return; + } + + $scope.percentProgress = percentProgress; + $scope.progressWidth = {width: percentProgress + "%"}; + if (percentProgress >= 5) { + $scope.progressText = percentProgress + " %"; + } else { + // Hidden since color combination is barely visible when progress portion is narrow. + $scope.progressText = ""; + } + }; + + $scope.reloadRoute = function() { + $route.reload(); + } + + var createVnfCallbackFunction = function(response) { + $scope.callbackResults = ""; + var color = "none"; + $scope.callbackStyle = { + "background-color" : color + }; + + /* + * This 1/2 delay was only added to visually highlight the status + * change. Probably not needed in the real application code. + */ + $timeout(function() { + $scope.callbackResults = UtilityService.getCurrentTime() + + " isSuccessful: " + response.isSuccessful; + if (response.isSuccessful) { + color = "#8F8"; + $scope.reloadRoute(); + } else { + color = "#F88"; + } + $scope.callbackStyle = { + "background-color" : color + }; + }, 500); + + + + }; + + var deleteCallbackFunction = function(response) { + $scope.callbackResults = ""; + var color = "none"; + $scope.callbackStyle = { + "background-color" : color + }; + + /* + * This 1/2 delay was only added to visually highlight the status + * change. Probably not needed in the real application code. + */ + $timeout(function() { + $scope.callbackResults = UtilityService.getCurrentTime() + + " isSuccessful: " + response.isSuccessful; + if (response.isSuccessful) { + color = "#8F8"; + $scope.reloadRoute(); + } else { + color = "#F88"; + } + $scope.callbackStyle = { + "background-color" : color + }; + }, 500); + + }; + + var createVfModuleCallbackFunction = function(response) { + $scope.callbackResults = ""; + var color = "none"; + $scope.callbackStyle = { + "background-color" : color + }; + + /* + * This 1/2 delay was only added to visually highlight the status + * change. Probably not needed in the real application code. + */ + $timeout(function() { + $scope.callbackResults = UtilityService.getCurrentTime() + + " isSuccessful: " + response.isSuccessful; + if (response.isSuccessful) { + color = "#8F8"; + $scope.reloadRoute(); + } else { + color = "#F88"; + } + $scope.callbackStyle = { + "background-color" : color + }; + }, 500); + + }; + + var deleteServiceInstanceCallbackFunction = function(response) { + $scope.callbackResults = ""; + var color = "none"; + $scope.callbackStyle = { + "background-color" : color + }; + + /* + * This 1/2 delay was only added to visually highlight the status + * change. Probably not needed in the real application code. + */ + $timeout(function() { + $scope.callbackResults = UtilityService.getCurrentTime() + + " isSuccessful: " + response.isSuccessful; + if (response.isSuccessful) { + color = "#8F8"; + $location.path("/instances/services") + } else { + color = "#F88"; + } + $scope.callbackStyle = { + "background-color" : color + }; + }, 500); + + }; + + var createVolumeGroupCallbackFunction = function(response) { + $scope.callbackResults = ""; + var color = "none"; + $scope.callbackStyle = { + "background-color" : color + }; + + /* + * This 1/2 delay was only added to visually highlight the status + * change. Probably not needed in the real application code. + */ + $timeout(function() { + $scope.callbackResults = UtilityService.getCurrentTime() + + " isSuccessful: " + response.isSuccessful; + if (response.isSuccessful) { + color = "#8F8"; + $scope.reloadRoute(); + } else { + color = "#F88"; + } + $scope.callbackStyle = { + "background-color" : color + }; + }, 500); + + + + }; + + }); +})(); diff --git a/vid/src/main/webapp/app/vid/scripts/controller/ServiceModelController.js b/vid/src/main/webapp/app/vid/scripts/controller/ServiceModelController.js new file mode 100644 index 000000000..855c23dde --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/ServiceModelController.js @@ -0,0 +1,196 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +(function () { + 'use strict'; + + app.controller("ServiceModelController", function ($scope, $http, $location, COMPONENT, DataService, vidService, + PropertyService) { + + $scope.popup = {}; + var re = /.*?:\/\/.*?:.*?\/(.*?)\//g; + var baseEndpoint = re.exec($location.absUrl())[1]; + + $scope.getServiceModels = function() { + $scope.status = "Fetching service catalog from ASDC. Please wait."; + $http.get('/' + baseEndpoint + '/rest/models/services?distributionStatus=DISTRIBUTED') + .then(function(response) { + $scope.services = []; + if (angular.isArray(response.data)) { + $scope.services = response.data; + $scope.viewPerPage=10; + $scope.totalPage=$scope.services.length/$scope.viewPerPage; + $scope.sortBy="name"; + $scope.scrollViewPerPage=2; + $scope.currentPage=1; + $scope.searchCategory; + $scope.searchString=""; + $scope.currentPageNum=1; + $scope.isSpinnerVisible = false; + $scope.isProgressVisible = false; + } else { + $scope.status = "Failed to get service models from ASDC."; + $scope.error = true; + $scope.isSpinnerVisible = false; + } + }, function (response) { + console.log("Error: " + response); + }); + } + $scope.init = function() { + // takes a default value, retrieves the prop value from the file system and sets it + var msecs = PropertyService.retrieveMsoMaxPollingIntervalMsec(1000); + PropertyService.setMsoMaxPollingIntervalMsec(msecs); + + // takes a default value, retrieves the prop value from the file system and sets it + var polls = PropertyService.retrieveMsoMaxPolls(7); + PropertyService.setMsoMaxPolls(polls); + + //PropertyService.setMsoBaseUrl("testmso"); + PropertyService.setServerResponseTimeoutMsec(10000); + } + + $scope.prevPage = function() { + $scope.currentPage--; + } + + $scope.nextPage = function() { + $scope.currentPage++; + } + + $scope.deployService = function(service) { + + console.log("Instantiating ASDC service " + service.uuid); + + $http.get('/' + baseEndpoint + '/rest/models/services/' + service.uuid) + .then(function successCallback(getServiceResponse) { + + var serviceModel = getServiceResponse.data; + DataService.setServiceName(serviceModel.service.name); + + DataService.setModelInfo(COMPONENT.SERVICE, { + "modelInvariantId": serviceModel.service.invariantUuid, + "modelVersion": serviceModel.service.version, + "modelNameVersionId": serviceModel.service.uuid, + "modelName": serviceModel.service.name, + "description": serviceModel.service.description, + "category":serviceModel.service.category + }); + + $scope.$broadcast("createComponent", { + componentId : COMPONENT.SERVICE, + callbackFunction : function(response) { + if (response.isSuccessful) { + vidService.setModel(serviceModel); + + var subscriberId = "Not Found"; + var serviceType = "Not Found"; + + var serviceInstanceId = response.instanceId; + + for (var i = 0; i < response.control.length; i++) { + if (response.control[i].id == "subscriberName") { + subscriberId = response.control[i].value; + } else if (response.control[i].id == "serviceType") { + serviceType = response.control[i].value; + } + } + + + $scope.refreshSubs(subscriberId,serviceType,serviceInstanceId); + + } + } + }); + + }, function errorCallback(response) { + console.log("Error: " + response); + }); + }; + + $scope.refreshSubs = function(subscriberId, serviceType, serviceInstanceId) { + $scope.status = "Fetching subscriber list from A&AI..."; + $scope.init(); + $http.get( PropertyService.getAaiBaseUrl() + "/aai_refresh_full_subscribers", { + + },{ + timeout: $scope.responseTimeoutMsec + }).then(function(response){ + + if (response.data.status < 200 || response.data.status > 202) { + $scope.showError("MSO failure - see log below for details") + return; + } + + $scope.customer = response.data.customer; // get data from json + + $scope.customerList = []; + + $scope.serviceInstanceToCustomer = []; + + angular.forEach($scope.customer, function(subVal, subKey) { + var cust = { "globalCustomerId": subVal["global-customer-id"], "subscriberName": subVal["subscriber-name"] }; + $scope.customerList.push(cust); + if (subVal["service-subscriptions"] != null) { + angular.forEach(subVal["service-subscriptions"]["service-subscription"], function(serviceSubscription, key) { + $scope.serviceInstanceId = []; + if (serviceSubscription["service-type"] != null) { + $scope.serviceType = serviceSubscription["service-type"]; + } else { + $scope.serviceType = "No Service Subscription Found"; + } + if (serviceSubscription["service-instances"] != null) { + angular.forEach(serviceSubscription["service-instances"]["service-instance"], function(instValue, instKey) { + var foo = { "serviceInstanceId": instValue["service-instance-id"], + "globalCustomerId": subVal["global-customer-id"], + "subscriberName": subVal["subscriber-name"] }; + $scope.serviceInstanceToCustomer.push(foo); + }); + } + }); + } + }); + DataService.setServiceInstanceToCustomer($scope.serviceInstanceToCustomer); + var serviceIdList = []; + $http.get(PropertyService.getAaiBaseUrl() + "/aai_get_services", { + },{ + timeout: $scope.responseTimeoutMsec + }).then(function(response) { + angular.forEach(response.data, function(value, key) { + angular.forEach(value, function(subVal, key) { + var newVal = { "id" : subVal["service-id"], "description" : subVal["service-description"] }; + serviceIdList.push(newVal); + DataService.setServiceIdList(serviceIdList); + + $location.search({ + "subscriberId": subscriberId, + "serviceType": serviceType, + "serviceInstanceId": serviceInstanceId + }); + + $location.path("/instantiate"); + }); + }); + }); + }) + ["catch"]($scope.handleServerError); + }; + }); +})(); diff --git a/vid/src/main/webapp/app/vid/scripts/controller/VidApp.js b/vid/src/main/webapp/app/vid/scripts/controller/VidApp.js new file mode 100644 index 000000000..acc185cf8 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/VidApp.js @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +(function () { + 'use strict'; + + app.config(['$routeProvider', '$locationProvider', function ($routeProvider) { + $routeProvider + .when('/models/services', { + controller: 'ServiceModelController', + templateUrl: 'app/vid/scripts/view-models/serviceModels.htm' + }) + .when('/instances/services', { + templateUrl : "app/vid/scripts/view-models/aaiGetSubs.htm", + controller : "aaiSubscriberController" + }) + .when('/instances/subdetails', { + templateUrl : "app/vid/scripts/view-models/aaiSubDetails.htm", + controller : "aaiSubscriberController" + }) + .when('/instantiate', { + controller: 'InstantiationController', + templateUrl: 'app/vid/scripts/view-models/instantiate.htm' + }) + .otherwise({ + redirectTo: '/models/services' + }); + }]); + + app.service('vidService', function() { + var _model = undefined; + var _instance = undefined; + + this.setModel = function(model) { + _model = model; + }; + + this.getModel = function() { + return _model; + }; + + this.setInstance = function(instance) { + _instance = instance; + }; + + this.getInstance = function() { + return _instance; + }; + }); +})(); diff --git a/vid/src/main/webapp/app/vid/scripts/controller/aaiSubscriberController.js b/vid/src/main/webapp/app/vid/scripts/controller/aaiSubscriberController.js new file mode 100644 index 000000000..aa3b5223a --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/aaiSubscriberController.js @@ -0,0 +1,763 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +app.controller("aaiSubscriberController", [ "COMPONENT", "DataService", "PropertyService", "$scope", "$http", "$timeout", "$location", "$log", "$route", "UtilityService", "vidService", + function(COMPONENT, DataService, PropertyService, $scope, $http, $timeout, $location, $log, $route, UtilityService, vidService) { + + $scope.showVnfDetails = function(vnf) { + console.log("showVnfDetails"); + DataService.setVnfInstanceId("VNF_INSTANCE_ID_12345"); + DataService + .setInventoryItem(aaiResult["inventory-response-items"]["inventory-response-item"][0]); + + $scope.$broadcast("showComponentDetails", { + componentId : COMPONENT.VNF, + callbackFunction : callbackFunction + }); + } + $scope.popup = new Object(); + + + $scope.isPopupVisible = false; + $scope.defaultBaseUrl = ""; + $scope.responseTimeoutMsec = 60000; + + $scope.serviceTypes=[ "Select a service type" ]; + $scope.defaultSubscriberName=[ "Select a subscriber name" ]; + + var callbackFunction = function(response) { + alert(response); + }; + + $scope.getSubs = function() { + $scope.status = "Fetching subscriber list from A&AI..."; + $scope.init(); + $http.get( PropertyService.getAaiBaseUrl() + "/aai_get_full_subscribers" + '?r=' + Math.random(), { + + },{ + timeout: $scope.responseTimeoutMsec + }).then($scope.handleInitialResponse) + ["catch"]($scope.handleServerError); + var serviceIdList = []; + $http.get(PropertyService.getAaiBaseUrl() + "/aai_get_services" + '?r=' + Math.random(), { + },{ + timeout: $scope.responseTimeoutMsec + }).then(function(response) { + angular.forEach(response.data, function(value, key) { + angular.forEach(value, function(subVal, key) { + var newVal = { "id" : subVal["service-id"], "description" : subVal["service-description"] }; + serviceIdList.push(newVal); + DataService.setServiceIdList(serviceIdList); + }); + }); + }); + }; + + $scope.refreshSubs = function() { + $scope.status = "Fetching subscriber list from A&AI..."; + $scope.init(); + $http.get(PropertyService.getAaiBaseUrl() + "/aai_refresh_full_subscribers" + '?r=' + Math.random(), { + + },{ + timeout: $scope.responseTimeoutMsec + }).then($scope.handleInitialResponse) + ["catch"]($scope.handleServerError); + }; + + $scope.getSubDetails = function(request) { + + $scope.init(); + $scope.selectedSubscriber = $location.search().selectedSubscriber; + $scope.selectedServiceInstance = $location.search().selectedServiceInstance; + $scope.status = "Fetching subscriber details from A&AI for " + $scope.selectedSubscriber; + $http.get(PropertyService.getAaiBaseUrl() + "/aai_sub_details/" + $scope.selectedSubscriber + '?r=' + Math.random(), { + + },{ + timeout: $scope.responseTimeoutMsec + }).then(function(response) { + $scope.subscriber = response.data; + $scope.selectedSubscriberName = $scope.subscriber["subscriber-name"]; + + $scope.displayData= []; + if ($scope.subscriber["service-subscriptions"] != null) { + angular.forEach($scope.subscriber["service-subscriptions"]["service-subscription"], function(serviceSubscription, key) { + $scope.serviceInstanceId = []; + if (serviceSubscription["service-type"] != null) { + $scope.serviceType = serviceSubscription["service-type"]; + } else { + $scope.serviceType = "No Service Subscription Found"; + } + if (serviceSubscription["service-instances"] != null) { + angular.forEach(serviceSubscription["service-instances"]["service-instance"], function(instValue, instKey) { + // put them together, i guess + var inst = { "serviceInstanceId": instValue["service-instance-id"], + "personaModelId": instValue["persona-model-id"], + "personaModelVersion": instValue["persona-model-version"], + "serviceInstanceName": instValue["service-instance-name"] + }; + if ($scope.selectedServiceInstance != null) { + if (instValue["service-instance-id"] == $scope.selectedServiceInstance) { + $scope.serviceInstanceId.push(inst); + } + } else { + $scope.serviceInstanceId.push(inst); + } + }); + } else { + if ($scope.serviceInstanceId == []) { + $scope.serviceInstanceId = [ "No Service Instance Found" ]; + } + } + angular.forEach($scope.serviceInstanceId, function(subVal, subKey) { + $scope.displayData.push({ + globalCustomerId : $scope.selectedSubscriber, + subscriberName : $scope.selectedSubscriberName, + serviceType : $scope.serviceType, + serviceInstanceId : subVal.serviceInstanceId, + personaModelId : subVal.personaModelId, + personaModelVersion : subVal.personaModelVersion, + serviceInstanceName : subVal.serviceInstanceName + }); + }); + }); + } else { + $scope.displayData.push({ + globalCustomerId : $scope.selectedSubscriber, + subscriberName : $scope.selectedSubscriberName, + serviceType : "No Service Subscription Found", + serviceInstanceId : "No Service Instance Found" + }); + } + $scope.viewPerPage=10; + $scope.totalPage=$scope.displayData.length/$scope.viewPerPage; + $scope.scrollViewPerPage=2; + $scope.currentPage=1; + $scope.searchCategory; + $scope.searchString=""; + $scope.currentPageNum=1; + $scope.defaultSort="subscriberName" + $scope.setProgress(100); // done + $scope.status = "Done"; + $scope.isSpinnerVisible = false; + }); + } + + + $scope.$on("deleteInstance", function(event, request) { + // $log.debug("deleteInstance: request:"); + // $log.debug(request); + $scope.init(); + // Use this line instead of the subsequent $http.post to change from POST to DELETE + // $http["delete"]($scope.baseUrl + request.url,{timeout: $scope.responseTimeoutMsec}).then($scope.requestOkay + $http.post($scope.baseUrl + request.url, { + requestDetails: request.requestDetails + },{ + timeout: $scope.responseTimeoutMsec + }).then($scope.handleInitialResponse) + ["catch"]($scope.handleServerError); + }); + + $scope.init = function() { + + //PropertyService.setAaiBaseUrl("testaai"); + //PropertyService.setAsdcBaseUrl("testasdc"); + + // takes a default value, retrieves the prop value from the file system and sets it + var msecs = PropertyService.retrieveMsoMaxPollingIntervalMsec(1000); + PropertyService.setMsoMaxPollingIntervalMsec(msecs); + + // takes a default value, retrieves the prop value from the file system and sets it + var polls = PropertyService.retrieveMsoMaxPolls(7); + PropertyService.setMsoMaxPolls(polls); + + //PropertyService.setMsoBaseUrl("testmso"); + PropertyService.setServerResponseTimeoutMsec(10000); + + /* + * Common parameters that would typically be set when the page is + * displayed for a specific service instance id. + */ + +// DataService.setSubscriberName("Mobility"); +// DataService.setGlobalCustomerId("CUSTID12345") +// DataService.setServiceType("Mobility Type 1"); +// DataService.setServiceName("Mobility Service 1"); +// DataService.setServiceInstanceId("mmsc-test-service-instance"); + + $scope.baseUrl = $scope.defaultBaseUrl; + + $scope.isSpinnerVisible = true; + $scope.isProgressVisible = true; + $scope.isPopupVisible = true; + $scope.requestId = ""; + $scope.error = ""; + $scope.pollAttempts = 0; + $scope.log = ""; + $scope.enableCloseButton(false); + $scope.resetProgress(); + $scope.setProgress(2); // Show "a little" progress + } + + $scope.getComponentList = function(event, request) { + + $scope.isSpinnerVisible = true; + $scope.isProgressVisible = true; + $scope.isPopupVisible = true; + $scope.requestId = ""; + $scope.error = ""; + $scope.pollAttempts = 0; + $scope.log = ""; + + $scope.resetProgress(); + $scope.setProgress(2); // Show "a little" progress + + //subscriberId=jimmy-testing&serviceType=gamma-01%2F1&serviceInstanceId=jimmy2-01%2F01%2F%2F01 + $scope.globalCustomerId = $location.search().subscriberId; + $scope.serviceType = $location.search().serviceType; + $scope.serviceInstanceId = $location.search().serviceInstanceId; + + //$scope.getAsdcModel($location.search().modelUuid); + + // this should be in a config file? + $scope.namedQueryId = "ed0a0f5b-cf79-4784-88b2-911cd726cd3d"; + $scope.url = PropertyService.getAaiBaseUrl() + "/aai_sub_viewedit" + + "/" + encodeURIComponent($scope.namedQueryId) + + "/" + encodeURIComponent($scope.globalCustomerId) + + "/" + encodeURIComponent($scope.serviceType) + + "/" + encodeURIComponent($scope.serviceInstanceId) + '?r=' + Math.random(); + + $scope.status = "Fetching service instance data from A&AI for service-instance-id=" + $scope.serviceInstanceId; + $http.get($scope.url, { + },{ + timeout: $scope.responseTimeoutMsec + }).then($scope.handleInitialResponseInventoryItems) + ["catch"]($scope.handleServerError); + } + + $scope.handleServerError = function(response, status) { + alert(response.statusText); + } + + $scope.getAsdcModel = function(disData) { + $http.get(PropertyService.getAaiBaseUrl() + '/rest/models/services') + .then(function successCallback(response) { + var myUuid = null; + var lastVersion = -1; + angular.forEach(response.data, function(model, key) { + if (angular.equals(model.invariantUUID,disData.personaModelId)) { + if (model.version > lastVersion) { + lastVersion = model.version; + myUuid = model.uuid; + } + + } + }); + if (myUuid == null) + { + console.log("aaiSubscriber getAsdcModel - No matching model found matching the persona Model Id = " + disData.personaModelId); + } + else + { + console.log(myUuid); + $http.get(PropertyService.getAaiBaseUrl() + '/rest/models/services/' + myUuid) + .then(function successCallback(response2) { + vidService.setModel(response2.data); + window.location.href = "#/instantiate?subscriberId=" + disData.globalCustomerId + "&serviceType=" + disData.serviceType + "&serviceInstanceId=" + disData.serviceInstanceId; + console.log("aaiSubscriber getAsdcModel DONE!!!!"); + }); + } + }, function errorCallback(response) { + //TODO + }); + } + + $scope.getTenants = function(globalCustomerId) { + $http.get(PropertyService.getAaiBaseUrl() + '/aai_get_tenants' + globalCustomerId + '?r=' + Math.random()) + .then(function successCallback(response) { + return response.data; + //$location.path("/instantiate"); + }, function errorCallback(response) { + //TODO + }); + } + + $scope.handleInitialResponseInventoryItems = function(response) { + // $log.debug("handleInitialResponse: response contents:"); + // $log.debug(response); + try { + + if (response.status < 200 || response.status > 202) { + $scope.handleServerError(response, response.status); + return; + } + + $scope.inventoryResponseItemList = response.data["inventory-response-item"]; // get data from json + console.log($scope.inventoryResponseItemList.toString()); + + $scope.displayData = []; + $scope.vnfs = []; + + $scope.counter = 100; + + angular.forEach($scope.inventoryResponseItemList, function(inventoryResponseItem, key) { + + $scope.inventoryResponseItem = inventoryResponseItem; + + $scope.serviceInstanceToCustomer = DataService.getServiceInstanceToCustomer(); + var subscriberName = ""; + angular.forEach($scope.serviceInstanceToCustomer, function(servInst, key2) { + if (servInst.serviceInstanceId === $scope.serviceInstanceId) { + subscriberName = servInst.subscriberName; + } + }); + $scope.service.instance = { + "name": $scope.inventoryResponseItem["service-instance"]["service-instance-name"], + "serviceInstanceId": $scope.serviceInstanceId, + "serviceType": $scope.serviceType, + "globalCustomerId": $scope.globalCustomerId, + "subscriberName": subscriberName, + "id": $scope.serviceInstanceId, + "inputs": { + "a": { + "type": "String", + "description": "This variable is 'a'", + "default": "A default" + }, + "b": { + "type": "String", + "description": "This variable is 'b'", + "default": "B default" + }, + }, + "object": $scope.inventoryResponseItem["service-instance"], + "vnfs": [], + "networks": [] + } + + if (inventoryResponseItem["inventory-response-items"] != null) { + + angular.forEach(inventoryResponseItem["inventory-response-items"]["inventory-response-item"], function(subInventoryResponseItem, key) { + // i expect to find vnfs now + + if (subInventoryResponseItem["l3-network"] != null) { + var l3NetworkObject = subInventoryResponseItem["l3-network"]; + var l3Network = { "id": $scope.counter++, + "name": l3NetworkObject["network-name"], + "itemType": "l3-network", + "nodeId": l3NetworkObject["network-id"], + "nodeType": l3NetworkObject["network-type"], + "nodeStatus": l3NetworkObject["orchestration-status"], + "object": l3NetworkObject, + "nodes": [] + }; + $scope.service.instance["networks"].push(l3Network); + } + + if (subInventoryResponseItem["generic-vnf"] != null) { + var genericVnfObject = subInventoryResponseItem["generic-vnf"]; + + var genericVnf = { + "name": genericVnfObject["vnf-name"], + "id": $scope.counter++, + "itemType": "vnf", + "nodeType": genericVnfObject["vnf-type"], + "nodeId": genericVnfObject["vnf-id"], + "nodeStatus": genericVnfObject["orchestration-status"], + "object": genericVnfObject, + "vfModules": [], + "volumeGroups": [], + "availableVolumeGroups": [] + }; + $scope.service.instance["vnfs"].push(genericVnf); + + // look for volume-groups + if (subInventoryResponseItem["inventory-response-items"] != null) { + angular.forEach(subInventoryResponseItem["inventory-response-items"]["inventory-response-item"], function(vfmodules, key) { + + if (vfmodules["volume-group"] != null) { + var volumeGroupObject = vfmodules["volume-group"]; + var volumeGroup = { "id": $scope.counter++, + "name": volumeGroupObject["volume-group-name"], + "itemType": "volume-group", + "nodeId": volumeGroupObject["volume-group-id"], + "nodeType": volumeGroupObject["vnf-type"], + "nodeStatus": volumeGroupObject["orchestration-status"], + "object": volumeGroupObject, + "nodes": [] + }; + genericVnf["volumeGroups"].push(volumeGroup); + genericVnf["availableVolumeGroups"].push(volumeGroup); + } + }); + } + // now we've loaded up the availableVolumeGroups, we can use it + if (subInventoryResponseItem["inventory-response-items"] != null) { + angular.forEach(subInventoryResponseItem["inventory-response-items"]["inventory-response-item"], function(vfmodules, key) { + + if (vfmodules["vf-module"] != null) { + var vfModuleObject = vfmodules["vf-module"]; + var vfModule = { "id": $scope.counter++, + "name": vfModuleObject["vf-module-name"], + "itemType": "vf-module", + "nodeType": "vf-module", + "nodeStatus": vfModuleObject["orchestration-status"], + "volumeGroups": [], + "object": vfModuleObject, + "networks": [] + }; + genericVnf["vfModules"].push(vfModule); + if (vfmodules["inventory-response-items"] != null) { + angular.forEach(vfmodules["inventory-response-items"]["inventory-response-item"], function(networks, key) { + if (networks["l3-network"] != null) { + var l3NetworkObject = networks["l3-network"]; + var l3Network = { "id": $scope.counter++, + "name": l3NetworkObject["network-name"], + "itemType": "l3-network", + "nodeId": l3NetworkObject["network-id"], + "nodeType": l3NetworkObject["network-type"], + "nodeStatus": l3NetworkObject["orchestration-status"], + "object": l3NetworkObject, + "nodes": [] + }; + vfModule["networks"].push(l3Network); + } + if (networks["volume-group"] != null) { + var volumeGroupObject = networks["volume-group"]; + + var volumeGroup = { "id": $scope.counter++, + "name": volumeGroupObject["volume-group-name"], + "itemType": "volume-group", + "nodeId": volumeGroupObject["volume-group-id"], + "nodeType": volumeGroupObject["vnf-type"], + "nodeStatus": volumeGroupObject["orchestration-status"], + "object": volumeGroupObject, + "nodes": [] + }; + var tmpVolGroup = []; + + angular.forEach(genericVnf["availableVolumeGroups"], function(avgroup, key) { + if (avgroup.name != volumeGroup.name) { + tmpVolGroup.push(avgroup); + } + }); + + genericVnf["availableVolumeGroups"] = tmpVolGroup; + + vfModule["volumeGroups"].push(volumeGroup); + } + + }); + } + } + }); + } + } + }); + } + }); + + $scope.setProgress(100); // done + $scope.status = "Done"; + $scope.isSpinnerVisible = false; + console.log("HERE!!!"); + } catch (error) { + console.log(error); + } + } + + $scope.handleInitialResponse = function(response) { + try { + $scope.enableCloseButton(true); + $scope.updateLog(response); + if (response.data.status < 200 || response.data.status > 202) { + $scope.showError("MSO failure - see log below for details") + return; + } + + $scope.setProgress(100); // done + $scope.status = "Done"; + $scope.isSpinnerVisible = false; + + $scope.customer = response.data.customer; // get data from json + + $scope.customerList = []; + + $scope.serviceInstanceToCustomer = []; + //$scope.serviceIdList = []; + angular.forEach($scope.customer, function(subVal, subKey) { + var cust = { "globalCustomerId": subVal["global-customer-id"], "subscriberName": subVal["subscriber-name"] }; + $scope.customerList.push(cust); + if (subVal["service-subscriptions"] != null) { + + + angular.forEach(subVal["service-subscriptions"]["service-subscription"], function(serviceSubscription, key) { + $scope.serviceInstanceId = []; + if (serviceSubscription["service-type"] != null) { +// var newVal = { "id" : serviceSubscription["service-type"], "description" : serviceSubscription["service-type"] }; +// if ($scope.serviceIdList.indexOf(newVal) == -1) { +// $scope.serviceIdList.push(newVal); +// } + $scope.serviceType = serviceSubscription["service-type"]; + } else { + $scope.serviceType = "No Service Subscription Found"; + } + if (serviceSubscription["service-instances"] != null) { + angular.forEach(serviceSubscription["service-instances"]["service-instance"], function(instValue, instKey) { + var foo = { "serviceInstanceId": instValue["service-instance-id"], + "globalCustomerId": subVal["global-customer-id"], + "subscriberName": subVal["subscriber-name"] }; + $scope.serviceInstanceToCustomer.push(foo); + }); + } + }); + } + }); +// DataService.setServiceIdList($scope.serviceIdList); + DataService.setServiceInstanceToCustomer($scope.serviceInstanceToCustomer); + } catch (error) { + $scope.showContentError(error); + } + } + + $scope.autoGetSubs = function() { + /* + * Optionally comment in / out one of these method calls (or add a similar + * entry) to auto-invoke an entry when the test screen is redrawn. + */ + $scope.getSubs(); + + } + + $scope.pollStatus = function () { + /* + * The "?r=" argument overrides caching. This was needed for Internet Explorer 11. + * + * Ideally this should NOT be needed and appears to be an Angular bug. + */ + $http.get($scope.baseUrl + "mso_get_orch_req/" + $scope.requestId + "?r=" + Math.random(), { + cache: false, // This alternative did NOT seem to disable caching but was retained as a reference + timeout: $scope.responseTimeoutMsec + }).then($scope.handlePollResponse) + ["catch"]($scope.handleServerError); + } + + $scope.handlePollResponse = function(response) { + try { + // $log.debug("handlePollResponse: response contents:"); + // $log.debug(response); + $scope.updateLog(response); + + if (response.data.status < 200 || response.data.status > 202) { + $scope.showError("MSO failure - see log below for details") + return; + } + +// UtilityService.checkUndefined("request", response.data.entity.request); +// UtilityService.checkUndefined("requestStatus", response.data.entity.request.requestStatus); + +// $scope.setProgress(response.data.entity.request.requestStatus.percentProgress); + +// var requestState = response.data.entity.request.requestStatus.requestState; +// if (requestState == "InProgress") { +// requestState = "In Progress"; +// } +// var statusMessage = response.data.entity.request.requestStatus.statusMessage; +// if (UtilityService.hasContents(statusMessage)) { +// $scope.status = requestState + " - " + statusMessage; +// } else { +// $scope.status = requestState; +// } +// if (requestState == "Complete") { +// $scope.isSpinnerVisible = false; +// return; +// } +// if (requestState == "Failure") { +// $scope.showError("MSO failure - see log below for details") +// return; +// } +// if (++$scope.pollAttempts > $scope.properties.msoMaxPolls) { +// $scope.showError("Maximum number of poll attempts exceeded"); +// } else { +// $scope.timer = $timeout($scope.pollStatus, $scope.properties.msoMaxPollingIntervalMsec); +// } + } catch (error) { + $scope.showContentError(error); + } + } + + $scope.updateLog = function(response) { +// $scope.log = UtilityService.getCurrentTime() + " HTTP Status: " + +// UtilityService.getHttpStatusText(response.data.status) + "\n" + +// angular.toJson(response.data.entity, true) + "\n\n" + $scope.log; +// UtilityService.checkUndefined("entity", response.data.entity); +// UtilityService.checkUndefined("status", response.data.status); + } + + $scope.handleServerError = function(response, status) { + $scope.enableCloseButton(true); + var message = UtilityService.getHttpErrorMessage(response); + if (message != ""){ + message = " (" + message + ")"; + } + $scope.showError("System failure" + message); + } + + $scope.showContentError = function(message) { + // $log.debug(message); + console.log(message); + if (UtilityService.hasContents(message)) { + $scope.showError("System failure (" + message + ")"); + } else { + $scope.showError("System failure"); + } + } + + $scope.showError = function(message) { + $scope.isSpinnerVisible = false; + $scope.isProgressVisible = false; + $scope.error = message; + $scope.status = "Error"; + } + + $scope.close = function() { + if ($scope.timer != undefined) { + $timeout.cancel($scope.timer); + } + $scope.isPopupVisible = false; + } + + + + /* + * Consider converting the progress bar mechanism, the disabled button handling + * and the following methods to generic Angular directive(s) and/or approach. + */ + + $scope.enableCloseButton = function(isEnabled) { + var selector = "div[ng-controller=msoCommitController] button"; + + $scope.isCloseEnabled = isEnabled; + + if (isEnabled) { + $(selector).addClass("button--primary").removeClass("button--inactive").attr("btn-type", "primary"); + } else { + $(selector).removeClass("button--primary").addClass("button--inactive").attr("btn-type", "disabled"); + } + } + + $scope.resetProgress = function() { + $scope.percentProgress = 0; + $scope.progressClass = "progress-bar progress-bar-info"; + } + + $scope.setProgress = function(percentProgress) { + percentProgress = parseInt(percentProgress); + if (percentProgress >= 100) { + $scope.progressClass = "progress-bar progress-bar-success"; + } + + if (percentProgress < $scope.percentProgress) { + return; + } + + $scope.percentProgress = percentProgress; + $scope.progressWidth = {width: percentProgress + "%"}; + if (percentProgress >= 5) { + $scope.progressText = percentProgress + " %"; + } else { + // Hidden since color combination is barely visible when progress portion is narrow. + $scope.progressText = ""; + } + } + + $scope.reloadRoute = function() { + $route.reload(); + } + + $scope.prevPage = function() { + $scope.currentPage--; + } + + $scope.nextPage = function() { + $scope.currentPage++; + } + $scope.getSubscriberDet = function(selectedCustomer,selectedServiceInstance){ + if (selectedCustomer != null) { + window.location.href = '#/instances/subdetails?selectedSubscriber=' + selectedCustomer; + } else if (selectedServiceInstance != null) { + selectedServiceInstance.trim(); + var serviceInstanceToCustomer = $scope.serviceInstanceToCustomer; + var notFound = true; + angular.forEach(serviceInstanceToCustomer, function(inst, key) { + if (inst.serviceInstanceId == selectedServiceInstance) { + + notFound = false; + window.location.href = '#/instances/subdetails?selectedSubscriber=' + inst.globalCustomerId + '&selectedServiceInstance=' + selectedServiceInstance; + } + }); + if (notFound) { + alert("That service instance does not exist. Please try again."); + } + } else { + alert("Please select a subscriber or enter a service instance"); + } + }; +} +]); + + +app.controller('TreeCtrl', ['$scope', function ($scope) { + $scope.remove = function (scope) { + scope.remove(); + }; + + $scope.toggle = function (scope) { + scope.toggle(); + }; + + $scope.moveLastToTheBeginning = function () { + var a = $scope.data.pop(); + $scope.data.splice(0, 0, a); + }; + + $scope.newSubItem = function (scope) { + var nodeData = scope.$modelValue; + nodeData.nodes.push({ + id: nodeData.id * 10 + nodeData.nodes.length, + title: nodeData.title + '.' + (nodeData.nodes.length + 1), + nodes: [] + }); + }; + + $scope.collapseAll = function () { + $scope.$broadcast('angular-ui-tree:collapse-all'); + }; + + $scope.expandAll = function () { + $scope.$broadcast('angular-ui-tree:expand-all'); + }; + + +}]); + + + diff --git a/vid/src/main/webapp/app/vid/scripts/controller/creationDialogController.js b/vid/src/main/webapp/app/vid/scripts/controller/creationDialogController.js new file mode 100644 index 000000000..5e5c51d6e --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/creationDialogController.js @@ -0,0 +1,162 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var creationDialogController = function( COMPONENT, FIELD, $scope, $http, $timeout, $log, + CreationService, UtilityService) { + + $scope.isDialogVisible = false; + $scope.summaryControl = {}; + $scope.userProvidedControl = {}; + + var callbackFunction = undefined; + var componentId = undefined; + + $scope.$on("createComponent", function(event, request) { + + $scope.isSpinnerVisible = true; + $scope.isErrorVisible = false; + $scope.isDataVisible = false; + $scope.isConfirmEnabled = false; + $scope.isDialogVisible = true; + $scope.popup.isVisible = true; + + callbackFunction = request.callbackFunction; + componentId = request.componentId; + CreationService.initializeComponent(request.componentId); + + CreationService.setHttpErrorHandler(function(response) { + showError("System failure", UtilityService + .getHttpErrorMessage(response)); + }); + + $scope.componentName = CreationService.getComponentDisplayName(); + + CreationService.getParameters(handleGetParametersResponse); + + }); + + var handleGetParametersResponse = function(parameters) { + $scope.summaryControl.setList(parameters.summaryList); + $scope.userProvidedControl.setList(parameters.userProvidedList); + + $scope.isSpinnerVisible = false; + $scope.isDataVisible = true; + $scope.isConfirmEnabled = true; + }; + + var validateInstanceName = function(iname) { + var patt1 = /^([a-z])+([0-9a-z\-_]*)$/i; + + if ( iname == null ){ + return false; + } + if ( !iname.match(patt1) ) { + return false; + } + return true; + } + + $scope.userParameterChanged = function(id) { + CreationService.updateUserParameterList(id, $scope.userProvidedControl); + } + + $scope.confirm = function() { + + var requiredFields = $scope.userProvidedControl.getRequiredFields(); + if (requiredFields !== "") { + showError("Missing data", requiredFields); + return; + } + // validate the instance names for volumeGroup, vfModule, network + + if ( componentId != COMPONENT.SERVICE ) { + var paramList = $scope.userProvidedControl.getList(); + var instanceName = ""; + + if ( paramList != null ) { + for (var i = 0; i < paramList.length; i++) { + if (paramList[i].id === FIELD.ID.INSTANCE_NAME) { + instanceName = paramList[i].value; + break; + } + } + } + var isValid = validateInstanceName (instanceName); + if ( isValid ) { + $scope.isErrorVisible = false; + } else { + showError("Invalid instance name: " + instanceName, + "The instance name must contain only alphanumeric or \"_-.\" characters, and must start with an alphabetic character"); + return; + } + } + var requestDetails = CreationService + .getMsoRequestDetails($scope.userProvidedControl.getList()); + + $scope.isDialogVisible = false; + + $scope.$broadcast("createInstance", { + url : CreationService.getMsoUrl(), + requestDetails : requestDetails, + callbackFunction : function(response) { + if (response.isSuccessful) { + $scope.popup.isVisible = false; + runCallback(response); + } else { + $scope.isDialogVisible = true; + } + } + }); + } + + $scope.cancel = function() { + $scope.isDialogVisible = false; + $scope.popup.isVisible = false; + runCallback(false); + } + + var runCallback = function(response) { + if (angular.isFunction(callbackFunction)) { + callbackFunction({ + isSuccessful : response.isSuccessful, + control : $scope.userProvidedControl.getList(), + instanceId : response.instanceId + }); + } + } + + var showError = function(summary, details) { + var message = summary; + if (UtilityService.hasContents(details)) { + message += " (" + details + ")"; + } + $scope.isSpinnerVisible = false; + $scope.isErrorVisible = true; + $scope.error = message; + } + +} + +app + .controller("creationDialogController", [ "COMPONENT", "FIELD", "$scope", "$http", + "$timeout", "$log", "CreationService", "UtilityService", + creationDialogController ]); diff --git a/vid/src/main/webapp/app/vid/scripts/controller/deletionDialogController.js b/vid/src/main/webapp/app/vid/scripts/controller/deletionDialogController.js new file mode 100644 index 000000000..caac6de9b --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/deletionDialogController.js @@ -0,0 +1,117 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var deletionDialogController = function($scope, $http, $timeout, $log, + DeletionService, UtilityService) { + + $scope.isDialogVisible = false; + $scope.summaryControl = {}; + $scope.userProvidedControl = {}; + + var callbackFunction = undefined; + + $scope.$on("deleteComponent", function(event, request) { + + $scope.isDataVisible = false; + $scope.isSpinnerVisible = false; + $scope.isErrorVisible = false; + $scope.isDialogVisible = true; + $scope.popup.isVisible = true; + $scope.isConfirmEnabled = false; + + callbackFunction = request.callbackFunction; + + DeletionService.initializeComponent(request.componentId); + + $scope.componentName = DeletionService.getComponentDisplayName(); + + $scope.summaryControl.setList(DeletionService.getSummaryList()); + + DeletionService.getParameters(handleGetParametersResponse); + + }); + + var handleGetParametersResponse = function(parameters, dontshow) { + $scope.summaryControl.setList(parameters.summaryList); + $scope.userProvidedControl.setList(parameters.userProvidedList); + + $scope.isSpinnerVisible = false; + if (dontshow) + $scope.isDataVisible = false; + else + $scope.isDataVisible = true; + $scope.isConfirmEnabled = true; + }; + + $scope.userParameterChanged = function(id) { + DeletionService.updateUserParameterList(id, $scope.userProvidedControl); + } + + $scope.confirm = function() { + + var requiredFields = $scope.userProvidedControl.getRequiredFields(); + if (requiredFields === "") { + $scope.isErrorVisible = false; + } else { + showError("Missing data", requiredFields); + return; + } + + + var requestDetails = DeletionService.getMsoRequestDetails($scope.userProvidedControl.getList()); + + $scope.isDialogVisible = false; + + $scope.$broadcast("deleteInstance", { + url : DeletionService.getMsoUrl(), + requestDetails : requestDetails, + callbackFunction : function(isSuccessful) { + if (isSuccessful) { + $scope.popup.isVisible = false; + runCallback(true); + } else { + $scope.isDialogVisible = true; + } + } + }); + + } + + $scope.cancel = function() { + $scope.isDialogVisible = false; + $scope.popup.isVisible = false; + runCallback(false); + } + + var runCallback = function(isSuccessful) { + if (angular.isFunction(callbackFunction)) { + callbackFunction({ + isSuccessful : isSuccessful + }); + } + } +} + +app + .controller("deletionDialogController", [ "$scope", "$http", + "$timeout", "$log", "DeletionService", "UtilityService", + deletionDialogController ]); diff --git a/vid/src/main/webapp/app/vid/scripts/controller/detailsDialogController.js b/vid/src/main/webapp/app/vid/scripts/controller/detailsDialogController.js new file mode 100644 index 000000000..5f58ae319 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/detailsDialogController.js @@ -0,0 +1,84 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var detailsDialogController = function($scope, $http, $timeout, $log, + MsoService, DetailsService, UtilityService) { + + $scope.isDialogVisible = false; + $scope.summaryControl = {}; + $scope.detailsControl = {}; + + $scope.$on("showComponentDetails", function(event, request) { + + $scope.log = ""; + $scope.isSpinnerVisible = true; + $scope.isErrorVisible = false; + $scope.isDialogVisible = true; + $scope.popup.isVisible = true; + + DetailsService.initializeComponent(request.componentId); + + $scope.componentName = DetailsService.getComponentDisplayName(); + + $scope.summaryControl.setList(DetailsService.getSummaryList()); + + $scope.detailsControl.setList(DetailsService.getDetailsList()); + + UtilityService.setHttpErrorHandler(function(response) { + showError("System failure", UtilityService + .getHttpErrorMessage(response)); + }); + + MsoService.getOrchestrationRequests( + DetailsService.getMsoFilterString(), handleGetResponse); + }); + + var handleGetResponse = function(response) { + $scope.isSpinnerVisible = false; + try { + $scope.log = MsoService + .getFormattedGetOrchestrationRequestsResponse(response); + } catch (error) { + $scope.log = MsoService.getFormattedCommonResponse(response); + MsoService.showResponseContentError(error, showError); + } + } + + $scope.close = function() { + $scope.isDialogVisible = false; + $scope.popup.isVisible = false; + } + + var showError = function(summary, details) { + var message = summary; + if (UtilityService.hasContents(details)) { + message += " (" + details + ")"; + } + $scope.isSpinnerVisible = false; + $scope.isErrorVisible = true; + $scope.error = message; + } +} + +app.controller("detailsDialogController", [ "$scope", "$http", "$timeout", + "$log", "MsoService", "DetailsService", "UtilityService", + detailsDialogController ]); diff --git a/vid/src/main/webapp/app/vid/scripts/controller/dummy.txt b/vid/src/main/webapp/app/vid/scripts/controller/dummy.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/dummy.txt diff --git a/vid/src/main/webapp/app/vid/scripts/controller/msoCommitController.js b/vid/src/main/webapp/app/vid/scripts/controller/msoCommitController.js new file mode 100644 index 000000000..ef3adeb32 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/msoCommitController.js @@ -0,0 +1,249 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +/* + * "msoCommitController.js" provides controller code to commit MSO requests. + * + * HIGHLIGHTS: + * + * Parent HTML/JSP code is expected to include "msoCommit.htm" (via + * "ng-include") and this file (via "<script>"). "msoCommit.jsp" (displayed + * when the parent code includes "msoCommit.htm") renders a popup window, but + * initially hides the display. + * + * The parent controller code is expected to broadcast either the + * "createInstance" or "deleteInstance" events when it is ready to commit the + * code. + * + * This controller receives these events (via "$scope.on" declarations), calls + * "$scope.init()" to "unhide" and initialize the popup display and then makes a + * REST request to the appropriate server Java controller. + * + * The initial REST response is handled by "handleInitialResponse". This method + * then polls the server (via "getRequestStatus") if the request is successful. + * + * The subsequent "getRequestStatus" responses are handled by + * "handleGetResponse". + * + * "handleInitialResponse" and "handleGetResponse" primarily filter response + * data, manipulate the display and provide error handling. + * + * The mechanism has these dependencies (in addition to "msoCommit.htm"): + * + * 1) Three services: MsoService, PropertyService and UtilityService + * + * 2) The popup window directive found in "popupWindow.htm" and + * "popupWindowDirective.js" + * + * 2) Display styling defined in "dialogs.css" + * + * CAVEATS: + * + * The parent HTML is assumed to be the "popup-window" directive and the + * corresponding parent controller is assumed to define the object + * "$scope.popup". + */ + +var msoCommitController = function($scope, $http, $timeout, $window, $log, + MsoService, PropertyService, UtilityService, DataService) { + + $scope.isViewVisible = false; + $scope.progressBarControl = {}; + $scope.popupWindowControl = {}; + + var _this = this; + + $scope.$on("createInstance", function(event, request) { + init(request); + MsoService.createInstance(request, handleInitialResponse); + }); + + $scope.$on("deleteInstance", function(event, request) { + init(request); + MsoService.deleteInstance(request, handleInitialResponse); + }); + + var init = function(request) { + $scope.status = "Submitting Request"; + $scope.isSpinnerVisible = true; + $scope.isProgressVisible = true; + $scope.error = ""; + $scope.log = ""; + $scope.isCloseEnabled = false; + $scope.isViewVisible = true; + $scope.popup.isVisible = true; + + _this.pollAttempts = 0; + _this.callbackFunction = request.callbackFunction; + + if (angular.isFunction($scope.progressBarControl.reset)) { + $scope.progressBarControl.reset(); + } + $scope.percentProgress = 2; // Show "a little" progress + + UtilityService.setHttpErrorHandler(function(response) { + $scope.isCloseEnabled = true; + showError("System failure", UtilityService + .getHttpErrorMessage(response)); + }); + } + + var handleInitialResponse = function(response) { + try { + updateViewAfterInitialResponse(response); + _this.timer = $timeout(getRequestStatus, PropertyService + .getMsoMaxPollingIntervalMsec()); + + $scope.instanceId = response.data.entity.instanceId; + if ($scope.instanceId == null) { + $scope.instanceId = response.data.entity.requestReferences.instanceId; + } + } catch (error) { + MsoService.showResponseContentError(error, showError); + } + } + + var getRequestStatus = function() { + MsoService.getOrchestrationRequest(_this.requestId, handleGetResponse); + } + + var handleGetResponse = function(response) { + try { + if (isUpdateViewAfterGetResponseComplete(response)) { + return; + } + console.log ( "msoCommitController _this.pollAttempts=" + _this.pollAttempts + " max polls=" + PropertyService.getMsoMaxPolls()); + if (++_this.pollAttempts > PropertyService.getMsoMaxPolls()) { + showError("Maximum number of poll attempts exceeded"); + } else { + _this.timer = $timeout(getRequestStatus, PropertyService + .getMsoMaxPollingIntervalMsec()); + } + } catch (error) { + MsoService.showResponseContentError(error, showError); + } + } + + var updateViewAfterInitialResponse = function(response) { + $scope.isCloseEnabled = true; + + updateLog(response); + + _this.requestId = UtilityService.checkUndefined("requestId", + UtilityService.checkUndefined("requestReferences", + response.data.entity.requestReferences).requestId); + + $scope.percentProgress = 4; // Show "a little more" progress + $scope.status = "In Progress"; + } + + /* + * Updates the view and returns "true" if the MSO operation has returned a + * "Complete" status. + */ + var isUpdateViewAfterGetResponseComplete = function(response) { + console.log("msoCommitController isUpdateViewAfterGetResponseComplete"); + updateLog(response); + + var requestStatus = UtilityService.checkUndefined("requestStatus", + UtilityService.checkUndefined("request", + response.data.entity.request).requestStatus); + + var requestState = requestStatus.requestState; + console.log("msoCommitController requestState=" + requestState); + // look for "progress" or "pending" + var patt1 = /progress/i; + var patt2 = /pending/i; + var result1 = patt1.test(requestState); + var result2 = patt2.test(requestState) + if (result1 || result2) { + requestState = "In Progress"; + } + var statusMessage = requestStatus.statusMessage; + console.log("msoCommitController statusMessage=" + statusMessage); + if (UtilityService.hasContents(statusMessage)) { + $scope.status = requestState + " - " + statusMessage; + } else { + $scope.status = requestState; + } + if (UtilityService.hasContents(requestStatus.percentProgress)) { + $scope.percentProgress = requestStatus.percentProgress; + } + + if (requestState.toLowerCase() === "Failed".toLowerCase()) { + throw { + type : "msoFailure" + }; + } + + if (requestState.toLowerCase() === "Complete".toLowerCase()) { + $scope.isSpinnerVisible = false; + return true; + } + + return false; + } + + var updateLog = function(response) { + $scope.log = MsoService.getFormattedCommonResponse(response) + + $scope.log; + UtilityService.checkUndefined("entity", response.data.entity); + UtilityService.checkUndefined("status", response.data.status); + MsoService.checkValidStatus(response); + } + + $scope.close = function() { + if (_this.timer !== undefined) { + $timeout.cancel(_this.timer); + } + $scope.isViewVisible = false; + if (angular.isFunction(_this.callbackFunction)) { + if ($scope.error === "") { + _this.callbackFunction({ + isSuccessful : true, + instanceId : $scope.instanceId + }); + } else { + _this.callbackFunction({ + isSuccessful : false + }); + } + } else { + $scope.popup.isVisible = false; + } + } + + var showError = function(summary, details) { + var message = summary; + if (UtilityService.hasContents(details)) { + message += " (" + details + ")"; + } + $scope.isSpinnerVisible = false; + $scope.isProgressVisible = false; + $scope.error = message; + $scope.status = "Error"; + } +} + +app.controller("msoCommitController", [ "$scope", "$http", "$timeout", + "$window", "$log", "MsoService", "PropertyService", "UtilityService", + msoCommitController ]); diff --git a/vid/src/main/webapp/app/vid/scripts/controller/sample-page-controller.js b/vid/src/main/webapp/app/vid/scripts/controller/sample-page-controller.js new file mode 100644 index 000000000..0f5494556 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/sample-page-controller.js @@ -0,0 +1,81 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +app.controller('samplePageController', function($scope, $http,ProfileService,modalService){ + $scope.tableData=[]; + $scope.viewPerPage=20; + $scope.scrollViewPerPage=2; + $scope.currentPage=1; + $scope.totalPage; + $scope.searchCategory; + $scope.searchString=""; + $scope.currentPageNum=1; + ProfileService.getProfilePagination(1,$scope.viewPerPage).then(function(data){ + var j = data; + $scope.data = JSON.parse(j.data); + $scope.tableData =JSON.parse($scope.data.profileList); + $scope.totalPages =JSON.parse($scope.data.totalPage); + for(x in $scope.tableData){ + if($scope.tableData[x].active_yn=='Y') + $scope.tableData[x].active_yn=true; + else + $scope.tableData[x].active_yn=false; + } + //$scope.resetMenu(); + },function(error){ + console.log("failed"); + reloadPageOnce(); + }); + + $scope.$watch('currentPageNum', function(val) { + + ProfileService.getProfilePagination(val,$scope.viewPerPage).then(function(data){ + var j = data; + $scope.data = JSON.parse(j.data); + $scope.tableData =JSON.parse($scope.data.profileList); + $scope.totalPages =JSON.parse($scope.data.totalPage); + for(x in $scope.tableData){ + if($scope.tableData[x].active_yn=='Y') + $scope.tableData[x].active_yn=true; + else + $scope.tableData[x].active_yn=false; + } + //$scope.resetMenu(); + },function(error){ + console.log("failed"); + }); + + }); + + $scope.editRow = function(profileId){ + window.location = 'userProfile#/profile/' + profileId; + } + + $scope.toggleProfileActive = function(rowData) { + modalService.popupConfirmWinWithCancel("Confirm","You are about to change user's active status. Do you want to continue?", + function(){ + $http.get("profile/toggleProfileActive?profile_id="+rowData.id).success(function(){}); + }, + function(){ + rowData.active=!rowData.active; + }) + }; + +}); diff --git a/vid/src/main/webapp/app/vid/scripts/controller/sample-page-iframe-controller.js b/vid/src/main/webapp/app/vid/scripts/controller/sample-page-iframe-controller.js new file mode 100644 index 000000000..99f66de7e --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/sample-page-iframe-controller.js @@ -0,0 +1,24 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +app.controller('samplePageWithIframeController', function($scope, $http,ProfileService,modalService){ + + +}); diff --git a/vid/src/main/webapp/app/vid/scripts/controller/sampleController.js b/vid/src/main/webapp/app/vid/scripts/controller/sampleController.js new file mode 100644 index 000000000..190ac301d --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/sampleController.js @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +app.config(function($routeProvider) { + $routeProvider + .when('/iframe', { + templateUrl: 'app/fusionapp/scripts/view-models/sampleWithIframe.html', + controller : "samplePageWithIframeController" + }) + .otherwise({ + templateUrl: 'app/fusionapp/scripts/view-models/sample.html', + controller : "samplePageController" + }); +}); diff --git a/vid/src/main/webapp/app/vid/scripts/controller/subscriberSearch.js b/vid/src/main/webapp/app/vid/scripts/controller/subscriberSearch.js new file mode 100644 index 000000000..110c07ad1 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/controller/subscriberSearch.js @@ -0,0 +1,385 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +app.requires.push('ngRoute'); +app.requires.push('ui.tree'); + +app.config(function($routeProvider) { + $routeProvider + .when("/subviewedit", { + templateUrl : "app/vid/scripts/view-models/aaiSubViewEdit.htm", + controller : "aaiSubscriberSearchController" + + }) + .when("/subdetails", { + templateUrl : "app/vid/scripts/view-models/aaiSubDetails.htm", + controller : "aaiSubscriberController" + + }) + .otherwise({ + templateUrl : "app/vid/scripts/view-models/aaiGetSubs.htm", + controller : "aaiSubscriberSearchController" + }); +}); + +app.config(function(treeConfig) { + treeConfig.defaultCollapsed = true; // collapse nodes by default + }); + +app.factory("user",function(){ + return {}; +}); + +app.controller("aaiSubscriberSearchController", [ "$scope", "$timeout", "$log", "UtilityService", "user", "PropertyService", + function($scope, $timeout, $log, UtilityService, user, PropertyService) { + + $scope.baseUrl = ""; + $scope.responseTimeoutMsec = 10000; + $scope.msoMaxPollingIntervalMsec = 1000; + $scope.msoMaxPolls = 7; + + $scope.init = function(properties) { + // takes a default value, retrieves the prop value from the file system and sets it + var msecs = PropertyService.retrieveMsoMaxPollingIntervalMsec(1000); + PropertyService.setMsoMaxPollingIntervalMsec(msecs); + + // takes a default value, retrieves the prop value from the file system and sets it + var polls = PropertyService.retrieveMsoMaxPolls(7); + PropertyService.setMsoMaxPolls(polls); + + PropertyService.setServerResponseTimeoutMsec(10000); + + // These two properties only added for testing + properties.msoDefaultBaseUrl = $scope.baseUrl; + properties.responseTimeoutMsec = $scope.responseTimeoutMsec; + + UtilityService.setProperties(properties); + } + + $scope.autoGetSubs = function() { + /* + * Optionally comment in / out one of these method calls (or add a similar + * entry) to auto-invoke an entry when the test screen is redrawn. + */ + $timeout(function() { + $scope.getSubscribers(); + // $scope.deleteServiceInstance(); + // $scope.generateInvalidUrl405(); + }, 100); + } + + $scope.autoGetSubDetails = function() { + /* + * Optionally comment in / out one of these method calls (or add a similar + * entry) to auto-invoke an entry when the test screen is redrawn. + */ + $timeout(function() { + $scope.getSubDetails(); + // $scope.deleteServiceInstance(); + // $scope.generateInvalidUrl405(); + }, 100); + } + + $scope.autoPopulateViewEdit = function() { + /* + * Optionally comment in / out one of these method calls (or add a similar + * entry) to auto-invoke an entry when the test screen is redrawn. + */ + $timeout(function() { + $scope.getComponentList(); + // $scope.deleteServiceInstance(); + // $scope.generateInvalidUrl405(); + }, 100); + } + + $scope.refreshSubs = function() { + /* + * Optionally comment in / out one of these method calls (or add a similar + * entry) to auto-invoke an entry when the test screen is redrawn. + */ + $timeout(function() { + $scope.refreshSubscribers(); + // $scope.deleteServiceInstance(); + // $scope.generateInvalidUrl405(); + }, 100); + } + + $scope.autoStartQueryTest = function() { + /* + * Optionally comment in / out one of these method calls (or add a similar + * entry) to auto-invoke an entry when the test screen is redrawn. + */ + $timeout(function() { + // $scope.queryServiceInstance(); + }, 100); + } + + $scope.queryServiceInstance = function() { + /* + * Example of method call needed to query a service instance. + */ + $scope.$broadcast("queryServiceInstance", { + serviceInstanceId: "bc305d54-75b4-431b-adb2-eb6b9e546014" + }); + } + + $scope.getSubscribers = function() { + /* + * Example of method call needed to commit an instance creation request. + */ + $scope.$broadcast("getSubs", { + url : "aai_get_subscribers", + requestDetails : createServiceRequestDetails + }); + } + + $scope.getSubDetails = function() { + /* + * Example of method call needed to commit an instance creation request. + */ + $scope.$broadcast("getSubDetails", { + url : "aai_sub_details", + requestDetails : createServiceRequestDetails + }); + } + + $scope.getComponentList = function() { + /* + * Example of method call needed to commit an instance creation request. + */ + $scope.$broadcast("getComponentList", { + url : "aai_sub_viewedit", + requestDetails : createServiceRequestDetails + }); + } + + + $scope.refreshSubscribers = function() { + /* + * Example of method call needed to commit an instance creation request. + */ + $scope.$broadcast("getSubs", { + url : "aai_refresh_subscribers", + requestDetails : createServiceRequestDetails + }); + } + + $scope.deleteServiceInstance = function() { + /* + * Example of method call needed to commit an instance deletion request. + */ + $scope.$broadcast("deleteInstance", { + url : "mso_delete_svc_instance/bc305d54-75b4-431b-adb2-eb6b9e546014", + requestDetails : deleteServiceRequestDetails + }); + } + + $scope.createNetworkInstance = function() { + $scope.$broadcast("createInstance", { + url : "mso_create_nw_instance", + requestDetails : createNetworkRequestDetails + }); + } + + $scope.deleteNetworkInstance = function() { + $scope.$broadcast("deleteInstance", { + url : "mso_delete_nw_instance/bc305d54-75b4-431b-adb2-eb6b9e546014/networks/ff305d54-75b4-ff1b-fff1-eb6b9e5460ff", + requestDetails : deleteNetworkRequestDetails + }); + } + + $scope.generateError = function(testName) { + // Clone example request object + var request = JSON.parse(JSON.stringify(createServiceRequestDetails)); + request.modelInfo.modelName = testName; + $scope.$broadcast("createInstance", { + url : "mso_create_svc_instance", + requestDetails : request + }); + } + + $scope.generateInvalidUrl404 = function() { + var properties = UtilityService.getProperties(properties); + properties.msoDefaultBaseUrl = "/INVALID_STRING/"; + UtilityService.setProperties(properties); + $scope.$broadcast("refreshProperties"); + + $scope.$broadcast("createInstance", { + url : "mso_create_svc_instance", + requestDetails : createServiceRequestDetails + }); + + properties.msoDefaultBaseUrl = $scope.baseUrl; + UtilityService.setProperties(properties); + $scope.$broadcast("refreshProperties"); + } + + $scope.generateInvalidUrl405 = function() { + $scope.$broadcast("createInstance", { + url : "INVALID_STRING_mso_create_svc_instance", + requestDetails : createServiceRequestDetails + }); + } + + /* + * Test data objects: + */ + + var subscriberInfo = { + globalSubscriberId : "C12345", + subscriberName : "General Electric Division 12" + }; + + var createServiceRequestDetails = { + modelInfo : { + modelType : "service", + modelId : "sn5256d1-5a33-55df-13ab-12abad84e764", + modelNameVersionId : "ab6478e4-ea33-3346-ac12-ab121484a333", + modelName : "WanBonding", + modelVersion : "1" + }, + subscriberInfo : subscriberInfo, + requestParameters : { + vpnId : "1a2b3c4d5e6f", + productName : "Trinity", + customerId : "icore9883749" + } + }; + + var deleteServiceRequestDetails = { + modelInfo : { + modelType : "service", + modelId : "sn5256d1-5a33-55df-13ab-12abad84e764", + modelNameVersionId : "ab6478e4-ea33-3346-ac12-ab121484a333", + modelName : "WanBonding", + modelVersion : "1" + } + }; + + var createNetworkRequestDetails = { + modelInfo : { + modelType : "network", + modelId : "ff5256d1-5a33-55df-aaaa-12abad84e7ff", + modelNameVersionId : "fe6478e4-ea33-3346-aaaa-ab121484a3fe", + modelName : "vIsbcOamNetwork", + modelVersion : "1" + }, + relatedModelList : [ + { + relatedModel : { + instanceId : "ff305d54-75b4-431b-adb2-eb6b9e5ff000", + modelInfo : { + modelType : "service", + modelId : "ff3514e3-5a33-55df-13ab-12abad84e7ff", + modelNameVersionId : "fe6985cd-ea33-3346-ac12-ab121484a3fe", + modelName : "Intercarrier Interconnect Session Border Controller", + modelVersion : "1" + } + } + }, + { + relatedModel : { + instanceId : "ff305d54-75b4-ff1b-adb2-eb6b9e5460ff", + modelInfo : { + modelType : "vnf", + modelId : "ff5256d1-5a33-55df-13ab-12abad84e7ff", + modelNameVersionId : "fe6478e4-ea33-3346-ac12-ab121484a3fe", + modelName : "vIsbc", + modelVersion : "1" + } + } + }, + { + relatedModel : { + instanceId : "ff305d54-75b4-ff1b-bdb2-eb6b9e5460ff", + modelInfo : { + modelType : "vfModule", + modelId : "ff5256d1-5a33-55df-13ab-22abad84e7ff", + modelNameVersionId : "fe6478e4-ea33-3346-bc12-ab121484a3fe", + modelName : "vIsbcRtpExpansionModule", + modelVersion : "1" + } + } + } ], + subscriberInfo : subscriberInfo, + requestParameters : { + /* + * FYI: quotes around field names are needed due to embedded "-" + * characters + */ + "cidr-mask" : "255.255.255.000", + "gateway-address" : "10.10.125.1", + "dhcp-enabled" : "true" + } + }; + + var deleteNetworkRequestDetails = { + modelInfo : { + modelType : "network", + modelId : "ff5256d1-5a33-55df-aaaa-12abad84e7ff", + modelNameVersionId : "fe6478e4-ea33-3346-aaaa-ab121484a3fe", + modelName : "vIsbcOamNetwork", + modelVersion : "1" + }, + relatedModelList : [ + { + relatedModel : { + instanceId : "ff305d54-75b4-431b-adb2-eb6b9e5ff000", + modelInfo : { + modelType : "service", + modelId : "ff3514e3-5a33-55df-13ab-12abad84e7ff", + modelNameVersionId : "fe6985cd-ea33-3346-ac12-ab121484a3fe", + modelName : "Intercarrier Interconnect Session Border Controller", + modelVersion : "1" + } + } + }, + { + relatedModel : { + instanceId : "ff305d54-75b4-ff1b-adb2-eb6b9e5460ff", + modelInfo : { + modelType : "vnf", + modelId : "ff5256d1-5a33-55df-13ab-12abad84e7ff", + modelNameVersionId : "fe6478e4-ea33-3346-ac12-ab121484a3fe", + modelName : "vIsbc", + modelVersion : "1" + } + } + }, + { + relatedModel : { + instanceId : "ff305d54-75b4-ff1b-bdb2-eb6b9e5460ff", + modelInfo : { + modelType : "vfModule", + modelId : "ff5256d1-5a33-55df-13ab-22abad84e7ff", + modelNameVersionId : "fe6478e4-ea33-3346-bc12-ab121484a3fe", + modelName : "vIsbcRtpExpansionModule", + modelVersion : "1" + } + } + } ] + }; + $scope.getSubscriberDet = function(selectedCustomer){ + window.location.href = '#subdetails?selectedSubscriber=' + selectedCustomer; + }; + } +]); diff --git a/vid/src/main/webapp/app/vid/scripts/directives/dummy.txt b/vid/src/main/webapp/app/vid/scripts/directives/dummy.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/directives/dummy.txt diff --git a/vid/src/main/webapp/app/vid/scripts/directives/extensionsDirective.js b/vid/src/main/webapp/app/vid/scripts/directives/extensionsDirective.js new file mode 100644 index 000000000..1309a0f62 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/directives/extensionsDirective.js @@ -0,0 +1,79 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +/* + * Defines "extensions" to standard Angular directives. Provides attributes that + * can be included in HTML tags. + * + * SYNTAX: ngx-enabled="true | false" + * + * Enables / disables an element. Currently only supports button elements that + * include the "att-button" element. This extension was added since the similar + * standard Angular "ng-disabled" attribute does not handle buttons that use the + * ECOMP styling. + * + * SYNTAX: ngx-visible="true | false" + * + * Sets an element to visible / hidden. Different from ng-show / ng-hide as + * follows: + * + * ng-show=false or ng-hide=true - Element is completely hidden. + * + * ngx-visible=false - Element is not displayed. However, a blank area is + * displayed where the element would display if ngx-visible is set to true. + */ + +app.directive('ngxEnabled', function() { + return { + restrict : "A", + link : function(scope, element, attrs) { + attrs.$observe("ngxEnabled", function(value) { + if (attrs.attButton === "") { + if (value === "true") { + element.attr("btn-type", "primary").removeClass( + "button--inactive").addClass("button--primary") + .prop('disabled', false); + } else { + element.attr("btn-type", "disabled").removeClass( + "button--primary").addClass("button--inactive") + .prop('disabled', true); + } + } + }); + } + } +}); + +app.directive('ngxVisible', function() { + return { + restrict : "A", + link : function(scope, element, attrs) { + attrs.$observe("ngxVisible", function(value) { + if (value === "true") { + element.css("visibility", "visible"); + } else { + element.css("visibility", "hidden"); + } + }); + } + } +}); diff --git a/vid/src/main/webapp/app/vid/scripts/directives/parameterBlockDirective.js b/vid/src/main/webapp/app/vid/scripts/directives/parameterBlockDirective.js new file mode 100644 index 000000000..16d2387c4 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/directives/parameterBlockDirective.js @@ -0,0 +1,309 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var parameterBlockDirective = function($log, PARAMETER, UtilityService) { + /* + * If "IS_SINGLE_OPTION_AUTO_SELECTED" is set to "true" ... + * + * IF these 3 conditions all exist: + * + * 1) The parameter type is PARAMETER.SELECT + * + * 2) AND the "prompt" attribute is set to a string. + * + * 3) AND the optionList" only contains a single entry + * + * THEN the "prompt" will not be displayed as an initial select option. + */ + + var IS_SINGLE_OPTION_AUTO_SELECTED = false; + + /* + * Optionally remove "nameStyle" and "valueStyle" "width" entries to set + * dynamic sizing. + */ + var tableStyle = "width: auto; margin: 0 auto; border-collapse: collapse; border: none;"; + var nameStyle = "width: 220px; text-align: left; vertical-align: middle; font-weight: bold; padding: 3px 5px; border: none;"; + var valueStyle = "width: 400px; text-align: left; vertical-align: middle; padding: 3px 5px; border: none;"; + var checkboxValueStyle = "width: 400px; text-align: center; vertical-align: middle; padding: 3px 5px; border: none;" + var textInputStyle = "height: 25px; padding: 2px 5px;"; + var checkboxInputStyle = "height: 18px; width: 18px; padding: 2px 5px;"; + var selectStyle = "height: 25px; padding: 2px; text-align: center;"; + var requiredLabelStyle = "width: 25px; padding: 5px 10px 10px 5px;"; + var textInputPrompt = "Enter data"; + + var getParameterHtml = function(parameter, editable) { + var style = valueStyle; + var attributeString = ""; + if (parameter.type === PARAMETER.BOOLEAN) { + style = checkboxValueStyle; + } + if (UtilityService.hasContents(parameter.description)) { + attributeString += " title=' " + parameter.description + " '"; + } + var html = "<tr><td style='" + nameStyle + "'" + attributeString + ">" + + getNameHtml(parameter) + "</td><td style='" + style + "'>"; + if (editable === undefined) { + if (UtilityService.hasContents(parameter.value)) { + html += parameter.value; + } + } else { + html += getValueHtml(parameter); + } + html += "</td></tr>"; + return html; + }; + + var updateParameter = function(parameter, element, editable) { + $(element).parent().parent().children("td").first().html( + getNameHtml(parameter)); + if (editable === undefined) { + $(element).html(parameter.value); + } else { + $(element).parent().html(getValueHtml(parameter)); + } + }; + + var getNameHtml = function(parameter) { + if (parameter.isVisible === false) { + return ""; + } + var name = ""; + if (UtilityService.hasContents(parameter.name)) { + name = parameter.name; + } else { + name = parameter.id; + } + var requiredLabel = ""; + if (parameter.isRequired) { + requiredLabel = "<img src='app/vid/images/asterisk.png' style='" + + requiredLabelStyle + "'></img>"; + } + return name + ":" + requiredLabel; + }; + + var getValueHtml = function(parameter) { + var attributeString = " parameter-id='" + parameter.id + "'"; + var additionalStyle = ""; + if (parameter.isEnabled === false) { + attributeString += " disabled='disabled'"; + } + if (parameter.isRequired) { + attributeString += " is-required='true'"; + } + if (UtilityService.hasContents(parameter.description)) { + attributeString += " title=' " + parameter.description + " '"; + } + if (parameter.isVisible === false) { + additionalStyle = "visibility: hidden;"; + } + var name = ""; + if (UtilityService.hasContents(parameter.name)) { + name = parameter.name; + } else { + name = parameter.id; + } + attributeString += " parameter-name='" + name + "'"; + + switch (parameter.type) { + case PARAMETER.BOOLEAN: + if (parameter.value) { + attributeString += " checked='checked'"; + } + return "<input type='checkbox'" + attributeString + " style='" + + checkboxInputStyle + additionalStyle + "'></input>"; + break; + case PARAMETER.SELECT: + if (UtilityService.hasContents(parameter.prompt)) { + attributeString += " prompt='" + parameter.prompt + "'"; + } + return "<select" + attributeString + " style='" + selectStyle + + additionalStyle + "'>" + getOptionListHtml(parameter) + + "</select>"; + break; + case PARAMETER.STRING: + default: + var value = ""; + if (UtilityService.hasContents(parameter.value)) { + value = " value='" + parameter.value + "'"; + } + if (UtilityService.hasContents(parameter.prompt)) { + attributeString += " placeholder='" + parameter.prompt + "'"; + } else if (textInputPrompt !== "") { + attributeString += " placeholder='" + textInputPrompt + "'"; + } + return "<input type='text'" + attributeString + " style='" + + textInputStyle + additionalStyle + "'" + value + + "></input>"; + } + }; + + var getOptionListHtml = function(parameter) { + + var html = ""; + + if (!angular.isArray(parameter.optionList) + || parameter.optionList.length === 0) { + return ""; + } + + if (UtilityService.hasContents(parameter.prompt)) { + if (!(IS_SINGLE_OPTION_AUTO_SELECTED && parameter.optionList.length === 1)) { + html += "<option value=''>" + parameter.prompt + "</option>"; + } + } + + for (var i = 0; i < parameter.optionList.length; i++) { + var option = parameter.optionList[i]; + var name = option.name; + var value = ""; + if (option.id === undefined) { + value = option.name; + } else { + if (name === undefined) { + name = option.id; + } + value = option.id; + } + html += "<option value='" + value + "'>" + name + "</option>"; + } + return html; + }; + + var getParameter = function(element, expectedId) { + var id = $(element).attr("parameter-id"); + if (expectedId !== undefined && expectedId !== id) { + return undefined; + } + var parameter = { + id : id + }; + if ($(element).prop("type") === "checkbox") { + parameter.value = $(element).prop("checked"); + } else { + if ($(element).prop("type") === "text") { + $(element).val($(element).val().trim()); + } + parameter.value = $(element).val(); + } + if ($(element).prop("selectedIndex") === undefined) { + parameter.selectedIndex = -1; + } else { + parameter.selectedIndex = $(element).prop("selectedIndex"); + if (UtilityService.hasContents($(element).attr("prompt"))) { + parameter.selectedIndex--; + } + } + return parameter; + }; + + var getRequiredField = function(element) { + if ($(element).prop("type") === "text") { + $(element).val($(element).val().trim()); + } + if ($(element).val() === "" || $(element).val() === null) { + return '"' + $(element).attr("parameter-name") + '"'; + } else { + return ""; + } + }; + + var callback = function(element, scope) { + scope.callback({ + id : $(element).attr("parameter-id") + }); + }; + + return { + restrict : "EA", + replace : true, + template : "<div><table style='" + tableStyle + "'></table></div>", + scope : { + control : "=", + callback : "&" + }, + link : function(scope, element, attrs) { + + var control = scope.control || {}; + + control.setList = function(parameterList) { + var html = ""; + for (var i = 0; i < parameterList.length; i++) { + html += getParameterHtml(parameterList[i], attrs.editable); + } + element.html(html); + element.find("input, select").bind("change", function() { + callback(this, scope); + }); + } + + control.updateList = function(parameterList) { + element.find("input, select").each( + function() { + for (var i = 0; i < parameterList.length; i++) { + if (parameterList[i].id === $(this).attr( + "parameter-id")) { + updateParameter(parameterList[i], this, + attrs.editable); + } + } + }); + } + + control.getList = function(expectedId) { + var parameterList = new Array(); + element.find("input, select").each(function() { + var parameter = getParameter(this, expectedId); + if (parameter !== undefined) { + parameterList.push(parameter); + } + }); + return parameterList; + } + + control.getRequiredFields = function() { + var requiredFields = ""; + var count = 0; + element.find("input, select").each(function() { + if ($(this).attr("is-required") === "true") { + var requiredField = getRequiredField(this); + if (requiredField !== "") { + if (++count == 1) { + requiredFields = requiredField; + } + } + } + }); + if (--count <= 0) { + return requiredFields; + } else if (count == 1) { + return requiredFields + " and 1 other field"; + } else { + return requiredFields + " and " + count + " other fields"; + } + } + } + } +} + +app.directive('parameterBlock', [ "$log", "PARAMETER", "UtilityService", + parameterBlockDirective ]); diff --git a/vid/src/main/webapp/app/vid/scripts/directives/popupWindowDirective.js b/vid/src/main/webapp/app/vid/scripts/directives/popupWindowDirective.js new file mode 100644 index 000000000..a52d5862a --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/directives/popupWindowDirective.js @@ -0,0 +1,88 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var popupWindowDirective = function($log, $window) { + + function getZIndex(element) { + var maxZIndex = 0; + $(window.document).find("*").each(function() { + var zIndex = parseInt($(this).css("z-index")); + if (zIndex > maxZIndex) { + maxZIndex = zIndex; + } + }); + + return maxZIndex; + } + + var scrollPosition = { + x : 0, + y : 0 + }; + + var link = function(scope, element, attrs, controller, transcludeFn) { + + var zIndex = getZIndex(element.parent()) + 1; + + element.css("z-index", zIndex + 1); + + var backgroundStyle = "display: none; position: fixed; z-index:" + + zIndex + ";" + "top: 0; left: 0; width: 100%; height: 100%;" + + "background-color: #000000; opacity: 0.5"; + + var className = attrs["class"]; + var classString = ""; + if (className !== undefined && className !== null && className !== "") { + element.children().children().children().children().addClass( + className); + element.removeClass(className); + } + + element.before("<div style='" + backgroundStyle + "'></div>"); + + attrs.$observe("ngxShow", function(value) { + if (value === "true") { + scrollPosition = { + x : $window.pageXOffset, + y : $window.pageYOffset + } + $window.scrollTo(0, 0); + element.css("display", "table"); + element.prev().css("display", "block"); + } else if (value === "false") { + element.css("display", "none"); + element.prev().css("display", "none"); + $window.scrollTo(scrollPosition.x, scrollPosition.y); + } + }); + } + + return { + restrict : "EA", + transclude : true, + replace : true, + link : link, + templateUrl : "app/vid/scripts/view-models/popupWindow.htm" + }; +} + +app.directive("popupWindow", [ "$log", "$window", popupWindowDirective ]); diff --git a/vid/src/main/webapp/app/vid/scripts/directives/progressBarDirective.js b/vid/src/main/webapp/app/vid/scripts/directives/progressBarDirective.js new file mode 100644 index 000000000..5ffada8a3 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/directives/progressBarDirective.js @@ -0,0 +1,173 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +/* + * "progressBarDirective.js" provides a progress bar directive. + * + * SYNTAX: + * + * <div progress-bar value="percentProgress"></div> + * + * "percentProgress" is the numeric percent progress to be displayed (0 to 100) + * expressed as a number only (i.e. no trailing "%"). An "scoped" Angular value + * can be used (e.g. "{{percentProgress}}"). + * + * Two additional attributes can also be included: + * + * increases-only="true | false" + * + * Normally, the progress bar always updates the display with whatever value is + * set. Alternatively, if "increases-only" is set to "true", the display will + * only be updated if "percentProgress" is >= the previous value. + * + * control="control" + * + * Provides a method ... $scope.control.reset()" ... that a controller can call + * to reset the progress to it's initial zero state. This would only expected to + * be needed if A) increases-only is set to true and B) there is a need to reset + * the controller to 0. If increases-only is set to false or not present, an + * alternative method of resetting the progress is to just tset percentProgress + * to 0. + * + * CAVEATS: + * + * 1) The extended attribute "ngx-show" should be used instead of "ng-show" if + * the control needs to be conditionally visible. Example: + * ngx-show="{{isProgressVisible}}" + * + * 2) $scope.control.reset() should be conditionally called as follows IF it is + * called immediately after HTML is rendered. This is due to a timing-related + * behavior. + * + * 3) The progress bar displays values of "0" and "100" if precentProgress is, + * respectively, less than 0 or greater than 100. + * + * CUSTOM STYLING: + * + * The ECOMP portal styling uses the class named "progress". The class + * attributes can be overridden in CSS. This example was tested: + * + * .progress { margin: 0px 10px; height: 40px } + * + * Additional styling can be applied to the progress-bar element. Example: + * + * div[progress-bar=""] { padding-top: 10px; } + * + * if (angular.isFunction($scope.control.reset)) { $scope.control.reset(); } + * + * DEPENDENCIES: + * + * This code assumes dependency files provided by the ECOMP Portal framework are + * included. For example, ".../app/fusion/external/ebz/sandbox/styles/base.css" + * is one required dependency. There may also be others. + */ + +var progressBarDirective = function() { + + var style = "font-weight: bold;"; + /* + * The 3 "aria-*" properties were added as per an Internet reference + * example. These appear to have no impact on current behavior but are + * retained for future reference. + */ + var properties = "class='progress-bar' role='progressbar' " + + "aria-valuenow='' aria-valuemin='0' aria-valuemax='100'"; + var previousValue = 0; + + var updateProgress = function(element, attrs, valueAsString) { + if (valueAsString === undefined || valueAsString === null + || valueAsString === "") { + valueAsString = "0"; + } + var valueAsInteger = parseInt(valueAsString); + if (valueAsInteger > 100) { + valueAsInteger = 100; + valueAsString = "100"; + } + if (attrs.increasesOnly === "true") { + if (valueAsInteger >= previousValue) { + previousValue = valueAsInteger; + } else { + return; + } + } + element.css("width", valueAsString + "%"); + if (valueAsInteger >= 100) { + element.removeClass("progress-bar-info").addClass( + "progress-bar-success"); + } else { + element.removeClass("progress-bar-success").addClass( + "progress-bar-info"); + } + if (valueAsInteger >= 5) { + element.html(valueAsString + " %"); + } else { + /* + * Hide text since color combination is barely visible when progress + * portion is narrow. + */ + element.html(""); + } + } + + return { + restrict : "EA", + transclude : true, + replace : true, + template : "<div ng-transclude " + properties + " style='" + style + + "'></div>", + scope : { + control : "=", + progressBar : "@" + }, + link : function(scope, element, attrs) { + + /* + * It should be possible to alternatively add this wrapper in the + * template instead of using "element.wrap". Some techniques were + * attempted but were unsuccessful. + */ + element.wrap("<div class='progress'></div"); + + var control = scope.control || {}; + + control.reset = function() { + previousValue = 0; + updateProgress(element, attrs, 0); + } + + attrs.$observe("value", function(valueString) { + updateProgress(element, attrs, valueString); + }); + + attrs.$observe("ngxShow", function(valueString) { + if (valueString === "false") { + element.parent().hide(); + } else { + element.parent().show(); + } + }); + } + } +} + +app.directive("progressBar", progressBarDirective); diff --git a/vid/src/main/webapp/app/vid/scripts/services/aaiService.js b/vid/src/main/webapp/app/vid/scripts/services/aaiService.js new file mode 100644 index 000000000..063f7a988 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/services/aaiService.js @@ -0,0 +1,111 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var AaiService = function($http, $log, PropertyService, UtilityService) { + return { + getSubscriptionServiceTypeList : function(globalCustomerId, + successCallbackFunction) { + $log + .debug("AaiService:getSubscriptionServiceTypeList: globalCustomerId: " + + globalCustomerId); + $http.get( + PropertyService.getAaiBaseUrl() + + "/aai_sub_details/" + + globalCustomerId + "?r=" + Math.random(), + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(function(response) { + if (response.data && response.data["service-subscriptions"]) { + var serviceTypes = []; + var serviceSubscriptions = response.data["service-subscriptions"]["service-subscription"]; + + for (var i = 0; i < serviceSubscriptions.length; i++) { + serviceTypes.push(serviceSubscriptions[i]["service-type"]); + } + + successCallbackFunction(serviceTypes); + } else { + successCallbackFunction([]); + } + })["catch"] + (UtilityService.runHttpErrorHandler); + }, + getLcpCloudRegionTenantList : function(globalCustomerId, serviceType, + successCallbackFunction) { + $log + .debug("AaiService:getLcpCloudRegionTenantList: globalCustomerId: " + + globalCustomerId); + var url = PropertyService.getAaiBaseUrl() + + "/aai_get_tenants/" + + globalCustomerId + "/" + serviceType + "?r=" + Math.random(); + + $http.get(url, + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(function(response) { + var lcpCloudRegionTenants = []; + var aaiLcpCloudRegionTenants = response.data; + + lcpCloudRegionTenants.push({ + "cloudRegionId": "", + "tenantName": "Please choose a region", + "tenantId": "" + }); + + for (var i = 0; i < aaiLcpCloudRegionTenants.length; i++) { + lcpCloudRegionTenants.push({ + "cloudRegionId": aaiLcpCloudRegionTenants[i]["cloudRegionID"], + "tenantName": aaiLcpCloudRegionTenants[i]["tenantName"], + "tenantId": aaiLcpCloudRegionTenants[i]["tenantID"] + }); + } + + successCallbackFunction(lcpCloudRegionTenants); + })["catch"] + (UtilityService.runHttpErrorHandler); + }, + getSubscribers : function(successCallbackFunction) { + $log + .debug("AaiService:getSubscribers"); + var url = PropertyService.getAaiBaseUrl() + + "/aai_get_subscribers?r=" + Math.random(); + + $http.get(url, + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(function(response) { + if (response.data) { + successCallbackFunction(response.data.customer); + } else { + successCallbackFunction([]); + } + })["catch"] + (UtilityService.runHttpErrorHandler); + } + } +} + +app.factory("AaiService", [ "$http", "$log", "PropertyService", + "UtilityService", AaiService ]); diff --git a/vid/src/main/webapp/app/vid/scripts/services/asdcService.js b/vid/src/main/webapp/app/vid/scripts/services/asdcService.js new file mode 100644 index 000000000..532b8f508 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/services/asdcService.js @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var AsdcService = function($http, $log, PropertyService, UtilityService) { + return { + getModel : function(modelId, successCallbackFunction) { + $log.debug("SdcService:getModel: modelId: " + modelId); + $http.get( + PropertyService.getAsdcBaseUrl() + "/getModel/" + modelId + + "?r=" + Math.random(), + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(successCallbackFunction)["catch"] + (UtilityService.runHttpErrorHandler); + } + } +} + +app.factory("AsdcService", [ "$http", "$log", "PropertyService", + "UtilityService", AsdcService ]); diff --git a/vid/src/main/webapp/app/vid/scripts/services/componentService.js b/vid/src/main/webapp/app/vid/scripts/services/componentService.js new file mode 100644 index 000000000..7c1cfcb9c --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/services/componentService.js @@ -0,0 +1,148 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var ComponentService = function($log, COMPONENT, UtilityService) { + + var _this = this; + + var componentList = [ { + id : COMPONENT.NETWORK, + displayName : "Network" + }, { + id : COMPONENT.SERVICE, + displayName : "Service Instance" + }, { + id : COMPONENT.VNF, + displayName : "Virtual Network Function" + }, { + id : COMPONENT.VF_MODULE, + displayName : "VF Module" + }, { + id : COMPONENT.VOLUME_GROUP, + displayName : "Volume Group" + } ]; + + var getInventoryInfo = function(suffix, inventoryItem) { + var pattern = new RegExp(suffix + "-"); + for ( var key in inventoryItem) { + if (pattern.exec(key)) { + return inventoryItem[key]; + } + } + }; + + /* + * Converts 'id' to a user friendly version. + * + * The algorithm used is: + * + * 1) If "id" found in COMPONENT.FULL_NAME_MAP, return the name found in the + * map. + * + * 2) Otherwise, if camel case, add "-" between camel case words. + * + * 3) Split id into multiple "partial names" assuming "-" is the delimiter. + * + * 4) Map any partial names found in COMPONENT.PARTIAL_NAME_MAP to the name + * found in the map. + * + * 5) Use partial names whenever not found in map. + * + * 5) Return name by combining all partial names with " " delimiter. + */ + var getDisplayName = function(id) { + var tmp = COMPONENT.FULL_NAME_MAP[id.toLowerCase()]; + if (UtilityService.hasContents(tmp)) { + return tmp; + } + /* + * Add "-" if camel case found. + */ + var id = id.replace(/([a-z](?=[A-Z]))/g, '$1-'); + var name = ""; + var arg = id.split("-"); + for (var i = 0; i < arg.length; i++) { + if (i > 0) { + name += " "; + } + var tmp = COMPONENT.PARTIAL_NAME_MAP[arg[i].toLowerCase()]; + if (UtilityService.hasContents(tmp)) { + name += tmp; + } else { + name += arg[i].slice(0, 1).toUpperCase() + arg[i].slice(1); + } + } + return name; + }; + + return { + initialize : function(componentId) { + for (var i = 0; i < componentList.length; i++) { + if (componentList[i].id === componentId) { + _this.componentId = componentList[i].id; + return componentId; + } + } + throw "ComponentService:initializeComponent: componentId not found: " + + componentId; + }, + getComponentDisplayName : function() { + for (var i = 0; i < componentList.length; i++) { + if (componentList[i].id === _this.componentId) { + return componentList[i].displayName; + } + } + }, + getInventoryInfo : getInventoryInfo, + getInventoryParameterList : function(suffix, inventoryItem) { + var parameterList = new Array(); + // var pattern = new RegExp("-[intv][a-z]*$"); + // var inventoryInfo = getInventoryInfo(suffix, inventoryItem); + for ( var id in inventoryItem) { + //if (pattern.exec(id)) { + parameterList.push({ + id : id, + value : inventoryItem[id] + }); + //} + } + return parameterList; + }, + getDisplayNames : function(inputList) { + var outputList = new Array(); + for (var i = 0; i < inputList.length; i++) { + var entry = angular.copy(inputList[i]); + if (!UtilityService.hasContents(entry.name)) { + entry.name = getDisplayName(entry.id); + } + outputList.push(entry); + } + return outputList; + }, + getFieldDisplayName : function(name) { + return getDisplayName(name); + } + } +} + +app.factory("ComponentService", [ "$log", "COMPONENT", "UtilityService", + ComponentService ]); diff --git a/vid/src/main/webapp/app/vid/scripts/services/creationService.js b/vid/src/main/webapp/app/vid/scripts/services/creationService.js new file mode 100644 index 000000000..fda27eac3 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/services/creationService.js @@ -0,0 +1,683 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +/* + * "CreationService" isolates the "component-specific" logic required by the + * "CreationDialog" controller. + * + * "Components" are defined as the 5 element types managed by the dialogs: A) + * Service B) VNF C) VF Module D) Volume Group and E) Network. + * + */ + +var CreationService = function($log, AaiService, AsdcService, DataService, + ComponentService, COMPONENT, FIELD, PARAMETER, UtilityService) { + + var _this = this; + + var getAsyncOperationList = function() { + switch (_this.componentId) { + case COMPONENT.SERVICE: + return [ getSubscribers ]; + case COMPONENT.NETWORK: + return []; + case COMPONENT.VNF: + return [ getLcpCloudRegionTenantList ]; + case COMPONENT.VF_MODULE: + return [ getLcpCloudRegionTenantList ]; + case COMPONENT.VOLUME_GROUP: + return [ getLcpCloudRegionTenantList ]; + } + }; + + /* + * "getSummaryList" and "getUserProvidedList" return parameters that should + * be displayed in the summary and user provided sections, respectively. The + * functions are expected to return lists that are in the format needed by + * the parameter-block directive. + */ + + var getSummaryList = function() { + + /* + * These placeholders should be removed and their usage in + * "getSummaryList" should be replaced by appropriate code as the + * requirements and interfaces firm up. + */ + + var PLACEHOLDER_RESOURCE_DESCRIPTION = "Resource Description (PLACEHOLDER)"; + var PLACEHOLDER_SERVICE_CATEGORY = "Service Category (PLACEHOLDER)"; + var PLACEHOLDER_VF_MODULE_DESCRIPTION = "VF Module Description (PLACEHOLDER)"; + var PLACEHOLDER_VF_MODULE_LABEL = "VF Module Label (PLACEHOLDER)"; + var PLACEHOLDER_VF_MODULE_TYPE = "VF Module Type (PLACEHOLDER)"; + + _this.parameterList = new Array(); + + /* + * Common fields displayed at the top of all create instance screens. + */ + addToList(FIELD.NAME.SERVICE_NAME, DataService.getServiceName()); + + switch (_this.componentId) { + case COMPONENT.SERVICE: + addToList(FIELD.NAME.SERVICE_INVARIANT_UUID, DataService + .getModelInfo(_this.componentId)["modelInvariantId"]); + addToList(FIELD.NAME.SERVICE_VERSION, DataService + .getModelInfo(_this.componentId)["modelVersion"]); + addToList(FIELD.NAME.SERVICE_UUID, DataService + .getModelInfo(_this.componentId)["modelNameVersionId"]); + addToList(FIELD.NAME.SERVICE_DESCRIPTION, DataService + .getModelInfo(_this.componentId)["description"]); + addToList(FIELD.NAME.SERVICE_CATEGORY, DataService + .getModelInfo(_this.componentId)["category"]); + break; + case COMPONENT.VF_MODULE: + addToList(FIELD.NAME.SUBSCRIBER_NAME, DataService + .getSubscriberName()); + addToList(FIELD.NAME.SERVICE_INSTANCE_NAME, DataService + .getServiceInstanceName()); + addToList(FIELD.NAME.MODEL_NAME, DataService + .getModelInfo(_this.componentId)["modelName"]); + addToList(FIELD.NAME.MODEL_INVARIANT_UUID, DataService + .getModelInfo(_this.componentId)["modelInvariantId"]); + addToList(FIELD.NAME.MODEL_VERSION, DataService + .getModelInfo(_this.componentId)["modelVersion"]); + addToList(FIELD.NAME.MODEL_UUID, DataService + .getModelInfo(_this.componentId)["modelNameVersionId"]); + break; + case COMPONENT.NETWORK: + case COMPONENT.VNF: + case COMPONENT.VOLUME_GROUP: + addToList(FIELD.NAME.SUBSCRIBER_NAME, DataService + .getSubscriberName()); + addToList(FIELD.NAME.SERVICE_INSTANCE_NAME, DataService + .getServiceInstanceName()); + addToList(FIELD.NAME.MODEL_NAME, DataService + .getModelInfo(_this.componentId)["modelName"]); + addToList(FIELD.NAME.MODEL_INVARIANT_UUID, DataService + .getModelInfo(_this.componentId)["modelInvariantId"]); + addToList(FIELD.NAME.MODEL_VERSION, DataService + .getModelInfo(_this.componentId)["modelVersion"]); + addToList(FIELD.NAME.MODEL_UUID, DataService + .getModelInfo(_this.componentId)["modelNameVersionId"]); + break; + } + + return _this.parameterList; + }; + + var getUserProvidedList = function() { + + var parameterList = [ FIELD.PARAMETER.INSTANCE_NAME ]; + + switch (_this.componentId) { + case COMPONENT.SERVICE: + parameterList = parameterList.concat([ getSubscribersParameter(), + FIELD.PARAMETER.SERVICE_TYPE_DISABLED ]); + break; + case COMPONENT.NETWORK: + case COMPONENT.VNF: + parameterList = parameterList.concat([ getServiceId(), + getLcpRegion(), FIELD.PARAMETER.LCP_REGION_TEXT_HIDDEN, + FIELD.PARAMETER.TENANT_DISABLED ]); + break; + case COMPONENT.VF_MODULE: + parameterList = parameterList.concat([ + getLcpRegion(), + FIELD.PARAMETER.LCP_REGION_TEXT_HIDDEN, + FIELD.PARAMETER.TENANT_DISABLED + ]); + + var availableVolumeGroupList = DataService.getAvailableVolumeGroupList(); + + if (availableVolumeGroupList && availableVolumeGroupList.length > 0) { + var availableVolumeGroupNames = ["None"]; + + for (var i = 0; i < availableVolumeGroupList.length; i++) { + availableVolumeGroupNames.push(availableVolumeGroupList[i].instance.name); + } + + parameterList.push(addOptionList( + FIELD.PARAMETER.AVAILABLE_VOLUME_GROUP, + availableVolumeGroupNames)); + } + break; + case COMPONENT.VOLUME_GROUP: + parameterList = parameterList.concat([ getLcpRegion(), + FIELD.PARAMETER.LCP_REGION_TEXT_HIDDEN, + FIELD.PARAMETER.TENANT_DISABLED ]); + } + + parameterList.push(FIELD.PARAMETER.SUPPRESS_ROLLBACK); + + addArbitraryParameters(parameterList); + + return parameterList; + }; + + var addArbitraryParameters = function(parameterList) { + var inputs = DataService.getModelInfo(_this.componentId).inputs; + if (inputs) { + for ( var key in inputs) { + parameterList.push({ + id : key, + /* + * "name" is the display name. The simplest option is to just + * display this value (e.g. "name: key"). An alternative used + * here is to use "getFieldDisplayName" to display a more "user + * friendly" value. See "componentService:getDisplayName" for + * mapping details. + */ + name : ComponentService.getFieldDisplayName(key), + value : inputs[key]["default"], + isRequired : true, + /* + * If the field needs to be considered required, the attribute + * "isRequired: true" can be added here. + */ + description : inputs[key]["description"] + }); + } + } + }; + + var addToList = function(name, value) { + _this.parameterList.push({ + name : name, + value : value + }); + }; + + /* + * The "*Mso*" functions return URL and request details that can be passed + * to the MSO controller. The request details defines the info passed as + * part of the POST body. + */ + + var getMsoUrl = function() { + switch (_this.componentId) { + case COMPONENT.NETWORK: + return "mso_create_nw_instance/" + + DataService.getServiceInstanceId(); + case COMPONENT.SERVICE: + return "mso_create_svc_instance"; + case COMPONENT.VNF: + return "mso_create_vnf_instance/" + + DataService.getServiceInstanceId(); + case COMPONENT.VF_MODULE: + return "mso_create_vfmodule_instance/" + + DataService.getServiceInstanceId() + "/vnfs/" + + DataService.getVnfInstanceId(); + case COMPONENT.VOLUME_GROUP: + return "mso_create_volumegroup_instance/" + + DataService.getServiceInstanceId() + "/vnfs/" + + DataService.getVnfInstanceId(); + } + }; + + var getMsoRequestDetails = function(parameterList) { + console.log("getMsoRequestDetails invoked"); + var modelInfo = DataService.getModelInfo(_this.componentId); + var requestDetails = { + requestInfo : { + instanceName : getValueFromList(FIELD.ID.INSTANCE_NAME, + parameterList), + source : "VID", + suppressRollback : getValueFromList(FIELD.ID.SUPPRESS_ROLLBACK, + parameterList), + }, + modelInfo : { + modelType : _this.componentId, + modelInvariantId : modelInfo.modelInvariantId, + modelNameVersionId : modelInfo.modelNameVersionId, + modelName : modelInfo.modelName, + modelVersion : modelInfo.modelVersion + }, + requestParameters : { + userParams : getArbitraryParameters(parameterList) + } + }; + + switch (_this.componentId) { + case COMPONENT.SERVICE: + requestDetails.subscriberInfo = { + globalSubscriberId : DataService.getGlobalCustomerId(), + subscriberName : DataService.getSubscriberName() + }; + requestDetails.requestParameters.subscriptionServiceType = getValueFromList( + FIELD.ID.SERVICE_TYPE, parameterList); + break; + case COMPONENT.NETWORK: + case COMPONENT.VNF: + console.log("getMsoRequestDetails COMPONENT.VNF"); + var lcpRegion = getValueFromList(FIELD.ID.LCP_REGION, parameterList); + if (lcpRegion === FIELD.KEY.LCP_REGION_TEXT) { + lcpRegion = getValueFromList(FIELD.ID.LCP_REGION_TEXT, + parameterList); + } + requestDetails.cloudConfiguration = { + lcpCloudRegionId : lcpRegion, + tenantId : getValueFromList(FIELD.ID.TENANT, parameterList) + }; + requestDetails.requestInfo.productFamilyId = getValueFromList( + FIELD.ID.PRODUCT_FAMILY, parameterList); + // override model info for VNF since it needs the customization name + var vnfModelInfo = { + modelType : _this.componentId, + modelInvariantId : modelInfo.modelInvariantId, + modelNameVersionId : modelInfo.modelNameVersionId, + modelName : modelInfo.modelName, + modelVersion : modelInfo.modelVersion, + modelCustomizationName : modelInfo.modelCustomizationName + }; + requestDetails.modelInfo = vnfModelInfo; + break; + case COMPONENT.VF_MODULE: + var lcpRegion = getValueFromList(FIELD.ID.LCP_REGION, parameterList); + if (lcpRegion === FIELD.KEY.LCP_REGION_TEXT) { + lcpRegion = getValueFromList(FIELD.ID.LCP_REGION_TEXT, + parameterList); + } + requestDetails.cloudConfiguration = { + lcpCloudRegionId : lcpRegion, + tenantId : getValueFromList(FIELD.ID.TENANT, parameterList) + }; + break; + case COMPONENT.VOLUME_GROUP: + var lcpRegion = getValueFromList(FIELD.ID.LCP_REGION, parameterList); + if (lcpRegion === FIELD.KEY.LCP_REGION_TEXT) { + lcpRegion = getValueFromList(FIELD.ID.LCP_REGION_TEXT, + parameterList); + } + requestDetails.cloudConfiguration = { + lcpCloudRegionId : lcpRegion, + tenantId : getValueFromList(FIELD.ID.TENANT, parameterList) + }; + + break; + } + + var relatedInstanceList = getRelatedInstanceList(parameterList); + + if (relatedInstanceList !== undefined) { + requestDetails.relatedInstanceList = relatedInstanceList; + } + + return requestDetails; + }; + + var getRelatedInstanceList = function(parameterList) { + var relatedInstanceList = new Array(); + switch (_this.componentId) { + case COMPONENT.SERVICE: + return undefined; + case COMPONENT.NETWORK: + case COMPONENT.VNF: + addRelatedInstance(relatedInstanceList, COMPONENT.SERVICE, + DataService.getServiceInstanceId()); + break; + case COMPONENT.VF_MODULE: + addRelatedInstance(relatedInstanceList, COMPONENT.SERVICE, + DataService.getServiceInstanceId()); + addRelatedInstance(relatedInstanceList, COMPONENT.VNF, DataService + .getVnfInstanceId()); + + var availableVolumeGroup = getValueFromList( + FIELD.ID.AVAILABLE_VOLUME_GROUP, parameterList); + + if (UtilityService.hasContents(availableVolumeGroup) && availableVolumeGroup !== "None") { + var availableVolumeGroups = DataService.getAvailableVolumeGroupList(); + + for (var i = 0; i < availableVolumeGroups.length; i++) { + if (availableVolumeGroups[i].instance.name == availableVolumeGroup) { + DataService.setModelInfo(COMPONENT.VOLUME_GROUP, DataService.getModelInfo(COMPONENT.VF_MODULE)); + DataService.setVolumeGroupInstanceId(availableVolumeGroups[i].instance.object["volume-group-id"]); + break; + } + } + + addRelatedInstance(relatedInstanceList, COMPONENT.VOLUME_GROUP, + DataService.getVolumeGroupInstanceId()); + } + break; + case COMPONENT.VOLUME_GROUP: + addRelatedInstance(relatedInstanceList, COMPONENT.SERVICE, + DataService.getServiceInstanceId()); + addRelatedInstance(relatedInstanceList, COMPONENT.VNF, DataService + .getVnfInstanceId()); + break; + } + + return relatedInstanceList; + }; + + var addRelatedInstance = function(relatedInstanceList, componentId, + instanceId) { + var modelInfo = DataService.getModelInfo(componentId); + var relatedInstance; + if (modelInfo !== undefined) { + if (componentId === COMPONENT.VNF) { + relatedInstance = { + "instanceId" : instanceId, + "modelInfo" : { + "modelType" : componentId, + "modelName" : modelInfo.modelName, + "modelInvariantId" : modelInfo.modelInvariantId, + "modelVersion" : modelInfo.modelVersion, + "modelNameVersionId" : modelInfo.modelNameVersionId, + "modelCustomizationName" : modelInfo.modelCustomizationName + } + }; + } else { + relatedInstance = { + "instanceId" : instanceId, + "modelInfo" : { + "modelType" : componentId, + "modelName" : modelInfo.modelName, + "modelInvariantId" : modelInfo.modelInvariantId, + "modelVersion" : modelInfo.modelVersion, + "modelNameVersionId" : modelInfo.modelNameVersionId + } + }; + } + relatedInstanceList.push({ + relatedInstance : relatedInstance + }); + } + }; + + /* + * var getArbitraryParameters = function(parameterList) { var + * arbitraryParameters = new Object(); for (var i = 0; i < + * parameterList.length; i++) { var parameter = parameterList[i]; switch + * (parameter.id) { case FIELD.ID.INSTANCE_NAME: case + * FIELD.ID.PRODUCT_FAMILY: case FIELD.ID.LCP_REGION: case + * FIELD.ID.LCP_REGION_TEXT: case FIELD.ID.SERVICE_TYPE: case + * FIELD.ID.TENANT: case FIELD.ID.SUPPRESS_ROLLBACK: break; default: + * arbitraryParameters[parameter.id] = parameter.value; } } return + * arbitraryParameters; } + */ + var getArbitraryParameters = function(parameterList) { + var arbitraryParameters = new Object(); + var arbitraryArray = new Array(); + for (var i = 0; i < parameterList.length; i++) { + var parameter = parameterList[i]; + switch (parameter.id) { + case FIELD.ID.AVAILABLE_VOLUME_GROUP: + break; + case FIELD.ID.INSTANCE_NAME: + break; + case FIELD.ID.PRODUCT_FAMILY: + break; + case FIELD.ID.LCP_REGION: + break; + case FIELD.ID.LCP_REGION_TEXT: + break; + case FIELD.ID.SERVICE_TYPE: + break; + case FIELD.ID.TENANT: + break; + case FIELD.ID.SUPPRESS_ROLLBACK: + break; + case FIELD.ID.SUBSCRIBER_NAME: + break; + default: + arbitraryParameters = { + name : parameter.id, + value : parameter.value + } + arbitraryArray.push(arbitraryParameters); + } + } + return (arbitraryArray); + } + + var getModel = function() { + AsdcService.getModel(DataService.getModelId(), function(response) { + DataService.setModelInfo(_this.componentId, { + modelInvariantId : response.data.invariantUUID, + modelNameVersionId : response.data.uuid, + modelName : response.data.name, + modelVersion : response.data.version, + inputs : response.data.inputs + }); + UtilityService.startNextAsyncOperation(); + }); + }; + + var getSubscriptionServiceTypeList = function() { + AaiService.getSubscriptionServiceTypeList(DataService + .getGlobalCustomerId(), function(response) { + DataService.setSubscriptionServiceTypeList(response); + UtilityService.startNextAsyncOperation(); + }); + }; + + var getSubscribers = function() { + AaiService.getSubscribers(function(response) { + DataService.setSubscribers(response); + UtilityService.startNextAsyncOperation(); + }); + }; + + var getLcpCloudRegionTenantList = function() { + AaiService.getLcpCloudRegionTenantList(DataService + .getGlobalCustomerId(), DataService.getServiceType(), function( + response) { + DataService.setCloudRegionTenantList(response); + UtilityService.startNextAsyncOperation(); + }); + }; + + var internalGetParametersHandler = function() { + if (angular.isFunction(_this.getParametersHandler)) { + _this.getParametersHandler({ + summaryList : getSummaryList(), + userProvidedList : getUserProvidedList() + }); + } + }; + + var getSubscribersParameter = function() { + var subscribers = DataService.getSubscribers(); + var parameter = FIELD.PARAMETER.SUBSCRIBER_NAME; + parameter.optionList = []; + + for (var i = 0; i < subscribers.length; i++) { + parameter.optionList.push({ + id : subscribers[i]["global-customer-id"], + name : subscribers[i]["subscriber-name"] + }) + } + return parameter; + }; + + var getServiceId = function() { + var serviceIdList = DataService.getServiceIdList(); + var serviceTypeList = DataService.getSubscriptionServiceTypeList(); + var parameter = FIELD.PARAMETER.PRODUCT_FAMILY; + parameter.optionList = new Array(); + + if (serviceTypeList == null) { + getSubscriptionServiceTypeList(); + serviceTypeList = DataService.getSubscriptionServiceTypeList(); + } + var went = 0; + for (var i = 0; i < serviceIdList.length; i++) { + var go = 0; + var name = serviceIdList[i].id; + + if (serviceTypeList != null) { + console.log("STL: " + serviceTypeList); + for (var k = 0; k < serviceTypeList.length; k++) { + if (angular.equals(name,serviceTypeList[k])) { + go = 1; + went = 1; + } + } + } else { + go = 1; + went = 1; + } + if (go == 1) { + parameter.optionList.push({ + id : serviceIdList[i].id, + name : serviceIdList[i].description + }); + } + } // load them all, ours wasn't in the list + if (went == 0) { + for (var i = 0; i < serviceIdList.length; i++) { + parameter.optionList.push({ + id : serviceIdList[i].id, + name : serviceIdList[i].description + }); + } + } + return parameter; + }; + + var getLcpRegion = function() { + var cloudRegionTenantList = DataService.getCloudRegionTenantList(); + var parameter = FIELD.PARAMETER.LCP_REGION; + parameter.optionList = new Array(); + for (var i = 0; i < cloudRegionTenantList.length; i++) { + for (var j = 0; j < parameter.optionList.length; j++) { + if (parameter.optionList[j].id === cloudRegionTenantList[i].cloudRegionId) { + break; + } + } + if (j < parameter.optionList.length) { + continue; + } + parameter.optionList.push({ + id : cloudRegionTenantList[i].cloudRegionId + }); + } + return parameter; + }; + + var getTenantList = function(cloudRegionId) { + var cloudRegionTenantList = DataService.getCloudRegionTenantList(); + var parameter = FIELD.PARAMETER.TENANT_ENABLED; + parameter.optionList = new Array(); + for (var i = 0; i < cloudRegionTenantList.length; i++) { + if (cloudRegionTenantList[i].cloudRegionId === cloudRegionId) { + parameter.optionList.push({ + id : cloudRegionTenantList[i].tenantId, + name : cloudRegionTenantList[i].tenantName + }); + } + } + return parameter; + + }; + + var addOptionList = function(parameter, optionSimpleArray) { + var optionList = new Array(); + if (!angular.isArray(optionSimpleArray)) { + return optionList; + } + for (var i = 0; i < optionSimpleArray.length; i++) { + optionList.push({ + name : optionSimpleArray[i] + }); + } + parameter.optionList = optionList; + return parameter; + }; + + var getValueFromList = function(id, parameterList) { + for (var i = 0; i < parameterList.length; i++) { + if (parameterList[i].id === id) { + return parameterList[i].value; + } + } + }; + + var updateUserParameterList = function(updatedId, parameterListControl) { + if (updatedId === FIELD.ID.LCP_REGION) { + var list = parameterListControl.getList(updatedId); + if (list[0].selectedIndex >= 0) { + parameterListControl + .updateList([ getTenantList(list[0].value) ]); + } else { + parameterListControl + .updateList([ FIELD.PARAMETER.TENANT_DISABLED ]); + } + if (list[0].value === FIELD.KEY.LCP_REGION_TEXT) { + parameterListControl + .updateList([ FIELD.PARAMETER.LCP_REGION_TEXT_VISIBLE ]); + } else { + parameterListControl + .updateList([ FIELD.PARAMETER.LCP_REGION_TEXT_HIDDEN ]); + } + } else if (updatedId === FIELD.ID.SUBSCRIBER_NAME) { + var list = parameterListControl.getList(updatedId); + if (list[0].selectedIndex >= 0) { + DataService.setGlobalCustomerId(list[0].value); + + AaiService.getSubscriptionServiceTypeList(DataService + .getGlobalCustomerId(), function(response) { + DataService.setSubscriptionServiceTypeList(response); + var serviceTypeParameters = FIELD.PARAMETER.SERVICE_TYPE; + serviceTypeParameters.optionList = []; + + for (var i = 0; i < response.length; i++) { + serviceTypeParameters.optionList.push({ + "id" : response[i], + "name" : response[i] + }); + } + parameterListControl.updateList([ serviceTypeParameters ]); + }); + + } else { + parameterListControl + .updateList([ FIELD.PARAMETER.SERVICE_TYPE_DISABLED ]); + } + } + }; + + return { + initializeComponent : function(componentId) { + _this.componentId = ComponentService.initialize(componentId); + }, + setHttpErrorHandler : function(httpErrorHandler) { + _this.httpErrorHandler = httpErrorHandler; + }, + getComponentDisplayName : ComponentService.getComponentDisplayName, + getParameters : function(getParametersHandler) { + _this.getParametersHandler = getParametersHandler; + UtilityService.setHttpErrorHandler(_this.httpErrorHandler); + UtilityService.startAsyncOperations(getAsyncOperationList(), + internalGetParametersHandler); + }, + updateUserParameterList : updateUserParameterList, + getMsoRequestDetails : getMsoRequestDetails, + getMsoUrl : getMsoUrl + } +} + +app.factory("CreationService", [ "$log", "AaiService", "AsdcService", + "DataService", "ComponentService", "COMPONENT", "FIELD", "PARAMETER", + "UtilityService", CreationService ]); diff --git a/vid/src/main/webapp/app/vid/scripts/services/dataService.js b/vid/src/main/webapp/app/vid/scripts/services/dataService.js new file mode 100644 index 000000000..724d4b12c --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/services/dataService.js @@ -0,0 +1,197 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var DataService = function($log, DataService) { + + var _this = this; + + return { + getAvailableVolumeGroupList : function() { + return _this.availableVolumeGroupList; + }, + setAvailableVolumeGroupList : function(availableVolumeGroupList) { + _this.availableVolumeGroupList = availableVolumeGroupList; + }, + getCloudRegionTenantList : function() { + return _this.cloudRegionTenantList; + }, + setCloudRegionTenantList : function(cloudRegionTenantList) { + _this.cloudRegionTenantList = cloudRegionTenantList; + }, + getGlobalCustomerId : function() { + return _this.globalCustomerId; + }, + setGlobalCustomerId : function(globalCustomerId) { + _this.globalCustomerId = globalCustomerId; + }, + getInventoryItem : function() { + return _this.inventoryItem; + }, + setInventoryItem : function(inventoryItem) { + _this.inventoryItem = inventoryItem; + }, + getModelId : function() { + return _this.modelId; + }, + setModelId : function(modelId) { + _this.modelId = modelId; + }, + getModelInstanceName : function() { + return _this.modelInstanceName; + }, + setModelInstanceName : function(modelInstanceName) { + _this.modelInstanceName = modelInstanceName; + }, + getModelInfo : function(componentId) { + return _this.modelInfo[componentId]; + }, + setModelInfo : function(componentId, modelInfo) { + if (_this.modelInfo === undefined) { + _this.modelInfo = new Object; + } + _this.modelInfo[componentId] = modelInfo; + }, + getNetworkInstanceId : function() { + return _this.networkInstanceId; + }, + setNetworkInstanceId : function(networkInstanceId) { + _this.networkInstanceId = networkInstanceId; + }, + getServiceIdList : function() { + return _this.serviceIdList; + }, + setServiceIdList : function(serviceIdList) { + _this.serviceIdList = serviceIdList; + }, + getServiceInstanceId : function() { + return _this.serviceInstanceId; + }, + setServiceInstanceId : function(serviceInstanceId) { + _this.serviceInstanceId = serviceInstanceId; + }, + getServiceInstanceName : function() { + return _this.serviceInstanceName; + }, + setServiceInstanceName : function(serviceInstanceName) { + _this.serviceInstanceName = serviceInstanceName; + }, + getServiceName : function() { + return _this.serviceName; + }, + setServiceName : function(serviceName) { + _this.serviceName = serviceName; + }, + getServiceType : function() { + return _this.serviceType; + }, + setServiceType : function(serviceType) { + _this.serviceType = serviceType; + }, + getServiceUuid : function() { + return _this.serviceUuid; + }, + setServiceUuid : function(serviceUuid) { + _this.serviceUuid = serviceUuid; + }, + getSubscriberId : function() { + return _this.subscriberId; + }, + setSubscriberId : function(subscriberId) { + _this.subscriberId = subscriberId; + }, + getSubscriberName : function() { + return _this.subscriberName; + }, + setSubscriberName : function(subscriberName) { + _this.subscriberName = subscriberName; + }, + getSubscribers : function() { + return _this.subscribers; + }, + setSubscribers : function(subscribers) { + _this.subscribers = subscribers; + }, + getSubscriptionServiceTypeList : function() { + return _this.subscriptionServiceTypeList; + }, + setSubscriptionServiceTypeList : function(subscriptionServiceTypeList) { + _this.subscriptionServiceTypeList = subscriptionServiceTypeList; + }, + getUserParams : function() { + return _this.userParams; + }, + setUserParams : function(userParams) { + _this.userParams = userParams; + }, + getUserServiceInstanceName : function() { + return _this.userServiceInstanceName; + }, + setUserServiceInstanceName : function(userServiceInstanceName) { + _this.userServiceInstanceName = userServiceInstanceName; + }, + getVfModuleInstanceId : function() { + return _this.vfModuleInstanceId; + }, + setVfModuleInstanceId : function(vfModuleInstanceId) { + _this.vfModuleInstanceId = vfModuleInstanceId; + }, + getVnfInstanceId : function() { + return _this.vnfInstanceId; + }, + setVnfInstanceId : function(vnfInstanceId) { + _this.vnfInstanceId = vnfInstanceId; + }, + getVolumeGroupInstanceId : function() { + return _this.volumeGroupInstanceId; + }, + setVolumeGroupInstanceId : function(volumeGroupInstanceId) { + _this.volumeGroupInstanceId = volumeGroupInstanceId; + }, + getLcpRegion : function() { + return _this.lcpRegion; + }, + setLcpRegion : function(lcpRegion) { + _this.lcpRegion = lcpRegion; + }, + getTenant : function() { + return _this.tenant; + }, + setTenant : function(tenant) { + _this.tenant = tenant; + }, + getTreeHandle : function() { + return _this.treeHandle; + }, + setTreeHandle : function(treeHandle) { + _this.treeHandle = treeHandle; + }, + setServiceInstanceToCustomer : function(serviceInstanceToCustomer) { + _this.serviceInstanceToCustomer = []; + _this.serviceInstanceToCustomer = serviceInstanceToCustomer; + }, + getServiceInstanceToCustomer : function() { + return _this.serviceInstanceToCustomer; + } + } +} + +app.factory("DataService", [ "$log", DataService ]); diff --git a/vid/src/main/webapp/app/vid/scripts/services/deletionService.js b/vid/src/main/webapp/app/vid/scripts/services/deletionService.js new file mode 100644 index 000000000..5ab5ee79b --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/services/deletionService.js @@ -0,0 +1,442 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var DeletionService = function($log, AaiService, AsdcService, DataService, + ComponentService, COMPONENT, FIELD, UtilityService) { + + var _this = this; + + var getAsyncOperationList = function() { + switch (_this.componentId) { + case COMPONENT.SERVICE: + return [ getSubscribers ]; + case COMPONENT.NETWORK: + return []; + case COMPONENT.VNF: + return [ getLcpCloudRegionTenantList ]; + case COMPONENT.VF_MODULE: + return [ getLcpCloudRegionTenantList ]; + case COMPONENT.VOLUME_GROUP: + return [ getLcpCloudRegionTenantList ]; + } + }; + + var getLcpCloudRegionTenantList = function() { + AaiService.getLcpCloudRegionTenantList(DataService + .getGlobalCustomerId(), DataService.getServiceType(), function( + response) { + DataService.setCloudRegionTenantList(response); + UtilityService.startNextAsyncOperation(); + }); + }; + + var getSubscribers = function() { + AaiService.getSubscribers(function(response) { + DataService.setSubscribers(response); + UtilityService.startNextAsyncOperation(); + }); + }; + + var internalGetParametersHandler = function() { + if (angular.isFunction(_this.getParametersHandler)) { + if (_this.componentId == COMPONENT.SERVICE) + _this.getParametersHandler({ + summaryList : getSummaryList(), + userProvidedList : getUserProvidedList() + }, true); + else + _this.getParametersHandler({ + summaryList : getSummaryList(), + userProvidedList : getUserProvidedList() + }, false); + } + }; + + var getSubscribersParameter = function() { + var subscribers = DataService.getSubscribers(); + var parameter = FIELD.PARAMETER.SUBSCRIBER_NAME; + parameter.optionList = []; + + for (var i = 0; i < subscribers.length; i++) { + parameter.optionList.push({ + id : subscribers[i]["global-customer-id"], + name : subscribers[i]["subscriber-name"] + }) + } + return parameter; + }; + + var getServiceId = function() { + var serviceIdList = DataService.getServiceIdList(); + var parameter = FIELD.PARAMETER.PRODUCT_FAMILY; + parameter.optionList = new Array(); + for (var i = 0; i < serviceIdList.length; i++) { + parameter.optionList.push({ + id : serviceIdList[i].id, + name : serviceIdList[i].description + }); + } + return parameter; + }; + + var getUserProvidedList = function() { + + //var parameterList = [ FIELD.PARAMETER.INSTANCE_NAME ]; + + var parameterList = []; + + switch (_this.componentId) { + case COMPONENT.SERVICE: +// parameterList = parameterList.concat([ getSubscribersParameter(), +// FIELD.PARAMETER.SERVICE_TYPE_DISABLED ]); + parameterList = []; + break; + case COMPONENT.NETWORK: + case COMPONENT.VNF: + parameterList = parameterList.concat([ //getServiceId(), + getLcpRegion(), FIELD.PARAMETER.LCP_REGION_TEXT_HIDDEN, + FIELD.PARAMETER.TENANT_DISABLED ]); + break; + case COMPONENT.VF_MODULE: + parameterList = parameterList.concat([ + getLcpRegion(), + FIELD.PARAMETER.LCP_REGION_TEXT_HIDDEN, + FIELD.PARAMETER.TENANT_DISABLED + ]); + + break; + case COMPONENT.VOLUME_GROUP: + parameterList = parameterList.concat([ getLcpRegion(), + FIELD.PARAMETER.LCP_REGION_TEXT_HIDDEN, + FIELD.PARAMETER.TENANT_DISABLED ]); + } + + parameterList.push(FIELD.PARAMETER.SUPPRESS_ROLLBACK); + + //addArbitraryParameters(parameterList); + + return parameterList; + }; + var getSummaryList = function() { + switch (_this.componentId) { + case COMPONENT.NETWORK: + case COMPONENT.SERVICE: + case COMPONENT.VNF: + case COMPONENT.VF_MODULE: + case COMPONENT.VOLUME_GROUP: + var summaryList = [ { + name : FIELD.NAME.SUBSCRIBER_NAME, + value : DataService.getSubscriberName() + }, { + name : FIELD.NAME.CUSTOMER_ID, + value : DataService.getGlobalCustomerId() + }, { + name : FIELD.NAME.SERVICE_UUID, + value : DataService.getServiceUuid() + }, { + name : FIELD.NAME.SERVICE_NAME, + value : DataService.getServiceName() + /* }, { + name : FIELD.NAME.USER_SERVICE_INSTANCE_NAME, + value : DataService.getUserServiceInstanceName()*/ + } ]; + + _this.parameterList = new Array(); + + addToList(FIELD.NAME.SERVICE_NAME, DataService.getServiceName()); + + switch (_this.componentId) { + case COMPONENT.SERVICE: + addToList(FIELD.NAME.SERVICE_INVARIANT_UUID, DataService + .getModelInfo(_this.componentId)["modelInvariantId"]); + addToList(FIELD.NAME.SERVICE_VERSION, DataService + .getModelInfo(_this.componentId)["modelVersion"]); + addToList(FIELD.NAME.SERVICE_UUID, DataService + .getModelInfo(_this.componentId)["modelNameVersionId"]); + addToList(FIELD.NAME.SERVICE_DESCRIPTION, DataService + .getModelInfo(_this.componentId)["description"]); + addToList(FIELD.NAME.SERVICE_CATEGORY, DataService + .getModelInfo(_this.componentId)["category"]); + break; + case COMPONENT.VF_MODULE: + addToList(FIELD.NAME.SUBSCRIBER_NAME, DataService + .getSubscriberName()); + addToList(FIELD.NAME.SERVICE_INSTANCE_NAME, DataService + .getServiceInstanceName()); + addToList(FIELD.NAME.MODEL_NAME, DataService + .getModelInfo(_this.componentId)["modelName"]); + addToList(FIELD.NAME.MODEL_INVARIANT_UUID, DataService + .getModelInfo(_this.componentId)["modelInvariantId"]); + addToList(FIELD.NAME.MODEL_VERSION, DataService + .getModelInfo(_this.componentId)["modelVersion"]); + addToList(FIELD.NAME.MODEL_UUID, DataService + .getModelInfo(_this.componentId)["modelNameVersionId"]); + break; + case COMPONENT.NETWORK: + case COMPONENT.VNF: + case COMPONENT.VOLUME_GROUP: + addToList(FIELD.NAME.SUBSCRIBER_NAME, DataService + .getSubscriberName()); + addToList(FIELD.NAME.SERVICE_INSTANCE_NAME, DataService + .getServiceInstanceName()); + addToList(FIELD.NAME.MODEL_NAME, DataService + .getModelInfo(_this.componentId)["modelName"]); + addToList(FIELD.NAME.MODEL_INVARIANT_UUID, DataService + .getModelInfo(_this.componentId)["modelInvariantId"]); + addToList(FIELD.NAME.MODEL_VERSION, DataService + .getModelInfo(_this.componentId)["modelVersion"]); + addToList(FIELD.NAME.MODEL_UUID, DataService + .getModelInfo(_this.componentId)["modelNameVersionId"]); + break; + } + + var additionalList = ComponentService.getInventoryParameterList( + _this.componentId, DataService.getInventoryItem()); + + return summaryList.concat(ComponentService + .getDisplayNames(additionalList)); + } + }; + + var getMsoUrl = function() { + switch (_this.componentId) { + case COMPONENT.NETWORK: + return "mso_delete_nw_instance/" + + DataService.getServiceInstanceId() + "/networks/" + + DataService.getNetworkInstanceId(); + case COMPONENT.SERVICE: + return "mso_delete_svc_instance/" + + DataService.getServiceInstanceId(); + case COMPONENT.VNF: + return "mso_delete_vnf_instance/" + + DataService.getServiceInstanceId() + "/vnfs/" + + DataService.getVnfInstanceId(); + case COMPONENT.VF_MODULE: + return "mso_delete_vfmodule_instance/" + + DataService.getServiceInstanceId() + "/vnfs/" + + DataService.getVnfInstanceId() + "/vfModules/" + + DataService.getVfModuleInstanceId(); + case COMPONENT.VOLUME_GROUP: + return "mso_delete_volumegroup_instance/" + + DataService.getServiceInstanceId() + "/vnfs/" + + DataService.getVnfInstanceId() + "/volumeGroups/" + + DataService.getVolumeGroupInstanceId(); + } + } + + var addToList = function(name, value) { + _this.parameterList.push({ + name : name, + value : value + }); + }; + + var getMsoRequestDetails = function(parameterList) { + console.log("getMsoRequestDetails invoked"); + var inventoryInfo = ComponentService.getInventoryInfo( + _this.componentId, DataService.getInventoryItem()); + var modelInfo = DataService.getModelInfo(_this.componentId); + var requestDetails = { + modelInfo : { + modelType : _this.componentId, + modelInvariantId : modelInfo.modelInvariantId, + modelNameVersionId : modelInfo.modelNameVersionId, + modelName : modelInfo.modelName, + modelCustomizationName : modelInfo.modelCustomizationName, + modelVersion : modelInfo.modelVersion + }, + requestInfo : { + source : "VID" + } + }; + + switch (_this.componentId) { + case COMPONENT.SERVICE: + break; + case COMPONENT.VNF: + console.log("getMsoRequestDetails COMPONENT.VNF"); + var lcpRegion = getValueFromList(FIELD.ID.LCP_REGION, parameterList); + if (lcpRegion === FIELD.KEY.LCP_REGION_TEXT) { + lcpRegion = getValueFromList(FIELD.ID.LCP_REGION_TEXT, + parameterList); + } + requestDetails.cloudConfiguration = { + lcpCloudRegionId : lcpRegion, + tenantId : getValueFromList(FIELD.ID.TENANT, parameterList) + }; + + break; + case COMPONENT.VF_MODULE: + var lcpRegion = getValueFromList(FIELD.ID.LCP_REGION, parameterList); + if (lcpRegion === FIELD.KEY.LCP_REGION_TEXT) { + lcpRegion = getValueFromList(FIELD.ID.LCP_REGION_TEXT, + parameterList); + } + requestDetails.cloudConfiguration = { + lcpCloudRegionId : lcpRegion, + tenantId : getValueFromList(FIELD.ID.TENANT, parameterList) + }; + break; + case COMPONENT.VOLUME_GROUP: + var lcpRegion = getValueFromList(FIELD.ID.LCP_REGION, parameterList); + if (lcpRegion === FIELD.KEY.LCP_REGION_TEXT) { + lcpRegion = getValueFromList(FIELD.ID.LCP_REGION_TEXT, + parameterList); + } + requestDetails.cloudConfiguration = { + lcpCloudRegionId : lcpRegion, + tenantId : getValueFromList(FIELD.ID.TENANT, parameterList) + }; + + break; + default: + requestDetails.cloudConfiguration = { + lcpCloudRegionId : DataService.getLcpRegion(), + tenantId : DataService.getTenant() + }; + } + return requestDetails; + } + + var getLcpRegion = function() { + var cloudRegionTenantList = DataService.getCloudRegionTenantList(); + var parameter = FIELD.PARAMETER.LCP_REGION; + parameter.optionList = new Array(); + for (var i = 0; i < cloudRegionTenantList.length; i++) { + for (var j = 0; j < parameter.optionList.length; j++) { + if (parameter.optionList[j].id === cloudRegionTenantList[i].cloudRegionId) { + break; + } + } + if (j < parameter.optionList.length) { + continue; + } + parameter.optionList.push({ + id : cloudRegionTenantList[i].cloudRegionId + }); + } + return parameter; + }; + + var getTenantList = function(cloudRegionId) { + var cloudRegionTenantList = DataService.getCloudRegionTenantList(); + var parameter = FIELD.PARAMETER.TENANT_ENABLED; + parameter.optionList = new Array(); + for (var i = 0; i < cloudRegionTenantList.length; i++) { + if (cloudRegionTenantList[i].cloudRegionId === cloudRegionId) { + parameter.optionList.push({ + id : cloudRegionTenantList[i].tenantId, + name : cloudRegionTenantList[i].tenantName + }); + } + } + return parameter; + + }; + + var addOptionList = function(parameter, optionSimpleArray) { + var optionList = new Array(); + if (!angular.isArray(optionSimpleArray)) { + return optionList; + } + for (var i = 0; i < optionSimpleArray.length; i++) { + optionList.push({ + name : optionSimpleArray[i] + }); + } + parameter.optionList = optionList; + return parameter; + }; + + var getValueFromList = function(id, parameterList) { + for (var i = 0; i < parameterList.length; i++) { + if (parameterList[i].id === id) { + return parameterList[i].value; + } + } + }; + + var updateUserParameterList = function(updatedId, parameterListControl) { + if (updatedId === FIELD.ID.LCP_REGION) { + var list = parameterListControl.getList(updatedId); + if (list[0].selectedIndex >= 0) { + parameterListControl + .updateList([ getTenantList(list[0].value) ]); + } else { + parameterListControl + .updateList([ FIELD.PARAMETER.TENANT_DISABLED ]); + } + if (list[0].value === FIELD.KEY.LCP_REGION_TEXT) { + parameterListControl + .updateList([ FIELD.PARAMETER.LCP_REGION_TEXT_VISIBLE ]); + } else { + parameterListControl + .updateList([ FIELD.PARAMETER.LCP_REGION_TEXT_HIDDEN ]); + } + } else if (updatedId === FIELD.ID.SUBSCRIBER_NAME) { + var list = parameterListControl.getList(updatedId); + if (list[0].selectedIndex >= 0) { + DataService.setGlobalCustomerId(list[0].value); + + AaiService.getSubscriptionServiceTypeList(DataService + .getGlobalCustomerId(), function(response) { + DataService.setSubscriptionServiceTypeList(response); + var serviceTypeParameters = FIELD.PARAMETER.SERVICE_TYPE; + serviceTypeParameters.optionList = []; + + for (var i = 0; i < response.length; i++) { + serviceTypeParameters.optionList.push({ + "id" : response[i], + "name" : response[i] + }); + } + parameterListControl.updateList([ serviceTypeParameters ]); + }); + + } else { + parameterListControl + .updateList([ FIELD.PARAMETER.SERVICE_TYPE_DISABLED ]); + } + } + }; + + return { + initializeComponent : function(componentId) { + _this.componentId = ComponentService.initialize(componentId); + }, + getComponentDisplayName : ComponentService.getComponentDisplayName, + getSummaryList : getSummaryList, + getParameters : function(getParametersHandler) { + _this.getParametersHandler = getParametersHandler; + UtilityService.setHttpErrorHandler(_this.httpErrorHandler); + UtilityService.startAsyncOperations(getAsyncOperationList(), + internalGetParametersHandler); + }, + updateUserParameterList : updateUserParameterList, + getMsoRequestDetails : getMsoRequestDetails, + getMsoUrl : getMsoUrl + } +} + +app.factory("DeletionService", [ "$log", "AaiService", "AsdcService", + "DataService", "ComponentService", "COMPONENT", "FIELD", + "UtilityService", DeletionService ]); diff --git a/vid/src/main/webapp/app/vid/scripts/services/detailsService.js b/vid/src/main/webapp/app/vid/scripts/services/detailsService.js new file mode 100644 index 000000000..38f161d05 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/services/detailsService.js @@ -0,0 +1,98 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var DetailsService = function($log, DataService, ComponentService, COMPONENT, + FIELD, UtilityService) { + + var _this = this; + + var getSummaryList = function() { + switch (_this.componentId) { + case COMPONENT.NETWORK: + case COMPONENT.SERVICE: + case COMPONENT.VNF: + case COMPONENT.VF_MODULE: + case COMPONENT.VOLUME_GROUP: + return [ { + name : FIELD.NAME.SUBSCRIBER_NAME, + value : DataService.getSubscriberName() + }, { + name : FIELD.NAME.SERVICE_INSTANCE_ID, + value : DataService.getServiceInstanceId() + }, { + name : FIELD.NAME.SERVICE_TYPE, + value : DataService.getServiceType() + } ]; + } + }; + + var getDetailsList = function() { + switch (_this.componentId) { + case COMPONENT.NETWORK: + case COMPONENT.SERVICE: + case COMPONENT.VNF: + case COMPONENT.VF_MODULE: + case COMPONENT.VOLUME_GROUP: + return ComponentService.getDisplayNames(ComponentService + .getInventoryParameterList(_this.componentId, DataService + .getInventoryItem())); + } + }; + + var getMsoFilterString = function() { + + var instanceId = ""; + + switch (_this.componentId) { + case COMPONENT.NETWORK: + instanceId = DataService.getNetworkInstanceId(); + break; + case COMPONENT.SERVICE: + instanceId = DataService.getServiceInstanceId(); + break; + case COMPONENT.VNF: + instanceId = DataService.getVnfInstanceId(); + break; + case COMPONENT.VF_MODULE: + instanceId = DataService.getVfModuleInstanceId(); + break; + case COMPONENT.VOLUME_GROUP: + instanceId = DataService.getVolumeGroupInstanceId(); + } + + return "filter=" + _this.componentId + "InstanceId:EQUALS:" + + instanceId; + }; + + return { + initializeComponent : function(componentId) { + _this.componentId = ComponentService.initialize(componentId); + }, + getComponentDisplayName : ComponentService.getComponentDisplayName, + getSummaryList : getSummaryList, + getDetailsList : getDetailsList, + getMsoFilterString : getMsoFilterString + } +} + +app.factory("DetailsService", [ "$log", "DataService", "ComponentService", + "COMPONENT", "FIELD", "UtilityService", DetailsService ]); diff --git a/vid/src/main/webapp/app/vid/scripts/services/msoService.js b/vid/src/main/webapp/app/vid/scripts/services/msoService.js new file mode 100644 index 000000000..2d4344685 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/services/msoService.js @@ -0,0 +1,146 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var MsoService = function($http, $log, PropertyService, UtilityService) { + + var _this = this; + + /* + * Common function to handle both create and delete instance requests + */ + var requestInstanceUpdate = function(request, successCallbackFunction) { + $log.debug("MsoService:requestInstanceUpdate: request:"); + $log.debug(request); + $http.post(PropertyService.getMsoBaseUrl() + "/" + request.url, { + requestDetails : request.requestDetails + }, { + timeout : PropertyService.getServerResponseTimeoutMsec() + }).then(successCallbackFunction)["catch"] + (UtilityService.runHttpErrorHandler); + } + + var checkValidStatus = function(response) { + if (response.data.status < 200 || response.data.status > 202) { + throw { + type : "msoFailure" + } + } + } + + var addListEntry = function(name, value) { + var entry = '"' + name + '": '; + if (value === undefined) { + return entry + "undefined"; + } else { + return entry + '"' + value + '"'; + } + } + + return { + createInstance : requestInstanceUpdate, + deleteInstance : requestInstanceUpdate, + getOrchestrationRequest : function(requestId, successCallbackFunction) { + $log.debug("MsoService:getOrchestrationRequest: requestId: " + + requestId); + $http.get( + PropertyService.getMsoBaseUrl() + "/mso_get_orch_req/" + + requestId + "?r=" + Math.random(), + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(successCallbackFunction)["catch"] + (UtilityService.runHttpErrorHandler); + }, + getOrchestrationRequests : function(filterString, + successCallbackFunction) { + $log.debug("MsoService:getOrchestrationRequests: filterString: " + + filterString); + $http.get( + PropertyService.getMsoBaseUrl() + "/mso_get_orch_reqs/" + + encodeURIComponent(filterString) + "?r=" + + Math.random(), + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(successCallbackFunction)["catch"] + (UtilityService.runHttpErrorHandler); + }, + getFormattedCommonResponse : function(response) { + return UtilityService.getCurrentTime() + " HTTP Status: " + + UtilityService.getHttpStatusText(response.data.status) + + "\n" + angular.toJson(response.data.entity, true) + + "\n\n"; + }, + checkValidStatus : checkValidStatus, + getFormattedGetOrchestrationRequestsResponse : function(response) { + UtilityService.checkUndefined("entity", response.data.entity); + UtilityService.checkUndefined("status", response.data.status); + checkValidStatus(response); + + var list = response.data.entity.requestList + UtilityService.checkUndefined("requestList", list); + + var message = ""; + + for (var i = 0; i < list.length; i++) { + var request = list[i].request; + message += addListEntry("requestId", request.requestId) + ",\n"; + message += addListEntry("requestType", request.requestType) + + ",\n"; + var status = request.requestStatus; + if (status === undefined) { + message += addListEntry("requestStatus", undefined) + "\n"; + } else { + message += addListEntry("timestamp", status.timestamp) + + ",\n"; + message += addListEntry("requestState", status.requestState) + + ",\n"; + message += addListEntry("statusMessage", + status.statusMessage) + + ",\n"; + message += addListEntry("percentProgress", + status.percentProgress) + + "\n"; + } + if (i < (list.length - 1)) { + message += "\n"; + } + } + return message; + }, + showResponseContentError : function(error, showFunction) { + switch (error.type) { + case "undefinedObject": + showFunction("System failure", error.message); + break; + case "msoFailure": + showFunction("MSO failure", "see log below for details") + break; + default: + showFunction("System failure"); + } + } + } +} + +app.factory("MsoService", [ "$http", "$log", "PropertyService", + "UtilityService", MsoService ]); diff --git a/vid/src/main/webapp/app/vid/scripts/services/propertyService.js b/vid/src/main/webapp/app/vid/scripts/services/propertyService.js new file mode 100644 index 000000000..bfdc7ef33 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/services/propertyService.js @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var PropertyService = function($location, $http) { + + var RE = /.*?:\/\/.*?:.*?\/(.*?)\//g; + var BASE_PATH = RE.exec($location.absUrl())[1]; + var DEFAULT_AAI_BASE_URL = "/" + BASE_PATH; + var DEFAULT_ASDC_BASE_URL = "asdc"; + var DEFAULT_MSO_MAX_POLLING_INTERVAL_MSEC = 60000; + var DEFAULT_MSO_MAX_POLLS = 10; + var DEFAULT_MSO_BASE_URL = "/" + BASE_PATH + "/mso"; + var DEFAULT_SERVER_RESPONSE_TIMEOUT_MSEC = 60000; + var MSO_POLLING_INTERVAL_MSECS = "mso_polling_interval_msecs"; + var MSO_MAX_POLLS = "mso_max_polls"; + + var _this = this; + + _this.asdcBaseUrl = DEFAULT_ASDC_BASE_URL; + _this.aaiBaseUrl = DEFAULT_AAI_BASE_URL; + _this.msoMaxPollingIntervalMsec = DEFAULT_MSO_MAX_POLLING_INTERVAL_MSEC; + _this.msoMaxPolls = DEFAULT_MSO_MAX_POLLS; + _this.msoBaseUrl = DEFAULT_MSO_BASE_URL; + _this.serverResponseTimeoutMsec = DEFAULT_SERVER_RESPONSE_TIMEOUT_MSEC; + + return { + getAaiBaseUrl : function() { + return _this.aaiBaseUrl; + }, + setAaiBaseUrl : function(aaiBaseUrl) { + _this.aaiBaseUrl = aaiBaseUrl; + }, + getAsdcBaseUrl : function() { + return _this.asdcBaseUrl; + }, + setAsdcBaseUrl : function(asdcBaseUrl) { + _this.asdcBaseUrl = asdcBaseUrl; + }, + retrieveMsoMaxPollingIntervalMsec : function(defaultvalue) { + _this.msoMaxPollingIntervalMsec = defaultvalue; + $http.get( _this.aaiBaseUrl + "/get_property/" + MSO_POLLING_INTERVAL_MSECS + "/" + defaultvalue, { + + },{ + timeout: _this.serverResponseTimeoutMsec + }).then(function(response) { + //console.log ( "retrieveMsoMaxPollingIntervalMsec: " ); console.log ( JSON.stringify(response) ); + //console.log ( "retrieveMsoMaxPollingIntervalMsec: " + response.data ); + _this.msoMaxPollingIntervalMsec = response.data; + console.log ("retrieveMsoMaxPollingIntervalMsec: " + _this.msoMaxPollingIntervalMsec); + },function errorCallback(response) { + console.log ( "retrieveMsoMaxPollingIntervalMsec: " + response.status ); + //console.log ( "retrieveMsoMaxPollingIntervalMsec: " ); console.log ( JSON.stringify(response) ); + }); + return _this.msoMaxPollingIntervalMsec; + }, + getMsoMaxPollingIntervalMsec : function() { + return _this.msoMaxPollingIntervalMsec; + }, + setMsoMaxPollingIntervalMsec : function(msoMaxPollingIntervalMsec) { + _this.msoMaxPollingIntervalMsec = msoMaxPollingIntervalMsec; + }, + retrieveMsoMaxPolls : function(defaultvalue) { + _this.msoMaxPolls = defaultvalue; + $http.get( _this.aaiBaseUrl + "/get_property/" + MSO_MAX_POLLS + "/" + defaultvalue, { + + },{ + timeout: _this.serverResponseTimeoutMsec + }).then(function(response) { + //console.log ( "retrieveMsoMaxPolls: " ); console.log ( JSON.stringify(response) ); + //console.log ( "retrieveMsoMaxPolls: " + response.data.entity ); + _this.msoMaxPolls = response.data; + console.log ("retrieveMsoMaxPolls: " + _this.msoMaxPolls); + }); + return _this.msoMaxPolls; + }, + getMsoMaxPolls : function() { + return _this.msoMaxPolls; + }, + setMsoMaxPolls : function(msoMaxPolls) { + _this.msoMaxPolls = msoMaxPolls; + }, + getMsoBaseUrl : function() { + return _this.msoBaseUrl; + }, + setMsoBaseUrl : function(msoBaseUrl) { + _this.msoBaseUrl = msoBaseUrl; + }, + getServerResponseTimeoutMsec : function() { + return _this.serverResponseTimeoutMsec; + }, + setServerResponseTimeoutMsec : function(serverResponseTimeoutMsec) { + _this.serverResponseTimeoutMsec = serverResponseTimeoutMsec; + } + }; +} + +app.factory("PropertyService", PropertyService); diff --git a/vid/src/main/webapp/app/vid/scripts/services/utilityService.js b/vid/src/main/webapp/app/vid/scripts/services/utilityService.js new file mode 100644 index 000000000..fc7d97123 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/services/utilityService.js @@ -0,0 +1,228 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +/* + * "UtilityService" contains various generic methods. + * + * (*** DEPRECATED - Use PropertyService instead ***) setProperties() and + * getProperties() + * + * SYNTAX: hasContents(object) + * + * Returns "true" if "object" contains contents (i.e. is NOT undefined, null or + * ""), "false" otherwise. + * + * SYNTAX: checkUndefined(name, value) + * + * Throws an exception if "value" is undefined. The exception includes "name" as + * the cause of the exception. Returns "value" if it is defined. + * + * SYNTAX: getCurrentTime() + * + * Returns the current local date and time in the format "MM/DD/YY HH:MM:SS" + * + * SYNTAX: setHttpErrorHandler(function) + * + * Sets the HTTP error handler to "function". + * + * SYNTAX: runHttpErrorHandler(response, status) + * + * Logs warning messages and the runs the HTTP error handler previously set by + * "setHttpErrorHandler". The intended usage is for "$http" calls. Example: + * $http.get(...).then(...)["catch"](UtilityService.runHttpErrorHandler); + * + * SYNTAX: getHttpStatusText(statusCode) + * + * Expects "statusCode" to be an HTTP response code (e.g. 404). The function + * returns a string that includes both the code and an equivalent text summary. + * Example: "Not found (404)" + * + * SYNTAX: getHttpErrorMessage(response) + * + * Expects "response" to be the response object generated by a "$http" error + * condition. "getHttpErrorMessage" examines the object and returns a summary + * string for some known conditions. + */ + +var UtilityService = function($log) { + + var _this = this; + + function hasContents(object) { + if (object === undefined || object === null || object === "") { + return false; + } + return true; + } + + function padZero(number) { + if (number < 10) { + return "0" + number; + } else { + return "" + number; + } + } + + var httpErrorHandler = function(response, status) { + $log.warn("UtilityService:httpErrorHandler: response:"); + $log.warn(response); + $log.warn("UtilityService:httpErrorHandler: status:"); + $log.warn(status); + if (angular.isFunction(_this.httpErrorHandler)) { + _this.httpErrorHandler(response, status); + } + }; + + var startNextAsyncOperation = function() { + if (_this.asyncOperations.count < _this.asyncOperations.operationList.length) { + _this.asyncOperations.operationList[_this.asyncOperations.count++] + (); + } else { + if (angular.isFunction(_this.asyncOperations.callbackFunction)) { + _this.asyncOperations.callbackFunction(); + } + } + }; + + return { + setProperties : function(properties) { + _this.properties = properties; + }, + getProperties : function() { + return _this.properties; + }, + hasContents : hasContents, + checkUndefined : function(name, value) { + if (value === undefined) { + throw { + type : "undefinedObject", + message : "undefined object: \"" + name + "\"" + }; + } + return value; + }, + getCurrentTime : function() { + var time = new Date(); + return padZero(time.getMonth() + 1) + "/" + + padZero(time.getDate() + 1) + "/" + + (time.getFullYear() - 2000) + " " + + padZero(time.getHours()) + ":" + + padZero(time.getMinutes()) + ":" + + padZero(time.getSeconds()) + }, + getHttpStatusText : function(statusCode) { + var statusMap = { + "200" : "OK", + "201" : "Created", + "202" : "Accepted", + "400" : "Bad Request", + "401" : "Unauthorized", + "404" : "Not Found", + "405" : "Method Not Allowed", + "409" : "Locked", + "500" : "Internal Server Error", + "503" : "Service Unavailable", + "504" : "Gateway Timeout" + } + + if (status === undefined) { + return "Undefined"; + } + + var statusText = statusMap[statusCode]; + if (statusText === undefined) { + statusText = "Unknown"; + } + + return statusText + " (" + statusCode + ")"; + }, + getHttpErrorMessage : function(response) { + var data = response.data; + if (response.status === 500 && hasContents(data.exception)) { + var summary = "exception: " + data.exception; + if (hasContents(data.message)) { + summary += " message: " + data.message; + } + return summary; + } + if (response.status === 0 && response.statusText === "") { + /* + * This logic is somewhat "fuzzy". Potential (brainstorming) + * enhancements if users find the message unreliable include: + * + * A) SERVER TIMEOUT: perhaps a newer version of Angular can + * reliably determine timeouts. + * + * B) SERVER TIMEOUT: recording start / end times and using that + * to determine if timeout occured + * + * C) SESSION TIMEOUT "Potentially" examine cookies, although + * that may not be feasible if cookies are set to "httponly". + */ + if (data === null) { + return "possible server timeout"; + } + if (data === "") { + return "Possible reasons include a session timeout or a server issue. " + + "A session timeout might be resolved by refreshing the screen and re-logging in"; + } + } + var summary = ""; + if (response.status !== undefined && response.status > 0) { + summary = "status: " + response.status; + } + if (hasContents(response.statusText)) { + if (summary !== "") { + summary += " "; + } + summary += "message: " + response.statusText; + } + return summary; + }, + setHttpErrorHandler : function(httpErrorHandler) { + _this.httpErrorHandler = httpErrorHandler; + }, + runHttpErrorHandler : function(response, status) { + httpErrorHandler(response, status); + }, + startAsyncOperations : function(operationList, callbackFunction) { + for (var i = 0; i < operationList.length; i++) { + if (!angular.isFunction(operationList[i])) { + throw "UtilityService:startAsyncOperations: invalid function: index: " + + i; + } + } + _this.asyncOperations = { + operationList : operationList, + callbackFunction : callbackFunction, + count : 0 + }; + startNextAsyncOperation(); + }, + startNextAsyncOperation : startNextAsyncOperation, + stopAsyncOperations : function() { + _this.asyncOperations.count = _this.asyncOperations.operationList.length; + } + } +} + +app.factory("UtilityService", UtilityService); diff --git a/vid/src/main/webapp/app/vid/scripts/utils/dummy.txt b/vid/src/main/webapp/app/vid/scripts/utils/dummy.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/utils/dummy.txt diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/aaiGetSubs.htm b/vid/src/main/webapp/app/vid/scripts/view-models/aaiGetSubs.htm new file mode 100644 index 000000000..7d46e3dac --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/aaiGetSubs.htm @@ -0,0 +1,79 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + +<link rel="stylesheet" type="text/css" href="app/vid/styles/aaiGetSubs.css" /> +<link rel="stylesheet" type="text/css" href="app/vid/styles/aaiSubDetails.css" /> +<script src="app/vid/scripts/controller/aaiSubscriberController.js"></script> +<div ng-controller="aaiSubscriberController" ng-cloak> + + <div> + <div class="statusLine" ng-class="{true:'aaiVisible', false:'aaiHidden'}[isSpinnerVisible]"> + <img src="app/vid/images/spinner.gif"></img> + <label>Status:</label><span class="status">{{status}}</span> + </div> + + <h2 class="heading2"><center>Search Existing Service Instances</center></h2> + <br> + Please search by the Subscriber name or enter Service Instance Id below: <br><br> + + <table> + <tr> + <td style="width:30%"> + <div class="fn-ebz-container"> + <label class="fn-ebz-text-label">Subscriber Name:</label> + </div> + </td> + <td style="width:60%" nowrap> + <div class="fn-ebz-container" ng-init="autoGetSubs();"> + <select ng-model="selectedCustomer" ng-options="item.globalCustomerId as item.subscriberName for item in customerList | orderBy:'subscriberName'"> + <option value="">Select a subscriber</option></select> + <a class="btn btn-primary" ng-click="refreshSubs();" ><span class="glyphicon glyphicon-refresh"></span></a> + </div> + </td> + + </tr> + <tr> + <td style="width:30%"> + <div class="fn-ebz-container"> + <label class="fn-ebz-text-label">Service Instance Id:</label> + </div> + </td> + <td style="width:60%"> + <div class="fn-ebz-container"> + <input type="text" style="width: 350px;" name="selectedServiceInstance" ng-model="selectedServiceInstance"/> + </div> + </td> + + </tr> + <tr> + <td> + <td style="width:30%"> + <div class="fn-ebz-container"> + <button type="submit" att-button size="small" ng-click="getSubscriberDet(selectedCustomer,selectedServiceInstance);">Submit</button></a> + </div> + </td> + </td> + </tr> + </table> + + + </div> + +</div> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/aaiSubDetails.htm b/vid/src/main/webapp/app/vid/scripts/view-models/aaiSubDetails.htm new file mode 100644 index 000000000..90932875a --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/aaiSubDetails.htm @@ -0,0 +1,93 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + + <div ng-controller="aaiSubscriberController" ng-cloak> + + <div> + <div class="statusLine" ng-class="{true:'aaiVisible', false:'aaiHidden'}[isSpinnerVisible]"> + <img src="app/vid/images/spinner.gif"> + </img> + <label>Status:</label><span class="status">{{status}}</span> + </div> + + <h1 class="heading1"><center>Subscriber Details for {{selectedSubscriber}} ({{selectedSubscriberName}})</center></h1> + <br> + <div class="fn-ebz-container"> + Filter: + <input class="fn-ebz-text" type="text" ng-model="searchString" size="20" style="width: 250px;"> + </div> + <div ng-init="getSubDetails();"> + + <div style="margin-top: 30px"> + <table att-table width="100%" table-data="displayData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage" type="header"> + + <thead att-table-row> + <tr> + <th att-table-header sortable="true" key="viewSubDetails">View/Edit</th> + <th att-table-header sortable="true" key="globalCustomerId">Global Customer ID</th> + <th att-table-header sortable="true" key="subscriberName">Subscriber Name</th> + <th att-table-header sortable="true" key="serviceType">Service Type</th> + <th att-table-header default-sort="A" sortable="true" key="serviceInstanceName">Service Instance Name</th> + <th att-table-header sortable="true" key="serviceInstanceId">Service Instance ID</th> + </tr> + </thead> + <tbody att-table-row type="body" row-repeat="disData in displayData"> + <tr> + <td att-table-body> + <div> + <a alt="View/Edit" ng-click="getAsdcModel(disData);"> View/Edit </a> + </div> + </td> + <!-- <td att-table-body ><button type=button ng-click="getAsdcModel(disData);" att-button btn-type="primary" size="small">View/Edit</button></td> ---> + <td att-table-body ng-bind="disData['globalCustomerId']"></td> + <td att-table-body ng-bind="disData['subscriberName']"></td> + <td att-table-body ng-bind="disData['serviceType']"></td> + <td att-table-body ng-bind="disData['serviceInstanceName']"></td> + <td att-table-body ng-bind="disData['serviceInstanceId']"></td> + </tr> + </tbody> + </table> + <table width='100%'> + <tr> + <td width='33%' valign='middle'> + <span style="cursor: pointer" ng-if="currentPage>1"><button att-button size="small" ng-click="prevPage();">< prev page</button></span> + </td> + <td width='33%' valign='middle'> + Jump to page: + <input class="fn-ebz-text" type="text" ng-model="currentPage" size="5" style="width: 47px;"> + Results per page: <span style="cursor: pointer" ng-click="viewPerPage = 10" ng-style="viewPerPage === 10 && {'textDecoration':'underline','text-color':'black'}">10</span> + | <span style="cursor: pointer" ng-click="viewPerPage = 25" ng-style="viewPerPage === 25 && {'textDecoration':'underline','text-color':'black'}">25</span> + | <span style="cursor: pointer" ng-click="viewPerPage = 50" ng-style="viewPerPage === 50 && {'textDecoration':'underline','text-color':'black'}">50</span> + </td> + <td width='34%' align='right' valign='middle'> + <span style="cursor: pointer" ng-if="currentPage<totalPage"><button att-button ng-click="nextPage();">next page ></button></span> + </td> + </tr> + </table> + + + </div> + + </div> + + + </div> + + </div> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/aaiSubViewEdit.htm b/vid/src/main/webapp/app/vid/scripts/view-models/aaiSubViewEdit.htm new file mode 100644 index 000000000..53c9a6b04 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/aaiSubViewEdit.htm @@ -0,0 +1,147 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + +<div ng-controller="aaiSubscriberController" ng-cloak> + + <div popup-window class="popupContents" ngx-show="{{popup.isVisible}}" + ng-cloak> + <div ng-include="'app/vid/scripts/view-models/creationDialog.htm'"></div> + <div ng-include="'app/vid/scripts/view-models/deletionDialog.htm'"></div> + <div ng-include="'app/vid/scripts/view-models/detailsDialog.htm'"></div> + </div> + + <div> + <div class="statusLine"> + <img src="app/vid/images/spinner.gif" + ng-class="{true:'aaiVisible', false:'aaiHidden'}[isSpinnerVisible]"></img> + <label>Status:</label><span class="status">{{status}}</span> + </div> + + <h2 class="heading2"> + <center>VIEW/EDIT SERVICE INSTANCE <a class="btn btn-primary btn-xs pull-right" ng-click="reloadRoute();" ><span class="glyphicon glyphicon-refresh"></span></a></center> + </h2> + </center> + </h2> + <br> + + + <center> + <table border="1"> + <tr> + <th style="text-align: center" width="33%">SUBSCRIBER: + {{globalCustomerId}}</th> + <th style="text-align: center" width="34%">SERVICE TYPE: + {{serviceType}}</th> + <th style="text-align: center" width="33%">SERVICE INSTANCE + ID: {{serviceInstanceId}}</th> + <tr> + <tr> + <td colspan='3' style="text-align: center">Service Instance + Name: {{serviceInstanceName || "Not defined"}} + </td> + <tr> + </table> + + </center> + + + <br> + + <div ng-init="autoPopulateViewEdit();"> + <script type="text/ng-template" id="nodes_renderer.html"> + <div ui-tree-handle data-drag-enabled="false" class="tree-node tree-node-content"> + <a class="btn btn-success btn-xs" ng-if="node.nodes && node.nodes.length > 0" data-nodrag ng-click="toggle(this)"><span + class="glyphicon" + ng-class="{ + 'glyphicon-chevron-right': collapsed, + 'glyphicon-chevron-down': !collapsed + }"></span></a> + <div class='btn'>{{node.nodeType}}</div><div class='btn'>{{node.nodeId}}</div><div class='btn'>{{node.nodeStatus}}</div> + + <a class="pull-right btn btn-danger btn-xs" ng-if="node.delete != false" data-nodrag ng-click="showVnfDetails(node);"><span class="glyphicon glyphicon-remove"></a> + <a class="pull-right btn btn-primary btn-xs" ng-if="node.info != false" data-nodrag ng-click="showVnfDetails();"><span + class="glyphicon glyphicon-zoom-in"></span></a> + + </div> + <ol ui-tree-nodes ng-model="node.nodes" ng-class="{hidden: collapsed}"> + <li ng-repeat="node in node.nodes" ui-tree-node ng-include="'nodes_renderer.html'"> + </li> + </ol> +</script> + <b>EXISTING</b> + <div ng-controller="TreeCtrl"> + <div> + <div ui-tree id="tree-root" > + <ol ui-tree-nodes ng-model="treeList""> + <li ng-repeat="node in treeList" ui-tree-node data-nodrag + ng-include="'nodes_renderer.html'"></li> + </ol> + </div> + </div> + + </div> + <b>AVAILABLE</b> + + <script type="text/ng-template" id="nodes_renderer2.html"> + <div ui-tree-handle data-drag-enabled="false" class="tree-node tree-node-content" > + <a class="btn btn-success btn-xs" ng-if="node.nodes && node.nodes.length > 0" data-nodrag ng-click="toggle(this)"><span + class="glyphicon" + ng-class="{ + 'glyphicon-chevron-right': collapsed, + 'glyphicon-chevron-down': !collapsed + }"></span></a> + <div class='btn'>{{node.nodeType}}</div><div class='btn'>{{node.nodeId}}</div><div class='btn'>{{node.nodeStatus}}</div> + + <a class="pull-right btn btn-primary btn-xs" ng-if="node.delete != false" data-nodrag ng-click="callDelete(this)"> + <span class="glyphicon glyphicon-plus"></span> + </a> + + <a class="pull-right btn btn-primary btn-xs" ng-if="node.info != false" data-nodrag ng-click="showInfoDialog(node.itemType, node.nodeId, node.nodeType);"> + <span class="glyphicon glyphicon-zoom-in"></span> + </a> + + </div> + <ol ui-tree-nodes ng-model="node.nodes" ng-class="{hidden: collapsed}"> + <li ng-repeat="node in node.nodes" ui-tree-node ng-include="'nodes_renderer2.html'"> + </li> + </ol> +</script> + + <div ng-controller="TreeCtrl"> + <div> + <div ui-tree id="tree-root"> + <ol ui-tree-nodes ng-model="availableTreeList"> + <li ng-repeat="node in availableTreeList" ui-tree-node + data-nodrag ng-include="'nodes_renderer2.html'"></li> + </ol> + </div> + </div> + </div> + </div> + <div> + + <button type="button" " att-button + btn-type="primary" size="small">Show Details</button> + + <pre> + {{inventoryResponseItem | json}} + </pre> + </div> + </div> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/creationDialog.htm b/vid/src/main/webapp/app/vid/scripts/view-models/creationDialog.htm new file mode 100644 index 000000000..d016b8f5d --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/creationDialog.htm @@ -0,0 +1,64 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + +<div ng-controller="creationDialogController"> + + <div ng-show="isDialogVisible"> + <div class="titleLine"> + <img src="app/vid/images/spinner.gif" + ngx-visible="{{isSpinnerVisible}}"></img> + <h3>Create {{componentName}}</h3> + </div> + + <div class="error" ng-show="isErrorVisible"> + <img src="app/vid/images/error.png"></img>{{error}} + </div> + + <div ngx-visible="{{isDataVisible}}"> + <parameter-block control="summaryControl"></parameter-block> + <h4> + User Provided Data (<img class="requiredIndicator" + src="app/vid/images/asterisk.png" height='10' width='10'></img> indicates required field) + </h4> + <parameter-block control="userProvidedControl" + callback="userParameterChanged(id);" editable></parameter-block> + + <div class="prompt"> + <p> + Enter Data and <span>Confirm</span> to<br />Create <span>{{componentName}}</span> + </p> + <p> + <span>Cancel</span> to Return to Previous Page.<br />Data entered + will be lost + </p> + </div> + + </div> + <div class="buttonRow"> + <button ngx-enabled="{{isConfirmEnabled}}" att-button size="small" + ng-click="confirm();">Confirm</button> + <button type="button" ng-click="cancel();" att-button + btn-type="primary" size="small">Cancel</button> + </div> + </div> + + <div ng-include="'app/vid/scripts/view-models/msoCommit.htm'"></div> + +</div> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/deletionDialog.htm b/vid/src/main/webapp/app/vid/scripts/view-models/deletionDialog.htm new file mode 100644 index 000000000..029d6eaa8 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/deletionDialog.htm @@ -0,0 +1,80 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + +<div ng-controller="deletionDialogController"> + + <div ng-show="isDialogVisible"> + <div class="titleLine"> + <img src="app/vid/images/spinner.gif" + ngx-visible="{{isSpinnerVisible}}"></img> + <h3>Delete {{componentName}}</h3> + </div> + + <div class="error" ng-show="isErrorVisible"> + <img src="app/vid/images/error.png"></img>{{error}} + </div> + + <parameter-block control="summaryControl"></parameter-block> + + <div ngx-visible="{{isDataVisible}}"> + + <h4> + User Provided Data (<img class="requiredIndicator" + src="app/vid/images/asterisk.png" height='10' width='10'></img> indicates required field) + </h4> + <parameter-block control="userProvidedControl" + callback="userParameterChanged(id);" editable></parameter-block> + + <div class="prompt"> + <p> + Enter Data and <span>Confirm</span> to<br />Delete <span>{{componentName}}</span> + </p> + <p> + <span>Cancel</span> to Return to Previous Page.<br />Data entered + will be lost + </p> + </div> + </div> + +<!-- + <div class="prompt"> + <p> + <span>Confirm</span> to Request<br />DELETION of <span>{{componentName}}</span> + </p> + <p> + <span>Cancel</span> to Return to Previous Page + </p> + </div> --> + + <div class="buttonRow"> + <!-- <button type="button" ng-click="confirm();" att-button + btn-type="primary" size="small" class="confirm">Confirm</button> + <button type="button" ng-click="cancel();" att-button + btn-type="primary" size="small">Cancel</button> ---> + <button ngx-enabled="{{isConfirmEnabled}}" att-button size="small" + ng-click="confirm();">Confirm</button> + <button type="button" ng-click="cancel();" att-button + btn-type="primary" size="small">Cancel</button> + </div> + </div> + + <div ng-include="'app/vid/scripts/view-models/msoCommit.htm'"></div> + +</div> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/detailsDialog.htm b/vid/src/main/webapp/app/vid/scripts/view-models/detailsDialog.htm new file mode 100644 index 000000000..82afcbf50 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/detailsDialog.htm @@ -0,0 +1,48 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + +<div ng-controller="detailsDialogController" ng-show="isDialogVisible"> + + <div class="titleLine"> + <img src="app/vid/images/spinner.gif" + ngx-visible="{{isSpinnerVisible}}"></img> + <h3>Service Instance Details</h3> <!-- {{componentName}} --> + </div> + + <div class="error" ng-show="isErrorVisible"> + <img src="app/vid/images/error.png"></img>{{error}} + </div> + + <parameter-block control="summaryControl"></parameter-block> + + <h4>{{componentName}} Details</h4> + + <parameter-block control="detailsControl"></parameter-block> + + <h4>Instantiation Transactions</h4> + + <pre class="log">{{log}}</pre> + + <div class="buttonRow"> + <button type="button" ng-click="close();" att-button + btn-type="primary" size="small">Close</button> + </div> + +</div> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/dummy.txt b/vid/src/main/webapp/app/vid/scripts/view-models/dummy.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/dummy.txt diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/instantiate.htm b/vid/src/main/webapp/app/vid/scripts/view-models/instantiate.htm new file mode 100644 index 000000000..1cfa4fb2d --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/instantiate.htm @@ -0,0 +1,204 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + +<div ng-controller="InstantiationController"> + + <div popup-window class="popupContents" ngx-show="{{popup.isVisible}}" + ng-cloak> + <div ng-include="'app/vid/scripts/view-models/creationDialog.htm'"></div> + <div ng-include="'app/vid/scripts/view-models/deletionDialog.htm'"></div> + <div ng-include="'app/vid/scripts/view-models/detailsDialog.htm'"></div> + </div> + <div ng-controller="aaiSubscriberController" ng-init="getComponentList() "> + <div class="statusLine" ng-class="{true:'aaiVisible', false:'aaiHidden'}[isSpinnerVisible]"> + <img src="app/vid/images/spinner.gif"></img> + <label>Status:</label><span class="status">{{status}}</span> + </div> + + <h1 class="heading1" style="margin-top: 20px;">View/Edit Service Instance</h1> + <a class="btn btn-primary btn-xs pull-right" ng-click="reloadRoute();" ><span class="glyphicon glyphicon-refresh"></span></a> + + <br> + + <center> + <table att-table border="1" ng-model="service"> + <tr> + <th style="text-align: center" width="33%">SUBSCRIBER: + {{service.instance.globalCustomerId}}</th> + <th style="text-align: center" width="34%">SERVICE TYPE: + {{service.instance.serviceType}}</th> + <th style="text-align: center" width="33%">SERVICE INSTANCE + ID: {{service.instance.serviceInstanceId}}</th> + <tr> + <tr> + <td colspan='3' style="text-align: center">Service Instance + Name: {{service.instance.name || "Not defined"}} + </td> + <tr> + </table> + + </center> + + <div ui-tree data-drag-enabled="false" data-nodrop-enabled="true" style="margin: 30px"> + + <ol ui-tree-nodes="" ng-model="service" > + <li ng-repeat="aService in [service]" ui-tree-node> + <div ui-tree-handle class="tree-node tree-node-content"> + <a class="btn btn-success btn-xs" ng-if="(aService.instance.vnfs && aService.instance.vnfs.length > 0) || (aService.instance.networks && aService.instance.networks.length > 0)" data-nodrag ng-click="this.toggle()"> + <span class="glyphicon" ng-class="{'glyphicon-chevron-right': collapsed,'glyphicon-chevron-down': !collapsed}"></span> + </a> + SERVICE INSTANCE: {{aService.instance.name}} + <a ng-if="aService.instance.vnfs.length == 0" class="pull-right btn btn-danger btn-xs" data-nodrag ng-click="deleteService(aService.instance);"> + <span class="glyphicon glyphicon-remove"></span> + </a> + + <div class="pull-right btn-group" ng-if="aService.model.vnfs && !equals(aService.model.vnfs, {})"> + <button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + Add VNF<span class="caret"></span> + </button> + <ul class="dropdown-menu" ng-model="aService.model.vnfs"> + <li role="menuitem" ng-repeat="(vnfUuid, vnf) in aService.model.vnfs"> + <!-- 9-21 --> + <!-- <a ng-click="addVnfInstance(this, aService.instance, vnf)">{{vnf.name}}</a>--> + <a ng-click="addVnfInstance(vnf)">{{vnf.name}}</a> + </li> + </ul> + </div> + <!-- <div class="pull-right btn-group" ng-if="aService.model.networks && !equals(aService.model.networks, {})"> + <button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + Add Network<span class="caret"></span> + </button> + <ul class="dropdown-menu" ng-model="aService.model.networks"> + <li ng-repeat="(networkUuid, network) in aService.model.networks"> + <a ng-click="addNetworkInstance(network)">{{network.name}}</a> + </li> + </ul> + </div> --> + <a class="pull-right btn btn-primary btn-xs" data-nodrag ng-click="describeService(aService.instance)" style="margin-right: 8px;"> + <span class="glyphicon glyphicon-info-sign"></span> + </a> + </div> + <ol ui-tree-nodes="" ng-model="aService.instance.vnfs" ng-class="{hidden: collapsed}"> + <li ng-repeat="vnf in aService.instance.vnfs" ui-tree-node> + <div ui-tree-handle class="tree-node tree-node-content"> + <a class="btn btn-success btn-xs" ng-if="(vnf.vfModules && vnf.vfModules.length > 0) || (vnf.volumeGroups && vnf.volumeGroups.length > 0)" data-nodrag ng-click="this.toggle()"> + <span class="glyphicon" ng-class="{'glyphicon-chevron-right': collapsed,'glyphicon-chevron-down': !collapsed}"></span> + </a> + VNF: {{vnf.name}} | TYPE: {{vnf.nodeType}} | ORCH STATUS: {{vnf.nodeStatus}} + <a ng-if="(vnf.vfModules.length == 0) && (vnf.volumeGroups.length == 0)" class="pull-right btn btn-danger btn-xs" data-nodrag ng-click="deleteVnf(aService.instance, vnf)"> + <span class="glyphicon glyphicon-remove"></span> + </a> + <div class="pull-right btn-group" ng-if="aService.modelByInvariantUuid.vnfs[vnf.object['persona-model-id']][vnf.object['persona-model-version']].vfModules"> + <button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + Add VF-Module<span class="caret"></span> + </button> + <ul class="dropdown-menu" ng-model="vnf"> + <li ng-repeat="(vfModuleInvariantUuid, vfModuleVersionModel) in aService.modelByInvariantUuid.vnfs[vnf.object['persona-model-id']][vnf.object['persona-model-version']].vfModules"> + <a ng-repeat="(vfModuleVersion, vfModule) in vfModuleVersionModel" ng-click="addVfModuleInstance(vnf, vfModule)">{{vfModule.name}}</a> + </li> + </ul> + </div> + <div class="pull-right btn-group" ng-if="aService.modelByInvariantUuid.vnfs[vnf.object['persona-model-id']][vnf.object['persona-model-version']].volumeGroups"> + <button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + Add Volume Group<span class="caret"></span> + </button> + <ul class="dropdown-menu" ng-model="vnf"> + <li ng-repeat="(volumeGroupInvariantUuid, volumeGroupVersionModel) in aService.modelByInvariantUuid.vnfs[vnf.object['persona-model-id']][vnf.object['persona-model-version']].volumeGroups"> + <a ng-repeat="(volumeGroupVersion, volumeGroup) in volumeGroupVersionModel" ng-click="addVolumeGroupInstance(vnf, volumeGroup)">{{volumeGroup.name}}</a> + </li> + </ul> + </div> + <a class="pull-right btn btn-primary btn-xs" data-nodrag ng-click="describeVnf(aService.instance, vnf)" style="margin-right: 8px;"> + <span class="glyphicon glyphicon-info-sign"></span> + </a> + </div> + <ol ui-tree-nodes="" ng-model="vnf.vfModules" ng-class="{hidden: collapsed}"> + <li ng-repeat="vfModule in vnf.vfModules" ui-tree-node> + <div ui-tree-handle class="tree-node tree-node-content"> + <a class="btn btn-success btn-xs" ng-if="(vfModule.volumeGroups && vfModule.volumeGroups.length > 0)" data-nodrag ng-click="this.toggle()"> + <span class="glyphicon" ng-class="{'glyphicon-chevron-right': collapsed,'glyphicon-chevron-down': !collapsed}"></span> + </a> + VFMODULE: {{vfModule.name}} | TYPE: {{vfModule.nodeType}} | ORCH STATUS: {{vfModule.nodeStatus}} + <!-- --> + <a class="pull-right btn btn-danger btn-xs" data-nodrag ng-click="deleteVfModule(aService.instance, vfModule, vnf)"> + <span class="glyphicon glyphicon-remove"></span> + </a> + <div class="pull-right btn-group"> + <!-- <button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + Attach Volume Group<span class="caret"></span> + </button> + <ul class="dropdown-menu" ng-model="vnf.volumeGroups"> + <li ng-repeat="volumeGroup in vnf.availableVolumeGroups"> + <a ng-click="attachVolumeGroupInstance(vfModule, volumeGroup)">{{volumeGroup.name}}</a> + </li> + </ul> --> + </div> + <a class="pull-right btn btn-primary btn-xs" data-nodrag ng-click="describeVfModule(aService.instance, vfModule)" style="margin-right: 8px;"> + <span class="glyphicon glyphicon-info-sign"></span> + </a> + </div> + <ol ui-tree-nodes="" ng-model="vfModule.volumeGroups" ng-class="{hidden: collapsed}"> + <li ng-repeat="volumeGroup in vfModule.volumeGroups" ui-tree-node> + <div ui-tree-handle class="tree-node tree-node-content"> + VOLUME GROUP: {{volumeGroup.name}} | TYPE: {{volumeGroup.nodeType}} | ORCH STATUS: {{volumeGroup.nodeStatus}} + <!-- <a class="pull-right btn btn-danger btn-xs" data-nodrag ng-click="deleteVolumeGroup(aService.instance, vnf, vfModule, volumeGroup)"> + <span class="glyphicon glyphicon-remove"></span> + </a> --> + <a class="pull-right btn btn-primary btn-xs" data-nodrag ng-click="describeVolumeGroup(aService.instance, volumeGroup)" style="margin-right: 8px;"> + <span class="glyphicon glyphicon-info-sign"></span> + </a> + </div> + </li> + </ol> + </li> + </ol> + <ol ui-tree-nodes="" ng-model="vnf.availableVolumeGroups" ng-class="{hidden: collapsed}"> + <li ng-repeat="volumeGroup in vnf.availableVolumeGroups" ui-tree-node> + <div ui-tree-handle class="tree-node tree-node-content"> + VOLUME GROUP: {{volumeGroup.name}} | TYPE: {{volumeGroup.nodeType}} | ORCH STATUS: {{volumeGroup.nodeStatus}} + <a class="pull-right btn btn-danger btn-xs" data-nodrag ng-click="deleteVnfVolumeGroup(aService.instance, vnf, volumeGroup)"> + <span class="glyphicon glyphicon-remove"></span> + </a> + <a class="pull-right btn btn-primary btn-xs" data-nodrag ng-click="describeVolumeGroup(aService.instance, volumeGroup)" style="margin-right: 8px;"> + <span class="glyphicon glyphicon-info-sign"></span> + </a> + </div> + </li> + </ol> + </li> + </ol> + <ol ui-tree-nodes="" ng-model="aService.instance.networks" ng-class="{hidden: collapsed}"> + <li ng-repeat="network in aService.instance.networks" ui-tree-node> + <div ui-tree-handle class="tree-node tree-node-content"> + NETWORK: {{network.name}} | TYPE: {{network.nodeType}} | ORCH STATUS: {{network.nodeStatus}} + <!-- <a class="pull-right btn btn-danger btn-xs" data-nodrag ng-click="deleteNetwork(aService.instance, network)"> + <span class="glyphicon glyphicon-remove"></span> + </a> --> + <a class="pull-right btn btn-primary btn-xs" data-nodrag ng-click="describeNetwork(aService.instance, network)" style="margin-right: 8px;"> + <span class="glyphicon glyphicon-info-sign"></span> + </a> + </div> + </li> + </ol> + </li> + </ol> + </div> + </div> +</div> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/msoCommit.htm b/vid/src/main/webapp/app/vid/scripts/view-models/msoCommit.htm new file mode 100644 index 000000000..a47b98323 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/msoCommit.htm @@ -0,0 +1,47 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + +<div ng-controller="msoCommitController" ng-show="isViewVisible"> + + <div class="statusLine"> + <img src="app/vid/images/spinner.gif" + ngx-visible="{{isSpinnerVisible}}"> </img> <label>Status:</label><span + class="status">{{status}}</span> + </div> + + <div class="feedback"> + + <div progress-bar control="progressBarControl" + value="{{percentProgress}}" increases-only="true" + ngx-show="{{isProgressVisible}}"></div> + + <div class="error" ng-show="!isProgressVisible"> + <img src="app/vid/images/error.png"></img>{{error}} + </div> + + </div> + + <pre class="log">{{log}}</pre> + + <div class="buttonRow"> + <button ngx-enabled="{{isCloseEnabled}}" att-button size="small" + ng-click="close();">Close</button> + </div> +</div> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/popupWindow.htm b/vid/src/main/webapp/app/vid/scripts/view-models/popupWindow.htm new file mode 100644 index 000000000..57c40f3f6 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/popupWindow.htm @@ -0,0 +1,8 @@ +<table + style="display: none; position: absolute; left: 0; top: 0; width: 100%; height: 100%; border-collapse: collapse; margin: 0; padding: 0"> + <tr> + <td align="center" style="vertical-align: top; padding: 10px"><div + style="display: inline-block; padding: 5px; background-color: white" + ng-transclude></div></td> + </tr> +</table> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/sample.html b/vid/src/main/webapp/app/vid/scripts/view-models/sample.html new file mode 100644 index 000000000..9cfb10e49 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/sample.html @@ -0,0 +1,61 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + +<div ng-controller="samplePageController"> + + <h1 class="heading1" style="margin-top:10px;">Profile Search</h1> + + <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage"> + + <thead att-table-row type="header"> + <tr> + <th att-table-header sortable="true" key="id">User ID</th> + <th att-table-header sortable="true" key="lastName">Last Name</th> + <th att-table-header sortable="true" key="firstName">First Name</th> + <th att-table-header sortable="true" key="email">Email</th> + <th att-table-header sortable="true" key="orgUserId">User ID</th> + <th att-table-header sortable="true" key="org_manager_userid">Manager User ID</th> + </tr> + </thead> + <tbody att-table-row type="body" row-repeat="rowData in tableData"> + <tr> + <td att-table-body ng-bind="rowData['id']"></td> + <td att-table-body ng-bind="rowData['lastName']"></td> + <td att-table-body ng-bind="rowData['firstName']"></td> + <td att-table-body ng-bind="rowData['email']"></td> + <td att-table-body ng-bind="rowData['orgUserId']"></td> + <td att-table-body ng-bind="rowData['managerId']"></td> + </tr> + </tbody> + </table> + + <div class="fn-ebz-container"> + Rows Per Page: + <input class="fn-ebz-text" readonly type="text" ng-model="viewPerPage" size="5" style="width: 47px;"> + </div> + <div class="fn-ebz-container"> + Current Page: + <input class="fn-ebz-text" type="text" ng-model="currentPageNum" size="5" style="width: 47px;"> + </div> + <div class="fn-ebz-container"> + Total Page(s): + <input class="fn-ebz-text" type="text" ng-model="totalPages" size="5" readonly="true" style="width: 47px;"> + </div> +</div> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/sampleWithIframe.html b/vid/src/main/webapp/app/vid/scripts/view-models/sampleWithIframe.html new file mode 100644 index 000000000..ea128ece8 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/sampleWithIframe.html @@ -0,0 +1,23 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + +<div ng-controller="samplePageWithIframeController" style="margin-left: auto;margin-right: auto;height:700px;"> + <iframe style="margin-top:5px;width:100%;height:100%" frameBorder="0" vspace="0" src="user_profile"></iframe> +</div> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/serviceModels.htm b/vid/src/main/webapp/app/vid/scripts/view-models/serviceModels.htm new file mode 100644 index 000000000..84f14ab6b --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/serviceModels.htm @@ -0,0 +1,90 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> +<link rel="stylesheet" type="text/css" href="app/vid/styles/serviceModels.css" /> +<div popup-window class="popupContents" ngx-show="{{popup.isVisible}}" ng-cloak> + <div ng-include="'app/vid/scripts/view-models/creationDialog.htm'"/> +</div> +<div> + + <span class="statusLine" ng-class="{true:'smcVisible', false:'smcHidden'}[isSpinnerVisible]"> + <img src="app/vid/images/spinner.gif"></img> + </span> + <span class="statusLine" ng-class="{true:'progVisible', false:'progHidden'}[isProgressVisible]"> + <label>Status:</label><span class="status"><span ng-show="error"><font color='red'><b>Error: </b></font></span>{{status}}</span> + </span> + <br><br> + + <div class="fn-ebz-container"> + Filter: + <input class="fn-ebz-text" type="text" ng-model="searchString" size="20" style="width: 250px;"> + </div> + + <h1 class="heading1" style="margin-top:20px;">Browse SDC Service Models</h1> + <div style="margin-top:30px" ng-init="getServiceModels();"> + + <table att-table table-data="services" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage"> + <thead att-table-row type="header"> + <tr> + <th att-table-header key="action">Action</th> + <th att-table-header key="uuid">UUID</th> + <th att-table-header key="invariantUUID">Invariant UUID</th> + <th att-table-header default-sort="A" key="name">Name</th> + <th att-table-header key="version">Version</th> + <th att-table-header key="category">Category</th> + <th att-table-header key="distributionStatus">Distribution Status</th> + <th att-table-header key="lastUpdaterUserId">Last Updated By</th> + <th att-table-header key="toscaModelUrl">Tosca Model</th> + </tr> + </thead> + <tbody att-table-row type="body" row-repeat="service in services"> + <tr> + <td att-table-body ><button type=button ng-click="deployService(service)" att-button btn-type="primary" size="small">Deploy</button></td> + <td att-table-body ng-bind="service['uuid']"></td> + <td att-table-body ng-bind="service['invariantUUID']"></td> + <td att-table-body ng-bind="service['name']"></td> + <td att-table-body ng-bind="service['version']"></td> + <td att-table-body ng-bind="service['category']"></td> + <td att-table-body ng-bind="service['distributionStatus']"></td> + <td att-table-body ng-bind="service['lastUpdaterUserId']"></td> + <td att-table-body ng-bind="service['toscaModelUrl']"></td> + </tr> + </tbody> + </table> + <table width='100%'> + <tr> + <td width='33%' valign='middle'> + <span style="cursor: pointer" ng-if="currentPage>1"><button att-button size="small" ng-click="prevPage();">< prev page</button></span> + </td> + <td width='33%' valign='middle'> + Jump to page: + <input class="fn-ebz-text" type="text" ng-model="currentPage" size="5" style="width: 47px;"> + Results per page: <span style="cursor: pointer" ng-click="viewPerPage = 10" ng-style="viewPerPage === 10 && {'textDecoration':'underline','text-color':'black'}">10</span> + | <span style="cursor: pointer" ng-click="viewPerPage = 25" ng-style="viewPerPage === 25 && {'textDecoration':'underline','text-color':'black'}">25</span> + | <span style="cursor: pointer" ng-click="viewPerPage = 50" ng-style="viewPerPage === 50 && {'textDecoration':'underline','text-color':'black'}">50</span> + </td> + <td width='34%' align='right' valign='middle'> + <span style="cursor: pointer" ng-if="currentPage<totalPage"><button att-button ng-click="nextPage();">next page ></button></span> + </td> + </tr> + </table> + + </div> + </div> + diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/singlePageSample.html b/vid/src/main/webapp/app/vid/scripts/view-models/singlePageSample.html new file mode 100644 index 000000000..0e6c6f2a4 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/singlePageSample.html @@ -0,0 +1,87 @@ +<!DOCTYPE html> +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + +<html> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=edge" /> + <meta http-equiv="cache-control" content="max-age=0" /> + <meta http-equiv="cache-control" content="no-cache" /> + <meta http-equiv="expires" content="0" /> + <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" /> + <meta http-equiv="pragma" content="no-cache" /> + <!-- CSS --> + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/fn-ebz.css" > + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/demo.css" > + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/base.css" > + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/btn.css" > + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/dtpk.css" > + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/frms.css" > + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/sldr.css" > + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/style.css" > + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/tbs.css" > + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/portal_ebz_header.css"> + <link rel="stylesheet" type="text/css" href="static/fusion/css/jquery-ui.css"> + <!-- Basic AngularJS --> + <script src= "app/fusion/external/ebz/angular_js/angular.js"></script> + <script src= "app/fusion/external/ebz/angular_js/angular-sanitize.js"></script> + <script src= "app/fusion/external/ebz/angular_js/angular-route.min.js"></script> + <script src= "app/fusion/external/ebz/angular_js/app.js"></script> + <script src= "app/fusion/external/ebz/angular_js/gestures.js"></script> + <script src= "app/fusion/external/ebz/sandbox/att-abs-tpls.js" type="text/javascript"></script> + <!-- jQuery --> + <script src="static/js/jquery-1.10.2.js"></script> + <script src="static/js/jquery.mask.min.js" type="text/javascript"></script> + <script src="static/js/jquery-ui.js" type="text/javascript"></script> + <!-- AngularJS Gridster --> + <script src="static/fusion/js/att_angular_gridster/ui-gridster-tpls.js"></script> + <script src="static/fusion/js/att_angular_gridster/angular-gridster.js"></script> + <!-- AngularJS Config --> + <script src= "app/fusion/external/ebz/angular_js/app.js"></script> + <script src= "app/fusion/external/ebz/angular_js/checklist-model.js"></script> + <!-- Utility --> + <script src="app/fusion/scripts/modalService.js"></script> + <!-- Controller js --> + <script src="app/fusion/scripts/controllers/rolefunctionpopupController.js"></script> + <script src="app/fusion/scripts/controllers/modelpopupController.js"></script> + <script src="app/fusionapp/scripts/controller/sampleController.js"></script> + <script src="app/fusionapp/scripts/controller/sample-page-controller.js"></script> + <script src="app/fusionapp/scripts/controller/sample-page-iframe-controller.js"></script> + <!-- Header and Footer --> + + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/header.css"> + <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/footer.css" > + <script src="app/fusion/scripts/directives/footer.js"></script> + <script src="app/fusion/external/ebz/js/footer.js"></script> + <script src="app/fusion/scripts/directives/header.js"></script> + <script src="app/fusion/scripts/directives/leftMenu.js"></script> + <!-- Services --> + <script src="app/fusion/scripts/services/profileService.js"></script> + + </head> + <body class="appBody" ng-app="abs"> + <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html'"></div> + <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal.html'"></div> + <div q-header></div> + <div q-menu class="appLeftMenu"></div> + <div ng-view style="min-height: 450px;margin-top:-50px;margin-left:210px;margin-right:10px;"></div> + <div q-footer class="appFooter"></div> + </body> +</html> diff --git a/vid/src/main/webapp/app/vid/scripts/view-models/vidhome.htm b/vid/src/main/webapp/app/vid/scripts/view-models/vidhome.htm new file mode 100644 index 000000000..41b3b2a77 --- /dev/null +++ b/vid/src/main/webapp/app/vid/scripts/view-models/vidhome.htm @@ -0,0 +1,39 @@ +<!-- + ============LICENSE_START======================================================= + VID + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed 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. + ============LICENSE_END========================================================= + --> + +<div> + <h1 class="heading1">OpenECOMP</h1> + <br> + <h1 class="heading1"><u>Welcome to VID</u></h1> + <br> + The Virtual Infrastructure Deployment (VID) application allows infrastructure service deployment operators + to instantiate service instances and their constituent parts for Distributed service models required by the + OpenECOMP service operations that manage them, such as Mobility Network Services, etc. The models are defined by OpenECOMP component SDC. The service + deployment operator selects the service operations owner and model that they wish to instantiate. After + entry of appropriate data, the operator instructs VID to direct another OpenECOMP component, MSO, to instantiate + the selected service model. Once the service instance has been instantiated, the service operator can instruct + VID to direct MSO to instantiate the service instance's component VNFs, VF Modules, Networks and Volume Groups. + The VID user can also search for, and display, existing service instances and direct the instantiation of + subsequent instance components. + <br><br> + + <h1 class="heading1"><a href="mailto:portal@lists.openecomp.org" target="_top">Contact Us</a></h1> + <a href="mailto:portal@lists.openecomp.org" target="_top">Please click here to contact us.</a> +</div> |