github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/public/static/js/directives/directives.visualization.js (about) 1 var directives = directives || {}; 2 3 directives.visualization = angular.module('directives.visualization', ['md5']); 4 5 directives.visualization.directive('progressBar', function($filter) { 6 return function(scope, element, attrs) { 7 var lastVal = 0; 8 var lastClass = "progress-bar-success"; 9 var lastMax = 1; 10 11 element.html('<div class="progress-bar progress-bar-success" role="progressbar" style="width: 0%"></div>'); 12 13 scope.$watch(attrs.progressBar, function(val) { 14 if (isNaN(val)) {} else { 15 lastVal = val; 16 element.children('.progress-bar').css('width', (val / lastMax * 100) + '%'); 17 if (attrs.progressBarTitle) { 18 $(element).children('.progress-bar').tooltip({ 19 title: scope.$eval(attrs.progressBarTitle), 20 animation: false 21 }); 22 } 23 } 24 }); 25 26 scope.$watch(attrs.progressBarMax, function(val) { 27 if (isNaN(val)) {} else { 28 lastMax = val || 1; // don't allow val = 0; 29 element.children('.progress-bar').css('width', (lastVal / lastMax * 100) + '%'); 30 if (attrs.progressBarTitle) { 31 $(element).children('.progress-bar').tooltip({ 32 title: scope.$eval(attrs.progressBarTitle), 33 animation: false 34 }); 35 } 36 } 37 }); 38 39 if (attrs.progressBarClass) { 40 scope.$watch(attrs.progressBarClass, function(val) { 41 element.children('.progress-bar').removeClass(lastClass); 42 lastClass = $filter('statusFilter')(val); 43 element.children('.progress-bar').addClass(lastClass); 44 }); 45 } 46 } 47 }).directive('resultsBar', function() { 48 return { 49 scope: true, 50 restrict: 'A', 51 link: function(scope, element, attrs) { 52 scope.results = []; 53 scope.widthPerSlice = 100 + '%'; 54 55 scope.$parent.$watch(attrs.resultsBar, function(v) { 56 if (!v) { 57 return; 58 } 59 60 scope.results = v; 61 scope.widthPerSlice = (100 / (v.length || 1)) + "%"; 62 63 setTimeout(function() { 64 // Need to do setTimeout so template has a chance to catch up 65 $(element).children('.result-slice').each(function(i, el) { 66 if (i < scope.results.length) { 67 if (scope.results[i].tooltip) { 68 $(el).tooltip({ 69 title: scope.results[i].tooltip, 70 animation: false 71 }); 72 } 73 74 if (scope.results[i].link) { 75 $(el).attr('href', scope.results[i].link); 76 } 77 } 78 }); 79 }, 0); 80 }); 81 }, 82 template: '<a ng-repeat="result in results" ng-style="{ display : \'block\', width : widthPerSlice }" ' + 83 ' ng-class="result.class" class="result-slice"></div>' 84 }; 85 }) 86 //buildGrid creates a group of task boxes in react. It serves as a shim between 87 //our angularjs and the React code used to create and manage the boxes. 88 .directive('buildGrid', function gridDirective() { 89 return ({ 90 link: link, 91 scope: { 92 collapsed: "=", 93 onClose: "&", 94 build: "=" 95 } 96 }); 97 function link(scope, element, attributes) { 98 //project out the tasks from the uiTask struct to what the react code expects. 99 var tasks = _.map(scope.build.Tasks, function (task) { 100 var t = task.Task; 101 t.failed_test_names = task.failed_test_names; 102 return t; 103 }); 104 // bind the angular $destroy to a function that removes the react element 105 // from the DOM. 106 scope.$on("$destroy", unmountReactElement); 107 108 // bind angular's changes in the 'collapsed' variable to re-render the React 109 // element. 110 scope.$watch("collapsed", renderReactElement); 111 112 // renderReactElement packages the props and renders the React element into the DOM. 113 function renderReactElement() { 114 var props = { 115 onClose: function() { 116 scope.$apply(scope.onClose); 117 }, 118 build: { 119 id: scope.build.Build._id, 120 taskStatusCount: scope.build.taskStatusCount, 121 tasks: tasks 122 }, 123 rolledUp: false, 124 collapseInfo: { 125 collapsed: scope.collapsed, 126 activeTaskStatuses : ['failed','system-failed'] 127 } 128 } 129 ReactDOM.render( 130 React.createElement(Build, props), 131 element[0] 132 ); 133 } 134 function unmountReactElement() { 135 React.unmountComponentAtNode(element[0]); 136 } 137 } 138 }).directive('ngBindHtmlUnsafe', function() { 139 // Because ng-bind-html prevents you from entering text with left angle 140 // bracket (<) we can't use it for logs 141 return function(scope, element, attr) { 142 scope.$watch(attr.ngBindHtmlUnsafe, function(v) { 143 element.html(v); 144 }); 145 }; 146 });