Merge pull request #3953 from hashicorp/f-ui-polling-disconnect

UI: Polling Step 3 - Close connections when tabbing away
This commit is contained in:
Michael Lange
2018-03-08 12:51:33 -08:00
committed by GitHub
17 changed files with 106 additions and 26 deletions

View File

@@ -2,8 +2,9 @@ import { inject as service } from '@ember/service';
import Component from '@ember/component';
import { lazyClick } from '../helpers/lazy-click';
import { watchRelationship } from 'nomad-ui/utils/properties/watch';
import WithVisibilityDetection from 'nomad-ui/mixins/with-component-visibility-detection';
export default Component.extend({
export default Component.extend(WithVisibilityDetection, {
store: service(),
tagName: 'tr',
@@ -27,6 +28,17 @@ export default Component.extend({
}
},
visibilityHandler() {
if (document.hidden) {
this.get('watch').cancelAll();
} else {
const node = this.get('node');
if (node) {
this.get('watch').perform(node, 100);
}
}
},
willDestroy() {
this.get('watch').cancelAll();
this._super(...arguments);

View File

@@ -2,8 +2,9 @@ import { inject as service } from '@ember/service';
import Component from '@ember/component';
import { lazyClick } from '../helpers/lazy-click';
import { watchRelationship } from 'nomad-ui/utils/properties/watch';
import WithVisibilityDetection from 'nomad-ui/mixins/with-component-visibility-detection';
export default Component.extend({
export default Component.extend(WithVisibilityDetection, {
store: service(),
tagName: 'tr',
@@ -27,6 +28,17 @@ export default Component.extend({
}
},
visibilityHandler() {
if (document.hidden) {
this.get('watch').cancelAll();
} else {
const job = this.get('job');
if (job && !job.get('isLoading')) {
this.get('watch').perform(job, 100);
}
}
},
willDestroy() {
this.get('watch').cancelAll();
this._super(...arguments);

View File

@@ -37,7 +37,7 @@ export default Controller.extend(Sortable, Searchable, {
'system.namespaces.length',
function() {
const hasNamespaces = this.get('system.namespaces.length');
const activeNamespace = this.get('system.activeNamespace.id');
const activeNamespace = this.get('system.activeNamespace.id') || 'default';
return this.get('model')
.filter(job => !hasNamespaces || job.get('namespace.id') === activeNamespace)

View File

@@ -1,8 +1,13 @@
import Mixin from '@ember/object/mixin';
import { run } from '@ember/runloop';
import { assert } from '@ember/debug';
import $ from 'jquery';
export default Mixin.create({
windowResizeHandler() {
assert('windowResizeHandler needs to be overridden in the Component', false);
},
setupWindowResize: function() {
run.scheduleOnce('afterRender', this, () => {
this.set('_windowResizeHandler', this.get('windowResizeHandler').bind(this));

View File

@@ -0,0 +1,17 @@
import Mixin from '@ember/object/mixin';
import { assert } from '@ember/debug';
export default Mixin.create({
visibilityHandler() {
assert('visibilityHandler needs to be overridden in the Component', false);
},
setupDocumentVisibility: function() {
this.set('_visibilityHandler', this.get('visibilityHandler').bind(this));
document.addEventListener('visibilitychange', this.get('_visibilityHandler'));
}.on('init'),
removeDocumentVisibility: function() {
document.removeEventListener('visibilitychange', this.get('_visibilityHandler'));
}.on('willDestroy'),
});

View File

@@ -0,0 +1,17 @@
import Mixin from '@ember/object/mixin';
import { assert } from '@ember/debug';
export default Mixin.create({
visibilityHandler() {
assert('visibilityHandler needs to be overridden in the Route', false);
},
setupDocumentVisibility: function() {
this.set('_visibilityHandler', this.get('visibilityHandler').bind(this));
document.addEventListener('visibilitychange', this.get('_visibilityHandler'));
}.on('activate'),
removeDocumentVisibility: function() {
document.removeEventListener('visibilitychange', this.get('_visibilityHandler'));
}.on('deactivate'),
});

View File

@@ -1,16 +1,38 @@
import Mixin from '@ember/object/mixin';
import { computed } from '@ember/object';
import { assert } from '@ember/debug';
import WithVisibilityDetection from './with-route-visibility-detection';
export default Mixin.create({
export default Mixin.create(WithVisibilityDetection, {
watchers: computed(() => []),
cancelAllWatchers() {
this.get('watchers').forEach(watcher => {
assert('Watchers must be Ember Concurrency Tasks.', !!watcher.cancelAll);
watcher.cancelAll();
});
},
startWatchers() {
assert('startWatchers needs to be overridden in the Route', false);
},
setupController() {
this.startWatchers(...arguments);
return this._super(...arguments);
},
visibilityHandler() {
if (document.hidden) {
this.cancelAllWatchers();
} else {
this.startWatchers(this.controller, this.controller.get('model'));
}
},
actions: {
willTransition() {
this.get('watchers').forEach(watcher => {
assert('Watchers must be Ember Concurrency Tasks.', !!watcher.cancelAll);
watcher.cancelAll();
});
this.cancelAllWatchers();
},
},
});

View File

@@ -5,9 +5,8 @@ import { watchRecord } from 'nomad-ui/utils/properties/watch';
import WithWatchers from 'nomad-ui/mixins/with-watchers';
export default Route.extend(WithModelErrorHandling, WithWatchers, {
setupController(controller, model) {
startWatchers(controller, model) {
controller.set('watcher', this.get('watch').perform(model));
return this._super(...arguments);
},
watch: watchRecord('allocation'),

View File

@@ -1,5 +1,6 @@
import { inject as service } from '@ember/service';
import Route from '@ember/routing/route';
import { AbortError } from 'ember-data/adapters/errors';
export default Route.extend({
config: service(),
@@ -22,7 +23,9 @@ export default Route.extend({
},
error(error) {
this.controllerFor('application').set('error', error);
if (!(error instanceof AbortError)) {
this.controllerFor('application').set('error', error);
}
},
},
});

View File

@@ -19,10 +19,9 @@ export default Route.extend(WithWatchers, {
return model && model.get('allocations');
},
setupController(controller, model) {
startWatchers(controller, model) {
controller.set('watchModel', this.get('watch').perform(model));
controller.set('watchAllocations', this.get('watchAllocations').perform(model));
return this._super(...arguments);
},
watch: watchRecord('node'),

View File

@@ -4,9 +4,8 @@ import { watchAll } from 'nomad-ui/utils/properties/watch';
import WithWatchers from 'nomad-ui/mixins/with-watchers';
export default Route.extend(WithWatchers, {
setupController(controller) {
startWatchers(controller) {
controller.set('watcher', this.get('watch').perform());
return this._super(...arguments);
},
watch: watchAll('node'),

View File

@@ -4,9 +4,8 @@ import { watchAll } from 'nomad-ui/utils/properties/watch';
import WithWatchers from 'nomad-ui/mixins/with-watchers';
export default Route.extend(WithWatchers, {
setupController(controller) {
startWatchers(controller) {
controller.set('modelWatch', this.get('watch').perform());
return this._super(...arguments);
},
watch: watchAll('job'),

View File

@@ -10,10 +10,9 @@ export default Route.extend(WithWatchers, {
return RSVP.all([job.get('deployments'), job.get('versions')]).then(() => job);
},
setupController(controller, model) {
startWatchers(controller, model) {
controller.set('watchDeployments', this.get('watchDeployments').perform(model));
controller.set('watchVersions', this.get('watchVersions').perform(model));
return this._super(...arguments);
},
watchDeployments: watchRelationship('deployments'),

View File

@@ -4,15 +4,13 @@ import { watchRecord, watchRelationship } from 'nomad-ui/utils/properties/watch'
import WithWatchers from 'nomad-ui/mixins/with-watchers';
export default Route.extend(WithWatchers, {
setupController(controller, model) {
startWatchers(controller, model) {
controller.set('watchers', {
model: this.get('watch').perform(model),
summary: this.get('watchSummary').perform(model),
evaluations: this.get('watchEvaluations').perform(model),
deployments: this.get('watchDeployments').perform(model),
});
return this._super(...arguments);
},
watch: watchRecord('job'),

View File

@@ -19,14 +19,13 @@ export default Route.extend(WithWatchers, {
});
},
setupController(controller, model) {
startWatchers(controller, model) {
const job = model.get('job');
controller.set('watchers', {
job: this.get('watchJob').perform(job),
summary: this.get('watchSummary').perform(job),
allocations: this.get('watchAllocations').perform(job),
});
return this._super(...arguments);
},
watchJob: watchRecord('job'),

View File

@@ -9,9 +9,8 @@ export default Route.extend(WithWatchers, {
return job.get('versions').then(() => job);
},
setupController(controller, model) {
startWatchers(controller, model) {
controller.set('watcher', this.get('watchVersions').perform(model));
return this._super(...arguments);
},
watchVersions: watchRelationship('versions'),

View File

@@ -113,6 +113,7 @@ export default Factory.extend({
const jobSummary = server.create('job-summary', hasChildren ? 'withChildren' : 'withSummary', {
groupNames: groups.mapBy('name'),
job,
job_id: job.id,
namespace: job.namespace,
});