Skip to content

Commit

Permalink
UI: dom usage refactoring (#4924)
Browse files Browse the repository at this point in the history
Move all the dom-things to use the dom service in tabular-collection, feedback-dialog, list-collection and node show. Move get-component-factory into utils/dom and use dom.root() in a few more places

This includes an additional `dom.components` method which gives you a
list of components matching the selector instead of just one.
  • Loading branch information
johncowen authored and John Cowen committed Apr 29, 2019
1 parent 4e0ebfe commit e142855
Show file tree
Hide file tree
Showing 14 changed files with 103 additions and 77 deletions.
15 changes: 9 additions & 6 deletions ui-v2/app/components/app-view.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
import Component from '@ember/component';
import SlotsMixin from 'block-slots';
import { get } from '@ember/object';
import { inject as service } from '@ember/service';
import templatize from 'consul-ui/utils/templatize';
const $html = document.documentElement;
export default Component.extend(SlotsMixin, {
loading: false,
authorized: true,
enabled: true,
classNames: ['app-view'],
classNameBindings: ['enabled::disabled', 'authorized::unauthorized'],
dom: service('dom'),
didReceiveAttrs: function() {
// right now only manually added classes are hoisted to <html>
const $root = get(this, 'dom').root();
let cls = get(this, 'class') || '';
if (get(this, 'loading')) {
cls += ' loading';
} else {
$html.classList.remove(...templatize(['loading']));
$root.classList.remove(...templatize(['loading']));
}
if (cls) {
// its possible for 'layout' templates to change after insert
// check for these specific layouts and clear them out
[...$html.classList].forEach(function(item, i) {
[...$root.classList].forEach(function(item, i) {
if (templatize(['edit', 'show', 'list']).indexOf(item) !== -1) {
$html.classList.remove(item);
$root.classList.remove(item);
}
});
$html.classList.add(...templatize(cls.split(' ')));
$root.classList.add(...templatize(cls.split(' ')));
}
},
didInsertElement: function() {
Expand All @@ -34,7 +36,8 @@ export default Component.extend(SlotsMixin, {
didDestroyElement: function() {
const cls = get(this, 'class') + ' loading';
if (cls) {
$html.classList.remove(...templatize(cls.split(' ')));
const $root = get(this, 'dom').root();
$root.classList.remove(...templatize(cls.split(' ')));
}
},
});
9 changes: 6 additions & 3 deletions ui-v2/app/components/feedback-dialog.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import Component from '@ember/component';
import { get, set } from '@ember/object';
import { inject as service } from '@ember/service';
import qsaFactory from 'consul-ui/utils/dom/qsa-factory';
const $$ = qsaFactory();
import { Promise } from 'rsvp';

import SlotsMixin from 'block-slots';
const STATE_READY = 'ready';
const STATE_SUCCESS = 'success';
const STATE_ERROR = 'error';
export default Component.extend(SlotsMixin, {
wait: service('timeout'),
dom: service('dom'),
classNames: ['with-feedback'],
transition: '',
transitionClassName: 'feedback-dialog-out',
Expand All @@ -23,14 +23,17 @@ export default Component.extend(SlotsMixin, {
applyTransition: function() {
const wait = get(this, 'wait').execute;
const className = get(this, 'transitionClassName');
// TODO: Make 0 default in wait
wait(0)
.then(() => {
set(this, 'transition', className);
return wait(0);
})
.then(() => {
return new Promise(resolve => {
$$(`.${className}`, this.element)[0].addEventListener('transitionend', resolve);
get(this, 'dom')
.element(`.${className}`, this.element)
.addEventListener('transitionend', resolve);
});
})
.then(() => {
Expand Down
21 changes: 14 additions & 7 deletions ui-v2/app/components/hashicorp-consul.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import Component from '@ember/component';
import { get, set } from '@ember/object';
const $html = document.documentElement;
const $body = document.body;
import { inject as service } from '@ember/service';
export default Component.extend({
dom: service('dom'),
// TODO: could this be dom.viewport() ?
win: window,
isDropdownVisible: false,
didInsertElement: function() {
$html.classList.remove('template-with-vertical-menu');
get(this, 'dom')
.root()
.classList.remove('template-with-vertical-menu');
},
actions: {
dropdown: function(e) {
Expand All @@ -14,12 +18,15 @@ export default Component.extend({
}
},
change: function(e) {
const dom = get(this, 'dom');
const $root = dom.root();
const $body = dom.element('body');
if (e.target.checked) {
$html.classList.add('template-with-vertical-menu');
$body.style.height = $html.style.height = window.innerHeight + 'px';
$root.classList.add('template-with-vertical-menu');
$body.style.height = $root.style.height = get(this, 'win').innerHeight + 'px';
} else {
$html.classList.remove('template-with-vertical-menu');
$body.style.height = $html.style.height = null;
$root.classList.remove('template-with-vertical-menu');
$body.style.height = $root.style.height = null;
}
},
},
Expand Down
15 changes: 9 additions & 6 deletions ui-v2/app/components/list-collection.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { inject as service } from '@ember/service';
import { computed, get, set } from '@ember/object';
import Component from 'ember-collection/components/ember-collection';
import PercentageColumns from 'ember-collection/layouts/percentage-columns';
import style from 'ember-computed-style';
import WithResizing from 'consul-ui/mixins/with-resizing';
import qsaFactory from 'consul-ui/utils/dom/qsa-factory';
const $$ = qsaFactory();

export default Component.extend(WithResizing, {
dom: service('dom'),
tagName: 'div',
attributeBindings: ['style'],
height: 500,
Expand All @@ -30,11 +31,13 @@ export default Component.extend(WithResizing, {
};
}),
resize: function(e) {
const $self = this.element;
const $appContent = [...$$('main > div')][0];
// TODO: This top part is very similar to resize in tabular-collection
// see if it make sense to DRY out
const dom = get(this, 'dom');
const $appContent = dom.element('main > div');
if ($appContent) {
const rect = $self.getBoundingClientRect();
const $footer = [...$$('footer[role="contentinfo"]')][0];
const rect = this.element.getBoundingClientRect();
const $footer = dom.element('footer[role="contentinfo"]');
const space = rect.top + $footer.clientHeight;
const height = e.detail.height - space;
this.set('height', Math.max(0, height));
Expand Down
23 changes: 10 additions & 13 deletions ui-v2/app/components/tabular-collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@ import Grid from 'ember-collection/layouts/grid';
import SlotsMixin from 'block-slots';
import WithResizing from 'consul-ui/mixins/with-resizing';
import style from 'ember-computed-style';
import qsaFactory from 'consul-ui/utils/dom/qsa-factory';
import sibling from 'consul-ui/utils/dom/sibling';
import closest from 'consul-ui/utils/dom/closest';
import clickFirstAnchorFactory from 'consul-ui/utils/dom/click-first-anchor';
const clickFirstAnchor = clickFirstAnchorFactory(closest);

import { inject as service } from '@ember/service';
import { computed, get, set } from '@ember/object';
/**
* Heavily extended `ember-collection` component
Expand All @@ -24,8 +20,6 @@ import { computed, get, set } from '@ember/object';
* in the future
*/

// ember doesn't like you using `$` hence `$$`
const $$ = qsaFactory();
// need to copy Cell in wholesale as there is no way to import it
// there is no change made to `Cell` here, its only here as its
// private in `ember-collection`
Expand Down Expand Up @@ -85,9 +79,10 @@ const change = function(e) {
// 'actions_close' would mean that all menus have been closed
// therefore we don't need to calculate
if (e.currentTarget.getAttribute('id') !== 'actions_close') {
const $tr = closest('tr', e.currentTarget);
const $group = sibling(e.currentTarget, 'ul');
const $footer = [...$$('footer[role="contentinfo"]')][0];
const dom = get(this, 'dom');
const $tr = dom.closest('tr', e.currentTarget);
const $group = dom.sibling(e.currentTarget, 'ul');
const $footer = dom.element('footer[role="contentinfo"]');
const groupRect = $group.getBoundingClientRect();
const footerRect = $footer.getBoundingClientRect();
const groupBottom = groupRect.top + $group.clientHeight;
Expand Down Expand Up @@ -122,6 +117,7 @@ export default Component.extend(SlotsMixin, WithResizing, {
style: style('getStyle'),
checked: null,
hasCaption: false,
dom: service('dom'),
init: function() {
this._super(...arguments);
this.change = change.bind(this);
Expand All @@ -136,11 +132,12 @@ export default Component.extend(SlotsMixin, WithResizing, {
}),
resize: function(e) {
const $tbody = this.element;
const $appContent = [...$$('main > div')][0];
const dom = get(this, 'dom');
const $appContent = dom.element('main > div');
if ($appContent) {
const border = 1;
const rect = $tbody.getBoundingClientRect();
const $footer = [...$$('footer[role="contentinfo"]')][0];
const $footer = dom.element('footer[role="contentinfo"]');
const space = rect.top + $footer.clientHeight + border;
const height = e.detail.height - space;
this.set('height', Math.max(0, height));
Expand Down Expand Up @@ -273,7 +270,7 @@ export default Component.extend(SlotsMixin, WithResizing, {
},
actions: {
click: function(e) {
return clickFirstAnchor(e);
return get(this, 'dom').clickFirstAnchor(e);
},
},
});
8 changes: 4 additions & 4 deletions ui-v2/app/components/tabular-details.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import Component from '@ember/component';
import SlotsMixin from 'block-slots';
import closest from 'consul-ui/utils/dom/closest';
import clickFirstAnchorFactory from 'consul-ui/utils/dom/click-first-anchor';
const clickFirstAnchor = clickFirstAnchorFactory(closest);
import { inject as service } from '@ember/service';
import { get } from '@ember/object';

export default Component.extend(SlotsMixin, {
dom: service('dom'),
onchange: function() {},
actions: {
click: function(e) {
clickFirstAnchor(e);
get(this, 'dom').clickFirstAnchor(e);
},
change: function(item, e) {
this.onchange(e, item);
Expand Down
1 change: 1 addition & 0 deletions ui-v2/app/controllers/dc/acls/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default Controller.extend(WithFiltering, {
};
});
}),
// TODO: This should be using a searchable
filter: function(item, { s = '', type = '' }) {
const sLower = s.toLowerCase();
return (
Expand Down
21 changes: 9 additions & 12 deletions ui-v2/app/controllers/dc/nodes/show.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import { get, set, computed } from '@ember/object';
import { getOwner } from '@ember/application';
import WithSearching from 'consul-ui/mixins/with-searching';
import qsaFactory from 'consul-ui/utils/dom/qsa-factory';
import getComponentFactory from 'consul-ui/utils/get-component-factory';

const $$ = qsaFactory();
export default Controller.extend(WithSearching, {
dom: service('dom'),
queryParams: {
s: {
as: 'filter',
Expand Down Expand Up @@ -36,15 +33,15 @@ export default Controller.extend(WithSearching, {
actions: {
change: function(e) {
set(this, 'selectedTab', e.target.value);
const getComponent = getComponentFactory(getOwner(this));
// Ensure tabular-collections sizing is recalculated
// now it is visible in the DOM
[...$$('.tab-section input[type="radio"]:checked + div table')].forEach(function(item) {
const component = getComponent(item);
if (component && typeof component.didAppear === 'function') {
getComponent(item).didAppear();
}
});
get(this, 'dom')
.components('.tab-section input[type="radio"]:checked + div table')
.forEach(function(item) {
if (typeof item.didAppear === 'function') {
item.didAppear();
}
});
},
sortChecksByImportance: function(a, b) {
const statusA = get(a, 'Status');
Expand Down
3 changes: 1 addition & 2 deletions ui-v2/app/controllers/dc/services/show.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Controller from '@ember/controller';
import { get } from '@ember/object';
import { computed } from '@ember/object';
import { get, computed } from '@ember/object';
import sumOfUnhealthy from 'consul-ui/utils/sumOfUnhealthy';
import hasStatus from 'consul-ui/utils/hasStatus';
import WithHealthFiltering from 'consul-ui/mixins/with-health-filtering';
Expand Down
20 changes: 10 additions & 10 deletions ui-v2/app/routes/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,33 @@ import { inject as service } from '@ember/service';
import { hash } from 'rsvp';
import { get } from '@ember/object';
import { next } from '@ember/runloop';
import { Promise } from 'rsvp';
import WithBlockingActions from 'consul-ui/mixins/with-blocking-actions';
const $html = document.documentElement;
const removeLoading = function() {
return $html.classList.remove('ember-loading');
const removeLoading = function($from) {
return $from.classList.remove('ember-loading');
};
export default Route.extend(WithBlockingActions, {
export default Route.extend({
dom: service('dom'),
init: function() {
this._super(...arguments);
},
repo: service('repository/dc'),
settings: service('settings'),
actions: {
loading: function(transition, originRoute) {
const $root = get(this, 'dom').root();
let dc = null;
if (originRoute.routeName !== 'dc') {
const model = this.modelFor('dc') || { dcs: null, dc: { Name: null } };
dc = get(this, 'repo').getActive(model.dc.Name, model.dcs);
}
hash({
loading: !$html.classList.contains('ember-loading'),
loading: !$root.classList.contains('ember-loading'),
dc: dc,
}).then(model => {
next(() => {
const controller = this.controllerFor('application');
controller.setProperties(model);
transition.promise.finally(function() {
removeLoading();
removeLoading($root);
controller.setProperties({
loading: false,
dc: model.dc,
Expand Down Expand Up @@ -74,6 +73,7 @@ export default Route.extend(WithBlockingActions, {
if (error.status === '') {
error.message = 'Error';
}
const $root = get(this, 'dom').root();
hash({
error: error,
dc:
Expand All @@ -85,13 +85,13 @@ export default Route.extend(WithBlockingActions, {
dcs: model && model.dcs ? model.dcs : [],
})
.then(model => {
removeLoading();
removeLoading($root);
next(() => {
this.controllerFor('error').setProperties(model);
});
})
.catch(e => {
removeLoading();
removeLoading($root);
next(() => {
this.controllerFor('error').setProperties({ error: error });
});
Expand Down
Loading

0 comments on commit e142855

Please sign in to comment.