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

UI: dom usage refactoring #4924

Merged
merged 4 commits into from
Nov 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 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 'ember-block-slots';
import { get } from '@ember/object';
import { inject as service } from '@ember/service';
import SlotsMixin from 'ember-block-slots';
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 'ember-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,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my first question. Now I have all these things in the dom service, it would make sense to get window from there also. I was thinking of making a viewport method, which would be a nice word whether window was a browser window, an iframe (not really a window) like when ember testing, or anything else. To me the viewport is what we are actually talking about here.

I'm like 90% sure I want to do this, thought it might be useful to ask what others think?

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 'ember-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');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yuk, how did I ever think this was a good idea! 😄

Actually I need to have a better look and refresh my memory on these utils, maybe there was a reason, but I doubt it!

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 { inject as service } from '@ember/service';
import { get } from '@ember/object';
import SlotsMixin from 'ember-block-slots';
import closest from 'consul-ui/utils/dom/closest';
import clickFirstAnchorFactory from 'consul-ui/utils/dom/click-first-anchor';
const clickFirstAnchor = clickFirstAnchorFactory(closest);

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 (
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spotted I hadn't used the new searchables in the old acls system, actually I've just thought it will have been because it was old and I was changing as little as possible with the new ACL upgrade, possibly the 2nd PR to come in this series.

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
1 change: 1 addition & 0 deletions ui-v2/app/helpers/css-var.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 9 additions & 7 deletions ui-v2/app/routes/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,33 @@ import { inject as service } from '@ember/service';
import { hash } from 'rsvp';
import { get } from '@ember/object';
import { next } from '@ember/runloop';
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({
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 @@ -70,6 +71,7 @@ export default Route.extend({
if (error.status === '') {
error.message = 'Error';
}
const $root = get(this, 'dom').root();
hash({
error: error,
dc:
Expand All @@ -81,13 +83,13 @@ export default Route.extend({
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