Skip to content

Commit

Permalink
alt/option click to toggle children in component tree
Browse files Browse the repository at this point in the history
  • Loading branch information
nummi committed Jan 31, 2019
1 parent a31c214 commit 9b358be
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 17 deletions.
16 changes: 16 additions & 0 deletions app/components/disclosure-triangle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Component from '@ember/component';

export default Component.extend({
attributeBindings: ['title'],
classNameBindings: ['expanded:expanded:collapsed'],
tagName: 'button',
title: 'Click to toggle',

expanded: false,

click(event) {
event.preventDefault();
event.stopPropagation();
this.toggle(event.altKey);
}
});
57 changes: 51 additions & 6 deletions app/controllers/component-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ import {

import ComponentViewItem from 'ember-inspector/models/component-view-item';

const buildObjectIdList = function(children, list) {
children.forEach(function(child) {
if (child.children.length) {
list.push(child.value.objectId);
buildObjectIdList(child.children, list);
}
});
};

const getIdFromObj = function(obj) {
return get(obj, 'view.objectId') || get(obj, 'view.controller.objectId') || get(obj, 'view.elementId');
};

/**
* Takes the `viewTree` from `view-debug`'s `sendTree()` method, and recursively
* flattens it into an array of `ComponentViewItem` objects
Expand Down Expand Up @@ -50,6 +63,7 @@ const flattenSearchTree = (
activeSearch,
expanded: !activeSearch,
hasChildren: treeNode.children.length > 0,
children: treeNode.children
});

// remember if there is no active search, searchMatched will be true
Expand Down Expand Up @@ -123,11 +137,11 @@ export default Controller.extend({
let viewArray = this.get('viewArray');
let expandedStateCache = this.get('expandedStateCache');
viewArray.forEach(viewItem => {
let cachedExpansion = expandedStateCache[viewItem.view.objectId];
let cachedExpansion = expandedStateCache[getIdFromObj(viewItem)];
if (cachedExpansion !== undefined) {
viewItem.set('expanded', cachedExpansion);
} else {
expandedStateCache[viewItem.view.objectId] = viewItem.expanded;
expandedStateCache[getIdFromObj(viewItem)] = viewItem.expanded;
}
});

Expand Down Expand Up @@ -187,6 +201,33 @@ export default Controller.extend({
}
},

/**
* @param {array} objects Array of objectids
* @param {boolean} state expanded state for objects
*/
setExpandedStateForObjects(objects, state) {
this.get('filteredArray').forEach((item) => {
const id = getIdFromObj(item);
if (objects.includes(id)) {
item.set('expanded', state);
this.expandedStateCache[id] = state;
}
});
},

/**
* Builds array of objectids and the expanded state they should be set to
* @param {ComponentViewItem} item
*/
toggleWithChildren(item) {
const newState = !item.get('expanded');
const list = [];
const clickedId = getIdFromObj(item);

list.push(clickedId);
buildObjectIdList(item.children, list);
this.setExpandedStateForObjects(list, newState);
},

actions: {
previewLayer({
Expand Down Expand Up @@ -229,13 +270,17 @@ export default Controller.extend({
this.expandedStateCache = {};
this.get('filteredArray').forEach((item) => {
item.set('expanded', expanded);
this.expandedStateCache[item.view.objectId] = expanded;
this.expandedStateCache[getIdFromObj(item)] = expanded;
});
},

toggleExpanded(item) {
item.toggleProperty('expanded');
this.expandedStateCache[item.view.objectId] = item.get('expanded');
toggleExpanded(item, toggleChildren) {
if (toggleChildren) {
this.toggleWithChildren(item);
} else {
item.toggleProperty('expanded');
this.expandedStateCache[getIdFromObj(item)] = item.get('expanded');
}
},

inspect(objectId) {
Expand Down
1 change: 1 addition & 0 deletions app/models/component-view-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default EmberObject.extend({
*/
parentCount: 0,
expanded: true,
children: null,
hasChildren: true,
searchMatched: false,

Expand Down
17 changes: 6 additions & 11 deletions app/templates/components/component-tree-item.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,12 @@
{{action inspect item.view.objectId}}
>
{{#if item.hasChildren}}
<button
class="component-tree-item__expand {{if item.expanded "expanded" "collapsed"}}"
{{action toggleExpanded bubbles=false}}
>
{{svg-jar
"disclosure-triangle"
title="Toggle visibility"
width="9px"
height="9px"
}}
</button>
{{disclosure-triangle
class="component-tree-item__expand"
title="Click to toggle (alt/option click to toggle with children)"
expanded=item.expanded
toggle=(action toggleExpanded)
}}
{{/if}}

<code
Expand Down
5 changes: 5 additions & 0 deletions app/templates/components/disclosure-triangle.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{svg-jar
"disclosure-triangle"
width="9px"
height="9px"
}}
29 changes: 29 additions & 0 deletions tests/acceptance/component-tree-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,36 @@ module('Component Tab', function(hooks) {

treeNodes = findAll('.component-tree-item');
assert.equal(treeNodes.length, 3, 'the last node should be hidden');
});

test('It allows users to expand and collapse children with alt key', async function(assert) {
let viewTree = defaultViewTree();

await visit('/component-tree');
run(() => {
port.trigger('view:viewTree', { tree: viewTree });
});
await wait();

let expanders = findAll('.component-tree-item__expand.expanded');
assert.equal(expanders.length, 3, 'disclosure triangles all in expanded state');

// Click second component with alt key;
// this should collapse itself and children
let expanderEl = expanders[1];
await click(expanderEl, { altKey: true });
expanders = findAll('.component-tree-item__expand.expanded');
assert.equal(expanders.length, 1, 'clicked disclosure triangle no longer expanded');

expanders = findAll('.component-tree-item__expand');
expanderEl = expanders[1];
await click(expanderEl);

// After expanding second component without alt key
// the children should be collapsed
expanders = findAll('.component-tree-item__expand');
expanderEl = expanders[2];
assert.ok(true, expanderEl.classList.contains('collapsed'), 'child component was collapsed');
});

test('It should filter the view tree using the search text', async function(assert) {
Expand Down

0 comments on commit 9b358be

Please sign in to comment.