Mercurial > hg > thermostat-ng > web-client
changeset 180:53de35e22716
Convert jvm-gc module into component
Reviewed-by: jerboaa
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-September/024867.html
author | Andrew Azores <aazores@redhat.com> |
---|---|
date | Thu, 07 Sep 2017 08:06:46 -0400 |
parents | 8f116d9b0130 |
children | 8d3c8addabad |
files | src/app/components/jvm-info/jvm-gc/jvm-gc.component.js src/app/components/jvm-info/jvm-gc/jvm-gc.controller.js src/app/components/jvm-info/jvm-gc/jvm-gc.controller.spec.js src/app/components/jvm-info/jvm-gc/jvm-gc.html src/app/components/jvm-info/jvm-gc/jvm-gc.module.js src/app/components/jvm-info/jvm-gc/jvm-gc.routing.js src/app/components/jvm-info/jvm-gc/jvm-gc.routing.spec.js |
diffstat | 7 files changed, 142 insertions(+), 147 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/app/components/jvm-info/jvm-gc/jvm-gc.component.js Thu Sep 07 08:06:46 2017 -0400 @@ -0,0 +1,40 @@ +/** + * Copyright 2012-2017 Red Hat, Inc. + * + * Thermostat is distributed under the GNU General Public License, + * version 2 or any later version (with a special exception described + * below, commonly known as the "Classpath Exception"). + * + * A copy of GNU General Public License (GPL) is included in this + * distribution, in the file COPYING. + * + * Linking Thermostat code with other modules is making a combined work + * based on Thermostat. Thus, the terms and conditions of the GPL + * cover the whole combination. + * + * As a special exception, the copyright holders of Thermostat give you + * permission to link this code with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under + * terms of your choice, provided that you also meet, for each linked + * independent module, the terms and conditions of the license of that + * module. An independent module is a module which is not derived from + * or based on Thermostat code. If you modify Thermostat, you may + * extend this exception to your version of the software, but you are + * not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +import JvmGcController from './jvm-gc.controller.js'; +import service from './jvm-gc.service.js'; + +export default angular + .module('jvmGc', [ + JvmGcController, + service + ]) + .component('jvmGc', { + controller: 'JvmGcController', + template: require('./jvm-gc.html') + }) + .name;
--- a/src/app/components/jvm-info/jvm-gc/jvm-gc.controller.js Wed Sep 06 10:17:05 2017 -0400 +++ b/src/app/components/jvm-info/jvm-gc/jvm-gc.controller.js Thu Sep 07 08:06:46 2017 -0400 @@ -30,26 +30,19 @@ import service from './jvm-gc.service.js'; class JvmGcController { - constructor (jvmId, $scope, $interval, dateFilter, DATE_FORMAT, + constructor ($stateParams, $scope, $interval, dateFilter, DATE_FORMAT, metricToNumberFilter, jvmGcService, sanitizeService, $translate) { 'ngInject'; - this.jvmId = jvmId; - this.scope = $scope; + this.jvmId = $stateParams.jvmId; this.interval = $interval; this.dateFilter = dateFilter; this.dateFormat = DATE_FORMAT; this.metricToNumberFilter = metricToNumberFilter; this.jvmGcService = jvmGcService; - this.scope.sanitize = sanitizeService.sanitize; + this.sanitizeService = sanitizeService; this.translate = $translate; - this.scope.refreshRate = '1000'; - this.scope.dataAgeLimit = '30000'; - - this.scope.$watch('refreshRate', (cur, prev) => this.setRefreshRate(cur)); - this.scope.$watch('dataAgeLimit', () => this.trimData()); - - this.scope.$on('$destroy', () => this.stop()); + $scope.$on('$destroy', () => this.stop()); this.collectors = []; this.chartConfigs = {}; @@ -57,20 +50,43 @@ this.collectorData = new Map(); this.constructChartData(); - this.update(parseInt($scope.dataAgeLimit) / parseInt($scope.refreshRate)); + this.refreshRate = '1000'; + this.dataAgeLimit = '30000'; } start () { - this.setRefreshRate(this.scope.refreshRate); + this.refreshRate = this._refreshRate.toString(); } stop () { - if (angular.isDefined(this.refresh)) { - this.interval.cancel(this.refresh); - delete this.refresh; + if (angular.isDefined(this._refresh)) { + this.interval.cancel(this._refresh); + delete this._refresh; + } + } + + set refreshRate (val) { + this.stop(); + this._refreshRate = parseInt(val); + if (this._refreshRate > 0) { + this._refresh = this.interval(() => this.update(), this._refreshRate); + this.update(); } } + get refreshRate () { + return this._refreshRate.toString(); + } + + set dataAgeLimit (val) { + this._dataAgeLimit = val; + this.trimData(); + } + + get dataAgeLimit () { + return this._dataAgeLimit.toString(); + } + makeConfig (collector) { if (_.includes(this.collectors, collector)) { return; @@ -121,21 +137,13 @@ }); } - setRefreshRate (val) { - this.stop(); - if (val > 0) { - this.refresh = this.interval(() => this.update(), val); - this.update(); - } - } - trimData() { for (let entry of this.collectorData) { let collector = entry[0]; let samples = entry[1]; let now = Date.now(); - let oldestLimit = now - parseInt(this.scope.dataAgeLimit); + let oldestLimit = now - parseInt(this.dataAgeLimit); while (true) { let oldest = samples[0]; @@ -169,8 +177,8 @@ } } - update (limit = 1) { - this.jvmGcService.getJvmGcData(this.jvmId, limit) + update () { + this.jvmGcService.getJvmGcData(this.jvmId) .then(resp => this.processData(resp), angular.noop); } @@ -226,6 +234,10 @@ this.constructChartData(); } + sanitize (input) { + return this.sanitizeService.sanitize(input); + } + multichartFn (collector) { return new Promise(resolve => { this.jvmGcService.getJvmGcData(this.jvmId, 1, collector).then(resp => {
--- a/src/app/components/jvm-info/jvm-gc/jvm-gc.controller.spec.js Wed Sep 06 10:17:05 2017 -0400 +++ b/src/app/components/jvm-info/jvm-gc/jvm-gc.controller.spec.js Thu Sep 07 08:06:46 2017 -0400 @@ -30,7 +30,7 @@ beforeEach(angular.mock.module('app.filters')); beforeEach(angular.mock.module('jvmGc.controller')); - let scope, interval, dateFilterStub, dateFormatSpy, svc, promise, ctrl, translate; + let scope, interval, dateFilterStub, dateFormatSpy, svc, promise, ctrl, translate, sanitizeService; beforeEach(inject(($controller) => { 'ngInject'; @@ -41,20 +41,15 @@ } }; - scope = { - $on: sinon.spy(), - $watch: sinon.spy() - }; + scope = { $on: sinon.spy() }; interval = sinon.stub().returns('interval-sentinel'); interval.cancel = sinon.spy(); - promise = { - then: sinon.spy() - }; - svc = { - getJvmGcData: sinon.stub().returns(promise) - }; + promise = { then: sinon.spy() }; + svc = { getJvmGcData: sinon.stub().returns(promise) }; + + sanitizeService = { sanitize: sinon.spy() }; translate = sinon.stub().returns({ then: sinon.stub().yields({ @@ -65,12 +60,13 @@ }); ctrl = $controller('JvmGcController', { - jvmId: 'foo-jvmId', + $stateParams: { jvmId: 'foo-jvmId' }, $scope: scope, $interval: interval, dateFilter: dateFilterStub, DATE_FORMAT: dateFormatSpy, jvmGcService: svc, + sanitizeService: sanitizeService, $translate: translate }); })); @@ -80,7 +76,7 @@ }); it('should update on init', () => { - svc.getJvmGcData.should.be.calledWith('foo-jvmId', 30); + svc.getJvmGcData.should.be.calledWith('foo-jvmId'); }); it('should call to service on update', () => { @@ -112,20 +108,24 @@ }); it('should reset interval on refreshRate change', () => { - ctrl.should.not.have.ownProperty('refresh'); - ctrl.setRefreshRate(1); + ctrl.should.have.ownProperty('_refresh'); + ctrl.refreshRate = '1'; interval.should.be.calledWith(sinon.match.func, sinon.match(1)); - ctrl.should.have.ownProperty('refresh'); - ctrl.refresh.should.equal('interval-sentinel'); + ctrl.should.have.ownProperty('_refresh'); + ctrl._refresh.should.equal('interval-sentinel'); + ctrl.refreshRate.should.equal('1'); }); it('should trim data on dataAgeLimit change', () => { - scope.$watch.should.be.calledWith('dataAgeLimit'); - scope.$watch.args[1][0].should.equal('dataAgeLimit'); - let fn = scope.$watch.args[1][1]; - fn.should.be.a.Function(); + sinon.spy(ctrl, 'trimData'); + ctrl.trimData.should.not.be.called(); + ctrl.dataAgeLimit = 10000; + ctrl.trimData.should.be.calledOnce(); + ctrl.trimData.restore(); + ctrl.dataAgeLimit.should.equal('10000'); }); + it('should trim old data', () => { let oldSample = { micros: 100, @@ -138,7 +138,7 @@ }; ctrl.collectorData.set('fooCollector', [oldSample, futureSample]); - scope.$watch.args[1][1](); + ctrl.dataAgeLimit = '30000'; let expected = new Map(); expected.set('fooCollector', [futureSample]); @@ -147,35 +147,28 @@ }); it('should set interval on start', () => { - interval.should.not.be.called(); + interval.should.be.calledOnce(); + interval.should.be.calledWith(sinon.match.func, 1000); interval.cancel.should.not.be.called(); - - ctrl.start(); - - interval.cancel.should.not.be.called(); - interval.should.be.calledWith(sinon.match.func, '1000'); }); - it('should disable when setRefreshRate is called with a non-positive value', () => { + it('should disable when set refreshRate is called with a non-positive value', () => { interval.cancel.should.not.be.called(); - ctrl.setRefreshRate.should.not.be.called(); ctrl.update.should.not.be.called(); - ctrl.setRefreshRate(1); - - interval.cancel.should.not.be.called(); - ctrl.should.have.ownProperty('refresh'); - - ctrl.setRefreshRate(-1); + ctrl.refreshRate = '1'; interval.cancel.should.be.calledOnce(); - ctrl.should.not.have.ownProperty('refresh'); + ctrl.should.have.ownProperty('_refresh'); + + ctrl.refreshRate = '-1'; + + interval.cancel.should.be.calledTwice(); + ctrl.should.not.have.ownProperty('_refresh'); }); it('should call controller#update() on refresh', () => { - scope.$watch.should.be.calledWith(sinon.match('refreshRate'), sinon.match.func); - let f = scope.$watch.args[0][1]; - f(1); + ctrl.refreshRate = 1; let func = interval.args[0][0]; let callCount = svc.getJvmGcData.callCount; func(); @@ -233,18 +226,18 @@ ctrl.start(); let fn = cfg.onmouseover; fn.should.be.a.Function(); - interval.cancel.should.not.be.called(); + interval.cancel.should.be.calledOnce(); fn(); - interval.cancel.should.be.calledOnce(); + interval.cancel.should.be.calledTwice(); }); it('should start on mouseout', () => { ctrl.stop(); let fn = cfg.onmouseout; fn.should.be.a.Function(); - interval.should.not.be.called(); + interval.should.be.calledOnce(); fn(); - interval.should.be.calledOnce(); + interval.should.be.calledTwice(); }); }); @@ -422,20 +415,29 @@ }); it('should cancel refresh', () => { - ctrl.refresh = 'interval-sentinel'; + ctrl._refresh = 'interval-sentinel'; let func = scope.$on.args[0][1]; func(); interval.cancel.should.be.calledWith('interval-sentinel'); }); it('should do nothing if refresh is undefined', () => { - ctrl.refresh = undefined; + delete ctrl._refresh; let func = scope.$on.args[0][1]; func(); interval.cancel.should.not.be.called(); }); }); + describe('sanitize()', () => { + it('should delegate to sanitizeService', () => { + sanitizeService.sanitize.should.not.be.called(); + ctrl.sanitize('foo'); + sanitizeService.sanitize.should.be.calledOnce(); + sanitizeService.sanitize.should.be.calledWith('foo'); + }); + }); + describe('multichartFn', () => { it('should return a promise', () => { let res = ctrl.multichartFn();
--- a/src/app/components/jvm-info/jvm-gc/jvm-gc.html Wed Sep 06 10:17:05 2017 -0400 +++ b/src/app/components/jvm-info/jvm-gc/jvm-gc.html Thu Sep 07 08:06:46 2017 -0400 @@ -3,7 +3,7 @@ <div class="row" style="margin-top:2vh"> <div class="col-xs-12 col-md-3"> <label for="refreshCombo" class="label label-info" translate>jvmGc.REFRESH_RATE_LABEL</label> - <select name="refreshCombo" class="combobox form-control" ng-model="refreshRate"> + <select name="refreshCombo" class="combobox form-control" ng-model="$ctrl.refreshRate"> <option value="-1" translate>jvmGc.refresh.DISABLED</option> <option value="1000" selected translate="jvmGc.refresh.SECONDS" translate-values="{ SECONDS: 1, DEFAULT: true }" translate-interpolation="messageformat"></option> <option value="2000" translate="jvmGc.refresh.SECONDS" translate-values="{ SECONDS: 2 }" translate-interpolation="messageformat"></option> @@ -15,7 +15,7 @@ <div class="col-xs-12 col-md-3"> <label for="dataAgeCombo" class="label label-info" translate>jvmGc.MAX_DATA_AGE_LABEL</label> - <select name="dataAgeCombo" class="combobox form-control" ng-model="dataAgeLimit"> + <select name="dataAgeCombo" class="combobox form-control" ng-model="$ctrl.dataAgeLimit"> <option value="10000" translate="jvmGc.dataAge.SECONDS" translate-values="{ SECONDS: 10 }" translate-interpolation="messageformat"></option> <option value="30000" selected translate="jvmGc.dataAge.SECONDS" translate-values="{ SECONDS: 30, DEFAULT: true }" translate-interpolation="messageformat"></option> <option value="60000" translate="jvmGc.dataAge.MINUTES" translate-values="{ MINUTES: 1 }" translate-interpolation="messageformat"></option> @@ -33,11 +33,11 @@ <div class="card-pf-heading"> <label class="card-pf-title" translate>jvmGc.CARD_TITLE</label> </div> - <div ng-repeat="collector in ctrl.collectors"> + <div ng-repeat="collector in $ctrl.collectors"> <div class="card-pf-body text-center"> - <mc-add class="pull-right" svc-name="{{ctrl.jvmId}}-{{sanitize(collector)}}-gc" get-fn="ctrl.multichartFn(collector)"></mc-add> - <pf-line-chart id="chart-{{collector}}" config="ctrl.chartConfigs[collector]" - chart-data="ctrl.chartData[collector]" + <mc-add class="pull-right" svc-name="{{$ctrl.jvmId}}-{{$ctrl.sanitize(collector)}}-gc" get-fn="$ctrl.multichartFn(collector)"></mc-add> + <pf-line-chart id="chart-{{collector}}" config="$ctrl.chartConfigs[collector]" + chart-data="$ctrl.chartData[collector]" show-x-axis="true" show-y-axis="true" ></pf-line-chart>
--- a/src/app/components/jvm-info/jvm-gc/jvm-gc.module.js Wed Sep 06 10:17:05 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/** - * Copyright 2012-2017 Red Hat, Inc. - * - * Thermostat is distributed under the GNU General Public License, - * version 2 or any later version (with a special exception described - * below, commonly known as the "Classpath Exception"). - * - * A copy of GNU General Public License (GPL) is included in this - * distribution, in the file COPYING. - * - * Linking Thermostat code with other modules is making a combined work - * based on Thermostat. Thus, the terms and conditions of the GPL - * cover the whole combination. - * - * As a special exception, the copyright holders of Thermostat give you - * permission to link this code with independent modules to produce an - * executable, regardless of the license terms of these independent - * modules, and to copy and distribute the resulting executable under - * terms of your choice, provided that you also meet, for each linked - * independent module, the terms and conditions of the license of that - * module. An independent module is a module which is not derived from - * or based on Thermostat code. If you modify Thermostat, you may - * extend this exception to your version of the software, but you are - * not obligated to do so. If you do not wish to do so, delete this - * exception statement from your version. - */ - -import JvmGcController from './jvm-gc.controller.js'; -import service from './jvm-gc.service.js'; - -export default angular - .module('jvmGc', [ - JvmGcController, - service - ]) - .name;
--- a/src/app/components/jvm-info/jvm-gc/jvm-gc.routing.js Wed Sep 06 10:17:05 2017 -0400 +++ b/src/app/components/jvm-info/jvm-gc/jvm-gc.routing.js Thu Sep 07 08:06:46 2017 -0400 @@ -30,20 +30,13 @@ $stateProvider.state('jvmInfo.jvmGc', { url: '/garbage-collection', - controller: 'JvmGcController as ctrl', - templateProvider: $q => { - 'ngInject'; - return $q(resolve => - require.ensure([], () => resolve(require('./jvm-gc.html')) - ) - ); - }, + component: 'jvmGc', resolve: { - loadJvmGc: (loadJvmInfo, $q, $ocLazyLoad) => { + lazyLoad: ($q, $ocLazyLoad) => { 'ngInject'; return $q(resolve => { - require.ensure(['./jvm-gc.module.js'], () => { - let module = require('./jvm-gc.module.js'); + require.ensure(['./jvm-gc.component.js'], () => { + let module = require('./jvm-gc.component.js'); $ocLazyLoad.load({ name: module.default }); resolve(module); });
--- a/src/app/components/jvm-info/jvm-gc/jvm-gc.routing.spec.js Wed Sep 06 10:17:05 2017 -0400 +++ b/src/app/components/jvm-info/jvm-gc/jvm-gc.routing.spec.js Thu Sep 07 08:06:46 2017 -0400 @@ -55,33 +55,17 @@ args[1].url.should.equal('/garbage-collection'); }); - it('template provider should return jvm-gc.html', done => { - let providerFn = args[1].templateProvider[1]; - providerFn.should.be.a.Function(); - providerFn(q); + it('resolve should load jvm-gc component', done => { + let resolveFn = args[1].resolve.lazyLoad[2]; + resolveFn.should.be.a.Function(); + resolveFn(q, ocLazyLoad); q.should.be.calledOnce(); let deferred = q.args[0][0]; deferred.should.be.a.Function(); let resolve = sinon.stub().callsFake(val => { - val.should.equal(require('./jvm-gc.html')); - done(); - }); - deferred(resolve); - }); - - it('resolve should load jvm-gc module', done => { - let resolveFn = args[1].resolve.loadJvmGc[3]; - resolveFn.should.be.a.Function(); - resolveFn({}, q, ocLazyLoad); - q.should.be.calledOnce(); - - let deferred = q.args[0][0]; - deferred.should.be.a.Function(); - - let resolve = sinon.stub().callsFake(val => { - let mod = require('./jvm-gc.module.js'); + let mod = require('./jvm-gc.component.js'); ocLazyLoad.load.should.be.calledWith({ name: mod.default }); val.should.equal(mod); done();