diff --git a/app/components/container-picker.js b/app/components/container-picker.js new file mode 100644 index 0000000000..40d642b65c --- /dev/null +++ b/app/components/container-picker.js @@ -0,0 +1,11 @@ +import Component from '@ember/component'; + +export default Component.extend({ + containers: null, + + actions: { + onSelect(containerId) { + this.sendAction('selectContainer', containerId); + } + } +}); diff --git a/app/controllers/containers.js b/app/controllers/containers.js new file mode 100644 index 0000000000..ba528c4853 --- /dev/null +++ b/app/controllers/containers.js @@ -0,0 +1,7 @@ +import Controller from '@ember/controller'; +import { sort } from '@ember/object/computed'; + +export default Controller.extend({ + sortProperties: ['container_type_id', 'container_instance_id'], + sorted: sort('model', 'sortProperties') +}); diff --git a/app/router.js b/app/router.js index eb2894c15a..124272f7cd 100644 --- a/app/router.js +++ b/app/router.js @@ -30,13 +30,16 @@ Router.map(function() { }); this.route('render-tree', { resetNamespace: true }); - this.route('container-types', { resetNamespace: true }, function() { - this.route('container-type', { path: '/:type_id', resetNamespace: true }); + this.route('containers', { path: '/containers', resetNamespace: true }, function() { + this.route('container', { path: '/:container_type_id/instance/:container_instance_id' }, function() { + this.route('container-types', { path: '/type' }, function() { + this.route('container-type', { path: '/:type_id' }); + }); + }); }); this.route('deprecations', { resetNamespace: true }); }); - }); export default Router; diff --git a/app/routes/container-types/index.js b/app/routes/container-types/index.js deleted file mode 100644 index 7490103e31..0000000000 --- a/app/routes/container-types/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import TabRoute from "ember-inspector/routes/tab"; -export default TabRoute; diff --git a/app/routes/containers.js b/app/routes/containers.js new file mode 100644 index 0000000000..3a3d0b8556 --- /dev/null +++ b/app/routes/containers.js @@ -0,0 +1,29 @@ +import TabRoute from "ember-inspector/routes/tab"; + +export default TabRoute.extend({ + model() { + const port = this.get('port'); + return new Promise(resolve => { + port.one('container:all', function(message) { + let container_type_id, container_instance_id, containers; + containers = message.containers.map(function(containerRef) { + [container_type_id, container_instance_id] = containerRef.split(':'); + return { + container_type_id, + container_instance_id + } + }); + resolve(containers); + }); + port.send('container:all'); + }); + }, + + actions: { + selectContainer(containerIndex) { + let containerRef; + containerRef = this.get('controller.model').objectAt(containerIndex); + this.transitionTo('containers.container', containerRef); + } + } +}); diff --git a/app/routes/containers/container.js b/app/routes/containers/container.js new file mode 100644 index 0000000000..6f5c7f18d8 --- /dev/null +++ b/app/routes/containers/container.js @@ -0,0 +1,7 @@ +import Route from '@ember/routing/route'; + +export default Route.extend({ + model(params) { + return params; + } +}); diff --git a/app/routes/container-types.js b/app/routes/containers/container/container-types.js similarity index 59% rename from app/routes/container-types.js rename to app/routes/containers/container/container-types.js index 9307c188d0..11594b24ec 100644 --- a/app/routes/container-types.js +++ b/app/routes/containers/container/container-types.js @@ -2,13 +2,17 @@ import Route from '@ember/routing/route'; import { Promise } from 'rsvp'; export default Route.extend({ + controllerName: 'container-types', + model() { + let containerRef = this.modelFor('containers.container'); const port = this.get('port'); return new Promise(resolve => { port.one('container:types', function(message) { resolve(message.types); }); - port.send('container:getTypes'); + containerRef = containerRef.container_type_id+':'+containerRef.container_instance_id; + port.send('container:getTypes', { containerRef }); }); }, actions: { diff --git a/app/routes/container-type.js b/app/routes/containers/container/container-types/container-type.js similarity index 62% rename from app/routes/container-type.js rename to app/routes/containers/container/container-types/container-type.js index 970c6e87dc..af2c9e0a56 100644 --- a/app/routes/container-type.js +++ b/app/routes/containers/container/container-types/container-type.js @@ -1,8 +1,10 @@ import { Promise } from 'rsvp'; import { get } from '@ember/object'; -import TabRoute from "ember-inspector/routes/tab"; +import Route from '@ember/routing/route'; + +export default Route.extend({ + controllerName: 'container-type', -export default TabRoute.extend({ setupController(controller) { controller.setProperties({ search: '', @@ -11,8 +13,9 @@ export default TabRoute.extend({ this._super(...arguments); }, model(params) { - const type = params.type_id; + const containerType = params.type_id; const port = this.get('port'); + let containerRef = this.modelFor('containers.container'); return new Promise((resolve, reject) => { port.one('container:instances', message => { if (message.status === 200) { @@ -21,7 +24,8 @@ export default TabRoute.extend({ reject(message); } }); - port.send('container:getInstances', { containerType: type }); + containerRef = containerRef.container_type_id+':'+containerRef.container_instance_id; + port.send('container:getInstances', { containerRef, containerType }); }); }, @@ -29,7 +33,7 @@ export default TabRoute.extend({ actions: { error(err) { if (err && err.status === 404) { - this.transitionTo('container-types.index'); + this.transitionTo('containers.container.containers-types.container-type.index'); return false; } }, diff --git a/app/routes/containers/container/container-types/index.js b/app/routes/containers/container/container-types/index.js new file mode 100644 index 0000000000..64ddf589ad --- /dev/null +++ b/app/routes/containers/container/container-types/index.js @@ -0,0 +1,8 @@ +import Route from '@ember/routing/route'; + +export default Route.extend({ + afterModel() { + let containerType = this.modelFor('containers.container.container-types').firstObject; + return this.transitionTo('containers.container.container-types.container-type', containerType.name); + } +}); diff --git a/app/routes/containers/container/index.js b/app/routes/containers/container/index.js new file mode 100644 index 0000000000..3bede5fdee --- /dev/null +++ b/app/routes/containers/container/index.js @@ -0,0 +1,7 @@ +import Route from '@ember/routing/route'; + +export default Route.extend({ + beforeModel() { + this.transitionTo('containers.container.container-types'); + } +}); diff --git a/app/routes/containers/index.js b/app/routes/containers/index.js new file mode 100644 index 0000000000..b94f0f28d9 --- /dev/null +++ b/app/routes/containers/index.js @@ -0,0 +1,11 @@ +import Route from '@ember/routing/route'; + +export default Route.extend({ + beforeModel() { + let containers = this.modelFor('containers'); + if (containers) { + this.transitionTo('containers.container', containers[0]); + } + } +}); + diff --git a/app/templates/components/container-picker.hbs b/app/templates/components/container-picker.hbs new file mode 100644 index 0000000000..c9e611b91c --- /dev/null +++ b/app/templates/components/container-picker.hbs @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/app/templates/components/item-types.hbs b/app/templates/components/item-types.hbs index dd40b64493..1050e5b3f9 100644 --- a/app/templates/components/item-types.hbs +++ b/app/templates/components/item-types.hbs @@ -13,13 +13,14 @@ {{#each sorted as |itemType|}}
  • {{#link-to - (if (eq type "model") "records" "container-type") + (if (eq type "model") "records" "containers.container.container-types.container-type") (escape-url itemType.name) }} {{itemType.name}} ({{itemType.count}}) + {{/link-to}}
  • {{/each}} diff --git a/app/templates/container-types/index-toolbar.hbs b/app/templates/containers-toolbar.hbs similarity index 77% rename from app/templates/container-types/index-toolbar.hbs rename to app/templates/containers-toolbar.hbs index cfe85a1470..6d96d2b189 100644 --- a/app/templates/container-types/index-toolbar.hbs +++ b/app/templates/containers-toolbar.hbs @@ -1,4 +1,6 @@
    + {{container-picker containers=sorted selectContainer='selectContainer'}} + {{reload-button action="reload" classNames="toolbar__icon-button js-reload-container-btn" diff --git a/app/templates/containers.hbs b/app/templates/containers.hbs new file mode 100644 index 0000000000..e2147cab02 --- /dev/null +++ b/app/templates/containers.hbs @@ -0,0 +1 @@ +{{outlet}} \ No newline at end of file diff --git a/app/templates/containers/container.hbs b/app/templates/containers/container.hbs new file mode 100644 index 0000000000..e2147cab02 --- /dev/null +++ b/app/templates/containers/container.hbs @@ -0,0 +1 @@ +{{outlet}} \ No newline at end of file diff --git a/app/templates/container-types.hbs b/app/templates/containers/container/container-types.hbs similarity index 100% rename from app/templates/container-types.hbs rename to app/templates/containers/container/container-types.hbs diff --git a/app/templates/container-type.hbs b/app/templates/containers/container/container-types/container-type.hbs similarity index 100% rename from app/templates/container-type.hbs rename to app/templates/containers/container/container-types/container-type.hbs diff --git a/app/templates/nav.hbs b/app/templates/nav.hbs index 6e2683eaac..f72482f512 100644 --- a/app/templates/nav.hbs +++ b/app/templates/nav.hbs @@ -47,7 +47,7 @@ {{/link-to}}
  • - {{#link-to "container-types"}} + {{#link-to "containers"}} {{svg-jar "nav-container" width="20px" height="20px"}} Container {{/link-to}} diff --git a/ember_debug/container-debug.js b/ember_debug/container-debug.js index fe7cf6bd79..23f49db9ed 100644 --- a/ember_debug/container-debug.js +++ b/ember_debug/container-debug.js @@ -37,10 +37,34 @@ export default EmberObject.extend(PortMixin, { return type[0] === '-' || this.get('TYPES_TO_SKIP').indexOf(type) !== -1; }, - instancesByType() { + all() { + let containers = [ + 'app:main' + ]; + + const router = this.get('container').lookup('router:main'); + containers.pushObjects( Object.keys(router._engineInfoByRoute).map(function(key) { + return router._engineInfoByRoute[key].name + ':' + router._engineInfoByRoute[key].instanceId;} + ).uniq()); + + return containers; + }, + + getContainer(containerRef) { + if (containerRef === 'app:main') { + return this.get('container'); + } else { + const router = this.get('container').lookup('router:main'); + let container_type_id, container_instance_id; + [container_type_id, container_instance_id] = containerRef.split(':'); + return router._engineInstances[container_type_id][container_instance_id].__container__; + } + }, + + instancesByType(container) { let key; let instancesByType = {}; - let cache = this.get('container').cache; + let cache = container.cache; // Detect if InheritingDict (from Ember < 1.8) if (typeof cache.dict !== 'undefined' && typeof cache.eachLocal !== 'undefined') { cache = cache.dict; @@ -59,18 +83,20 @@ export default EmberObject.extend(PortMixin, { return instancesByType; }, - getTypes() { + getTypes(containerRef) { let key; let types = []; - const instancesByType = this.instancesByType(); + const container = this.getContainer(containerRef); + const instancesByType = this.instancesByType(container); for (key in instancesByType) { types.push({ name: key, count: instancesByType[key].length }); } return types; }, - getInstances(type) { - const instances = this.instancesByType()[type]; + getInstances(containerRef, type) { + const container = this.getContainer(containerRef); + const instances = this.instancesByType(container)[type]; if (!instances) { return null; } @@ -82,13 +108,19 @@ export default EmberObject.extend(PortMixin, { }, messages: { - getTypes() { + all() { + this.sendMessage('all', { + containers: this.all() + }); + }, + + getTypes(message) { this.sendMessage('types', { - types: this.getTypes() + types: this.getTypes(message.containerRef) }); }, getInstances(message) { - let instances = this.getInstances(message.containerType); + let instances = this.getInstances(message.containerRef, message.containerType); if (instances) { this.sendMessage('instances', { instances, diff --git a/ember_debug/route-debug.js b/ember_debug/route-debug.js index 0bace22f07..7ad56c517d 100644 --- a/ember_debug/route-debug.js +++ b/ember_debug/route-debug.js @@ -143,10 +143,18 @@ function buildSubTree(routeTree, route) { const router = this.get('router'); const routerLib = router._routerMicrolib || router.router; - routeHandler = routerLib.getHandler(handler); - controllerName = routeHandler.get('controllerName') || routeHandler.get('routeName'); - controllerFactory = owner.factoryFor ? owner.factoryFor(`controller:${controllerName}`) : owner._lookupFactory(`controller:${controllerName}`); - controllerClassName = this.getClassName(controllerName, 'controller'); + let isWithinEngine = router._engineInfoByRoute[handler]; + let hasBeenLoaded = router._seenHandlers[handler]; + if (isWithinEngine && !hasBeenLoaded) { + controllerName = 'Unloaded controller name'; + controllerFactory = true; + controllerClassName = 'Unloaded controller class name'; + } else { + routeHandler = routerLib.getHandler(handler); + controllerName = routeHandler.get('controllerName') || routeHandler.get('routeName'); + controllerFactory = owner.factoryFor ? owner.factoryFor(`controller:${controllerName}`) : owner._lookupFactory(`controller:${controllerName}`); + controllerClassName = this.getClassName(controllerName, 'controller'); + } templateName = this.getClassName(handler, 'template'); subTree[handler] = { diff --git a/tests/integration/components/container-picker-test.js b/tests/integration/components/container-picker-test.js new file mode 100644 index 0000000000..926bacc54e --- /dev/null +++ b/tests/integration/components/container-picker-test.js @@ -0,0 +1,26 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import hbs from 'htmlbars-inline-precompile'; + +module('Integration | Component | container-picker', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function(assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.set('myAction', function(val) { ... }); + + await render(hbs`{{container-picker}}`); + + assert.equal(this.element.textContent.trim(), ''); + + // Template block usage: + await render(hbs` + {{#container-picker}} + template block text + {{/container-picker}} + `); + + assert.equal(this.element.textContent.trim(), 'template block text'); + }); +}); diff --git a/tests/unit/routes/container-test.js b/tests/unit/routes/container-test.js new file mode 100644 index 0000000000..f22641c3ba --- /dev/null +++ b/tests/unit/routes/container-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | container', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:container'); + assert.ok(route); + }); +}); diff --git a/tests/unit/routes/containers-test.js b/tests/unit/routes/containers-test.js new file mode 100644 index 0000000000..2dbe90393a --- /dev/null +++ b/tests/unit/routes/containers-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | containers', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:containers'); + assert.ok(route); + }); +});