From d67b0910db71129e91430548d5ecd8f65417b010 Mon Sep 17 00:00:00 2001
From: Mathis Neumann <mathis@simpletechs.net>
Date: Tue, 21 Jun 2016 17:30:53 +0200
Subject: [PATCH] make objects in graph clickable which will trigger detail
 subroute and sidebar content

---
 app/adapters/application.js                   |  2 +-
 .../component.js                              | 12 +++++-----
 app/components/entity-details.js              |  5 ++++
 app/router.js                                 |  4 +++-
 app/routes/architectures/single.js            | 17 +++++++++++++
 app/routes/architectures/single/details.js    |  7 ++++++
 app/templates/architectures/single.hbs        |  5 +++-
 .../architectures/single/details.hbs          |  2 ++
 .../components/architecture-viewer.hbs        | 10 ++++----
 app/templates/components/entity-details.hbs   |  6 +++++
 package.json                                  |  1 +
 .../components/entity-details-test.js         | 24 +++++++++++++++++++
 12 files changed, 80 insertions(+), 15 deletions(-)
 create mode 100644 app/components/entity-details.js
 create mode 100644 app/routes/architectures/single/details.js
 create mode 100644 app/templates/architectures/single/details.hbs
 create mode 100644 app/templates/components/entity-details.hbs
 create mode 100644 tests/integration/components/entity-details-test.js

