Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to instantiate module lemur #996

Closed
explody opened this issue Nov 17, 2017 · 9 comments
Closed

Failed to instantiate module lemur #996

explody opened this issue Nov 17, 2017 · 9 comments
Labels

Comments

@explody
Copy link
Contributor

explody commented Nov 17, 2017

We've run into a UI error that popped up somewhere along the way, but we can't pinpoint exactly where, though we did have the app running ok previously (in a non-prod env, a git pull must have broken it but we don't know which rev). In short, the server runs fine but the UI renders only the index page, and fails to otherwise respond - links don't work, current username does not render.

We get this in the JS console:

Error: [$injector:modulerr] Failed to instantiate module lemur due to:
[$injector:modulerr] Failed to instantiate module chart.js due to:
[$injector:nomod] Module 'chart.js' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.4.9/$injector/nomod?p0=chart.js
minErr/<@http://localhost:8000/scripts/vendor.js:17042:12
module/<@http://localhost:8000/scripts/vendor.js:18980:17
ensure@http://localhost:8000/scripts/vendor.js:18904:38
module@http://localhost:8000/scripts/vendor.js:18978:14
loadModules/<@http://localhost:8000/scripts/vendor.js:21421:22
forEach@http://localhost:8000/scripts/vendor.js:17315:11
loadModules@http://localhost:8000/scripts/vendor.js:21405:5
loadModules/<@http://localhost:8000/scripts/vendor.js:21422:40
forEach@http://localhost:8000/scripts/vendor.js:17315:11
loadModules@http://localhost:8000/scripts/vendor.js:21405:5
createInjector@http://localhost:8000/scripts/vendor.js:21330:11
doBootstrap@http://localhost:8000/scripts/vendor.js:18651:20
bootstrap@http://localhost:8000/scripts/vendor.js:18672:12
bootstrapApplication/<@http://localhost:8000/scripts/main.js:38:7
fire@http://localhost:8000/scripts/vendor.js:3187:11
add@http://localhost:8000/scripts/vendor.js:3246:7
jQuery.fn.ready@http://localhost:8000/scripts/vendor.js:3496:2
bootstrapApplication@http://localhost:8000/scripts/main.js:37:5
processQueue@http://localhost:8000/scripts/vendor.js:31965:28
scheduleProcessQueue/<@http://localhost:8000/scripts/vendor.js:31981:27
$eval@http://localhost:8000/scripts/vendor.js:33225:16
$digest@http://localhost:8000/scripts/vendor.js:33043:15
$apply@http://localhost:8000/scripts/vendor.js:33333:13
done@http://localhost:8000/scripts/vendor.js:27765:36
completeRequest@http://localhost:8000/scripts/vendor.js:27963:7
requestLoaded@http://localhost:8000/scripts/vendor.js:27904:9

This smells an awful lot like a dependency issue to me but after blundering around with the bower/package JSONs, I haven't been able to fix it. Additionally, we've tried old revisions going back quite a way with no luck.

Could this be #722 redux?

@explody
Copy link
Contributor Author

explody commented Nov 17, 2017

We found a dev instance that had not yet been updated, and with a working UI. There were only minor differences in the bower list compared to our broken one, so we forced the current dev instance to the same versions of bower packages. Lo and behold, it worked! Login and other functionality are back. We only forced two packages down:

angular-smart-table#2.1.9 => angular-smart-table#2.1.8
angular-translate#2.16.0 => angular-translate#2.15.2

Though, this is a modestly significant version change from what's actually in bower.json, at least for angular-translate:

diff --git a/bower.json b/bower.json
index 4b13ce1..ee41789 100644
--- a/bower.json
+++ b/bower.json
@@ -31,10 +31,10 @@
     "font-awesome": "~4.5.0",
     "lodash": "~4.0.1",
     "underscore": "~1.8.3",
-    "angular-smart-table": "~2.1.6",
+    "angular-smart-table": "2.1.8",
     "angular-strap": ">= 2.2.2",
     "angular-underscore": "^0.5.0",
-    "angular-translate": "^2.9.0",
+    "angular-translate": "2.15.2",
     "angular-ui-switch": "~0.1.0",
     "angular-sanitize": "~1.5.0",
     "angular-file-saver": "~1.0.1",

We also don't know which of the two packages resulted in the fix, yet.

@kevgliss
Copy link
Contributor

Thanks for the info, so it looks like pinning to "angular-smart-table": "2.1.6" and "angular-translate": "2.9.0" resolves the issue you're seeing?

@kevgliss
Copy link
Contributor

Another possibility is we can update angular-chart to it's newest version (1.1.1, we are on 0.8.8). This may play more nicely with some of the newer angular packages.

@kevgliss
Copy link
Contributor

For what's it worth, I haven't been able to replicate this just yet. I did a fresh install of all node_modules and bower_components and was able to use the UI okay. My installed packages:

lemur /Users/kglisson/Documents/Code/Github/forks/lemur
├── angular#1.4.9 (latest is 1.6.7-build.5501+sha.55ba449)
├─┬ angular-animate#1.4.14 (latest is 1.6.7-build.5501+sha.55ba449)
│ └── angular#1.4.9 incompatible with 1.4.14 (1.4.14 available, latest is 1.6.7-build.5501+sha.55ba449)
├─┬ angular-bootstrap#1.1.2 (latest is 2.5.0)
│ └── angular#1.4.9 (1.6.7-build.5501+sha.55ba449 available)
├─┬ angular-chart.js#0.8.9 (latest is 1.1.1)
│ ├── Chart.js#1.0.2 (latest is 2.7.1)
│ └── angular#1.4.9 (1.4.14 available, latest is 1.6.7-build.5501+sha.55ba449)
├─┬ angular-clipboard#1.3.0 (latest is 1.6.2)
│ └── angular#1.4.9 (1.6.7-build.5501+sha.55ba449 available)
├─┬ angular-file-saver#1.0.3 (latest is 1.1.3)
│ ├── blob-polyfill#1.0.20150320 (latest is 2.0.20171115)
│ └── file-saver.js#1.20150507.2
├─┬ angular-loading-bar#0.8.0 (latest is 0.9.0)
│ └── angular#1.4.9 (1.6.7-build.5501+sha.55ba449 available)
├─┬ angular-moment#0.10.3 (latest is 1.1.0)
│ ├── angular#1.4.9 (1.4.14 available, latest is 1.6.7-build.5501+sha.55ba449)
│ └── moment#2.10.6 (latest is 2.19.2)
├─┬ angular-sanitize#1.5.11 (latest is 1.6.7-build.5501+sha.55ba449)
│ └── angular#1.4.9 incompatible with 1.5.11 (1.5.11 available, latest is 1.6.7-build.5501+sha.55ba449)
├── angular-smart-table#2.1.9
├─┬ angular-strap#2.3.12
│ └── angular#1.4.9 (1.6.7-build.5501+sha.55ba449 available)
├─┬ angular-translate#2.16.0
│ └── angular#1.4.9 (1.6.7-build.5501+sha.55ba449 available)
├─┬ angular-ui-router#0.2.18 (latest is 1.0.11)
│ └── angular#1.4.9 (1.6.7-build.5501+sha.55ba449 available)
├─┬ angular-ui-select#0.17.1 (latest is 0.19.8)
│ └── angular#1.4.9 (1.6.7-build.5501+sha.55ba449 available)
├── angular-ui-switch#0.1.1
├── angular-underscore#0.5.0
├─┬ angular-wizard#0.4.3 (latest is 1.1.1)
│ ├── angular#1.4.9
│ └── lodash#2.4.2 (latest is 4.17.4)
├─┬ angularjs-toaster#1.0.0 (latest is 2.2.0)
│ ├── angular#1.4.9 (1.6.7-build.5501+sha.55ba449 available)
│ └── angular-animate#1.4.14 (1.6.7-build.5501+sha.55ba449 available)
├─┬ bootstrap#3.3.7 (latest is 4.0.0-beta.2)
│ └── jquery#2.2.4 (3.2.1 available)
├─┬ bootswatch#3.3.7 (latest is 4.0.0-beta.2)
│ └── bootstrap#3.3.7 (latest is 4.0.0-beta.2)
├── d3#3.5.17 (latest is 4.11.0)
├── es5-shim#4.5.9
├── font-awesome#4.5.0 (latest is 4.7.0)
├── fontawesome#4.5.0 (latest is 4.7.0)
├── jquery#2.2.4 (latest is 3.2.1)
├── json3#3.3.2
├── lodash#2.4.2 incompatible with ~4.0.1 (4.0.9-npm-packages available, latest is 4.17.4)
├── moment#2.10.6 incompatible with ~2.11.1 (2.11.2 available, latest is 2.19.2)
├─┬ moment-range#2.1.0 (latest is 3.0.3)
│ └── moment#2.10.6 (2.19.2 available)
├─┬ ng-table#0.8.3 (latest is 4.0.0)
│ └── angular#1.4.9 (1.6.7-build.5501+sha.55ba449 available)
├─┬ ngletteravatar#4.0.4
│ └── angular#1.4.9
├─┬ restangular#1.5.2 (latest is 1.6.1)
│ ├── angular#1.4.9 (1.6.7-build.5501+sha.55ba449 available)
│ └── lodash#2.4.2 (4.17.4 available)
├─┬ satellizer#0.13.4 (latest is 0.15.5)
│ └── angular#1.4.9 (1.6.7-build.5501+sha.55ba449 available)
└── underscore#1.8.3

@enugentdt
Copy link

Hey, throwing in my two cents since I'm having this issue as well. I've got a system that's throwing these errors. I'm going to try a complete reinstall (thank goodness for VMs), but if you like, is there anything I should try as well, or any info that could help debug the issue? If you want me to upload the Xen boot drive (it's only 10GB), I can do that as well.

For now, I'm going to create a second VM and try a fresh reinstall. Let's see what happens, shall we?

@vsnine
Copy link
Contributor

vsnine commented Nov 24, 2017

I ran into this issue today. Setting the following in bower.json then running make release fixed the issue for me:

diff --git a/bower.json b/bower.json
index 4b13ce1..f7d5500 100644
--- a/bower.json
+++ b/bower.json
@@ -31,7 +31,7 @@
     "font-awesome": "~4.5.0",
     "lodash": "~4.0.1",
     "underscore": "~1.8.3",
-    "angular-smart-table": "~2.1.6",
+    "angular-smart-table": "2.1.8",
     "angular-strap": ">= 2.2.2",
     "angular-underscore": "^0.5.0",
     "angular-translate": "^2.9.0",

@explody
Copy link
Contributor Author

explody commented Nov 26, 2017

I should clarify that we pinned to

angular-smart-table#2.1.8
angular-translate#2.15.2

That's a downgrade from 2.1.9 and 2.16.0 respectively, which were the current versions that bower was pulling in at the time I reported this.

If pinning only angular-smart-table worked for @vsnine, that may be the only one that needs it but we haven't tested that yet.

@jchuong
Copy link
Contributor

jchuong commented Nov 28, 2017

FWIW, also getting this issue.

Building make release on my machine (OSX) or building the lemur-docker seems to be fine, but building the files on a fresh Docker image (Xenial but I have lemur-docker running in Xenial also) via Jenkins creates a different vendor.js than what I create locally. Specifically, smart-table's dist/smart-table.js doesn't look to be in the vendor.js, but index.js was.

EDIT: Pinning smart-table and translate from above seems to work for me.

My diff

--- ~/static » diff ~/static/real/scripts/vendor.js dist/scripts/vendor.js
80273,80274c80273,80806
< require('./dist/smart-table.js');
< module.exports = 'smart-table';
---
> /**
> * @version 2.1.8
> * @license MIT
> */
> (function (ng, undefined){
>     'use strict';
>
> ng.module('smart-table', []).run(['$templateCache', function ($templateCache) {
>     $templateCache.put('template/smart-table/pagination.html',
>         '<nav ng-if="numPages && pages.length >= 2"><ul class="pagination">' +
>         '<li ng-repeat="page in pages" ng-class="{active: page==currentPage}"><a href="javascript: void(0);" ng-click="selectPage(page)">{{page}}</a></li>' +
>         '</ul></nav>');
> }]);
>
>
> ng.module('smart-table')
>   .constant('stConfig', {
>     pagination: {
>       template: 'template/smart-table/pagination.html',
>       itemsByPage: 10,
>       displayedPages: 5
>     },
>     search: {
>       delay: 400, // ms
>       inputEvent: 'input'
>     },
>     select: {
>       mode: 'single',
>       selectedClass: 'st-selected'
>     },
>     sort: {
>       ascentClass: 'st-sort-ascent',
>       descentClass: 'st-sort-descent',
>       descendingFirst: false,
>       skipNatural: false,
>       delay:300
>     },
>     pipe: {
>       delay: 100 //ms
>     }
>   });
> ng.module('smart-table')
>   .controller('stTableController', ['$scope', '$parse', '$filter', '$attrs', function StTableController ($scope, $parse, $filter, $attrs) {
>     var propertyName = $attrs.stTable;
>     var displayGetter = $parse(propertyName);
>     var displaySetter = displayGetter.assign;
>     var safeGetter;
>     var orderBy = $filter('orderBy');
>     var filter = $filter('filter');
>     var safeCopy = copyRefs(displayGetter($scope));
>     var tableState = {
>       sort: {},
>       search: {},
>       pagination: {
>         start: 0,
>         totalItemCount: 0
>       }
>     };
>     var filtered;
>     var pipeAfterSafeCopy = true;
>     var ctrl = this;
>     var lastSelected;
>
>     function copyRefs (src) {
>       return src ? [].concat(src) : [];
>     }
>
>     function updateSafeCopy () {
>       safeCopy = copyRefs(safeGetter($scope));
>       if (pipeAfterSafeCopy === true) {
>         ctrl.pipe();
>       }
>     }
>
>     function deepDelete (object, path) {
>       if (path.indexOf('.') != -1) {
>         var partials = path.split('.');
>         var key = partials.pop();
>         var parentPath = partials.join('.');
>         var parentObject = $parse(parentPath)(object)
>         delete parentObject[key];
>         if (Object.keys(parentObject).length == 0) {
>           deepDelete(object, parentPath);
>         }
>       } else {
>         delete object[path];
>       }
>     }
>
>     if ($attrs.stSafeSrc) {
>       safeGetter = $parse($attrs.stSafeSrc);
>       $scope.$watch(function () {
>         var safeSrc = safeGetter($scope);
>         return safeSrc && safeSrc.length ? safeSrc[0] : undefined;
>       }, function (newValue, oldValue) {
>         if (newValue !== oldValue) {
>           updateSafeCopy();
>         }
>       });
>       $scope.$watch(function () {
>         var safeSrc = safeGetter($scope);
>         return safeSrc ? safeSrc.length : 0;
>       }, function (newValue, oldValue) {
>         if (newValue !== safeCopy.length) {
>           updateSafeCopy();
>         }
>       });
>       $scope.$watch(function () {
>         return safeGetter($scope);
>       }, function (newValue, oldValue) {
>         if (newValue !== oldValue) {
>           tableState.pagination.start = 0;
>           updateSafeCopy();
>         }
>       });
>     }
>
>     /**
>      * sort the rows
>      * @param {Function | String} predicate - function or string which will be used as predicate for the sorting
>      * @param [reverse] - if you want to reverse the order
>      */
>     this.sortBy = function sortBy (predicate, reverse) {
>       tableState.sort.predicate = predicate;
>       tableState.sort.reverse = reverse === true;
>
>       if (ng.isFunction(predicate)) {
>         tableState.sort.functionName = predicate.name;
>       } else {
>         delete tableState.sort.functionName;
>       }
>
>       tableState.pagination.start = 0;
>       return this.pipe();
>     };
>
>     /**
>      * search matching rows
>      * @param {String} input - the input string
>      * @param {String} [predicate] - the property name against you want to check the match, otherwise it will search on all properties
>      */
>     this.search = function search (input, predicate) {
>       var predicateObject = tableState.search.predicateObject || {};
>       var prop = predicate ? predicate : '$';
>
>       input = ng.isString(input) ? input.trim() : input;
>       $parse(prop).assign(predicateObject, input);
>       // to avoid to filter out null value
>       if (!input) {
>         deepDelete(predicateObject, prop);
>       }
>       tableState.search.predicateObject = predicateObject;
>       tableState.pagination.start = 0;
>       return this.pipe();
>     };
>
>     /**
>      * this will chain the operations of sorting and filtering based on the current table state (sort options, filtering, ect)
>      */
>     this.pipe = function pipe () {
>       var pagination = tableState.pagination;
>       var output;
>       filtered = tableState.search.predicateObject ? filter(safeCopy, tableState.search.predicateObject) : safeCopy;
>       if (tableState.sort.predicate) {
>         filtered = orderBy(filtered, tableState.sort.predicate, tableState.sort.reverse);
>       }
>       pagination.totalItemCount = filtered.length;
>       if (pagination.number !== undefined) {
>         pagination.numberOfPages = filtered.length > 0 ? Math.ceil(filtered.length / pagination.number) : 1;
>         pagination.start = pagination.start >= filtered.length ? (pagination.numberOfPages - 1) * pagination.number : pagination.start;
>         output = filtered.slice(pagination.start, pagination.start + parseInt(pagination.number));
>       }
>       displaySetter($scope, output || filtered);
>     };
>
>     /**
>      * select a dataRow (it will add the attribute isSelected to the row object)
>      * @param {Object} row - the row to select
>      * @param {String} [mode] - "single" or "multiple" (multiple by default)
>      */
>     this.select = function select (row, mode) {
>       var rows = copyRefs(displayGetter($scope));
>       var index = rows.indexOf(row);
>       if (index !== -1) {
>         if (mode === 'single') {
>           row.isSelected = row.isSelected !== true;
>           if (lastSelected) {
>             lastSelected.isSelected = false;
>           }
>           lastSelected = row.isSelected === true ? row : undefined;
>         } else {
>           rows[index].isSelected = !rows[index].isSelected;
>         }
>       }
>     };
>
>     /**
>      * take a slice of the current sorted/filtered collection (pagination)
>      *
>      * @param {Number} start - start index of the slice
>      * @param {Number} number - the number of item in the slice
>      */
>     this.slice = function splice (start, number) {
>       tableState.pagination.start = start;
>       tableState.pagination.number = number;
>       return this.pipe();
>     };
>
>     /**
>      * return the current state of the table
>      * @returns {{sort: {}, search: {}, pagination: {start: number}}}
>      */
>     this.tableState = function getTableState () {
>       return tableState;
>     };
>
>     this.getFilteredCollection = function getFilteredCollection () {
>       return filtered || safeCopy;
>     };
>
>     /**
>      * Use a different filter function than the angular FilterFilter
>      * @param filterName the name under which the custom filter is registered
>      */
>     this.setFilterFunction = function setFilterFunction (filterName) {
>       filter = $filter(filterName);
>     };
>
>     /**
>      * Use a different function than the angular orderBy
>      * @param sortFunctionName the name under which the custom order function is registered
>      */
>     this.setSortFunction = function setSortFunction (sortFunctionName) {
>       orderBy = $filter(sortFunctionName);
>     };
>
>     /**
>      * Usually when the safe copy is updated the pipe function is called.
>      * Calling this method will prevent it, which is something required when using a custom pipe function
>      */
>     this.preventPipeOnWatch = function preventPipe () {
>       pipeAfterSafeCopy = false;
>     };
>   }])
>   .directive('stTable', function () {
>     return {
>       restrict: 'A',
>       controller: 'stTableController',
>       link: function (scope, element, attr, ctrl) {
>
>         if (attr.stSetFilter) {
>           ctrl.setFilterFunction(attr.stSetFilter);
>         }
>
>         if (attr.stSetSort) {
>           ctrl.setSortFunction(attr.stSetSort);
>         }
>       }
>     };
>   });
>
> ng.module('smart-table')
>   .directive('stSearch', ['stConfig', '$timeout','$parse', function (stConfig, $timeout, $parse) {
>     return {
>       require: '^stTable',
>       link: function (scope, element, attr, ctrl) {
>         var tableCtrl = ctrl;
>         var promise = null;
>         var throttle = attr.stDelay || stConfig.search.delay;
>         var event = attr.stInputEvent || stConfig.search.inputEvent;
>
>         attr.$observe('stSearch', function (newValue, oldValue) {
>           var input = element[0].value;
>           if (newValue !== oldValue && input) {
>             ctrl.tableState().search = {};
>             tableCtrl.search(input, newValue);
>           }
>         });
>
>         //table state -> view
>         scope.$watch(function () {
>           return ctrl.tableState().search;
>         }, function (newValue, oldValue) {
>           var predicateExpression = attr.stSearch || '$';
>           if (newValue.predicateObject && $parse(predicateExpression)(newValue.predicateObject) !== element[0].value) {
>             element[0].value = $parse(predicateExpression)(newValue.predicateObject) || '';
>           }
>         }, true);
>
>         // view -> table state
>         element.bind(event, function (evt) {
>           evt = evt.originalEvent || evt;
>           if (promise !== null) {
>             $timeout.cancel(promise);
>           }
>
>           promise = $timeout(function () {
>             tableCtrl.search(evt.target.value, attr.stSearch || '');
>             promise = null;
>           }, throttle);
>         });
>       }
>     };
>   }]);
>
> ng.module('smart-table')
>   .directive('stSelectRow', ['stConfig', function (stConfig) {
>     return {
>       restrict: 'A',
>       require: '^stTable',
>       scope: {
>         row: '=stSelectRow'
>       },
>       link: function (scope, element, attr, ctrl) {
>         var mode = attr.stSelectMode || stConfig.select.mode;
>         element.bind('click', function () {
>           scope.$apply(function () {
>             ctrl.select(scope.row, mode);
>           });
>         });
>
>         scope.$watch('row.isSelected', function (newValue) {
>           if (newValue === true) {
>             element.addClass(stConfig.select.selectedClass);
>           } else {
>             element.removeClass(stConfig.select.selectedClass);
>           }
>         });
>       }
>     };
>   }]);
>
> ng.module('smart-table')
>   .directive('stSort', ['stConfig', '$parse', '$timeout', function (stConfig, $parse, $timeout) {
>     return {
>       restrict: 'A',
>       require: '^stTable',
>       link: function (scope, element, attr, ctrl) {
>
>         var predicate = attr.stSort;
>         var getter = $parse(predicate);
>         var index = 0;
>         var classAscent = attr.stClassAscent || stConfig.sort.ascentClass;
>         var classDescent = attr.stClassDescent || stConfig.sort.descentClass;
>         var stateClasses = [classAscent, classDescent];
>         var sortDefault;
>         var skipNatural = attr.stSkipNatural !== undefined ? attr.stSkipNatural : stConfig.sort.skipNatural;
>         var descendingFirst = attr.stDescendingFirst !== undefined ? attr.stDescendingFirst : stConfig.sort.descendingFirst;
>         var promise = null;
>         var throttle = attr.stDelay || stConfig.sort.delay;
>
>         if (attr.stSortDefault) {
>           sortDefault = scope.$eval(attr.stSortDefault) !== undefined ? scope.$eval(attr.stSortDefault) : attr.stSortDefault;
>         }
>
>         //view --> table state
>         function sort () {
>           if (descendingFirst) {
>             index = index === 0 ? 2 : index - 1;
>           } else {
>             index++;
>           }
>
>           var func;
>           predicate = ng.isFunction(getter(scope)) || ng.isArray(getter(scope)) ? getter(scope) : attr.stSort;
>           if (index % 3 === 0 && !!skipNatural !== true) {
>             //manual reset
>             index = 0;
>             ctrl.tableState().sort = {};
>             ctrl.tableState().pagination.start = 0;
>             func = ctrl.pipe.bind(ctrl);
>           } else {
>             func = ctrl.sortBy.bind(ctrl, predicate, index % 2 === 0);
>           }
>           if (promise !== null) {
>             $timeout.cancel(promise);
>           }
>           if (throttle < 0) {
>             func();
>           } else {
>             promise = $timeout(func, throttle);
>           }
>         }
>
>         element.bind('click', function sortClick () {
>           if (predicate) {
>             scope.$apply(sort);
>           }
>         });
>
>         if (sortDefault) {
>           index = sortDefault === 'reverse' ? 1 : 0;
>           sort();
>         }
>
>         //table state --> view
>         scope.$watch(function () {
>           return ctrl.tableState().sort;
>         }, function (newValue) {
>           if (newValue.predicate !== predicate) {
>             index = 0;
>             element
>               .removeClass(classAscent)
>               .removeClass(classDescent);
>           } else {
>             index = newValue.reverse === true ? 2 : 1;
>             element
>               .removeClass(stateClasses[index % 2])
>               .addClass(stateClasses[index - 1]);
>           }
>         }, true);
>       }
>     };
>   }]);
>
> ng.module('smart-table')
>   .directive('stPagination', ['stConfig', function (stConfig) {
>     return {
>       restrict: 'EA',
>       require: '^stTable',
>       scope: {
>         stItemsByPage: '=?',
>         stDisplayedPages: '=?',
>         stPageChange: '&'
>       },
>       templateUrl: function (element, attrs) {
>         if (attrs.stTemplate) {
>           return attrs.stTemplate;
>         }
>         return stConfig.pagination.template;
>       },
>       link: function (scope, element, attrs, ctrl) {
>
>         scope.stItemsByPage = scope.stItemsByPage ? +(scope.stItemsByPage) : stConfig.pagination.itemsByPage;
>         scope.stDisplayedPages = scope.stDisplayedPages ? +(scope.stDisplayedPages) : stConfig.pagination.displayedPages;
>
>         scope.currentPage = 1;
>         scope.pages = [];
>
>         function redraw () {
>           var paginationState = ctrl.tableState().pagination;
>           var start = 1;
>           var end;
>           var i;
>           var prevPage = scope.currentPage;
>           scope.totalItemCount = paginationState.totalItemCount;
>           scope.currentPage = Math.floor(paginationState.start / paginationState.number) + 1;
>
>           start = Math.max(start, scope.currentPage - Math.abs(Math.floor(scope.stDisplayedPages / 2)));
>           end = start + scope.stDisplayedPages;
>
>           if (end > paginationState.numberOfPages) {
>             end = paginationState.numberOfPages + 1;
>             start = Math.max(1, end - scope.stDisplayedPages);
>           }
>
>           scope.pages = [];
>           scope.numPages = paginationState.numberOfPages;
>
>           for (i = start; i < end; i++) {
>             scope.pages.push(i);
>           }
>
>           if (prevPage !== scope.currentPage) {
>             scope.stPageChange({newPage: scope.currentPage});
>           }
>         }
>
>         //table state --> view
>         scope.$watch(function () {
>           return ctrl.tableState().pagination;
>         }, redraw, true);
>
>         //scope --> table state  (--> view)
>         scope.$watch('stItemsByPage', function (newValue, oldValue) {
>           if (newValue !== oldValue) {
>             scope.selectPage(1);
>           }
>         });
>
>         scope.$watch('stDisplayedPages', redraw);
>
>         //view -> table state
>         scope.selectPage = function (page) {
>           if (page > 0 && page <= scope.numPages) {
>             ctrl.slice((page - 1) * scope.stItemsByPage, scope.stItemsByPage);
>           }
>         };
>
>         if (!ctrl.tableState().pagination.number) {
>           ctrl.slice(0, scope.stItemsByPage);
>         }
>       }
>     };
>   }]);
>
> ng.module('smart-table')
>   .directive('stPipe', ['stConfig', '$timeout', function (config, $timeout) {
>     return {
>       require: 'stTable',
>       scope: {
>         stPipe: '='
>       },
>       link: {
>
>         pre: function (scope, element, attrs, ctrl) {
>
>           var pipePromise = null;
>
>           if (ng.isFunction(scope.stPipe)) {
>             ctrl.preventPipeOnWatch();
>             ctrl.pipe = function () {
>
>               if (pipePromise !== null) {
>                 $timeout.cancel(pipePromise)
>               }
>
>               pipePromise = $timeout(function () {
>                 scope.stPipe(ctrl.tableState(), ctrl);
>               }, config.pipe.delay);
>
>               return pipePromise;
>             }
>           }
>         },
>
>         post: function (scope, element, attrs, ctrl) {
>           ctrl.pipe();
>         }
>       }
>     };
>   }]);
>
> })(angular);

'Real' being what Jenkins built on the left, and the diff showing what I generated manually. Will comment on pinning the versions and see if that helps.

@kevgliss
Copy link
Contributor

kevgliss commented Dec 4, 2017

I was able to re-create internally, I have pushed #1010 which has fixed this particular issue. Thanks all for reporting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants