diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..b4867fd72 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +*/node_modules/ +*/*/node_modules/ +.git/ +.dockerignore +Dockerfile diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..843c9e967 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,74 @@ +3.5.0 - November 10th , 2016 +---------------------------- +* Cloud Management - Capacity Report +* Telemetry Enhancements - SAE Dashboards +* Improved 'Design' page written in AngularJS +* Bots Library + +3.4.0 - SEptember 2nd , 2016 +---------------------------- +* Cloud Management - Daily/Weekly/Monthly cost and usage reports and trends +* Provider wise listing of unassigned instances in track +* New Wizard for setup +* Audit Trail for docker containers + + +3.3.0 - August 11th , 2016 +---------------------------- +* Composite blueprints enhancements +* Audit log trail implementation +* Script executor implementation +* Chef node import improvements +* Critical Bug Fixes + +3.2.1 - July 8th , 2016 +---------------------------- +* Composite blueprints implementation - To design and launch a complete application stack +* Critical Bug Fixes + +3.1.0 - June 14th, 2016 +---------------------------- +* Improved GUI with AngularJS +* Script Executor to enbale execution of shell scripts on selected instances +* Role based discovery of instances +* RDS and S3 Report from AWS Account + +3.0.6 - May 10th, 2016 +---------------------------- +* Update AWS tags from Catalyst +* Instance Level Cost and Usage Dashboards +* Option to edit and clone blueprints +* Attribute Editor for Blueprints + +3.0.5 - April 15th, 2016 +---------------------------- +* AWS tag based allocation of instances +* Promote feature for Application Deployments + +3.0.4 - March 21st, 2016 +---------------------------- +* Introducing IAM based authorization to AWS account +* Import Instances from AWS +* Application Deployment using Blueprints + +3.0.3 - March 7th, 2016 +---------------------------- +* Hardening application deployment history +* Security Fixes + +3.0.2 - February 26th, 2016 +---------------------------- +* Security Fixes +* Dashboards for AWS Summary and Cost + +3.0.1 - February 24th, 2016 +--------------------------- +* VMware Support - VM provisioning and management +* Bootstrap instances with Puppet + +3.0.0 - February 22nd, 2016 +--------------------------- + +Docs : http://catalyst.readthedocs.org + +* Initial public release diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..f923c0c25 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,33 @@ +FROM node:4.6.0 +RUN apt-get update -qq && apt-get install -y build-essential libpq-dev libkrb5-dev make g++ ruby libstdc++6 + +RUN npm install -g kerberos + +##Client +RUN npm install -g grunt-cli +RUN npm install -g npm +RUN npm install forever --global +RUN gem install sass +RUN curl -L https://www.opscode.com/chef/install.sh | bash + +RUN mkdir -p /rlc/client +RUN mkdir -p /rlc/server + +## Client +ADD ./client/cat3 /rlc/client/cat3 +ADD ./client/htmls /rlc/client/htmls +WORKDIR /rlc/client/cat3 +RUN npm install --production +RUN npm run-script build-prod + +## Server +WORKDIR /rlc/server +ADD ./server /rlc/server +RUN node install.js + +EXPOSE 3001 + +## Server App +# CMD forever start app.js +WORKDIR /rlc/server/app +CMD node app.js diff --git a/client/cat3/main.html b/client/cat3/main.html index 7aee82223..b3619babc 100644 --- a/client/cat3/main.html +++ b/client/cat3/main.html @@ -36,9 +36,6 @@ - - - @@ -111,6 +108,7 @@ + diff --git a/client/cat3/src/main.js b/client/cat3/src/main.js index 2720b2867..b1dc91af7 100644 --- a/client/cat3/src/main.js +++ b/client/cat3/src/main.js @@ -12,7 +12,7 @@ * All modules/feature will be through * */ -var angularApp = angular.module('catapp', ['ui.router','ngTouch','toastr','firebase', +var angularApp = angular.module('catapp', ['ui.router','ngTouch','toastr', 'global.login', 'global.breadcrumb', 'authentication', @@ -34,12 +34,6 @@ var angularApp = angular.module('catapp', ['ui.router','ngTouch','toastr','fireb angularApp.run(['$rootScope', 'auth', '$state', '$stateParams','$http','$window', function ($rootScope, Auth, $state, $stateParams,$http) { 'use strict'; - $http.get('/organizations/getTreeNew').success(function () { - // if(result.data && result.data.length >0){ - // console.log(result); - // $window.location.href="/private/index.html#ajax/Settings/Dashboard.html"; - // } - }); $rootScope.$on('$stateChangeStart', function (event, toState) { //More function params: function (event, toState, toParams, fromState, fromParams) function checkAuthentication() { diff --git a/client/cat3/src/partials/globals/drag-and-drop/angular-drag-and-drop-lists.min.js b/client/cat3/src/partials/globals/drag-and-drop/angular-drag-and-drop-lists.min.js deleted file mode 100644 index 46c5a2d4a..000000000 --- a/client/cat3/src/partials/globals/drag-and-drop/angular-drag-and-drop-lists.min.js +++ /dev/null @@ -1,590 +0,0 @@ -/** - * angular-drag-and-drop-lists v1.4.0 - * - * Copyright (c) 2014 Marcel Juenemann marcel@juenemann.cc - * Copyright (c) 2014-2016 Google Inc. - * https://github.com/marceljuenemann/angular-drag-and-drop-lists - * - * License: MIT - */ -angular.module('dndLists', []) - - /** - * Use the dnd-draggable attribute to make your element draggable - * - * Attributes: - * - dnd-draggable Required attribute. The value has to be an object that represents the data - * of the element. In case of a drag and drop operation the object will be - * serialized and unserialized on the receiving end. - * - dnd-selected Callback that is invoked when the element was clicked but not dragged. - * The original click event will be provided in the local event variable. - * - dnd-effect-allowed Use this attribute to limit the operations that can be performed. Options: - * - "move": The drag operation will move the element. This is the default. - * - "copy": The drag operation will copy the element. Shows a copy cursor. - * - "copyMove": The user can choose between copy and move by pressing the - * ctrl or shift key. *Not supported in IE:* In Internet Explorer this - * option will be the same as "copy". *Not fully supported in Chrome on - * Windows:* In the Windows version of Chrome the cursor will always be the - * move cursor. However, when the user drops an element and has the ctrl - * key pressed, we will perform a copy anyways. - * - HTML5 also specifies the "link" option, but this library does not - * actively support it yet, so use it at your own risk. - * - dnd-moved Callback that is invoked when the element was moved. Usually you will - * remove your element from the original list in this callback, since the - * directive is not doing that for you automatically. The original dragend - * event will be provided in the local event variable. - * - dnd-canceled Callback that is invoked if the element was dragged, but the operation was - * canceled and the element was not dropped. The original dragend event will - * be provided in the local event variable. - * - dnd-copied Same as dnd-moved, just that it is called when the element was copied - * instead of moved. The original dragend event will be provided in the local - * event variable. - * - dnd-dragstart Callback that is invoked when the element was dragged. The original - * dragstart event will be provided in the local event variable. - * - dnd-dragend Callback that is invoked when the drag operation ended. Available local - * variables are event and dropEffect. - * - dnd-type Use this attribute if you have different kinds of items in your - * application and you want to limit which items can be dropped into which - * lists. Combine with dnd-allowed-types on the dnd-list(s). This attribute - * should evaluate to a string, although this restriction is not enforced. - * - dnd-disable-if You can use this attribute to dynamically disable the draggability of the - * element. This is useful if you have certain list items that you don't want - * to be draggable, or if you want to disable drag & drop completely without - * having two different code branches (e.g. only allow for admins). - * **Note**: If your element is not draggable, the user is probably able to - * select text or images inside of it. Since a selection is always draggable, - * this breaks your UI. You most likely want to disable user selection via - * CSS (see user-select). - * - * CSS classes: - * - dndDragging This class will be added to the element while the element is being - * dragged. It will affect both the element you see while dragging and the - * source element that stays at it's position. Do not try to hide the source - * element with this class, because that will abort the drag operation. - * - dndDraggingSource This class will be added to the element after the drag operation was - * started, meaning it only affects the original element that is still at - * it's source position, and not the "element" that the user is dragging with - * his mouse pointer. - */ - .directive('dndDraggable', ['$parse', '$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround', - function($parse, $timeout, dndDropEffectWorkaround, dndDragTypeWorkaround) { - return function(scope, element, attr) { - // Set the HTML5 draggable attribute on the element - element.attr("draggable", "true"); - - // If the dnd-disable-if attribute is set, we have to watch that - if (attr.dndDisableIf) { - scope.$watch(attr.dndDisableIf, function(disabled) { - element.attr("draggable", !disabled); - }); - } - - /** - * When the drag operation is started we have to prepare the dataTransfer object, - * which is the primary way we communicate with the target element - */ - element.on('dragstart', function(event) { - event = event.originalEvent || event; - - // Check whether the element is draggable, since dragstart might be triggered on a child. - if (element.attr('draggable') == 'false') return true; - - // Serialize the data associated with this element. IE only supports the Text drag type - event.dataTransfer.setData("Text", angular.toJson(scope.$eval(attr.dndDraggable))); - - // Only allow actions specified in dnd-effect-allowed attribute - event.dataTransfer.effectAllowed = attr.dndEffectAllowed || "move"; - - // Add CSS classes. See documentation above - element.addClass("dndDragging"); - $timeout(function() { element.addClass("dndDraggingSource"); }, 0); - - // Workarounds for stupid browsers, see description below - dndDropEffectWorkaround.dropEffect = "none"; - dndDragTypeWorkaround.isDragging = true; - - // Save type of item in global state. Usually, this would go into the dataTransfer - // typename, but we have to use "Text" there to support IE - dndDragTypeWorkaround.dragType = attr.dndType ? scope.$eval(attr.dndType) : undefined; - - // Try setting a proper drag image if triggered on a dnd-handle (won't work in IE). - if (event._dndHandle && event.dataTransfer.setDragImage) { - event.dataTransfer.setDragImage(element[0], 0, 0); - } - - // Invoke callback - $parse(attr.dndDragstart)(scope, {event: event}); - - event.stopPropagation(); - }); - - /** - * The dragend event is triggered when the element was dropped or when the drag - * operation was aborted (e.g. hit escape button). Depending on the executed action - * we will invoke the callbacks specified with the dnd-moved or dnd-copied attribute. - */ - element.on('dragend', function(event) { - event = event.originalEvent || event; - - // Invoke callbacks. Usually we would use event.dataTransfer.dropEffect to determine - // the used effect, but Chrome has not implemented that field correctly. On Windows - // it always sets it to 'none', while Chrome on Linux sometimes sets it to something - // else when it's supposed to send 'none' (drag operation aborted). - var dropEffect = dndDropEffectWorkaround.dropEffect; - scope.$apply(function() { - switch (dropEffect) { - case "move": - $parse(attr.dndMoved)(scope, {event: event}); - break; - case "copy": - $parse(attr.dndCopied)(scope, {event: event}); - break; - case "none": - $parse(attr.dndCanceled)(scope, {event: event}); - break; - } - $parse(attr.dndDragend)(scope, {event: event, dropEffect: dropEffect}); - }); - - // Clean up - element.removeClass("dndDragging"); - $timeout(function() { element.removeClass("dndDraggingSource"); }, 0); - dndDragTypeWorkaround.isDragging = false; - event.stopPropagation(); - }); - - /** - * When the element is clicked we invoke the callback function - * specified with the dnd-selected attribute. - */ - element.on('click', function(event) { - if (!attr.dndSelected) return; - - event = event.originalEvent || event; - scope.$apply(function() { - $parse(attr.dndSelected)(scope, {event: event}); - }); - - // Prevent triggering dndSelected in parent elements. - event.stopPropagation(); - }); - - /** - * Workaround to make element draggable in IE9 - */ - element.on('selectstart', function() { - if (this.dragDrop) this.dragDrop(); - }); - }; - }]) - - /** - * Use the dnd-list attribute to make your list element a dropzone. Usually you will add a single - * li element as child with the ng-repeat directive. If you don't do that, we will not be able to - * position the dropped element correctly. If you want your list to be sortable, also add the - * dnd-draggable directive to your li element(s). Both the dnd-list and it's direct children must - * have position: relative CSS style, otherwise the positioning algorithm will not be able to - * determine the correct placeholder position in all browsers. - * - * Attributes: - * - dnd-list Required attribute. The value has to be the array in which the data of - * the dropped element should be inserted. - * - dnd-allowed-types Optional array of allowed item types. When used, only items that had a - * matching dnd-type attribute will be dropable. - * - dnd-disable-if Optional boolean expresssion. When it evaluates to true, no dropping - * into the list is possible. Note that this also disables rearranging - * items inside the list. - * - dnd-horizontal-list Optional boolean expresssion. When it evaluates to true, the positioning - * algorithm will use the left and right halfs of the list items instead of - * the upper and lower halfs. - * - dnd-dragover Optional expression that is invoked when an element is dragged over the - * list. If the expression is set, but does not return true, the element is - * not allowed to be dropped. The following variables will be available: - * - event: The original dragover event sent by the browser. - * - index: The position in the list at which the element would be dropped. - * - type: The dnd-type set on the dnd-draggable, or undefined if unset. - * - external: Whether the element was dragged from an external source. - * - dnd-drop Optional expression that is invoked when an element is dropped on the - * list. The following variables will be available: - * - event: The original drop event sent by the browser. - * - index: The position in the list at which the element would be dropped. - * - item: The transferred object. - * - type: The dnd-type set on the dnd-draggable, or undefined if unset. - * - external: Whether the element was dragged from an external source. - * The return value determines the further handling of the drop: - * - false: The drop will be canceled and the element won't be inserted. - * - true: Signalises that the drop is allowed, but the dnd-drop - * callback already took care of inserting the element. - * - otherwise: All other return values will be treated as the object to - * insert into the array. In most cases you want to simply return the - * item parameter, but there are no restrictions on what you can return. - * - dnd-inserted Optional expression that is invoked after a drop if the element was - * actually inserted into the list. The same local variables as for - * dnd-drop will be available. Note that for reorderings inside the same - * list the old element will still be in the list due to the fact that - * dnd-moved was not called yet. - * - dnd-external-sources Optional boolean expression. When it evaluates to true, the list accepts - * drops from sources outside of the current browser tab. This allows to - * drag and drop accross different browser tabs. Note that this will allow - * to drop arbitrary text into the list, thus it is highly recommended to - * implement the dnd-drop callback to check the incoming element for - * sanity. Furthermore, the dnd-type of external sources can not be - * determined, therefore do not rely on restrictions of dnd-allowed-type. - * - * CSS classes: - * - dndPlaceholder When an element is dragged over the list, a new placeholder child - * element will be added. This element is of type li and has the class - * dndPlaceholder set. Alternatively, you can define your own placeholder - * by creating a child element with dndPlaceholder class. - * - dndDragover Will be added to the list while an element is dragged over the list. - */ - .directive('dndList', ['$parse', '$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround', - function($parse, $timeout, dndDropEffectWorkaround, dndDragTypeWorkaround) { - return function(scope, element, attr) { - // While an element is dragged over the list, this placeholder element is inserted - // at the location where the element would be inserted after dropping - var placeholder = getPlaceholderElement(); - var placeholderNode = placeholder[0]; - var listNode = element[0]; - placeholder.remove(); - - var horizontal = attr.dndHorizontalList && scope.$eval(attr.dndHorizontalList); - var externalSources = attr.dndExternalSources && scope.$eval(attr.dndExternalSources); - - /** - * The dragenter event is fired when a dragged element or text selection enters a valid drop - * target. According to the spec, we either need to have a dropzone attribute or listen on - * dragenter events and call preventDefault(). It should be noted though that no browser seems - * to enforce this behaviour. - */ - element.on('dragenter', function (event) { - event = event.originalEvent || event; - if (!isDropAllowed(event)) return true; - event.preventDefault(); - }); - - /** - * The dragover event is triggered "every few hundred milliseconds" while an element - * is being dragged over our list, or over an child element. - */ - element.on('dragover', function(event) { - event = event.originalEvent || event; - - if (!isDropAllowed(event)) return true; - - // First of all, make sure that the placeholder is shown - // This is especially important if the list is empty - if (placeholderNode.parentNode != listNode) { - element.append(placeholder); - } - - if (event.target !== listNode) { - // Try to find the node direct directly below the list node. - var listItemNode = event.target; - while (listItemNode.parentNode !== listNode && listItemNode.parentNode) { - listItemNode = listItemNode.parentNode; - } - - if (listItemNode.parentNode === listNode && listItemNode !== placeholderNode) { - // If the mouse pointer is in the upper half of the child element, - // we place it before the child element, otherwise below it. - if (isMouseInFirstHalf(event, listItemNode)) { - listNode.insertBefore(placeholderNode, listItemNode); - } else { - listNode.insertBefore(placeholderNode, listItemNode.nextSibling); - } - } - } else { - // This branch is reached when we are dragging directly over the list element. - // Usually we wouldn't need to do anything here, but the IE does not fire it's - // events for the child element, only for the list directly. Therefore, we repeat - // the positioning algorithm for IE here. - if (isMouseInFirstHalf(event, placeholderNode, true)) { - // Check if we should move the placeholder element one spot towards the top. - // Note that display none elements will have offsetTop and offsetHeight set to - // zero, therefore we need a special check for them. - while (placeholderNode.previousElementSibling - && (isMouseInFirstHalf(event, placeholderNode.previousElementSibling, true) - || placeholderNode.previousElementSibling.offsetHeight === 0)) { - listNode.insertBefore(placeholderNode, placeholderNode.previousElementSibling); - } - } else { - // Check if we should move the placeholder element one spot towards the bottom - while (placeholderNode.nextElementSibling && - !isMouseInFirstHalf(event, placeholderNode.nextElementSibling, true)) { - listNode.insertBefore(placeholderNode, - placeholderNode.nextElementSibling.nextElementSibling); - } - } - } - - // At this point we invoke the callback, which still can disallow the drop. - // We can't do this earlier because we want to pass the index of the placeholder. - if (attr.dndDragover && !invokeCallback(attr.dndDragover, event, getPlaceholderIndex())) { - return stopDragover(); - } - - element.addClass("dndDragover"); - event.preventDefault(); - event.stopPropagation(); - return false; - }); - - /** - * When the element is dropped, we use the position of the placeholder element as the - * position where we insert the transferred data. This assumes that the list has exactly - * one child element per array element. - */ - element.on('drop', function(event) { - event = event.originalEvent || event; - - if (!isDropAllowed(event)) return true; - - // The default behavior in Firefox is to interpret the dropped element as URL and - // forward to it. We want to prevent that even if our drop is aborted. - event.preventDefault(); - - // Unserialize the data that was serialized in dragstart. According to the HTML5 specs, - // the "Text" drag type will be converted to text/plain, but IE does not do that. - var data = event.dataTransfer.getData("Text") || event.dataTransfer.getData("text/plain"); - var transferredObject; - try { - transferredObject = JSON.parse(data); - } catch(e) { - return stopDragover(); - } - - // Invoke the callback, which can transform the transferredObject and even abort the drop. - var index = getPlaceholderIndex(); - if (attr.dndDrop) { - transferredObject = invokeCallback(attr.dndDrop, event, index, transferredObject); - if (!transferredObject) { - return stopDragover(); - } - } - - // Insert the object into the array, unless dnd-drop took care of that (returned true). - if (transferredObject !== true) { - scope.$apply(function() { - scope.$eval(attr.dndList).splice(index, 0, transferredObject); - }); - } - invokeCallback(attr.dndInserted, event, index, transferredObject); - - // In Chrome on Windows the dropEffect will always be none... - // We have to determine the actual effect manually from the allowed effects - if (event.dataTransfer.dropEffect === "none") { - if (event.dataTransfer.effectAllowed === "copy" || - event.dataTransfer.effectAllowed === "move") { - dndDropEffectWorkaround.dropEffect = event.dataTransfer.effectAllowed; - } else { - dndDropEffectWorkaround.dropEffect = event.ctrlKey ? "copy" : "move"; - } - } else { - dndDropEffectWorkaround.dropEffect = event.dataTransfer.dropEffect; - } - - // Clean up - stopDragover(); - event.stopPropagation(); - return false; - }); - - /** - * We have to remove the placeholder when the element is no longer dragged over our list. The - * problem is that the dragleave event is not only fired when the element leaves our list, - * but also when it leaves a child element -- so practically it's fired all the time. As a - * workaround we wait a few milliseconds and then check if the dndDragover class was added - * again. If it is there, dragover must have been called in the meantime, i.e. the element - * is still dragging over the list. If you know a better way of doing this, please tell me! - */ - element.on('dragleave', function(event) { - event = event.originalEvent || event; - - element.removeClass("dndDragover"); - $timeout(function() { - if (!element.hasClass("dndDragover")) { - placeholder.remove(); - } - }, 100); - }); - - /** - * Checks whether the mouse pointer is in the first half of the given target element. - * - * In Chrome we can just use offsetY, but in Firefox we have to use layerY, which only - * works if the child element has position relative. In IE the events are only triggered - * on the listNode instead of the listNodeItem, therefore the mouse positions are - * relative to the parent element of targetNode. - */ - function isMouseInFirstHalf(event, targetNode, relativeToParent) { - var mousePointer = horizontal ? (event.offsetX || event.layerX) - : (event.offsetY || event.layerY); - var targetSize = horizontal ? targetNode.offsetWidth : targetNode.offsetHeight; - var targetPosition = horizontal ? targetNode.offsetLeft : targetNode.offsetTop; - targetPosition = relativeToParent ? targetPosition : 0; - return mousePointer < targetPosition + targetSize / 2; - } - - /** - * Tries to find a child element that has the dndPlaceholder class set. If none was found, a - * new li element is created. - */ - function getPlaceholderElement() { - var placeholder; - angular.forEach(element.children(), function(childNode) { - var child = angular.element(childNode); - if (child.hasClass('dndPlaceholder')) { - placeholder = child; - } - }); - return placeholder || angular.element("
  • "); - } - - /** - * We use the position of the placeholder node to determine at which position of the array the - * object needs to be inserted - */ - function getPlaceholderIndex() { - return Array.prototype.indexOf.call(listNode.children, placeholderNode); - } - - /** - * Checks various conditions that must be fulfilled for a drop to be allowed - */ - function isDropAllowed(event) { - // Disallow drop from external source unless it's allowed explicitly. - if (!dndDragTypeWorkaround.isDragging && !externalSources) return false; - - // Check mimetype. Usually we would use a custom drag type instead of Text, but IE doesn't - // support that. - if (!hasTextMimetype(event.dataTransfer.types)) return false; - - // Now check the dnd-allowed-types against the type of the incoming element. For drops from - // external sources we don't know the type, so it will need to be checked via dnd-drop. - if (attr.dndAllowedTypes && dndDragTypeWorkaround.isDragging) { - var allowed = scope.$eval(attr.dndAllowedTypes); - if (angular.isArray(allowed) && allowed.indexOf(dndDragTypeWorkaround.dragType) === -1) { - return false; - } - } - - // Check whether droping is disabled completely - if (attr.dndDisableIf && scope.$eval(attr.dndDisableIf)) return false; - - return true; - } - - /** - * Small helper function that cleans up if we aborted a drop. - */ - function stopDragover() { - placeholder.remove(); - element.removeClass("dndDragover"); - return true; - } - - /** - * Invokes a callback with some interesting parameters and returns the callbacks return value. - */ - function invokeCallback(expression, event, index, item) { - return $parse(expression)(scope, { - event: event, - index: index, - item: item || undefined, - external: !dndDragTypeWorkaround.isDragging, - type: dndDragTypeWorkaround.isDragging ? dndDragTypeWorkaround.dragType : undefined - }); - } - - /** - * Check if the dataTransfer object contains a drag type that we can handle. In old versions - * of IE the types collection will not even be there, so we just assume a drop is possible. - */ - function hasTextMimetype(types) { - if (!types) return true; - for (var i = 0; i < types.length; i++) { - if (types[i] === "Text" || types[i] === "text/plain") return true; - } - - return false; - } - }; - }]) - - /** - * Use the dnd-nodrag attribute inside of dnd-draggable elements to prevent them from starting - * drag operations. This is especially useful if you want to use input elements inside of - * dnd-draggable elements or create specific handle elements. Note: This directive does not work - * in Internet Explorer 9. - */ - .directive('dndNodrag', function() { - return function(scope, element, attr) { - // Set as draggable so that we can cancel the events explicitly - element.attr("draggable", "true"); - - /** - * Since the element is draggable, the browser's default operation is to drag it on dragstart. - * We will prevent that and also stop the event from bubbling up. - */ - element.on('dragstart', function(event) { - event = event.originalEvent || event; - - if (!event._dndHandle) { - // If a child element already reacted to dragstart and set a dataTransfer object, we will - // allow that. For example, this is the case for user selections inside of input elements. - if (!(event.dataTransfer.types && event.dataTransfer.types.length)) { - event.preventDefault(); - } - event.stopPropagation(); - } - }); - - /** - * Stop propagation of dragend events, otherwise dnd-moved might be triggered and the element - * would be removed. - */ - element.on('dragend', function(event) { - event = event.originalEvent || event; - if (!event._dndHandle) { - event.stopPropagation(); - } - }); - }; - }) - - /** - * Use the dnd-handle directive within a dnd-nodrag element in order to allow dragging with that - * element after all. Therefore, by combining dnd-nodrag and dnd-handle you can allow - * dnd-draggable elements to only be dragged via specific "handle" elements. Note that Internet - * Explorer will show the handle element as drag image instead of the dnd-draggable element. You - * can work around this by styling the handle element differently when it is being dragged. Use - * the CSS selector .dndDragging:not(.dndDraggingSource) [dnd-handle] for that. - */ - .directive('dndHandle', function() { - return function(scope, element, attr) { - element.attr("draggable", "true"); - - element.on('dragstart dragend', function(event) { - event = event.originalEvent || event; - event._dndHandle = true; - }); - }; - }) - - /** - * This workaround handles the fact that Internet Explorer does not support drag types other than - * "Text" and "URL". That means we can not know whether the data comes from one of our elements or - * is just some other data like a text selection. As a workaround we save the isDragging flag in - * here. When a dropover event occurs, we only allow the drop if we are already dragging, because - * that means the element is ours. - */ - .factory('dndDragTypeWorkaround', function(){ return {} }) - - /** - * Chrome on Windows does not set the dropEffect field, which we need in dragend to determine - * whether a drag operation was successful. Therefore we have to maintain it in this global - * variable. The bug report for that has been open for years: - * https://code.google.com/p/chromium/issues/detail?id=39399 - */ - .factory('dndDropEffectWorkaround', function(){ return {} }); \ No newline at end of file diff --git a/client/cat3/src/partials/sections/dashboard/analytics/analytics.html b/client/cat3/src/partials/sections/dashboard/analytics/analytics.html index 6c2df7210..d36774c2c 100644 --- a/client/cat3/src/partials/sections/dashboard/analytics/analytics.html +++ b/client/cat3/src/partials/sections/dashboard/analytics/analytics.html @@ -9,7 +9,8 @@
    Filter:
    -
    + +
    @@ -117,15 +118,41 @@
    -
    +
    - + + + +
    + + + + + + + + + + + + + + + + +
    -
    +
    {{filt.title}}: {{filt.name}} @@ -136,4 +163,15 @@
    -
    \ No newline at end of file +
    + diff --git a/client/cat3/src/partials/sections/dashboard/analytics/analytics.js b/client/cat3/src/partials/sections/dashboard/analytics/analytics.js index f25220e0e..410b3c6ee 100644 --- a/client/cat3/src/partials/sections/dashboard/analytics/analytics.js +++ b/client/cat3/src/partials/sections/dashboard/analytics/analytics.js @@ -39,11 +39,29 @@ return deferred.promise; }] } + }).state('dashboard.analytics.capacityReport', { + url: "analytics/capacityReport/", + templateUrl: "src/partials/sections/dashboard/analytics/view/capacityReport.html", + controller: "capacityReportCtrl as capRept", + params:{filterView:{usage:true,org:true,provi:true,instanceType:true,period:true},dashboardHide:true,otherTab:'Capacity',otherTabView:true,reportHide:true}, + resolve: { + auth: ["$q", function ($q) { + var deferred = $q.defer(); + // instead, go to a different page + if (modulePerms.analyticsBool()) { + // everything is fine, proceed + deferred.resolve(); + } else { + deferred.reject({redirectTo: 'dashboard'}); + } + return deferred.promise; + }] + } }).state('dashboard.analytics.usage', { url: "analytics/usage/", templateUrl: "src/partials/sections/dashboard/analytics/view/usage.html", controller: "usageCtrl as usage", - params:{filterView:{usage:true,org:true,provi:true,instanceType:true,resources:true}}, + params:{filterView:{period:true,usage:true,org:true,provi:true,instanceType:true,resources:true}}, resolve: { auth: ["$q", function ($q) { var deferred = $q.defer(); @@ -125,12 +143,7 @@ } $rootScope.stateItems = $state.params; }, true); - $scope.$on('CHANGE_splitUp', function (event, data) { - analytic.splitUp=data; - }); - $scope.$watch(function() { return analytic.splitUp}, function(newVal) { - $scope.$broadcast('CHANGE_VIEW',newVal); - }, true); + analytic.applyCount=0; //get organisation diff --git a/client/cat3/src/partials/sections/dashboard/analytics/analytics.scss b/client/cat3/src/partials/sections/dashboard/analytics/analytics.scss index 4335ee085..906a768fb 100644 --- a/client/cat3/src/partials/sections/dashboard/analytics/analytics.scss +++ b/client/cat3/src/partials/sections/dashboard/analytics/analytics.scss @@ -330,15 +330,7 @@ float: right; width: 57%; } - .form-control{ - height: 29px; - padding: 2px 10px; - font-size: 12px; - line-height: 1; - } - .with250{ - width: 250px !important; - } + } .form-item-container { .list-inline { @@ -364,4 +356,27 @@ } label { font-weight: 400 !important; +} +.ui-grid-viewport { + overflow-x: hidden !important; +} +.form-control{ + height: 29px; + padding: 2px 10px; + font-size: 12px; + line-height: 1; +} +.with250{ + width: 250px !important; +} +.weekPick { + position: absolute; + left: 24%; + background: #FFFFFF; + width: 217px; + z-index: 999; + padding: 7px 17px; + border: 1px solid #ccc; + border-radius: 5px; + margin: 2px; } \ No newline at end of file diff --git a/client/cat3/src/partials/sections/dashboard/analytics/analyticsServices.js b/client/cat3/src/partials/sections/dashboard/analytics/analyticsServices.js index fc2b31619..75b9d1102 100644 --- a/client/cat3/src/partials/sections/dashboard/analytics/analyticsServices.js +++ b/client/cat3/src/partials/sections/dashboard/analytics/analyticsServices.js @@ -10,14 +10,34 @@ $rootScope.filterNewEnt.period='month'; $rootScope.splitUpCosts=[]; $rootScope.filterNewEnt.platformId=[]; + var months=['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + var weekInd= 0 | new Date().getDate() / 7; + $rootScope.filterNewEnt.endDate={ + year:'2017', + week:weekInd.toString(), + month:months[new Date().getMonth()], + day:moment(new Date()).format('YYYY-MM-DD') + }; + $rootScope.filterNewEnt.date= $rootScope.filterNewEnt.endDate.month+' '+ $rootScope.filterNewEnt.endDate.year; }, applyFilter : function(filterApp,period){ + $rootScope.filterNewEnt.date= $rootScope.filterNewEnt.endDate.month+' '+ $rootScope.filterNewEnt.endDate.year; if($rootScope.organObject) { var obj = $rootScope.organObject, or = $rootScope.organNewEnt.org, bu = $rootScope.organNewEnt.buss, pr = $rootScope.organNewEnt.proj; if (period) { + if (period === 'day'){ + $rootScope.filterNewEnt.date= $rootScope.filterNewEnt.endDate.day; + }else if(period === 'week'){ + var dt = new Date($rootScope.filterNewEnt.endDate.month+' '+ $rootScope.filterNewEnt.endDate.year); + var wk=7*$rootScope.filterNewEnt.endDate.week; + console.log(moment(dt).add(wk, 'days').format('YYYY-MM-DD')); + $rootScope.filterNewEnt.date=moment(dt).add(wk, 'days').format('YYYY-MM-DD'); + } else { + $rootScope.filterNewEnt.date= $rootScope.filterNewEnt.endDate.month+' '+ $rootScope.filterNewEnt.endDate.year; + } $rootScope.filterNewEnt.period = period; } diff --git a/client/cat3/src/partials/sections/dashboard/analytics/controller/capacityReportCtrl.js b/client/cat3/src/partials/sections/dashboard/analytics/controller/capacityReportCtrl.js new file mode 100644 index 000000000..46182647a --- /dev/null +++ b/client/cat3/src/partials/sections/dashboard/analytics/controller/capacityReportCtrl.js @@ -0,0 +1,406 @@ +(function (angular) { + "use strict"; + angular.module('dashboard.analytics') + .controller('capacityReportCtrl', ['$scope', '$rootScope', '$state','analyticsServices', 'genericServices','$timeout','$location', '$anchorScroll','$modal',function ($scope,$rootScope,$state,analyticsServices,genSevs,$timeout,$location, $anchorScroll,$modal){ + $rootScope.stateItems = $state.params; + //analyticsServices.initFilter(); + $scope.gototab = function(id) { + // set the location.hash to the id of + // the element you wish to scroll to. + $location.hash(id); + + // call $anchorScroll() + $anchorScroll(); + }; + var capRept =this; + capRept.chartData=[]; + capRept.splitUp=null; + capRept.getCapacityData=function(fltObj){ + var param = { + // url: 'src/partials/sections/dashboard/analytics/data/cost.json?org' + url:'' + }; + if(fltObj && fltObj.org){ + var entityId=null; + if(fltObj.provider){ + entityId=fltObj.provider.id; + } else { + entityId=fltObj.org.id; + } + //param.url='http://d4d.rlcatalyst.com/analytics/capacity?parentEntityId=46d1da9a-d927-41dc-8e9e-7e926d927537&entityId=46d1da9a-d927-41dc-8e9e-7e926d927537&toTimeStamp=Mon%20Nov%2014%202016%2010:41:29%20GMT+0530%20(IST)&period=month'; + param.url='/analytics/capacity?parentEntityId='+fltObj.org.id+'&entityId='+entityId+'&toTimeStamp='+new Date()+'&period=month'; + } + + genSevs.promiseGet(param).then(function (result) { + capRept.chartData=result; + $rootScope.splitUpCapacities=[]; + capRept.serviceCapacity=result.capacity.AWS; + //capRept.serviceType=Object.keys(capRept.serviceCapacity.services)[0]; + capRept.serviceType='EC2'; + if(result.splitUpCapacities && Object.keys(result.splitUpCapacities).length >0) { + angular.forEach(result.splitUpCapacities, function (val, key) { + var a=key.replace(/([A-Z])/g, ' $1').replace(/^./, function(str) { + return str.toUpperCase(); + }); + $rootScope.splitUpCapacities.push({id:key,val:a}); + }); + if( $rootScope.splitUpCapacities && $rootScope.splitUpCapacities.length >0) { + $scope.$emit('CHANGE_splitUp', $rootScope.splitUpCapacities[0].id); + capRept.splitUp = $rootScope.splitUpCapacities[0].val; + capRept.createLable(result, $rootScope.splitUpCapacities[0].id); + } + } + capRept.createList(); + + }); + }; + + $rootScope.applyFilter =function(filterApp,period){ + analyticsServices.applyFilter(filterApp,period); + if($state.current.name === "dashboard.analytics.capacityReport") { + capRept.createList(); + } + }; + capRept.init =function(){ + $rootScope.organNewEnt.instanceType='Unassigned'; + $rootScope.organNewEnt.provider='0'; + $rootScope.$emit('INI_usage', 'Unassigned'); + $timeout(function () { + $rootScope.applyFilter(true,'month'); + capRept.getCapacityData($rootScope.filterNewEnt); + var treeNames = ['Cloud Management','Analytics','capacity']; + $rootScope.$emit('treeNameUpdate', treeNames); + },500); + }; + // new e################################### + $scope.openChart=function (id) { + $modal.open({ + animation: true, + templateUrl: 'src/partials/sections/dashboard/analytics/view/capacityChart.html', + controller: 'capacityChartCtrl as capChat', + backdrop : 'static', + keyboard: false, + resolve: { + items: function() { + return id; + } + } + }). + result.then(function() { + + }, function() { + + }); + }; + $scope.chefConfig=function (id) { + var promise = genSevs.editRunlist(id); + }; + capRept.createList = function () { + capRept.filterValue=''; + capRept.listGrid=[]; + var fltrObj=$rootScope.filterNewEnt; + + // for(var value in capRept.serviceCapacity) { + var value=capRept.serviceType; + capRept.listGrid[value]=[]; + capRept.listGrid[value].data=[]; + capRept.listGrid[value].paginationPageSizes= [25, 50, 100]; + capRept.listGrid[value].paginationPageSize=25; + $scope.colArray=['platformId','state','orgName','privateIpAddress','os']; + if(capRept.serviceType === 'EC2') { + capRept.listGrid[value].columnDefs = [ + {name: 'Instance Id', field: 'platformId', cellTooltip: true}, + {name: 'os', enableFiltering: true, displayName: 'OS', field: 'os', cellTooltip: true}, + {name: 'privateIpAddress', displayName: 'IP Address', cellTooltip: true}, + {name: 'state', displayName: 'Status', cellTooltip: true}, + { + name: 'Region', displayName: 'Region', + field: 'region', + cellTooltip: true + }, + {name: 'orgName', displayName: 'Org Name', field: 'orgName', cellTooltip: true}, + { + name: 'cost', + displayName: 'Cost', + cellTemplate: '' + }, + { + name: 'Action', + cellTooltip: true, + cellTemplate: " " + + "   " + } + // {name: 'Chef', cellTooltip: true,cellTemplate:""} + ]; + } + if(capRept.serviceType === 'RDS') { + $scope.colArray=['platformId','state','orgName','dbEngine'] + capRept.listGrid[value].columnDefs = [ + {name: 'Instance', field: 'platformId', cellTooltip: true}, + {name: 'dbEngine', enableFiltering: true, displayName: 'Engine', field: 'dbEngine', cellTooltip: true}, + {name: 'state', displayName: 'Status', cellTooltip: true}, + { + name: 'Region', displayName: 'Region', + field: 'region', + cellTooltip: true + }, + {name: 'orgName', displayName: 'Org Name', field: 'orgName', cellTooltip: true}, + { + name: 'cost', + displayName: 'Cost', + cellTemplate: '' + }, + { + name: 'Action', + cellTooltip: true, + cellTemplate: " " + + "   " + } + // {name: 'Chef', cellTooltip: true,cellTemplate:""} + ]; + } + if(capRept.serviceType === 'S3'){ + $scope.colArray=['bucketName','bucketOwnerName','orgName']; + capRept.listGrid[value].columnDefs=[ + {name: 'bucketName', field: 'bucketName', cellTooltip: true}, + {name: 'bucketOwnerName', field: 'bucketOwnerName', cellTooltip: true}, + {name: 'bucketSize', field: 'bucketSize', displayName:'Bucket Size (MB)', cellTooltip: true}, + {name: 'orgName', field: 'orgName', cellTooltip: true}, + {name: 'cost', displayName: 'Cost',cellTemplate: ''}, + {name: 'Action', cellTooltip: true,cellTemplate:" "} + ]; + } + capRept.listGrid[value].onRegisterApi=function (gridApi) { + gridApi.grid.registerRowsProcessor($scope.singleFilter, 200); + $scope.gridApi = gridApi; + }; + + if(capRept.serviceType === 'EC2' && fltrObj && fltrObj.provider && fltrObj.provider.id) { + if($rootScope.organNewEnt.instanceType === 'Managed') { + $scope.colArray.push('bgName'); + capRept.listGrid[value].columnDefs.splice(6,0,{name: 'bgName', displayName: 'Bg Name', field: 'bgName', cellTooltip: true}); + $scope.instanceType= 'managedInstances'; + } else if($rootScope.organNewEnt.instanceType === 'Assigned'){ + $scope.colArray.push('bgName'); + capRept.listGrid[value].columnDefs.splice(6,0,{name: 'bgName', displayName: 'Bg Name', field: 'bgName', cellTooltip: true}); + $scope.instanceType= 'unmanagedInstances'; + } else if($rootScope.organNewEnt.instanceType === 'Unassigned'){ + $scope.instanceType= 'unassigned-instances'; + } + var param = { + inlineLoader:true, + url: '/providers/' + fltrObj.provider.id + '/'+$scope.instanceType + //url:'src/partials/sections/dashboard/analytics/data/ins.json' + }; + genSevs.promiseGet(param).then(function (instResult) { + capRept.listGrid[value].data=[]; + if($rootScope.organNewEnt.instanceType === 'Managed') { + capRept.listGrid[value].data= instResult.managedInstances; + } else if($rootScope.organNewEnt.instanceType === 'Assigned'){ + capRept.listGrid[value].data= instResult.unmanagedInstances; + } else if($rootScope.organNewEnt.instanceType === 'Unassigned'){ + capRept.listGrid[value].data = instResult.data; + } + angular.forEach( capRept.listGrid[value].data,function (rs,k) { + if(rs.hardware && rs.hardware.os){ + capRept.listGrid[value].data[k].os=rs.hardware.os; + } + if(rs.providerData && rs.providerData.region){ + capRept.listGrid[value].data[k].region=rs.providerData.region; + } + if(rs.instanceState){ + capRept.listGrid[value].data[k].state=rs.instanceState; + } + if($rootScope.organNewEnt.instanceType === 'Managed'){ + capRept.listGrid[value].data[k].showSchedule=true; + } + }); + if(capRept.listGrid[value].data && capRept.listGrid[value].data.length === 0){ + capRept.listGrid[value].nodataFound =true; + } else { + capRept.listGrid[value].nodataFound =false; + } + }); + } else if(fltrObj && fltrObj.provider && fltrObj.provider.id){ + var param = { + inlineLoader:true, + url: '/resources?filterBy=providerDetails.id:'+fltrObj.provider.id+',resourceType:'+capRept.serviceType+',category:'+$rootScope.organNewEnt.instanceType.toLowerCase() + // url:'src/partials/sections/dashboard/analytics/data/ins.json' + }; + genSevs.promiseGet(param).then(function (instResult) { + ///// + capRept.listGrid[value].data = instResult.data; + if(capRept.serviceType === 'RDS'){ + angular.forEach(instResult.data,function (va,ke) { + capRept.listGrid[value].data[ke].platformId = va.resourceDetails.dbInstanceIdentifier; + capRept.listGrid[value].data[ke].dbEngine = va.resourceDetails.dbEngine; + capRept.listGrid[value].data[ke].state = va.resourceDetails.dbInstanceStatus; + capRept.listGrid[value].data[ke].providerData={}; + capRept.listGrid[value].data[ke].region = va.resourceDetails.region; + capRept.listGrid[value].data[ke].orgName = va.masterDetails.orgName; + capRept.listGrid[value].data[ke].showSchedule=false; + }); + } + + if(capRept.serviceType === 'S3'){ + angular.forEach(instResult.data,function (va,ke) { + capRept.listGrid[value].data[ke].platformId= va.resourceDetails.bucketName; + capRept.listGrid[value].data[ke].bucketName = va.resourceDetails.bucketName; + capRept.listGrid[value].data[ke].bucketOwnerName = va.resourceDetails.bucketOwnerName; + capRept.listGrid[value].data[ke].bucketSize = va.resourceDetails.bucketSize; + capRept.listGrid[value].data[ke].orgName = va.masterDetails.orgName; + }); + + } + /// + + + if(capRept.listGrid[value].data && capRept.listGrid[value].data.length === 0){ + capRept.listGrid[value].nodataFound =true; + } else { + capRept.listGrid[value].nodataFound =false; + } + }); + } + + //} + }; + $scope.$watch('capRept.serviceType',function (newValue, oldValue) { + capRept.createList(); + }); + $scope.aggregateInstanceCost=function (cost) { + if(cost){ + return cost.symbol+' '+ cost.aggregateInstanceCost; + } else { + return '....'; + } + }; + $scope.Schedule =function (id) { + var a=[]; + a.push(id); + genSevs.scheduleTime(a); + }; + $scope.filterInst = function() { + $scope.gridApi.grid.refresh(); + }; + $scope.singleFilter = function( renderableRows ){ + var matcher = new RegExp(capRept.filterValue); + renderableRows.forEach( function( row ) { + var match = false; + angular.forEach($scope.colArray,function( field ){ + if ( row.entity[field] && row.entity[field].match(matcher) ){ + match = true; + } + }); + if ( !match ){ + row.visible = false; + } + }); + return renderableRows; + }; + capRept.init(); + + + }]).controller('capacityChartCtrl',['$scope','$rootScope','items','genericServices','$modalInstance',function($scope,$rootScope,items,genSevs,$modalInstance){ + var capChat=this; + capChat.items=items; + capChat.trendLineChart={ + options:{}, + data:[] + }; + capChat.result=[]; + capChat.trendLineChart.options = { + chart: { + //type: 'stackedAreaChart', + type: 'lineChart', + height: 200, + margin: { + top: 20, + right: 20, + bottom:70, + left: 60 + }, + x: function (d) { + return d[0]; + }, + y: function (d) { + return d[1]; + }, + useVoronoi: false, + clipEdge: true, + duration: 10, + useInteractiveGuideline: true, + xAxis: { + axisLabel: 'Date', + showMaxMin: false, + tickFormat: function (d) { + return d3.time.format('%d/%m %H:%M')(new Date(d)); + } + }, + yAxis: { + axisLabel: 'Date', + tickFormat: function (d) { + return d3.format(',.2f')(d); + } + }, + zoom: { + enabled: true, + scaleExtent: [1, 10], + useFixedDomain: false, + useNiceScale: false, + horizontalOff: true, + verticalOff: true, + unzoomEventType: 'dblclick.zoom' + } + } + }; + capChat.legends=[]; + + capChat.getData=function(fltObj){ + capChat.trendLineChart.data = []; + capChat.sliptOptions=[]; + var $today = new Date(); + var $yesterday = new Date($today); + $yesterday.setDate($today.getDate() - 1); + if(fltObj && fltObj.resources && fltObj.resources.length >0) { + var $today = new Date(); + var $yesterday = new Date($today); + $yesterday.setDate($today.getDate() - 1); + var param = { + url: '/analytics/trend/usage?resource=' + items._id + '&fromTimeStamp=' + $yesterday + '&toTimeStamp=' + $today + '&interval=3600' + //url:'src/partials/sections/dashboard/analytics/data/usage.json' + }; + genSevs.promiseGet(param).then(function (result) { + angular.forEach(result,function (val,ke) { + capChat.sliptOptions.push(ke); + }); + capChat.splitUp=Object.keys(result)[0]; + capChat.result=result; + capChat.createChart(); + // } + }); + } + }; + capChat.createChart=function () { + var va = []; + capChat.trendLineChart.data = []; + if (capChat.result) { + capChat.trendLineChart.options.chart.yAxis.axisLabel=capChat.result[capChat.splitUp].unit; + angular.forEach(capChat.result[capChat.splitUp].dataPoints, function (value) { + va.push([Date.parse(value.fromTime), value.average]); + }); + capChat.trendLineChart.data.push({ + "key": items.platformId, + "values": va + }); + } + }; + capChat.splitChange=function() { + capChat.createChart(); + }; + capChat.getData($rootScope.filterNewEnt); + $scope.cancel = function() { + $modalInstance.dismiss('cancel'); + }; + }]); +})(angular); diff --git a/client/cat3/src/partials/sections/dashboard/analytics/controller/costCtrl.js b/client/cat3/src/partials/sections/dashboard/analytics/controller/costCtrl.js index 17d145288..2b557cf21 100644 --- a/client/cat3/src/partials/sections/dashboard/analytics/controller/costCtrl.js +++ b/client/cat3/src/partials/sections/dashboard/analytics/controller/costCtrl.js @@ -98,6 +98,9 @@ }; }; costObj.getCostData=function(fltObj){ + costObj.pieChat.data = []; + costObj.barChat.data = []; + costObj.costGridOptions.data = []; var param = { // url: 'src/partials/sections/dashboard/analytics/data/cost.json?org' url:'' @@ -109,8 +112,9 @@ } else { entityId=fltObj.org.id; } - //param.url='src/partials/sections/dashboard/analytics/data/cost.json'; - param.url='/analytics/cost/aggregate?parentEntityId='+fltObj.org.id+'&entityId='+entityId+'&toTimeStamp='+new Date()+'&period='+fltObj.period; + + // param.url='src/partials/sections/dashboard/analytics/data/cost.json'; + param.url='/analytics/cost/aggregate?parentEntityId='+fltObj.org.id+'&entityId='+entityId+'&toTimeStamp='+new Date(fltObj.date)+'&period='+fltObj.period; } genSevs.promiseGet(param).then(function (result) { @@ -124,17 +128,25 @@ $rootScope.splitUpCosts.push({id:key,val:a}); }); if( $rootScope.splitUpCosts && $rootScope.splitUpCosts.length >0) { - $scope.$emit('CHANGE_splitUp', $rootScope.splitUpCosts[0].id); - costObj.splitUp = $rootScope.splitUpCosts[0].val; - costObj.createLable(result, $rootScope.splitUpCosts[0].id); + if(!costObj.splitUp){ + costObj.splitUp=$rootScope.splitUpCosts[0].id; + } + costObj.createLable(result,costObj.splitUp); + } } else { costObj.createLable(result,'provider'); } }); }; + costObj.spliteChange= function() { + costObj.createLable( costObj.chartData, costObj.splitUp); + }; costObj.createLable= function(result,viewType){ + console.log(1); costObj.createChart(); + costObj.pieChat.data = []; + costObj.barChat.data = []; if(result && result.cost) { costObj.costGridOptions.data = []; costObj.costGridOptions.columnDefs = [ @@ -142,8 +154,6 @@ {name: 'totalCost', field: 'cost.totalCost'} ]; costObj.pieChat.totalCoust = result.cost.totalCost; - costObj.pieChat.data = []; - costObj.barChat.data = []; // create bar //if(viewType === 'ProviderView'){ @@ -168,6 +178,7 @@ var va = []; costObj.costGridOptions.columnDefs.push({ name: keyChild, + displayName:keyChild, field: 'cost.AWS.serviceCosts.' + keyChild }); if(result.splitUpCosts && Object.keys(result.splitUpCosts).length >0 ) { @@ -296,14 +307,6 @@ } }); }; - $scope.$on('CHANGE_VIEW', function (event, data) { - if (data) { - costObj.splitUp = data.replace(/([A-Z])/g, ' $1').replace(/^./, function (str) { - return str.toUpperCase(); - }); - costObj.createLable(costObj.chartData, data); - } - }); $rootScope.applyFilter =function(filterApp,period){ analyticsServices.applyFilter(filterApp,period); if($state.current.name === "dashboard.analytics.cost") { diff --git a/client/cat3/src/partials/sections/dashboard/analytics/controller/discoveryResourcesCtrl.js b/client/cat3/src/partials/sections/dashboard/analytics/controller/discoveryResourcesCtrl.js index b6bc9c2e0..6efa6442e 100644 --- a/client/cat3/src/partials/sections/dashboard/analytics/controller/discoveryResourcesCtrl.js +++ b/client/cat3/src/partials/sections/dashboard/analytics/controller/discoveryResourcesCtrl.js @@ -33,7 +33,7 @@ $scope.TagName.environmentTag=instResult.tagName+'-en'; $scope.TagName.envFild='tags.'+instResult.tagName; angular.forEach(instResult.tagValues,function(val){ - $scope.TagName.environment.push({id:val,name:val}) + $scope.TagName.environment.push({id:val,name:val}); }); }); // Bu @@ -44,7 +44,7 @@ $scope.TagName.bgTag=instResult.tagName+'-bu'; $scope.TagName.bgFild='tags.'+instResult.tagName; angular.forEach(instResult.tagValues,function(val){ - $scope.TagName.bg.push({id:val,name:val}) + $scope.TagName.bg.push({id:val,name:val}); }); }); // project @@ -55,7 +55,7 @@ $scope.TagName.projectTag=instResult.tagName+'-pr'; $scope.TagName.projFild='tags.'+instResult.tagName; angular.forEach(instResult.tagValues,function(val){ - $scope.TagName.project.push({id:val,name:val}) + $scope.TagName.project.push({id:val,name:val}); }); }); @@ -77,51 +77,51 @@ gridApi.grid.registerRowsProcessor( $scope.singleFilter, 200 ); $scope.gridApi=gridApi; gridApi.edit.on.afterCellEdit($scope, function (rowEntity, colDefa, newValue, oldValue) { - console.log(rowEntity); - confirmbox.showModal({}, { - closeButtonText: 'Cancel', - actionButtonText: 'Yes', - actionButtonStyle: 'cat-btn-update', - headerText: 'Update tag value', - bodyText: 'Are you sure you want to Update ?' - }).then(function() { - var tagna=colDefa.name.substring(0, colDefa.name.length-3); - var param = { - url: '/providers/' + fltrObj.provider.id + '/unassigned-instances/' + rowEntity._id, - data: { - tags:{} - } - }; - param.data.tags[tagna]=newValue; - console.log(param); - if(newValue !== oldValue) { - genSevs.promisePatch(param).then(function () { - toastr.success('Successfully updated.', 'Update'); - }); - } - },function() { - var param = { - url: '/providers/' + fltrObj.provider.id + '/' + $scope.instanceType - // url:'src/partials/sections/dashboard/analytics/data/ins.json' - }; - genSevs.promiseGet(param).then(function (instResult) { - if($rootScope.organNewEnt.instanceType === 'Managed') { - disResrc.gridOptionInstances.data = instResult.managedInstances; - } else if($rootScope.organNewEnt.instanceType === 'Assigned'){ - disResrc.gridOptionInstances.data = instResult.unmanagedInstances; - } else if($rootScope.organNewEnt.instanceType === 'Unassigned'){ - disResrc.gridOptionInstances.data = instResult.data; - } - disResrc.gridOptionInstances.isRowSelectable = function(row){ - if(row.entity.state !== 'running'){ - return false; - } else { - return true; + if(newValue !== oldValue) { + confirmbox.showModal({}, { + closeButtonText: 'Cancel', + actionButtonText: 'Yes', + actionButtonStyle: 'cat-btn-update', + headerText: 'Update tag value', + bodyText: 'Are you sure you want to Update ?' + }).then(function () { + var tagna = colDefa.name.substring(0, colDefa.name.length - 3); + var param = { + url: '/providers/' + fltrObj.provider.id + '/unassigned-instances/' + rowEntity._id, + data: { + tags: {} } }; + param.data.tags[tagna] = newValue; + console.log(param); + if (newValue !== oldValue) { + genSevs.promisePatch(param).then(function () { + toastr.success('Successfully updated.', 'Update'); + }); + } + }, function () { + var param = { + url: '/providers/' + fltrObj.provider.id + '/' + $scope.instanceType + // url:'src/partials/sections/dashboard/analytics/data/ins.json' + }; + genSevs.promiseGet(param).then(function (instResult) { + if ($rootScope.organNewEnt.instanceType === 'Managed') { + disResrc.gridOptionInstances.data = instResult.managedInstances; + } else if ($rootScope.organNewEnt.instanceType === 'Assigned') { + disResrc.gridOptionInstances.data = instResult.unmanagedInstances; + } else if ($rootScope.organNewEnt.instanceType === 'Unassigned') { + disResrc.gridOptionInstances.data = instResult.data; + } + disResrc.gridOptionInstances.isRowSelectable = function (row) { + if (row.entity.state !== 'running') { + return false; + } else { + return true; + } + }; + }); }); - }); - + } }); gridApi.selection.on.rowSelectionChanged($scope,function(row){ if(row.isSelected){ @@ -129,7 +129,6 @@ } else { $scope.selectInstanceRow.splice(row.entity._id,1); } - }); gridApi.selection.on.rowSelectionChangedBatch($scope,function(rows){ angular.forEach(rows,function(row){ @@ -369,12 +368,13 @@ }; disResrc.init(); - }]).controller('instanceManageCtrl',['$scope','$rootScope','items','$modalInstance','genericServices','$modal',function ($scope,$rootScope,items,$modalInstance,genericServices,$modal) { + }]).controller('instanceManageCtrl',['$scope','$rootScope','items','$modalInstance','genericServices','$modal','toastr',function ($scope,$rootScope,items,$modalInstance,genericServices,$modal,toastr) { $scope.items=items; var fltrObj=$rootScope.filterNewEnt; var reqBody = {}; $scope.monitorList = []; $scope.monitorId = 'null'; + $scope.IMGNewEnt={ passType:'password', org:$rootScope.organObject[0] @@ -382,7 +382,7 @@ //get configmanagement var params={ url:'/d4dMasters/organization/'+$scope.IMGNewEnt.org.orgid+'/configmanagement/list' - } + }; genericServices.promiseGet(params).then(function (list) { $scope.configOptions=list; }); @@ -390,7 +390,7 @@ //get monitors var monitorParam={ url:'/monitors?filterBy=orgId:' + $scope.IMGNewEnt.org.orgid - } + }; genericServices.promiseGet(monitorParam).then(function (list) { $scope.monitorList = list; }); @@ -410,12 +410,15 @@ } }; $scope.ok = function() { + if($scope.monitorId === 'null') { + $scope.monitorId = null; + } $scope.importSpinner = true; $scope.importSync = true; reqBody.orgId = $scope.IMGNewEnt.org.orgid; reqBody.bgId = $scope.IMGNewEnt.buss.rowid; reqBody.projectId = $scope.IMGNewEnt.proj.rowId; - reqBody.envId = $scope.IMGNewEnt.env.rowid + reqBody.envId = $scope.IMGNewEnt.env.rowid; reqBody.orgName = $scope.IMGNewEnt.org.name; reqBody.bgName = $scope.IMGNewEnt.buss.name; reqBody.projectName = $scope.IMGNewEnt.proj.name; @@ -433,7 +436,7 @@ inlineLoader: true, url:'/providers/' + fltrObj.provider.id + '/sync', data:reqBody - } + }; genericServices.promisePost(params).then(function (response) { if(response.taskId){ @@ -478,8 +481,7 @@ reqBody.credentials.pemFileData = pemfileText; $scope.postMethodImportByIp(); }; - - } + }; $scope.cancel = function() { $modalInstance.dismiss('cancel'); }; diff --git a/client/cat3/src/partials/sections/dashboard/analytics/controller/discoverySyncResultCtrl.js b/client/cat3/src/partials/sections/dashboard/analytics/controller/discoverySyncResultCtrl.js index e9668e5ba..c4a32d2b3 100644 --- a/client/cat3/src/partials/sections/dashboard/analytics/controller/discoverySyncResultCtrl.js +++ b/client/cat3/src/partials/sections/dashboard/analytics/controller/discoverySyncResultCtrl.js @@ -39,5 +39,5 @@ },1000); }; $scope.pollTaskStatus(0); - }]) + }]); })(angular); \ No newline at end of file diff --git a/client/cat3/src/partials/sections/dashboard/analytics/controller/discoveryTagMappingCtrl.js b/client/cat3/src/partials/sections/dashboard/analytics/controller/discoveryTagMappingCtrl.js index c6855d481..e30c2d0f2 100644 --- a/client/cat3/src/partials/sections/dashboard/analytics/controller/discoveryTagMappingCtrl.js +++ b/client/cat3/src/partials/sections/dashboard/analytics/controller/discoveryTagMappingCtrl.js @@ -25,25 +25,24 @@ $scope.newEnt.project.tagValues=[]; $scope.newEnt.businessGroup.tagValues=[]; $scope.newEnt.businessGroup.tagName=''; - $scope.newEnt.environment.tagName='' - $scope.newEnt.environment.tagValues=[];; + $scope.newEnt.environment.tagName=''; + $scope.newEnt.environment.tagValues=[]; disTgMap.getTagValues(false,'businessGroup'); disTgMap.getTagValues(false,'environment'); disTgMap.getTagValues(false,'project'); - angular.forEach(tagResult, function (val, key) { - $scope.newEnt[key].tagName = val.tagName; - $scope.newEnt[key].tagValues = val.tagValues; - $scope.newEnt[key].catalystEntityType = val.catalystEntityType; - angular.forEach(val.catalystEntityMapping, function (v, k) { - $scope.newEnt[key].catalystEntityMapping[k] = { - tagValues: v.tagValues, - catalystEntityId: v.catalystEntityId, - catalystEntityName: v.catalystEntityName - } - }); + angular.forEach(tagResult, function (val, key) { + $scope.newEnt[key].tagName = val.tagName; + $scope.newEnt[key].tagValues = val.tagValues; + $scope.newEnt[key].catalystEntityType = val.catalystEntityType; + angular.forEach(val.catalystEntityMapping, function (v, k) { + $scope.newEnt[key].catalystEntityMapping[k] = { + tagValues: v.tagValues, + catalystEntityId: v.catalystEntityId, + catalystEntityName: v.catalystEntityName + }; }); - + }); }); } }; diff --git a/client/cat3/src/partials/sections/dashboard/analytics/controller/usageCtrl.js b/client/cat3/src/partials/sections/dashboard/analytics/controller/usageCtrl.js index fec01faf9..f53d539ee 100644 --- a/client/cat3/src/partials/sections/dashboard/analytics/controller/usageCtrl.js +++ b/client/cat3/src/partials/sections/dashboard/analytics/controller/usageCtrl.js @@ -132,9 +132,7 @@ $timeout(function(){$rootScope.applyFilter(true,'month')},500); var treeNames = ['Cloud Management','Analytics','Usage']; $rootScope.$emit('treeNameUpdate', treeNames); - }; usage.init(); - }]); })(angular); diff --git a/client/cat3/src/partials/sections/dashboard/analytics/view/analyticsTreeMenu.html b/client/cat3/src/partials/sections/dashboard/analytics/view/analyticsTreeMenu.html index 16f1c72a9..d1c5e54bc 100644 --- a/client/cat3/src/partials/sections/dashboard/analytics/view/analyticsTreeMenu.html +++ b/client/cat3/src/partials/sections/dashboard/analytics/view/analyticsTreeMenu.html @@ -91,7 +91,7 @@
    -
  • +
  • diff --git a/client/cat3/src/partials/sections/dashboard/analytics/view/capacityChart.html b/client/cat3/src/partials/sections/dashboard/analytics/view/capacityChart.html new file mode 100644 index 000000000..a6ae0afe1 --- /dev/null +++ b/client/cat3/src/partials/sections/dashboard/analytics/view/capacityChart.html @@ -0,0 +1,33 @@ + + + + + \ No newline at end of file diff --git a/client/cat3/src/partials/sections/dashboard/analytics/view/capacityReport.html b/client/cat3/src/partials/sections/dashboard/analytics/view/capacityReport.html new file mode 100644 index 000000000..8adbfd1dc --- /dev/null +++ b/client/cat3/src/partials/sections/dashboard/analytics/view/capacityReport.html @@ -0,0 +1,63 @@ +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    + +
    +
    +
    + +

    + + +

    +
    + + + + +
    +
    +
    + + +
    +
    +
    + No Data Available. +
    +
    +
    +
    +
    +
    + +
    + \ No newline at end of file diff --git a/client/cat3/src/partials/sections/dashboard/analytics/view/cost.html b/client/cat3/src/partials/sections/dashboard/analytics/view/cost.html index d8cb1edb7..e2a47def6 100644 --- a/client/cat3/src/partials/sections/dashboard/analytics/view/cost.html +++ b/client/cat3/src/partials/sections/dashboard/analytics/view/cost.html @@ -10,7 +10,7 @@
    Segregated by -
    @@ -53,4 +53,4 @@

    Aggregate cos

    -
  • \ No newline at end of file + diff --git a/client/cat3/src/partials/sections/dashboard/bots/bots.scss b/client/cat3/src/partials/sections/dashboard/bots/bots.scss index ed52f151a..2e88a1839 100644 --- a/client/cat3/src/partials/sections/dashboard/bots/bots.scss +++ b/client/cat3/src/partials/sections/dashboard/bots/bots.scss @@ -12,6 +12,10 @@ margin-left: 23px; } +.marginbottom15 { + margin-bottom: 15px; +} + .paddingbottom10 { padding-bottom: 10px; } @@ -24,6 +28,14 @@ margin-top: 8px; } +.paddingleft0 { + padding-left: 0px; +} + +.marginright10 { + margin-right: 10px; +} + .cookbook-edit-text { background: #fff; } @@ -88,6 +100,14 @@ width: 100%; } + .filter-margin { + margin: 2px 10px 0 0; + } + + .filter-by-text { + margin-top: 4px; + } + .bot-library-search { height: 33px; margin-right: 12px; @@ -123,11 +143,11 @@ } .circle-tile-number { - padding: 5px 0 6px; - font-size: 26px; + padding: 0px 0 0px; + font-size: 30px; font-weight: 700; - line-height: 1; - height: 37px; + line-height: .6; + height: 28px; } .circle-tile-content { @@ -136,11 +156,12 @@ .circle-tile-description { text-transform: uppercase; + height: 29px; } .text-faded { - color: rgba(255,255,255,0.7); - font-weight: bold; + font-weight: normal; + color: #fff; } .dark-blue { @@ -183,8 +204,8 @@ font-size: 16px; } - a.cursor { - padding: 0 5px; + a { + padding: 0 8px; } .margin-21 { diff --git a/client/cat3/src/partials/sections/dashboard/bots/controller/audittrailCtrl.js b/client/cat3/src/partials/sections/dashboard/bots/controller/audittrailCtrl.js index f8aa58063..a88e4abf1 100644 --- a/client/cat3/src/partials/sections/dashboard/bots/controller/audittrailCtrl.js +++ b/client/cat3/src/partials/sections/dashboard/bots/controller/audittrailCtrl.js @@ -12,7 +12,6 @@ function ($scope, $rootScope, $state, genSevs, confirmbox, workzoneServices, toastr, workzoneUIUtils, $modal, uiGridOptionsService, $timeout) { var treeNames = ['BOTs','Audit Trail']; $rootScope.$emit('treeNameUpdate', treeNames); - var audit=this; var botAuditTrailUIGridDefaults = uiGridOptionsService.options(); $scope.paginationParams = botAuditTrailUIGridDefaults.pagination; $scope.paginationParams=[]; @@ -38,13 +37,13 @@ '' + '', cellTooltip: true}, - { name: 'Org',field:'masterDetails.orgName'}, - { name: 'BU',field:'masterDetails.bgName'}, + { name: 'Organization',field:'masterDetails.orgName'}, + { name: 'Business Group',field:'masterDetails.bgName'}, { name: 'Project',field:'masterDetails.projectName'}, - { name: 'Env',field:'masterDetails.envName'}, + { name: 'Environment',field:'masterDetails.envName'}, { name: 'User',field:'user'}, { name: 'Logs',cellTemplate: ''} - ] + ]; $scope.botAuditTrailGridOptions.data=[]; angular.extend($scope.botAuditTrailGridOptions,botAuditTrailUIGridDefaults.gridOption); }; diff --git a/client/cat3/src/partials/sections/dashboard/bots/controller/botChefLogCtrl.js b/client/cat3/src/partials/sections/dashboard/bots/controller/botChefLogCtrl.js index f92b18c22..aaf671ca0 100644 --- a/client/cat3/src/partials/sections/dashboard/bots/controller/botChefLogCtrl.js +++ b/client/cat3/src/partials/sections/dashboard/bots/controller/botChefLogCtrl.js @@ -68,24 +68,31 @@ $scope.selectedInstance = firstInstance; chefLogData.instanceChange(); }; - var resetAll = function(){ + /*var resetAll = function(){ $scope.isInstanceListLoading = true; chefLogData.chefHistoryItem = {}; chefLogData.nodeIdsWithActionLog = {}; helper.stopPolling(); //Ensuring polling is stopped, eventhough the scope values for instance id and actionlog id are updated on change helper.lastTimeStamp = ''; - }; + };*/ var init = function () { //get the details of one chef history entry var param = { url : '/bots/' + items.taskId + '/bots-history/' + items.historyId - } + }; genSevs.promiseGet(param).then(function (response) { chefLogData.createInstanceList(response); }); }; chefLogData.createInstanceList = function (historyItem) { - var nodeIds =historyItem.nodeIds ? historyItem.nodeIds : historyItem.auditTrailConfig.nodeIds ; + var nodeIds = []; + if(historyItem.nodeIds){ + nodeIds = historyItem.nodeIds; + }else{ + for(var i = 0; i < historyItem.auditTrailConfig.nodeIdsWithActionLog.length;i++){ + nodeIds.push(historyItem.auditTrailConfig.nodeIdsWithActionLog[i].nodeId); + } + } var nodeIdWithActionLogs = []; var requestObj = { "instanceIds": nodeIds @@ -111,7 +118,7 @@ $scope.isInstanceListLoading = false; toastr.error(error); $scope.errorMessage = ""; - }) + }); }; chefLogData.instanceChange = function () { $scope.isLogsLoading = true; @@ -122,8 +129,8 @@ urlParams = 'timestamp=' + chefLogData.chefHistoryItem.startedOn + '×tampEnded=' + chefLogData.chefHistoryItem.endedOn; var param = { url : "/instances/" + $scope.selectedInstance.nodeId + '/actionLogs/' + $scope.selectedInstance.actionLogId + - '/logs?' + urlParams - } + '/logs?' + urlParams + }; genSevs.promiseGet(param).then(function (response) { $scope.isLogsLoading = false; var logData = { @@ -138,8 +145,8 @@ var urlParams = 'timestamp=' + chefLogData.chefHistoryItem.startedOn; var param = { url : "/instances/" + $scope.selectedInstance.nodeId + '/actionLogs/' + $scope.selectedInstance.actionLogId + - '/logs?' + urlParams - } + '/logs?' + urlParams + }; genSevs.promiseGet(param).then(function (response) { $scope.isLogsLoading = false; helper.lastTimeStamp = helper.getlastTimeStamp(response) || chefLogData.chefHistoryItem.startedOn; diff --git a/client/cat3/src/partials/sections/dashboard/bots/controller/botLogsCtrl.js b/client/cat3/src/partials/sections/dashboard/bots/controller/botLogsCtrl.js index a74ada9e6..c97c3dbd0 100644 --- a/client/cat3/src/partials/sections/dashboard/bots/controller/botLogsCtrl.js +++ b/client/cat3/src/partials/sections/dashboard/bots/controller/botLogsCtrl.js @@ -10,7 +10,11 @@ angular.module('library.bots',[]) .controller('botLogsCtrl',['$scope', '$rootScope', 'genericServices', 'workzoneServices', 'toastr', '$modalInstance', 'items', '$timeout', function ($scope, $rootScope, genSevs, workzoneServices, toastr, $modalInstance, items, $timeout) { $scope.botName = items.auditTrailConfig.name; - $scope.nodeIds = items.auditTrailConfig.nodeIds; + //$scope.nodeIds = items.auditTrailConfig.nodeIds; + $scope.nodeIds = []; + for(var i = 0; i < items.auditTrailConfig.nodeIdsWithActionLog.length;i++){ + $scope.nodeIds.push(items.auditTrailConfig.nodeIdsWithActionLog[i].nodeId); + } $scope.taskType = items.auditTrailConfig.executionType; $scope.nodeIdsWithActionLog = items.auditTrailConfig.nodeIdsWithActionLog; $scope.isBotLogsLoading = true; diff --git a/client/cat3/src/partials/sections/dashboard/bots/controller/editParamsCtrl.js b/client/cat3/src/partials/sections/dashboard/bots/controller/editParamsCtrl.js index 1f938fed8..845dd0693 100644 --- a/client/cat3/src/partials/sections/dashboard/bots/controller/editParamsCtrl.js +++ b/client/cat3/src/partials/sections/dashboard/bots/controller/editParamsCtrl.js @@ -33,7 +33,7 @@ $scope.totalCount = 0; $scope.countInit = function() { return $scope.totalCount++; - } + }; if (items.botLinkedSubCategory === 'chef') { $scope.chefComponentSelectorList = responseFormatter.findDataForEditValue(items.botConfig.runlist); diff --git a/client/cat3/src/partials/sections/dashboard/bots/controller/libraryCtrl.js b/client/cat3/src/partials/sections/dashboard/bots/controller/libraryCtrl.js index cec610bc3..59624ca07 100644 --- a/client/cat3/src/partials/sections/dashboard/bots/controller/libraryCtrl.js +++ b/client/cat3/src/partials/sections/dashboard/bots/controller/libraryCtrl.js @@ -8,11 +8,16 @@ (function (angular) { "use strict"; angular.module('dashboard.bots') - .controller('libraryCtrl',['$scope', '$rootScope', '$state', 'genericServices', 'confirmbox', 'toastr', 'workzoneUIUtils', '$modal', 'uiGridOptionsService', '$timeout', function ($scope, $rootScope, $state, genSevs, confirmbox, toastr, workzoneUIUtils, $modal, uiGridOptionsService, $timeout) { + .controller('libraryCtrl',['$scope', '$rootScope', '$state', 'genericServices', 'confirmbox', 'toastr', 'workzoneUIUtils', '$modal', 'uiGridOptionsService', '$timeout', 'workzoneServices', function ($scope, $rootScope, $state, genSevs, confirmbox, toastr, workzoneUIUtils, $modal, uiGridOptionsService, $timeout, workzoneServices) { var treeNames = ['BOTs','Library']; $rootScope.$emit('treeNameUpdate', treeNames); var lib=this; + $rootScope.isOpenSidebar = false; $scope.totalBotsSelected = true; + $scope.botCategoryList = []; + workzoneServices.getBotCategoryList().then(function (catList) { + $scope.botCategoryList=catList.data; + }); var botLibraryUIGridDefaults = uiGridOptionsService.options(); $scope.paginationParams = botLibraryUIGridDefaults.pagination; $scope.paginationParams=[]; @@ -20,6 +25,10 @@ $scope.paginationParams.pageSize = 10; $scope.paginationParams.sortBy = 'createdOn'; $scope.paginationParams.sortOrder = 'desc'; + $scope.botLibrarySearch = ''; + $scope.botLibFilterBot = 'Task'; + $scope.botLibFilterTask = 'chef'; + $scope.botLibFilterCategory = 'Active Directory'; $scope.initGrids = function(){ $scope.botLibGridOptions={}; @@ -28,23 +37,24 @@ 'row.entity.botLinkedSubCategory'+ 'row.entity.taskType'+ 'row.entity.botType',cellTooltip: true}, - { name: 'BOT Type',displayName: 'BOT Type',field:'botLinkedCategory',cellTooltip: true}, + { name: 'BOT Type',displayName: 'BOT Type',field:'botType',cellTooltip: true}, { name: 'BOT Name',displayName: 'BOT Name',field:'botName',cellTooltip: true}, { name: 'Category',field:'botCategory',cellTooltip: true}, { name: 'description',field:'botDesc',cellTooltip: true}, + { name: 'BOT Created From',displayName: 'BOT Created From',field:'botLinkedCategory',cellTooltip: true}, { name: 'Organization',field:'masterDetails.orgName',cellTooltip: true}, { name: 'Total Runs',field:'executionCount'}, { name: 'BOT Action',width:200,displayName: 'BOT Action',cellTemplate: // ''+ - ''+ - ''+ + ''+ + ''+ //''+ - '' + - '' + + '' + + '' + //'' + - '' + '' } - ] + ]; $scope.botLibGridOptions.data=[]; angular.extend($scope.botLibGridOptions,botLibraryUIGridDefaults.gridOption); }; @@ -77,8 +87,6 @@ $scope.paginationParams.sortOrder = 'desc'; if($scope.paginationParams.page !== 1){ $scope.setFirstPageView();//if current page is not 1, then ui grid will trigger a call when set to 1. - }else{ - //$scope.botLibraryGridView(); } }; $scope.setPaginationDefaults(); @@ -91,6 +99,7 @@ $timeout(function() { $scope.botLibGridOptions.totalItems = result.metaData.totalRecords; $scope.botLibGridOptions.data=result.bots; + $scope.filterBy(); }, 100); $scope.isBotLibraryPageLoading = false; }, function(error) { @@ -102,20 +111,25 @@ $scope.botLibraryGridView(); $scope.searchBotNameCategory = function() { $scope.searchString = $scope.botLibrarySearch; + $scope.searchText = true; lib.gridOptions=[]; if($scope.totalBotsSelected) { var param={ url:'/bots?page=' + $scope.paginationParams.page +'&pageSize=' + $scope.paginationParams.pageSize +'&sortBy=' + $scope.paginationParams.sortBy +'&sortOrder=' + $scope.paginationParams.sortOrder+'&search=' + $scope.searchString - } + }; } else if($scope.runningBotsselected) { var param={ url:'/bots?actionStatus=running&page=' + $scope.paginationParams.page +'&pageSize=' + $scope.paginationParams.pageSize +'&sortBy=' + $scope.paginationParams.sortBy +'&sortOrder=' + $scope.paginationParams.sortOrder+'&search=' + $scope.searchString - } + }; + } else if($scope.scheduledBotsselected) { + var param={ + url:'/bots?filterBy=isBotScheduled:true&page=' + $scope.paginationParams.page +'&pageSize=' + $scope.paginationParams.pageSize +'&sortBy=' + $scope.paginationParams.sortBy +'&sortOrder=' + $scope.paginationParams.sortOrder+'&search=' + $scope.searchString + }; } else if($scope.failedBotsselected) { var param={ url:'/bots?actionStatus=failed&page=' + $scope.paginationParams.page +'&pageSize=' + $scope.paginationParams.pageSize +'&sortBy=' + $scope.paginationParams.sortBy +'&sortOrder=' + $scope.paginationParams.sortOrder+'&search=' + $scope.searchString - } - }; + }; + } genSevs.promiseGet(param).then(function (result) { $timeout(function() { $scope.botLibGridOptions.totalItems = result.metaData.totalRecords; @@ -128,6 +142,99 @@ $scope.errorMessage = "No Records found"; }); }; + $scope.clearBotSearchText = function() { + $scope.botLibrarySearch = ''; + $scope.searchText = false; + if($scope.totalBotsSelected) { + $scope.showAllBots(); + } else if($scope.runningBotsselected) { + $scope.showBotsRunning(); + }else if($scope.scheduledBotsselected) { + $scope.showBotsScheduled(); + } else if($scope.failedBotsselected) { + $scope.showBotsFailed(); + } + }; + + $scope.filterBy = function() { + if($scope.botLibFilter === 'botType') { + $scope.filterByBotType = true; + $scope.filterByTaskType = false; + $scope.filterByCategory = false; + $scope.subFilterBy = false; + } else if($scope.botLibFilter === 'taskType') { + $scope.filterByTaskType = true; + $scope.filterByBotType = false; + $scope.filterByCategory = false; + $scope.subFilterBy = false; + } else if($scope.botLibFilter === 'category') { + $scope.filterByCategory = true; + $scope.filterByBotType = false; + $scope.filterByTaskType = false; + $scope.subFilterBy = false; + } else { + $scope.subFilterBy = true; + $scope.filterByBotType = false; + $scope.filterByTaskType = false; + $scope.filterByCategory = false; + } + }; + + $rootScope.applyFilter = function() { + lib.gridOptions=[]; + $scope.botSummary=[]; + if ($scope.botLibFilter === 'botType') { + var summaryParam={ + url:'/audit-trail/bots-summary?filterBy=botType:'+$scope.botLibFilterBot+'' + }; + var param={ + url:'/bots?filterBy=botType:'+$scope.botLibFilterBot+'&page=' + $scope.paginationParams.page +'&pageSize=' + $scope.paginationParams.pageSize +'&sortBy=' + $scope.paginationParams.sortBy +'&sortOrder=' + $scope.paginationParams.sortOrder + }; + } else if($scope.botLibFilter === 'taskType') { + var summaryParam={ + url:'/audit-trail/bots-summary?filterBy=botLinkedSubCategory:'+$scope.botLibFilterTask+'' + }; + var param={ + url:'/bots?filterBy=botLinkedSubCategory:'+$scope.botLibFilterTask+'&page=' + $scope.paginationParams.page +'&pageSize=' + $scope.paginationParams.pageSize +'&sortBy=' + $scope.paginationParams.sortBy +'&sortOrder=' + $scope.paginationParams.sortOrder + }; + } else if($scope.botLibFilter === 'category') { + var summaryParam={ + url:'/audit-trail/bots-summary?filterBy=botCategory:'+$scope.botLibFilterCategory+'' + }; + var param={ + url:'/bots?filterBy=botCategory:'+$scope.botLibFilterCategory+'&page=' + $scope.paginationParams.page +'&pageSize=' + $scope.paginationParams.pageSize +'&sortBy=' + $scope.paginationParams.sortBy +'&sortOrder=' + $scope.paginationParams.sortOrder + }; + } else { + $scope.RefreshBotsLibrary(); + } + genSevs.promiseGet(summaryParam).then(function (response) { + $scope.botSummary = response; + $scope.totalSavedTimeForBots = parseInt($scope.botSummary.totalSavedTimeForBots); + }); + genSevs.promiseGet(param).then(function (result) { + $timeout(function() { + $scope.botLibGridOptions.totalItems = result.metaData.totalRecords; + $scope.botLibGridOptions.data=result.bots; + }, 100); + $scope.isBotLibraryPageLoading = false; + $scope.isOpenSidebar = false; + }, function(error) { + $scope.isBotLibraryPageLoading = false; + toastr.error(error); + $scope.errorMessage = "No Records found"; + $scope.isOpenSidebar = false; + }); + }; + + $scope.clearFilter = function() { + $scope.botLibFilter = ''; + $scope.subFilterBy = true; + $scope.filterByBotType = false; + $scope.filterByTaskType = false; + $scope.filterByCategory = false; + //$scope.isOpenSidebar = false; + }; + var gridBottomSpace = 265; $scope.gridHeight = workzoneUIUtils.makeTabScrollable('botLibraryPage') - gridBottomSpace; $scope.launchInstance = function(launch){ @@ -185,7 +292,7 @@ keyboard: false, resolve: { items: function () { - return bot + return bot; } } }).result.then(function () { @@ -201,7 +308,7 @@ actionButtonText: 'Delete', actionButtonStyle: 'cat-btn-delete', headerText: 'Delete Bot', - bodyText: 'Are you sure you want to delete this bots?' + bodyText: 'Are you sure you want to delete this BOT?' }; confirmbox.showModal({}, modalOptions).then(function() { var param={ @@ -209,7 +316,7 @@ }; genSevs.promiseDelete(param).then(function (response) { if (response) { - toastr.success('Successfully deleted'); + toastr.success('Successfully deleted.'); lib.summary(); if($scope.totalBotsSelected) { $scope.botLibraryGridView(); @@ -233,6 +340,10 @@ $scope.botLibraryGridView(); }); $scope.RefreshBotsLibrary = function() { + $scope.botLibFilter = ''; + $scope.botLibFilterBot = 'Task'; + $scope.botLibFilterTask = 'chef'; + $scope.botLibFilterCategory = 'Active Directory'; $scope.botLibrarySearch = ''; lib.summary(); if($scope.totalBotsSelected) { @@ -323,7 +434,7 @@ $scope.cancel= function() { $modalInstance.dismiss('cancel'); }; - }]).controller('botScheduleCtrl',['$scope', '$rootScope', 'genericServices', 'workzoneServices', 'toastr', '$modalInstance', 'items', '$timeout', function ($scope, $rootScope, genSevs, workzoneServices, toastr, $modalInstance, items, $timeout) { + }]).controller('botScheduleCtrl',['$scope', '$rootScope', 'genericServices', 'workzoneServices', 'toastr', '$modalInstance', 'items', function ($scope, $rootScope, genSevs, workzoneServices, toastr, $modalInstance, items) { if(items.isBotScheduled === true){ $scope._isEventSelected = true; $scope.isScheduled = true; @@ -374,7 +485,6 @@ $scope.defaultSelection(); } - $scope.dateChange= function () { var startDate = Date.parse($scope.schedulerStartOn); var endDate = Date.parse($scope.schedulerEndOn); @@ -383,7 +493,6 @@ } else { $scope.validDateRange=false; } - }; $scope.repeatCount = function(max, step) { @@ -396,7 +505,7 @@ }; $scope.isDaySelected = { flag:true - } + }; $scope.daysOfWeek = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]; @@ -416,15 +525,15 @@ }; var reqBody = null; if($scope.isScheduled === true || $scope.isScheduled === 'true'){ - reqBody = { + reqBody = { botScheduler:$scope.eventParams, isBotScheduled:true - } + }; }else{ - reqBody = { + reqBody = { botScheduler:{}, isBotScheduled:false - } + }; } var param={ url:'/bots/' + $scope.botId + '/scheduler', @@ -442,8 +551,8 @@ $scope.cancel = function() { $modalInstance.dismiss('cancel'); }; - }]).controller('botHistoryCtrl',["items", '$scope', '$modalInstance', '$modal', '$timeout', 'uiGridOptionsClient', 'genericServices', 'workzoneServices', - function(items, $scope, $modalInstance, $modal, $timeout, uiGridOptionsClient, genSevs, workzoneServices){ + }]).controller('botHistoryCtrl',["items", '$scope', '$modalInstance', '$modal', '$timeout', 'uiGridOptionsClient', 'genericServices', + function(items, $scope, $modalInstance, $modal, $timeout, uiGridOptionsClient, genSevs){ //UI Grid for chef Task starts $scope.botHistory = items; $scope.botId = items.botId; @@ -459,7 +568,7 @@ { name:'Logs',width: 70, cellTemplate:'
    '}, { name:'Start Time',field:'startedOn',cellTemplate:'{{row.entity.startedOn | timestampToLocaleTime}}', sort:{ direction: 'desc'}, cellTooltip: true}, - { name:'End Time',field:'timestampEnded',cellTemplate:'{{row.entity.endedOn | timestampToLocaleTime}}', cellTooltip: true}, + { name:'End Time',field:'endedOn',cellTemplate:'{{row.entity.endedOn | timestampToLocaleTime}}', cellTooltip: true}, { name:'Execution Time',cellTemplate:'{{grid.appScope.getExecutionTime(row.entity.endedOn,row.entity.startedOn)}} mins'}, { name:'Manual Time',cellTemplate: '{{row.entity.auditTrailConfig.manualExecutionTime}} mins', cellTooltip: true}, { name:'Saved Time',cellTemplate:'{{grid.appScope.getSavedTime(row.entity.endedOn,row.entity.startedOn)}} mins' + @@ -620,7 +729,7 @@ { name:'Logs',width: 70, cellTemplate:'
    '}, { name:'Start Time',field:'startedOn',cellTemplate:'{{row.entity.startedOn | timestampToLocaleTime}}', sort:{ direction: 'desc'}, cellTooltip: true}, - { name:'End Time',field:'timestampEnded',cellTemplate:'{{row.entity.timestampEnded | timestampToLocaleTime}}', cellTooltip: true}, + { name:'End Time',field:'endedOn',cellTemplate:'{{row.entity.endedOn | timestampToLocaleTime}}', cellTooltip: true}, { name:'Execution Time',cellTemplate:'{{grid.appScope.getExecutionTime(row.entity.endedOn,row.entity.startedOn)}} mins'}, { name:'Manual Time',cellTemplate: '{{row.entity.auditTrailConfig.manualExecutionTime}} mins', cellTooltip: true}, { name:'Saved Time',cellTemplate:'{{grid.appScope.getSavedTime(row.entity.endedOn,row.entity.startedOn)}} mins' + @@ -693,51 +802,27 @@ } $scope.historyLogs=function(hist) { - console.log(hist); - if(hist.auditTrailConfig && (hist.auditTrailConfig.executionType == 'chef') || (hist.auditTrailConfig.executionType == 'jenkins') || (hist.auditTrailConfig.executionType == 'script')) { - var modalInstance = $modal.open({ - animation: true, - templateUrl: 'src/partials/sections/dashboard/bots/view/botExecutionLogs.html', - controller: 'botExecutionLogsCtrl as botExecLogCtrl', - backdrop : 'static', - keyboard: false, - resolve: { - items: function() { - return { - taskId : hist.auditId, - historyId : hist.auditHistoryId ? hist.auditHistoryId : hist.auditTrailConfig.nodeIdsWithActionLog[0] && hist.auditTrailConfig.nodeIdsWithActionLog[0].actionLogId, - taskType:hist.auditTrailConfig.executionType - }; - } - } - }); - modalInstance.result.then(function(selectedItem) { - $scope.selected = selectedItem; - }, function() { - console.log('Modal Dismissed at ' + new Date()); - }); - } else { - var modalInstance = $modal.open({ - animation: true, - templateUrl: 'src/partials/sections/dashboard/workzone/instance/popups/instanceLogs.html', - controller: 'cpActionHistoryLogCtrl', - backdrop : 'static', - keyboard: false, - resolve: { - items: function() { - return { - actionHistoryData : hist, - cpInstance: hist - }; - } + var modalInstance = $modal.open({ + animation: true, + templateUrl: 'src/partials/sections/dashboard/bots/view/botExecutionLogs.html', + controller: 'botExecutionLogsCtrl as botExecLogCtrl', + backdrop : 'static', + keyboard: false, + resolve: { + items: function() { + return { + taskId : hist.auditId, + historyId : hist.auditHistoryId ? hist.auditHistoryId : hist.auditTrailConfig.nodeIdsWithActionLog[0] && hist.auditTrailConfig.nodeIdsWithActionLog[0].actionLogId, + taskType:hist.auditTrailConfig.executionType + }; } - }); - modalInstance.result.then(function(selectedItem) { - $scope.selected = selectedItem; - }, function() { - console.log('Modal Dismissed at ' + new Date()); - }); - }; + } + }); + modalInstance.result.then(function(selectedItem) { + $scope.selected = selectedItem; + }, function() { + console.log('Modal Dismissed at ' + new Date()); + }); } $scope.cancel= function() { diff --git a/client/cat3/src/partials/sections/dashboard/bots/view/botExecutionLogs.html b/client/cat3/src/partials/sections/dashboard/bots/view/botExecutionLogs.html index 8a6fc9461..ff1b70da1 100644 --- a/client/cat3/src/partials/sections/dashboard/bots/view/botExecutionLogs.html +++ b/client/cat3/src/partials/sections/dashboard/bots/view/botExecutionLogs.html @@ -13,10 +13,7 @@