diff --git a/app/adapters/application.js b/app/adapters/application.js
index 1ec0aad..3e8a768 100644
--- a/app/adapters/application.js
+++ b/app/adapters/application.js
@@ -7,7 +7,7 @@ import UrlTemplates from "ember-data-url-templates";
  * @return {Adapter} adapter that is used for all metamodel models
  */
 export default BaseAdapter.extend(UrlTemplates, {
-    urlTemplate: '{+host}/{+namespace}/systems{/systemId}/{pathForType}/{/id}',
+    urlTemplate: '{+host}/{+namespace}/{pathForType}{/id}',
     findAllUrlTemplate: '{+host}/{+namespace}/systems{/systemId}/{pathForType}/{?query*}',
 
     urlSegments: {
diff --git a/app/components/architecture-visualisation-cytoscape/component.js b/app/components/architecture-visualisation-cytoscape/component.js
index e0de2b8..f07e150 100644
--- a/app/components/architecture-visualisation-cytoscape/component.js
+++ b/app/components/architecture-visualisation-cytoscape/component.js
@@ -9,8 +9,8 @@ import coseBilkent from 'npm:cytoscape-cose-bilkent';
 coseBilkent(cytoscape); // register
 
 export default Ember.Component.extend({
-    theme: null,
-    layoutAlgorithm: 'cose',
+    theme: null, // set by architecture-viewer
+    layoutAlgorithm: null, // set by architecture-viewer
     classNames: ['cytoscapeRenderingSpace'],
     init: function() {
         cycola( cytoscape, window.cola );
@@ -37,10 +37,10 @@ export default Ember.Component.extend({
 
           layout: {
             name: this.get('layoutAlgorithm'),
-            maxSimulationTime: 1000,
-            padding: 6,
-            ungrabifyWhileSimulating: true,
-            infinite: false
+            // maxSimulationTime: 1000,
+            // padding: 6,
+            // ungrabifyWhileSimulating: true,
+            // infinite: false
           }
         });
 
diff --git a/app/components/entity-details.js b/app/components/entity-details.js
new file mode 100644
index 0000000..bd26aa6
--- /dev/null
+++ b/app/components/entity-details.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+    entity: null
+});
diff --git a/app/router.js b/app/router.js
index 7b6ee52..211b132 100644
--- a/app/router.js
+++ b/app/router.js
@@ -8,7 +8,9 @@ const Router = Ember.Router.extend({
 Router.map(function() {
     this.route('home', {path: '/'});
     this.route('architectures', function() {
-        this.route('single', {path: '/:systemId'});
+        this.route('single', {path: '/:systemId'}, function() {
+            this.route('details', {path: '/:entityType/:entityId'}); // use model properties for automatic matching
+        });
     });
 });
 
diff --git a/app/routes/architectures/single.js b/app/routes/architectures/single.js
index 606496c..b89ac00 100644
--- a/app/routes/architectures/single.js
+++ b/app/routes/architectures/single.js
@@ -28,5 +28,22 @@ export default Ember.Route.extend({
       this.set('loading', false);
       return graph;
     });
+  },
+  actions: {
+    loadDetails(rawEntity) {
+        this.debug('loadDetails action', rawEntity);
+        const entityType = rawEntity.type.toLowerCase();
+        const entityId = rawEntity.id;
+
+        /* I would love to not generate the url first, but there seem to be unknown (to me) assumptions about
+        * passing object parameters to transitionTo which break with the current path variables.
+        */
+        const url = this.router.generate('architectures.single.details', {
+            systemId: this.get('session.systemId'),
+            entityType,
+            entityId
+        });
+        this.transitionTo(url);
+    }
   }
 });
diff --git a/app/routes/architectures/single/details.js b/app/routes/architectures/single/details.js
new file mode 100644
index 0000000..8ef7367
--- /dev/null
+++ b/app/routes/architectures/single/details.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+    model(params) {
+        return this.store.findRecord(params.entityType.toLowerCase(), params.entityId); // TODO: match entity.type with model names
+    }
+});
diff --git a/app/templates/architectures/single.hbs b/app/templates/architectures/single.hbs
index c46db69..46f98c4 100644
--- a/app/templates/architectures/single.hbs
+++ b/app/templates/architectures/single.hbs
@@ -1 +1,4 @@
-{{architecture-viewer graph=model}}
\ No newline at end of file
+{{#architecture-viewer graph=model}}
+    {{!-- show entity details in sidebar if subroute (details) is used --}}
+    {{outlet}}
+{{/architecture-viewer}}
\ No newline at end of file
diff --git a/app/templates/architectures/single/details.hbs b/app/templates/architectures/single/details.hbs
new file mode 100644
index 0000000..f4b648a
--- /dev/null
+++ b/app/templates/architectures/single/details.hbs
@@ -0,0 +1,2 @@
+Hello Subroute!
+{{entity-details entity=model}}
\ No newline at end of file
diff --git a/app/templates/components/architecture-viewer.hbs b/app/templates/components/architecture-viewer.hbs
index f780a96..915841f 100644
--- a/app/templates/components/architecture-viewer.hbs
+++ b/app/templates/components/architecture-viewer.hbs
@@ -1,8 +1,8 @@
 <div class="row">
     <div class="col-md-10 visualisationContainer">
-        {{architecture-visualisation-cytoscape graph=graph layoutAlgorithm=layoutAlgorithm theme=theme select=(action "graphClick")}}
+        {{architecture-visualisation-cytoscape graph=graph layoutAlgorithm=layoutAlgorithm theme=theme select=(route-action 'loadDetails')}}
     </div>
-    <div class="col-md-2 visualistaionSidebar">
+    <div class="col-md-2 visualisationSidebar">
         <div class="form-group">
           <label for="layoutAlgorithm">Layout:</label>
           <select class="form-control" id="layoutAlgorithm" onchange={{action "selectLayoutAlgorithm" value="target.value"}}>
@@ -20,10 +20,8 @@
           </select>
         </div>
 
-        {{#if entityDetails}}
-            <h3>Details</h3>
-            {{entityDetails.type}}
-        {{/if}}
+        {{!-- this component can be used as a block, show content --}}
+        {{yield}}
     </div>
 </div>
 
diff --git a/app/templates/components/entity-details.hbs b/app/templates/components/entity-details.hbs
new file mode 100644
index 0000000..541c63a
--- /dev/null
+++ b/app/templates/components/entity-details.hbs
@@ -0,0 +1,6 @@
+id: {{entity.id}}
+name: {{entity.name}}
+type: {{entity.type}}
+systemId: {{entity.systemId}}
+
+{{log 'entity-details' entity}}
diff --git a/package.json b/package.json
index 7b621aa..a5a2741 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
     "ember-export-application-global": "^1.0.4",
     "ember-load-initializers": "^0.5.0",
     "ember-resolver": "^2.0.3",
+    "ember-route-action-helper": "0.3.2",
     "loader.js": "^4.0.0",
     "lodash": "^4.11.1",
     "node-sass": "^3.8.0"
diff --git a/tests/integration/components/entity-details-test.js b/tests/integration/components/entity-details-test.js
new file mode 100644
index 0000000..0b5314d
--- /dev/null
+++ b/tests/integration/components/entity-details-test.js
@@ -0,0 +1,24 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('entity-details', 'Integration | Component | entity details', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });
+
+  this.render(hbs`{{entity-details}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:
+  this.render(hbs`
+    {{#entity-details}}
+      template block text
+    {{/entity-details}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
-- 
GitLab