changeset 58:3b4046e0cc02 default

Merge from ng2-table branch. d7c947909ab888c013171b8c037e4f9fab30fe57
author casties
date Wed, 29 Mar 2017 17:19:12 +0200
parents 781a5387ca93 (current diff) d7c947909ab8 (diff)
children 0d51fefdbae6
files src/app/app-config.js src/app/app-config.js.map src/app/app-config.ts src/app/app.module.js src/app/app.module.js.map src/app/ismi-relation-types.js src/app/ismi-relation-types.js.map src/app/ismi-result-types.js src/app/ismi-result-types.js.map src/app/normalization.service.js src/app/normalization.service.js.map src/app/query-app.component.js src/app/query-app.component.js.map src/app/query-app.module.ts src/app/query-mode.js src/app/query-mode.js.map src/app/query-result-row.component.js src/app/query-result-row.component.js.map src/app/query-result-table.component.js src/app/query-result-table.component.js.map src/app/query-result.component.js src/app/query-result.component.js.map src/app/query-select.component.js src/app/query-select.component.js.map src/app/query-state.js src/app/query-state.js.map src/app/query-step.js src/app/query-step.js.map src/app/query.service.js src/app/query.service.js.map src/app/relation-type.js src/app/relation-type.js.map src/app/result-column.js src/app/result-column.js.map src/app/result-type.js src/app/result-type.js.map src/main.js src/main.js.map
diffstat 48 files changed, 1522 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/package.json	Mon Mar 20 18:50:31 2017 +0100
+++ b/package.json	Wed Mar 29 17:19:12 2017 +0200
@@ -1,6 +1,6 @@
 {
   "name": "ng2-ismi-query-app",
-  "version": "1.0.0",
+  "version": "1.1.0",
   "scripts": {
     "build": "tsc -p src/",
     "build:watch": "tsc -p src/ -w",
@@ -31,18 +31,17 @@
     "@angular/platform-browser": "~2.4.0",
     "@angular/platform-browser-dynamic": "~2.4.0",
     "@angular/router": "~3.4.0",
-
     "angular-in-memory-web-api": "~0.2.4",
+    "core-js": "^2.4.1",
+    "ng2-bootstrap": "^1.4.2",
+    "rxjs": "5.0.1",
     "systemjs": "0.19.40",
-    "core-js": "^2.4.1",
-    "rxjs": "5.0.1",
     "zone.js": "^0.7.4"
   },
   "devDependencies": {
     "concurrently": "^3.2.0",
     "lite-server": "^2.2.2",
     "typescript": "~2.0.10",
-
     "canonical-path": "0.0.2",
     "tslint": "^3.15.1",
     "lodash": "^4.16.4",
@@ -54,7 +53,6 @@
     "karma-jasmine-html-reporter": "^0.2.2",
     "protractor": "~4.0.14",
     "rimraf": "^2.5.4",
-
     "@types/node": "^6.0.46",
     "@types/jasmine": "2.5.36"
   },
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/app-config.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,7 @@
+"use strict";
+//export const NEO4J_BASE_URL = 'https://ismi-dev.mpiwg-berlin.mpg.de/neo4j-ismi/db/data';
+exports.NEO4J_BASE_URL = 'http://localhost:7474/db/data';
+exports.NEO4J_AUTHENTICATION = { 'user': 'neo4j', 'password': 'neo5j' };
+exports.OPENMIND_BASE_URL = 'https://ismi-dev.mpiwg-berlin.mpg.de/om4-ismi/';
+//export const OPENMIND_BASE_URL = 'http://localhost:18080/ismi-richfaces/';
+//# sourceMappingURL=app-config.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/app-config.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"app-config.js","sourceRoot":"","sources":["app-config.ts"],"names":[],"mappings":";AACA,0FAA0F;AAC7E,sBAAc,GAAG,+BAA+B,CAAC;AAEjD,4BAAoB,GAAG,EAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAC,CAAC;AAE9D,yBAAiB,GAAG,gDAAgD,CAAC;AAClF,4EAA4E"}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/app-config.ts	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,8 @@
+
+//export const NEO4J_BASE_URL = 'https://ismi-dev.mpiwg-berlin.mpg.de/neo4j-ismi/db/data';
+export const NEO4J_BASE_URL = 'http://localhost:7474/db/data';
+
+export const NEO4J_AUTHENTICATION = {'user': 'neo4j', 'password': 'neo5j'};
+
+export const OPENMIND_BASE_URL = 'https://ismi-dev.mpiwg-berlin.mpg.de/om4-ismi/';
+//export const OPENMIND_BASE_URL = 'http://localhost:18080/ismi-richfaces/';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/app.module.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,42 @@
+"use strict";
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var core_1 = require('@angular/core');
+var platform_browser_1 = require('@angular/platform-browser');
+var forms_1 = require('@angular/forms');
+var http_1 = require('@angular/http');
+var ng2_table_1 = require('ng2-table/ng2-table');
+var ng2_bootstrap_1 = require('ng2-bootstrap');
+var query_app_component_1 = require('./query-app.component');
+var query_select_component_1 = require('./query-select.component');
+//import { QueryResultComponent }  from './query-result.component';
+//import { QueryResultRowComponent }  from './query-result-row.component';
+var query_result_table_component_1 = require('./query-result-table.component');
+var query_service_1 = require('./query.service');
+var normalization_service_1 = require('./normalization.service');
+var AppModule = (function () {
+    function AppModule() {
+    }
+    AppModule = __decorate([
+        core_1.NgModule({
+            imports: [platform_browser_1.BrowserModule, forms_1.FormsModule, http_1.HttpModule,
+                ng2_table_1.Ng2TableModule, ng2_bootstrap_1.PaginationModule.forRoot()],
+            declarations: [query_app_component_1.QueryAppComponent, query_select_component_1.QuerySelectComponent,
+                //                  QueryResultComponent, QueryResultRowComponent 
+                query_result_table_component_1.QueryResultTableComponent],
+            providers: [query_service_1.QueryService, normalization_service_1.NormalizationService],
+            bootstrap: [query_app_component_1.QueryAppComponent]
+        }), 
+        __metadata('design:paramtypes', [])
+    ], AppModule);
+    return AppModule;
+}());
+exports.AppModule = AppModule;
+//# sourceMappingURL=app.module.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/app.module.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"app.module.js","sourceRoot":"","sources":["app.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,qBAA8B,eAAe,CAAC,CAAA;AAC9C,iCAA8B,2BAA2B,CAAC,CAAA;AAC1D,sBAA4B,gBAAgB,CAAC,CAAA;AAC7C,qBAA2B,eAAe,CAAC,CAAA;AAE3C,0BAA+B,qBAAqB,CAAC,CAAA;AACrD,8BAAiC,eAAe,CAAC,CAAA;AAEjD,oCAAmC,uBAAuB,CAAC,CAAA;AAC3D,uCAAsC,0BAA0B,CAAC,CAAA;AACjE,mEAAmE;AACnE,0EAA0E;AAC1E,6CAA2C,gCAAgC,CAAC,CAAA;AAC5E,8BAA6B,iBAAiB,CAAC,CAAA;AAC/C,sCAAqC,yBAAyB,CAAC,CAAA;AAY/D;IAAA;IAAyB,CAAC;IAT1B;QAAC,eAAQ,CAAC;YACR,OAAO,EAAO,CAAE,gCAAa,EAAE,mBAAW,EAAE,iBAAU;gBACtC,0BAAc,EAAE,gCAAgB,CAAC,OAAO,EAAE,CAAE;YAC5D,YAAY,EAAE,CAAE,uCAAiB,EAAE,6CAAoB;gBACzD,kEAAkE;gBAChD,wDAAyB,CAAE;YAC3C,SAAS,EAAK,CAAE,4BAAY,EAAE,4CAAoB,CAAE;YACpD,SAAS,EAAK,CAAE,uCAAiB,CAAE;SACpC,CAAC;;iBAAA;IACuB,gBAAC;AAAD,CAAC,AAA1B,IAA0B;AAAb,iBAAS,YAAI,CAAA"}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/app.module.ts	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,27 @@
+import { NgModule }      from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+import { HttpModule } from '@angular/http';
+
+import { Ng2TableModule } from 'ng2-table/ng2-table';
+import { PaginationModule } from 'ng2-bootstrap';
+
+import { QueryAppComponent }  from './query-app.component';
+import { QuerySelectComponent }  from './query-select.component';
+//import { QueryResultComponent }  from './query-result.component';
+//import { QueryResultRowComponent }  from './query-result-row.component';
+import { QueryResultTableComponent }  from './query-result-table.component';
+import { QueryService } from './query.service';
+import { NormalizationService } from './normalization.service';
+
+
+@NgModule({
+  imports:      [ BrowserModule, FormsModule, HttpModule,
+                  Ng2TableModule, PaginationModule.forRoot() ],
+  declarations: [ QueryAppComponent, QuerySelectComponent, 
+//                  QueryResultComponent, QueryResultRowComponent 
+                  QueryResultTableComponent ],
+  providers:    [ QueryService, NormalizationService ],
+  bootstrap:    [ QueryAppComponent ]
+})
+export class AppModule { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/ismi-relation-types.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,63 @@
+"use strict";
+var relation_type_1 = require('./relation-type');
+exports.RELATION_TYPES = {};
+addRelationType('is_part_of', 'is included in', 'includes');
+addRelationType('is_exemplar_of', 'title of witness', 'witnesses to title');
+addRelationType('was_created_by', 'created by', 'works of');
+addRelationType('has_subject', 'subject of title', 'titles with subject');
+addRelationType('has_role', 'roles of person', 'persons with role');
+addRelationType('is_alias_name_of', 'person name for alias', 'alias of person');
+addRelationType('is_alias_title_of', 'title name for alias', 'alias of title');
+addRelationType('is_commentary_on', 'is commentary on', 'list of commentaries');
+addRelationType('has_title_written_as', 'title in witness', 'witness with title as');
+addRelationType('has_author_written_as', 'author in witness', 'witness with author as');
+addRelationType('lived_in', 'place person lived in', 'persons who lived in');
+addRelationType('was_copied_by', 'witness copied by', 'witnesses that were copied by');
+addRelationType('was_born_in', 'place person was born in', 'persons who were born in');
+addRelationType('owned_by', 'codex owned by', 'persons who owned codex');
+addRelationType('was_student_of', 'studied with', 'persons studying with');
+addRelationType('died_in', 'place person died in', 'persons who died in');
+addRelationType('was_created_in', 'place title was created', 'titles that were created in');
+addRelationType('was_copied_in', 'place witness was copied', 'witnesses that were copied in');
+addRelationType('misattributed_to', 'title misattributed to', 'misattributions to person');
+addRelationType('was_dedicated_to', 'text dedicated to', 'texts that were dedicated to');
+addRelationType('is_version_of', 'standard text of different version', 'different version of standard text');
+addRelationType('is_translation_of', 'original text of a translation', 'translation of a text');
+addRelationType('has_floruit_date', 'floruit date of person', 'persons with floruit date');
+addRelationType('was_studied_by', 'persons studying this text', 'text studied by');
+//addRelationType('', '', '');
+function getRelationType(relType, isOutgoing) {
+    var name = relType;
+    if (isOutgoing === false) {
+        // add prefix to name
+        name = relation_type_1.invNamePrefix + name;
+    }
+    var rt = exports.RELATION_TYPES[name];
+    if (rt == null) {
+        rt = new relation_type_1.RelationType(relType, isOutgoing);
+    }
+    return rt;
+}
+exports.getRelationType = getRelationType;
+function getRelationByName(name) {
+    var rt = exports.RELATION_TYPES[name];
+    if (rt == null) {
+        if (name.indexOf(relation_type_1.invNamePrefix) == 0) {
+            // inverse relation
+            name = name.substr(relation_type_1.invNamePrefix.length);
+            rt = new relation_type_1.RelationType(name, false);
+        }
+        else {
+            rt = new relation_type_1.RelationType(name, true);
+        }
+    }
+    return rt;
+}
+exports.getRelationByName = getRelationByName;
+function addRelationType(name, outLabel, inLabel) {
+    // add outgoing relation
+    exports.RELATION_TYPES[name] = new relation_type_1.RelationType(name, true, outLabel);
+    // add inverse relation
+    exports.RELATION_TYPES[relation_type_1.invNamePrefix + name] = new relation_type_1.RelationType(name, false, inLabel);
+}
+//# sourceMappingURL=ismi-relation-types.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/ismi-relation-types.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"ismi-relation-types.js","sourceRoot":"","sources":["ismi-relation-types.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/ismi-result-types.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,14 @@
+"use strict";
+var result_type_1 = require('./result-type');
+exports.ISMI_RESULT_TYPES = {
+    '*': new result_type_1.ResultType('*', 'ismi_id', [
+        'ismi_id', 'label'
+    ]),
+    'PERSON': new result_type_1.ResultType('PERSON', 'ismi_id', [
+        'ismi_id', 'name_translit', 'name', 'birth_date', 'death_date'
+    ]),
+    'TEXT': new result_type_1.ResultType('TEXT', 'ismi_id', [
+        'ismi_id', 'full_title_translit', 'full_title', 'creation_date'
+    ])
+};
+//# sourceMappingURL=ismi-result-types.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/ismi-result-types.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"ismi-result-types.js","sourceRoot":"","sources":["ismi-result-types.ts"],"names":[],"mappings":";AAAA,4BAAyB,eAAe,CAAC,CAAA;AAG9B,yBAAiB,GAAgC;IACxD,GAAG,EAAE,IAAI,wBAAU,CAAC,GAAG,EAAE,SAAS,EAAE;QAC5B,SAAS,EAAE,OAAO;KACrB,CAAC;IACN,QAAQ,EAAE,IAAI,wBAAU,CAAC,QAAQ,EAAE,SAAS,EAAE;QAC1C,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY;KACjE,CAAC;IACF,MAAM,EAAE,IAAI,wBAAU,CAAC,MAAM,EAAE,SAAS,EAAE;QACtC,SAAS,EAAE,qBAAqB,EAAE,YAAY,EAAE,eAAe;KAClE,CAAC;CACL,CAAA"}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/normalization.service.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,40 @@
+"use strict";
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var core_1 = require('@angular/core');
+var http_1 = require('@angular/http');
+require('rxjs/Rx'); // import all RxJS operators
+var app_config_1 = require('./app-config');
+var NormalizationService = (function () {
+    function NormalizationService(_http) {
+        this._http = _http;
+    }
+    NormalizationService.prototype.fetchArabicTranslitNormalizedString = function (text) {
+        console.debug("fetching arabic translit normalized string: ", text);
+        var headers = new http_1.Headers();
+        headers.append('Accept', 'application/json');
+        // put headers in options
+        var opts = { 'headers': headers };
+        // make get request asynchronously
+        var url = app_config_1.OPENMIND_BASE_URL + 'jsonInterface?method=normalize_string&type=arabic_translit&text=';
+        url += encodeURIComponent(text);
+        var resp = this._http.get(url, opts)
+            .map(function (res) { return res.json(); });
+        // return Observable
+        return resp;
+    };
+    NormalizationService = __decorate([
+        core_1.Injectable(), 
+        __metadata('design:paramtypes', [http_1.Http])
+    ], NormalizationService);
+    return NormalizationService;
+}());
+exports.NormalizationService = NormalizationService;
+//# sourceMappingURL=normalization.service.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/normalization.service.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"normalization.service.js","sourceRoot":"","sources":["normalization.service.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,qBAAyB,eAAe,CAAC,CAAA;AACzC,qBAA4B,eAAe,CAAC,CAAA;AAE5C,QAAO,SAAS,CAAC,CAAA,CAAC,4BAA4B;AAE9C,2BAAgC,cAAc,CAAC,CAAA;AAG/C;IAEI,8BAAoB,KAAW;QAAX,UAAK,GAAL,KAAK,CAAM;IAAG,CAAC;IAEnC,kEAAmC,GAAnC,UAAoC,IAAY;QAC5C,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,IAAI,CAAC,CAAC;QACpE,IAAI,OAAO,GAAG,IAAI,cAAO,EAAE,CAAC;QAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QAC7C,yBAAyB;QACzB,IAAI,IAAI,GAAG,EAAC,SAAS,EAAE,OAAO,EAAC,CAAC;QAChC,kCAAkC;QAClC,IAAI,GAAG,GAAG,8BAAiB,GAAC,kEAAkE,CAAC;QAC/F,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC;aAEnC,GAAG,CAAC,UAAA,GAAG,IAAI,OAAA,GAAG,CAAC,IAAI,EAAE,EAAV,CAAU,CAAC,CAAC;QACxB,oBAAoB;QACpB,MAAM,CAAC,IAAI,CAAC;IAChB,CAAC;IAnBL;QAAC,iBAAU,EAAE;;4BAAA;IAqBb,2BAAC;AAAD,CAAC,AApBD,IAoBC;AApBY,4BAAoB,uBAoBhC,CAAA"}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-app.component.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,88 @@
+"use strict";
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var core_1 = require('@angular/core');
+var query_service_1 = require('./query.service');
+var QueryAppComponent = (function () {
+    function QueryAppComponent(_queryService) {
+        var _this = this;
+        this._queryService = _queryService;
+        console.debug("QueryAppComponent constructor!");
+        var newState = this.getStateStringFromUrlFragment();
+        // initialize query service using external state
+        this._queryService.setup(newState);
+        this.queryStepList = [];
+        // set state in queryStepList
+        if (this._queryService.state.getNumSteps() > 0) {
+            // use state from URL
+            this._queryService.state.steps
+                .forEach(function (elem) { return _this.queryStepList.push('param'); });
+        }
+        else {
+            // new empty state
+            this.addQueryStep();
+        }
+    }
+    QueryAppComponent.prototype.getStateStringFromUrlFragment = function () {
+        var hash = window.location.hash;
+        if (hash) {
+            var fragb = hash.substr(1);
+            // base64 decode
+            var fragu = window.atob(fragb);
+            // url decode
+            var frag = decodeURIComponent(fragu);
+            // reset hash
+            window.location.hash = '';
+            return frag;
+        }
+        return null;
+    };
+    QueryAppComponent.prototype.getUrlFragmentFromState = function () {
+        var stateStr = this._queryService.state.getStateAsString();
+        var frag = '#';
+        if (stateStr.length > 0) {
+            var fragu = encodeURIComponent(stateStr);
+            var fragb = window.btoa(fragu);
+            frag += fragb;
+        }
+        return frag;
+    };
+    QueryAppComponent.prototype.addQueryStep = function () {
+        this.queryStepList.push('step');
+    };
+    QueryAppComponent.prototype.removeQueryStep = function () {
+        this.queryStepList.pop();
+        this._queryService.state.steps.pop();
+    };
+    QueryAppComponent.prototype.resetQuery = function () {
+        // reset everything by reloading
+        window.location.reload();
+    };
+    QueryAppComponent.prototype.showQueryUrl = function () {
+        var url = window.location.href;
+        url = url.replace(/#.*/, '') + this.getUrlFragmentFromState();
+        window.prompt("URL to current query state", url);
+    };
+    QueryAppComponent.prototype.onQueryChanged = function (event) {
+        console.debug("app.onquerychanged! event=", event);
+        this._queryService.runQuery();
+        this.queryState = this._queryService.getState();
+    };
+    QueryAppComponent = __decorate([
+        core_1.Component({
+            selector: 'query-app',
+            template: "\n    <div class=\"container\">    \n        <h1>ISMI-Lab Query Builder</h1>\n    </div>\n    <div class=\"container\">    \n        <div>Select a query step:</div>\n        <query-select *ngFor=\"let step of queryStepList; let i=index;\"\n            [queryStep]=\"step\" [index]=\"i\" \n            (queryChanged)=\"onQueryChanged($event)\"></query-select>\n        <div>\n          <button (click)=\"addQueryStep()\">add step</button>\n          <button (click)=\"removeQueryStep()\">remove step</button>\n          <button (click)=\"resetQuery()\">reset query</button>\n          <button (click)=\"showQueryUrl()\">get query url</button>\n        </div>\n    </div>\n    <div class=\"container\">\n        <query-result *ngIf=\"queryState?.results\"\n            [resultInfo]=\"queryState.resultInfo\"\n            [queryState]=\"queryState\">\n        </query-result>\n    </div>\n        ",
+        }), 
+        __metadata('design:paramtypes', [query_service_1.QueryService])
+    ], QueryAppComponent);
+    return QueryAppComponent;
+}());
+exports.QueryAppComponent = QueryAppComponent;
+//# sourceMappingURL=query-app.component.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-app.component.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"query-app.component.js","sourceRoot":"","sources":["query-app.component.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
--- a/src/app/query-app.component.ts	Mon Mar 20 18:50:31 2017 +0100
+++ b/src/app/query-app.component.ts	Wed Mar 29 17:19:12 2017 +0200
@@ -1,5 +1,4 @@
 import {Component} from '@angular/core';
-//import {HTTP_PROVIDERS} from '@angular/http';
 
 import {QueryState} from './query-state';
 import {QueryStep} from './query-step';
@@ -7,10 +6,6 @@
 import {QueryService} from './query.service';
 import {NormalizationService} from './normalization.service';
 
-import {QuerySelectComponent} from './query-select.component';
-import {QueryResultComponent} from './query-result.component';
-//import {QueryResultTableComponent} from './query-result-table.component';
-
 @Component({
     selector: 'query-app',
     template: `
@@ -25,6 +20,8 @@
         <div>
           <button (click)="addQueryStep()">add step</button>
           <button (click)="removeQueryStep()">remove step</button>
+          <button (click)="resetQuery()">reset query</button>
+          <button (click)="showQueryUrl()">get query url</button>
         </div>
     </div>
     <div class="container">
@@ -34,8 +31,6 @@
         </query-result>
     </div>
         `,
-    //directives: [QuerySelectComponent, QueryResultTableComponent],
-    //providers: [QueryService, NormalizationService, HTTP_PROVIDERS]
 })
     
 export class QueryAppComponent { 
@@ -43,9 +38,46 @@
     public queryStepList: string[];
         
     constructor(private _queryService: QueryService) {
-        this._queryService.setup();
+        console.debug("QueryAppComponent constructor!");
+        let newState = this.getStateStringFromUrlFragment();
+        // initialize query service using external state
+        this._queryService.setup(newState);
         this.queryStepList = [];
-        this.addQueryStep();
+        // set state in queryStepList
+        if (this._queryService.state.getNumSteps() > 0) {
+            // use state from URL
+            this._queryService.state.steps
+                .forEach((elem) => this.queryStepList.push('param'));
+        } else {
+            // new empty state
+            this.addQueryStep();
+        }
+    }
+    
+    getStateStringFromUrlFragment(): string {
+        let hash: string = window.location.hash;
+        if (hash) {
+            let fragb: string = hash.substr(1);
+            // base64 decode
+            let fragu = window.atob(fragb);
+            // url decode
+            let frag = decodeURIComponent(fragu);
+            // reset hash
+            window.location.hash = '';
+            return frag;
+        }
+        return null;
+    }
+    
+    getUrlFragmentFromState() {
+        let stateStr = this._queryService.state.getStateAsString();
+        let frag = '#';
+        if (stateStr.length > 0) {
+            let fragu = encodeURIComponent(stateStr);
+            let fragb = window.btoa(fragu);
+            frag += fragb;
+        }
+        return frag;
     }
     
     addQueryStep() {
@@ -57,6 +89,17 @@
         this._queryService.state.steps.pop();
     }
     
+    resetQuery() {
+        // reset everything by reloading
+        window.location.reload();
+    }
+    
+    showQueryUrl() {
+        let url = window.location.href 
+        url = url.replace(/#.*/, '') + this.getUrlFragmentFromState();
+        window.prompt("URL to current query state", url);
+    }
+    
     onQueryChanged(event: any) {
         console.debug("app.onquerychanged! event=", event);
         this._queryService.runQuery();
--- a/src/app/query-app.module.ts	Mon Mar 20 18:50:31 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-import { NgModule }      from '@angular/core';
-import { BrowserModule } from '@angular/platform-browser';
-import { FormsModule } from '@angular/forms';
-import { HttpModule } from '@angular/http';
-
-import { QueryAppComponent }  from './query-app.component';
-import { QuerySelectComponent }  from './query-select.component';
-import { QueryResultComponent }  from './query-result.component';
-import { QueryResultRowComponent }  from './query-result-row.component';
-//import { QueryResultTableComponent }  from './query-result-table.component';
-import { QueryService } from './query.service';
-import { NormalizationService } from './normalization.service';
-
-
-@NgModule({
-  imports:      [ BrowserModule, FormsModule, HttpModule ],
-  declarations: [ QueryAppComponent, QuerySelectComponent, 
-                  QueryResultComponent, QueryResultRowComponent ],
-  providers:    [ QueryService, NormalizationService ],
-  bootstrap:    [ QueryAppComponent ]
-})
-export class AppModule { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-mode.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,18 @@
+"use strict";
+function getQueryModeById(id) {
+    return exports.QUERY_MODES.find(function (elem) { return elem.id === id; });
+}
+exports.getQueryModeById = getQueryModeById;
+exports.QUERY_MODES = [
+    { id: 'type_is', label: 'Object type is' },
+    { id: 'att_contains', label: 'Attribute (contains)' },
+    { id: 'att_contains_norm', label: 'Attribute (contains normalized)' },
+    { id: 'att_num_range', label: 'Attribute (number range)' },
+    { id: 'relation_is', label: 'Relation type is' },
+    { id: 'id_is', label: 'Object ID is' }
+];
+exports.FIRST_QUERY_MODES = [
+    { id: 'type_is', label: 'Object type is' },
+    { id: 'id_is', label: 'Object ID is' }
+];
+//# sourceMappingURL=query-mode.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-mode.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"query-mode.js","sourceRoot":"","sources":["query-mode.ts"],"names":[],"mappings":";AAKA,0BAAiC,EAAU;IACvC,MAAM,CAAC,mBAAW,CAAC,IAAI,CAAC,UAAC,IAAI,IAAK,OAAA,IAAI,CAAC,EAAE,KAAK,EAAE,EAAd,CAAc,CAAC,CAAC;AACtD,CAAC;AAFe,wBAAgB,mBAE/B,CAAA;AAEU,mBAAW,GAAgB;IAClC,EAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAC,gBAAgB,EAAC;IACvC,EAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,sBAAsB,EAAC;IACnD,EAAC,EAAE,EAAE,mBAAmB,EAAE,KAAK,EAAE,iCAAiC,EAAC;IACnE,EAAC,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,0BAA0B,EAAC;IACxD,EAAC,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,kBAAkB,EAAC;IAC9C,EAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAC;CACvC,CAAC;AAES,yBAAiB,GAAgB;IACxC,EAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAC,gBAAgB,EAAC;IACvC,EAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAC;CACvC,CAAC"}
\ No newline at end of file
--- a/src/app/query-mode.ts	Mon Mar 20 18:50:31 2017 +0100
+++ b/src/app/query-mode.ts	Wed Mar 29 17:19:12 2017 +0200
@@ -3,6 +3,10 @@
     label: string;
 }
 
+export function getQueryModeById(id: string) {
+    return QUERY_MODES.find((elem) => elem.id === id);
+}
+
 export var QUERY_MODES: QueryMode[] = [
     {id: 'type_is', label:'Object type is'},
     {id: 'att_contains', label: 'Attribute (contains)'},
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-result-row.component.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,29 @@
+"use strict";
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var core_1 = require('@angular/core');
+var QueryResultRowComponent = (function () {
+    function QueryResultRowComponent() {
+    }
+    QueryResultRowComponent.prototype.ngOnInit = function () {
+        console.debug("row init! rowType=", this.rowType, " columns=", this.columns, " rowData=", this.rowData);
+    };
+    QueryResultRowComponent = __decorate([
+        core_1.Component({
+            selector: 'tr.resultRow',
+            template: "\n        <ng-container *ngIf=\"rowType=='node'\">\n          <td style=\"vertical-align: top;\"\n            *ngFor=\"let col of columns\">\n            <a *ngIf=\"col && col.name=='link'\" href=\"{{rowData[col.name]}}\" target=\"_blank\">Link</a>\n            <span *ngIf=\"col && col.name!='link'\">{{rowData[col.name]}}</span>\n          </td>\n        </ng-container>\n        <ng-container *ngIf=\"rowType=='text'\">\n          <td style=\"vertical-align: top;\">{{rowData}}</td>\n        </ng-container>\n        ",
+            inputs: ['rowData', 'rowType', 'columns']
+        }), 
+        __metadata('design:paramtypes', [])
+    ], QueryResultRowComponent);
+    return QueryResultRowComponent;
+}());
+exports.QueryResultRowComponent = QueryResultRowComponent;
+//# sourceMappingURL=query-result-row.component.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-result-row.component.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"query-result-row.component.js","sourceRoot":"","sources":["query-result-row.component.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,qBAAwB,eAAe,CAAC,CAAA;AAmBxC;IAAA;IASA,CAAC;IAHG,0CAAQ,GAAR;QACI,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5G,CAAC;IAzBL;QAAC,gBAAS,CAAC;YACP,QAAQ,EAAE,cAAc;YACxB,QAAQ,EAAE,0gBAWL;YACL,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;SAC5C,CAAC;;+BAAA;IAWF,8BAAC;AAAD,CAAC,AATD,IASC;AATY,+BAAuB,0BASnC,CAAA"}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-result-table.component.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,127 @@
+"use strict";
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var core_1 = require('@angular/core');
+var QueryResultTableComponent = (function () {
+    function QueryResultTableComponent() {
+        this.showTable = false;
+        this.currentPage = 1;
+        this.itemsPerPage = 10;
+        this.maxSize = 5;
+        this.numPages = 1;
+        this.length = 0;
+        this.config = {
+            paging: true,
+            sorting: { 'columns': this.columns },
+        };
+    }
+    QueryResultTableComponent.prototype.ngOnChanges = function (changes) {
+        console.debug("result table changed! changes=", changes);
+        this.data = this.queryState.results;
+        if (this.data.length > 0) {
+            this.allColumns = this.queryState.resultColumns;
+            this.columns = this.allColumns.filter(function (c) { return c.show; });
+            this.config.sorting = this.columns;
+            this.config.paging = { 'page': this.currentPage, 'itemsPerPage': this.itemsPerPage };
+            this.showTable = (this.data.length < 1000);
+            this.onChangeTable(this.config);
+        }
+    };
+    QueryResultTableComponent.prototype.ngOnInit = function () {
+        console.debug("result table init!");
+    };
+    QueryResultTableComponent.prototype.onSelectNumItems = function (event) {
+        var selected = event.target.value;
+        console.debug("selected number of items:", selected);
+        var num = parseInt(selected);
+        if (num == 0) {
+            this.itemsPerPage = this.length;
+        }
+        else {
+            this.itemsPerPage = num;
+        }
+        // update something
+        this.config.paging = { 'page': this.currentPage, 'itemsPerPage': this.itemsPerPage };
+        this.onChangeTable(this.config);
+    };
+    QueryResultTableComponent.prototype.onSelectCols = function (event) {
+        console.debug("select cols:", this.allColumns);
+        this.columns = this.allColumns.filter(function (c) { return c.show; });
+        this.config.sorting = this.columns;
+    };
+    QueryResultTableComponent.prototype.changePage = function (page, data) {
+        if (data === void 0) { data = this.data; }
+        var start = (page.page - 1) * page.itemsPerPage;
+        var end = page.itemsPerPage > -1 ? (start + page.itemsPerPage) : data.length;
+        return data.slice(start, end);
+    };
+    QueryResultTableComponent.prototype.changeSort = function (data, config) {
+        if (!config.sorting) {
+            return data;
+        }
+        var columns = this.columns.filter(function (c) { return c.sort; });
+        // simple sorting
+        var sorted = data.sort(function (previous, current) {
+            for (var i = 0; i < columns.length; i++) {
+                var sort = columns[i].sort;
+                var columnName = columns[i].name;
+                if (previous[columnName] > current[columnName]) {
+                    return sort === 'desc' ? -1 : 1;
+                }
+                else if (previous[columnName] < current[columnName]) {
+                    return sort === 'asc' ? -1 : 1;
+                }
+            }
+            return 0;
+        });
+        return sorted;
+    };
+    QueryResultTableComponent.prototype.changeFilter = function (data, config) {
+        var _this = this;
+        if (!config.filtering) {
+            return data;
+        }
+        var filteredData = data.filter(function (item) {
+            return item[config.filtering.columnName].match(_this.config.filtering.filterString);
+        });
+        return filteredData;
+    };
+    QueryResultTableComponent.prototype.onChangeTable = function (config, page) {
+        if (page === void 0) { page = config.paging; }
+        console.debug("onChangeTable config=", config, " page=", page);
+        if (config.filtering) {
+            Object.assign(this.config.filtering, config.filtering);
+        }
+        if (config.sorting) {
+            Object.assign(this.config.sorting, config.sorting);
+            // changing sorting resets page
+            if (page == null) {
+                this.currentPage = 1;
+                page = { 'page': this.currentPage, 'itemsPerPage': this.itemsPerPage };
+            }
+        }
+        //let filteredData = this.changeFilter(this.data, this.config);
+        //let sortedData = this.changeSort(filteredData, this.config);
+        var sortedData = this.changeSort(this.data, this.config);
+        this.rows = (page && this.config.paging) ? this.changePage(page, sortedData) : sortedData;
+        this.length = sortedData.length;
+    };
+    QueryResultTableComponent = __decorate([
+        core_1.Component({
+            selector: 'query-result',
+            template: "\n    <div *ngIf=\"queryState?.numResults > 0\">\n        <span>Cypher query:</span>\n        <pre>{{queryState.getQueryText()}}</pre>\n        <h2>Query result</h2>\n        <pre>{{resultInfo}}</pre>\n        <div *ngIf=\"showTable\"><button (click)=\"showTable=false\">hide results</button></div>\n        <div *ngIf=\"!showTable\"><button (click)=\"showTable=true\">show results</button></div>\n        <div *ngIf=\"showTable\">\n            <div>Show \n                <select name=\"numItems\" (change)=\"onSelectNumItems($event)\">\n                    <option value=\"10\">10</option>\n                    <option value=\"100\">100</option>\n                    <option value=\"0\">all</option>\n                </select>\n                results per page.\n            </div>\n            <div>\n                <form (ngSubmit)=\"onSelectCols($event)\">\n                    Columns:\n                    <span *ngFor=\"let col of allColumns\">\n                        <input type=\"checkbox\" name=\"col{{col.name}}\" value=\"{{col.name}}\" [(ngModel)]=\"col.show\">{{col.name}}\n                    </span> \n                    <button type=\"submit\">change columns</button>\n                </form>\n            </div>\n            <pagination *ngIf=\"config.paging\" class=\"pagination-sm\"\n                        [(ngModel)]=\"currentPage\"\n                        [totalItems]=\"length\"\n                        [itemsPerPage]=\"itemsPerPage\"\n                        [maxSize]=\"maxSize\"\n                        [boundaryLinks]=\"true\"\n                        [rotate]=\"false\"\n                        (pageChanged)=\"onChangeTable(config, $event)\"\n                        (numPages)=\"numPages = $event\">\n            </pagination>\n            <ng-table \n                     [config]=\"config\"\n                     (tableChanged)=\"onChangeTable($event)\"\n                     [rows]=\"rows\" [columns]=\"columns\">\n            </ng-table>\n        </div>\n    </div>\n    <div *ngIf=\"!(queryState?.numResults > 0)\">\n        <h2>No results found</h2>\n    </div>\n       ",
+            inputs: ['queryState', 'resultInfo']
+        }), 
+        __metadata('design:paramtypes', [])
+    ], QueryResultTableComponent);
+    return QueryResultTableComponent;
+}());
+exports.QueryResultTableComponent = QueryResultTableComponent;
+//# sourceMappingURL=query-result-table.component.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-result-table.component.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"query-result-table.component.js","sourceRoot":"","sources":["query-result-table.component.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
--- a/src/app/query-result-table.component.ts	Mon Mar 20 18:50:31 2017 +0100
+++ b/src/app/query-result-table.component.ts	Wed Mar 29 17:19:12 2017 +0200
@@ -1,14 +1,11 @@
 import {Component, OnInit} from '@angular/core';
 
-//import {NG_TABLE_DIRECTIVES} from 'ng2-table/ng2-table';
-//import {PAGINATION_DIRECTIVES} from 'ng2-bootstrap/ng2-bootstrap';
-
 import {QueryState} from './query-state';
 
 @Component({
     selector: 'query-result',
     template: `
-    <div *ngIf="queryState?.results">
+    <div *ngIf="queryState?.numResults > 0">
         <span>Cypher query:</span>
         <pre>{{queryState.getQueryText()}}</pre>
         <h2>Query result</h2>
@@ -17,7 +14,7 @@
         <div *ngIf="!showTable"><button (click)="showTable=true">show results</button></div>
         <div *ngIf="showTable">
             <div>Show 
-                <select (change)="onSelectNumItems($event)">
+                <select name="numItems" (change)="onSelectNumItems($event)">
                     <option value="10">10</option>
                     <option value="100">100</option>
                     <option value="0">all</option>
@@ -27,16 +24,14 @@
             <div>
                 <form (ngSubmit)="onSelectCols($event)">
                     Columns:
-                    <span *ngFor=" let col of allColumns">
-                        <input type="checkbox" value="{{col.name}}" [(ngModel)]="col.show">{{col.name}}
+                    <span *ngFor="let col of allColumns">
+                        <input type="checkbox" name="col{{col.name}}" value="{{col.name}}" [(ngModel)]="col.show">{{col.name}}
                     </span> 
                     <button type="submit">change columns</button>
                 </form>
             </div>
-            <div *ngIf="config.paging">Page {{page}} of {{numPages}}</div>
-            <pagination *ngIf="config.paging"
-                        class="pagination-sm"
-                        [(ngModel)]="page"
+            <pagination *ngIf="config.paging" class="pagination-sm"
+                        [(ngModel)]="currentPage"
                         [totalItems]="length"
                         [itemsPerPage]="itemsPerPage"
                         [maxSize]="maxSize"
@@ -46,15 +41,17 @@
                         (numPages)="numPages = $event">
             </pagination>
             <ng-table 
-                     [config]="config.sorting"
+                     [config]="config"
                      (tableChanged)="onChangeTable($event)"
                      [rows]="rows" [columns]="columns">
             </ng-table>
         </div>
     </div>
-        `,
-    inputs: ['queryState', 'resultInfo'],
-//    directives: [NG_TABLE_DIRECTIVES, PAGINATION_DIRECTIVES]
+    <div *ngIf="!(queryState?.numResults > 0)">
+        <h2>No results found</h2>
+    </div>
+       `,
+    inputs: ['queryState', 'resultInfo']
 })
 
 export class QueryResultTableComponent implements OnInit { 
@@ -69,7 +66,7 @@
     
     public rows: Array<any>;
      
-    public page: number = 1;
+    public currentPage: number = 1;
     public itemsPerPage: number = 10;
     public maxSize: number = 5;
     public numPages: number = 1;
@@ -84,12 +81,14 @@
     ngOnChanges(changes: any) {
         console.debug("result table changed! changes=", changes);
         this.data = this.queryState.results;
-        this.allColumns = this.queryState.resultColumns;
-        this.columns = this.allColumns.filter(c => c.show);
-        this.config.sorting = this.columns;
-        this.config.paging = {'page': this.page, 'itemsPerPage': this.itemsPerPage};
-        this.showTable = (this.data.length < 1000);
-        this.onChangeTable(this.config);
+        if (this.data.length > 0) {
+            this.allColumns = this.queryState.resultColumns;
+            this.columns = this.allColumns.filter(c => c.show);
+            this.config.sorting = this.columns;
+            this.config.paging = {'page': this.currentPage, 'itemsPerPage': this.itemsPerPage};
+            this.showTable = (this.data.length < 1000);
+            this.onChangeTable(this.config);
+        }
     }
     
     ngOnInit() {
@@ -106,7 +105,7 @@
             this.itemsPerPage = num;
         }
         // update something
-        this.config.paging = {'page': this.page, 'itemsPerPage': this.itemsPerPage};
+        this.config.paging = {'page': this.currentPage, 'itemsPerPage': this.itemsPerPage};
         this.onChangeTable(this.config);
     }
     
@@ -116,7 +115,7 @@
         this.config.sorting = this.columns;
     }
     
-    changePage(page:any, data:Array<any> = this.data):Array<any> {
+    changePage(page: any, data: Array<any> = this.data): Array<any> {
         let start = (page.page - 1) * page.itemsPerPage;
         let end = page.itemsPerPage > -1 ? (start + page.itemsPerPage) : data.length;
         return data.slice(start, end);
@@ -163,8 +162,8 @@
             Object.assign(this.config.sorting, config.sorting);
             // changing sorting resets page
             if (page == null) {
-                this.page = 1;
-                page = {'page': this.page, 'itemsPerPage': this.itemsPerPage};
+                this.currentPage = 1;
+                page = {'page': this.currentPage, 'itemsPerPage': this.itemsPerPage};
             }
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-result.component.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,27 @@
+"use strict";
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var core_1 = require('@angular/core');
+var QueryResultComponent = (function () {
+    function QueryResultComponent() {
+    }
+    QueryResultComponent = __decorate([
+        core_1.Component({
+            selector: 'query-result',
+            template: "\n        <div *ngIf=\"queryState\">\n          <span>Cypher query:</span>\n          <pre>{{queryState.resultCypherQuery}}</pre>\n          <p>Query results ({{queryState.resultInfo}}):</p>\n          <table border=\"1\">\n            <tr>\n              <ng-container *ngIf=\"queryState.resultTypes=='node' && queryState.resultColumns\">\n                <th *ngFor=\"let col of queryState.resultColumns\">{{col?col.title:col}}</th>\n              </ng-container>\n            </tr>\n            <tr class=\"resultRow\" *ngFor=\"let row of queryState.results\"\n                [rowData]=\"row\" [rowType]=\"queryState.resultTypes\"\n                [columns]=\"queryState.resultColumns\">\n            </tr>\n          </table>\n        </div>\n        ",
+            //directives: [QueryResultRowComponent],
+            inputs: ['queryState', 'resultInfo']
+        }), 
+        __metadata('design:paramtypes', [])
+    ], QueryResultComponent);
+    return QueryResultComponent;
+}());
+exports.QueryResultComponent = QueryResultComponent;
+//# sourceMappingURL=query-result.component.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-result.component.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"query-result.component.js","sourceRoot":"","sources":["query-result.component.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,qBAAgC,eAAe,CAAC,CAAA;AA8BhD;IAAA;IAKA,CAAC;IA7BD;QAAC,gBAAS,CAAC;YACP,QAAQ,EAAE,cAAc;YACxB,QAAQ,EAAE,svBAiBL;YACL,wCAAwC;YACxC,MAAM,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;SACvC,CAAC;;4BAAA;IAOF,2BAAC;AAAD,CAAC,AALD,IAKC;AALY,4BAAoB,uBAKhC,CAAA"}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-select.component.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,211 @@
+"use strict";
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var core_1 = require('@angular/core');
+var query_step_1 = require('./query-step');
+var query_service_1 = require('./query.service');
+var normalization_service_1 = require('./normalization.service');
+var ismi_relation_types_1 = require('./ismi-relation-types');
+var QuerySelectComponent = (function () {
+    function QuerySelectComponent(_queryService, _normService) {
+        this._queryService = _queryService;
+        this._normService = _normService;
+        // output queryChanged
+        this.queryChanged = new core_1.EventEmitter();
+    }
+    QuerySelectComponent.prototype.ngOnInit = function () {
+        this.setup();
+    };
+    QuerySelectComponent.prototype.setup = function () {
+        console.log("query-select setup step=", this.queryStep);
+        var step = this._queryService.state.steps[this.index]; // i-1?
+        if (step != null) {
+            this.setQueryStep(step);
+        }
+    };
+    QuerySelectComponent.prototype.getQueryModes = function () {
+        this.queryModes = this._queryService.getQueryModes(this.index);
+        return this.queryModes;
+    };
+    QuerySelectComponent.prototype.onSelectMode = function (event) {
+        var selected = event.target.value;
+        this.selectedMode = this.queryModes.find(function (mode) { return mode.id === selected; });
+        this.queryOptions = this._queryService.getQueryOptions(this.selectedMode);
+    };
+    QuerySelectComponent.prototype.onSelectOption = function (event) {
+        var selected = event.target.value;
+        console.debug("selected option:", selected);
+        this.selectedOption = selected;
+        this.onSubmit();
+    };
+    QuerySelectComponent.prototype.onSubmit = function () {
+        console.debug("Submit! selectedMode=", this.selectedMode, " selectedOption=", this.selectedOption, " queryInput=", this.queryInput);
+        var step = this.getQueryStep();
+        /*
+         * set step and submit change event
+         */
+        if (step != null) {
+            this._queryService.setQueryStep(this.index, step);
+            this.queryChanged.emit(this._queryService.getState());
+        }
+        return false;
+    };
+    /**
+     * Returns QueryStep from current form state.
+     */
+    QuerySelectComponent.prototype.getQueryStep = function () {
+        var _this = this;
+        var step = null;
+        if (this.selectedMode.id === 'type_is') {
+            /*
+             * type_is
+             */
+            var opt = this.selectedOption;
+            if (opt) {
+                step = new query_step_1.QueryStep(this.selectedMode, { 'objectType': opt });
+            }
+        }
+        else if (this.selectedMode.id === 'relation_is') {
+            /*
+             * relation_is
+             */
+            var opt = this.selectedOption;
+            if (opt) {
+                var rel = ismi_relation_types_1.getRelationByName(opt);
+                step = new query_step_1.QueryStep(this.selectedMode, { 'relationType': rel });
+            }
+        }
+        else if (this.selectedMode.id === 'id_is') {
+            /*
+             * id is
+             */
+            var val = this.queryInput;
+            if (val) {
+                step = new query_step_1.QueryStep(this.selectedMode, { 'value': val });
+            }
+        }
+        else if (this.selectedMode.id === 'att_contains') {
+            /*
+             * att_contains
+             */
+            var att = this.selectedOption;
+            var val = this.queryInput;
+            if (att && val) {
+                step = new query_step_1.QueryStep(this.selectedMode, { 'attribute': att, 'value': val });
+            }
+        }
+        else if (this.selectedMode.id === 'att_num_range') {
+            /*
+             * att_num_range
+             */
+            var att = this.selectedOption;
+            var nlo = this.queryInput;
+            var nhi = this.queryInput2;
+            if (att && nlo && nhi) {
+                step = new query_step_1.QueryStep(this.selectedMode, { 'attribute': att, 'numLo': nlo, 'numHi': nhi });
+            }
+        }
+        else if (this.selectedMode.id === 'att_contains_norm') {
+            /*
+             * att_contains_norm
+             *
+             * calls normalization service and submits event in callback
+             */
+            var att_1 = this.selectedOption;
+            var val_1 = this.queryInput;
+            if (att_1 && val_1) {
+                // run search term through normalizer 
+                this._normService.fetchArabicTranslitNormalizedString(val_1)
+                    .subscribe(function (data) {
+                    console.debug("openmind norm data=", data);
+                    step = new query_step_1.QueryStep(_this.selectedMode, { 'attribute': att_1, 'value': val_1, 'normValue': data.normalized_text });
+                    _this._queryService.setQueryStep(_this.index, step);
+                    // query has changed now
+                    _this.queryChanged.emit(_this._queryService.getState());
+                }, function (err) { return console.error("openmind norm error=", err); }, function () { return console.debug("openmind norm query Complete"); });
+                // query has not been set yet (gets set in callback)
+                return null;
+            }
+        }
+        return step;
+    };
+    /**
+     * Sets form state from given QueryStep.
+     */
+    QuerySelectComponent.prototype.setQueryStep = function (step) {
+        var mode = step.mode;
+        this.selectedMode = mode;
+        if (mode.id === 'id_is') {
+            /*
+         * id_is
+         */
+            this.queryInput = step.params.value;
+        }
+        else if (mode.id === 'type_is') {
+            /*
+             * type_is
+             */
+            var name_1 = step.params.objectType;
+            this.queryOptions = [name_1];
+            this.selectedOption = name_1;
+        }
+        else if (this.selectedMode.id === 'relation_is') {
+            /*
+             * relation_is
+             */
+            var name_2 = step.params.relationType.name;
+            var rel = ismi_relation_types_1.getRelationByName(name_2);
+            this.queryOptions = [rel];
+            this.selectedOption = name_2;
+        }
+        else if (this.selectedMode.id === 'att_contains') {
+            /*
+             * att_contains
+             */
+            var name_3 = step.params.attribute;
+            this.queryOptions = [name_3];
+            this.selectedOption = name_3;
+            this.queryInput = step.params.value;
+        }
+        else if (this.selectedMode.id === 'att_num_range') {
+            /*
+             * att_num_range
+             */
+            var name_4 = step.params.attribute;
+            this.queryOptions = [name_4];
+            this.selectedOption = name_4;
+            this.queryInput = step.params.numLo;
+            this.queryInput2 = step.params.numHi;
+        }
+        else if (this.selectedMode.id === 'att_contains_norm') {
+            /*
+             * att_contains_norm
+             */
+            var name_5 = step.params.attribute;
+            this.queryOptions = [name_5];
+            this.selectedOption = name_5;
+            this.queryInput = step.params.value;
+        }
+        // TODO: implement other modes
+        this.resultInfo = step.resultInfo;
+    };
+    QuerySelectComponent = __decorate([
+        core_1.Component({
+            selector: 'query-select',
+            template: "\n<p *ngIf=\"resultInfo\">&nbsp;&nbsp;&nbsp;result: {{resultInfo}}</p>\n<div>\n    <form (ngSubmit)=\"onSubmit()\">\n        <select name=\"mode\" (change)=\"onSelectMode($event)\">\n            <option></option>\n            <option *ngFor=\"let mode of getQueryModes()\" \n                [selected]=\"mode.id==selectedMode?.id\" [value]=\"mode.id\">\n                {{mode.label}}\n            </option>\n        </select>\n\n        <span *ngIf=\"selectedMode?.id=='type_is'\">\n            <select name=\"option\" *ngIf=\"queryOptions\" [ngModel]=\"selectedOption\" (change)=\"onSelectOption($event)\">\n                <option></option>\n                <option *ngFor=\"let option of queryOptions\" [value]=\"option\">\n                    {{option}}\n                </option>\n            </select>\n        </span>\n\n        <span *ngIf=\"selectedMode?.id=='relation_is'\">\n            <select name=\"option\" *ngIf=\"queryOptions\" [ngModel]=\"selectedOption\" (change)=\"onSelectOption($event)\">\n                <option></option>\n                <option *ngFor=\"let option of queryOptions\" [value]=\"option.getName()\">\n                    {{option.getLabel()}}\n                </option>\n            </select>\n        </span>\n\n        <span *ngIf=\"selectedMode?.id=='att_contains' || selectedMode?.id=='att_contains_norm'\">\n            <select name=\"option\" [ngModel]=\"selectedOption\" (change)=\"selectedOption=$event.target.value\">\n                <option></option>\n                <option *ngFor=\"let option of queryOptions\" [value]=\"option\">\n                    {{option}}\n                </option>\n            </select>\n            <span>contains</span>\n            <input type=\"text\" name=\"value\" [(ngModel)]=\"queryInput\"/>\n        </span>\n\n        <span *ngIf=\"selectedMode?.id=='att_num_range'\">\n            <select name=\"option\" [ngModel]=\"selectedOption\" (change)=\"selectedOption=$event.target.value\">\n                <option></option>\n                <option *ngFor=\"let option of queryOptions\" [value]=\"option\">\n                    {{option}}\n                </option>\n            </select>\n            <span>is between</span>\n            <input type=\"text\" name=\"value1\" [(ngModel)]=\"queryInput\"/>\n            <span>and</span>\n            <input type=\"text\" name=\"value2\" [(ngModel)]=\"queryInput2\"/>\n        </span>\n\n        <span *ngIf=\"selectedMode?.id=='id_is'\">\n            <input type=\"text\" name=\"value\" [(ngModel)]=\"queryInput\"/>\n        </span>\n\n        <button type=\"submit\">Submit</button>\n    </form>\n</div>\n        ",
+            inputs: ['queryStep', 'index'],
+            outputs: ['queryChanged']
+        }), 
+        __metadata('design:paramtypes', [query_service_1.QueryService, normalization_service_1.NormalizationService])
+    ], QuerySelectComponent);
+    return QuerySelectComponent;
+}());
+exports.QuerySelectComponent = QuerySelectComponent;
+//# sourceMappingURL=query-select.component.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-select.component.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"query-select.component.js","sourceRoot":"","sources":["query-select.component.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
--- a/src/app/query-select.component.ts	Mon Mar 20 18:50:31 2017 +0100
+++ b/src/app/query-select.component.ts	Wed Mar 29 17:19:12 2017 +0200
@@ -17,7 +17,8 @@
     <form (ngSubmit)="onSubmit()">
         <select name="mode" (change)="onSelectMode($event)">
             <option></option>
-            <option *ngFor="let mode of getQueryModes()" [value]="mode.id">
+            <option *ngFor="let mode of getQueryModes()" 
+                [selected]="mode.id==selectedMode?.id" [value]="mode.id">
                 {{mode.label}}
             </option>
         </select>
@@ -80,9 +81,9 @@
     public queryStep: string;
     public index: number;
     public resultInfo: string;
-    public queryModes: QueryMode[];
+    public queryModes: Array<QueryMode>;
     public selectedMode: QueryMode;
-    public queryOptions: string[];
+    public queryOptions: any[];
     public selectedOption: string;
     public queryInput: string;
     public queryInput2: string;
@@ -98,9 +99,9 @@
     
     setup() {
         console.log("query-select setup step=", this.queryStep);
-        var step = this._queryService.state.steps[this.index-1];
+        var step = this._queryService.state.steps[this.index]; // i-1?
         if (step != null) {
-            this.resultInfo = step.resultInfo;
+            this.setQueryStep(step);
         }
     }
     
@@ -124,8 +125,26 @@
     
     onSubmit() {
         console.debug("Submit! selectedMode=", this.selectedMode, " selectedOption=", this.selectedOption, " queryInput=", this.queryInput);
-        var step: QueryStep;
-        if (this.selectedMode.id == 'type_is') {
+    
+        let step = this.getQueryStep();
+
+        /*
+         * set step and submit change event
+         */
+        if (step != null) {
+            this._queryService.setQueryStep(this.index, step);
+            this.queryChanged.emit(this._queryService.getState());
+        }
+        return false;
+    }
+    
+    /**
+     * Returns QueryStep from current form state.
+     */
+    getQueryStep(): QueryStep {
+        let step: QueryStep = null;
+
+        if (this.selectedMode.id === 'type_is') {
             /*
              * type_is
              */
@@ -133,7 +152,7 @@
             if (opt) {
                 step = new QueryStep(this.selectedMode, {'objectType': opt});
             }
-        } else if (this.selectedMode.id == 'relation_is') {
+        } else if (this.selectedMode.id === 'relation_is') {
             /*
              * relation_is
              */
@@ -142,7 +161,7 @@
                 let rel = getRelationByName(opt);
                 step = new QueryStep(this.selectedMode, {'relationType': rel});
             }
-        } else if (this.selectedMode.id == 'id_is') {
+        } else if (this.selectedMode.id === 'id_is') {
             /*
              * id is
              */
@@ -150,7 +169,7 @@
             if (val) {
                 step = new QueryStep(this.selectedMode, {'value': val});
             }
-        } else if (this.selectedMode.id == 'att_contains') {
+        } else if (this.selectedMode.id === 'att_contains') {
             /*
              * att_contains
              */
@@ -159,7 +178,7 @@
             if (att && val) {
                 step = new QueryStep(this.selectedMode, {'attribute': att, 'value': val});
             }
-        } else if (this.selectedMode.id == 'att_num_range') {
+        } else if (this.selectedMode.id === 'att_num_range') {
             /*
              * att_num_range
              */
@@ -169,7 +188,7 @@
             if (att && nlo && nhi) {
                 step = new QueryStep(this.selectedMode, {'attribute': att, 'numLo': nlo, 'numHi': nhi});
             }
-        } else if (this.selectedMode.id == 'att_contains_norm') {
+        } else if (this.selectedMode.id === 'att_contains_norm') {
             /*
              * att_contains_norm
              * 
@@ -191,17 +210,71 @@
                     err => console.error("openmind norm error=", err),
                     () => console.debug("openmind norm query Complete")
                 );
-                // query has not been set yet
-                return;
+                // query has not been set yet (gets set in callback)
+                return null;
            }
         }
-
-        /*
-         * set step and submit change event
+        return step;
+    }
+    
+    /**
+     * Sets form state from given QueryStep.
+     */
+    setQueryStep(step: QueryStep) {
+        let mode = step.mode;
+        this.selectedMode = mode;
+        if (mode.id === 'id_is') {
+            /*
+         * id_is
          */
-        if (step != null) {
-            this._queryService.setQueryStep(this.index, step);
-            this.queryChanged.emit(this._queryService.getState());
+            this.queryInput = step.params.value;
+            
+        } else if (mode.id === 'type_is') {
+            /*
+             * type_is
+             */
+            let name = step.params.objectType;
+            this.queryOptions = [name];
+            this.selectedOption = name;
+            
+        } else if (this.selectedMode.id === 'relation_is') {
+            /*
+             * relation_is
+             */
+            let name = step.params.relationType.name
+            let rel = getRelationByName(name);
+            this.queryOptions = [rel];
+            this.selectedOption = name;
+            
+        } else if (this.selectedMode.id === 'att_contains') {
+            /*
+             * att_contains
+             */
+            let name = step.params.attribute
+            this.queryOptions = [name];
+            this.selectedOption = name;
+            this.queryInput = step.params.value;
+            
+        } else if (this.selectedMode.id === 'att_num_range') {
+            /*
+             * att_num_range
+             */
+            let name = step.params.attribute
+            this.queryOptions = [name];
+            this.selectedOption = name;
+            this.queryInput = step.params.numLo;
+            this.queryInput2 = step.params.numHi;
+            
+        } else if (this.selectedMode.id === 'att_contains_norm') {
+            /*
+             * att_contains_norm
+             */
+            let name = step.params.attribute
+            this.queryOptions = [name];
+            this.selectedOption = name;
+            this.queryInput = step.params.value;
         }
+        // TODO: implement other modes
+        this.resultInfo = step.resultInfo;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-state.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,71 @@
+"use strict";
+var query_step_1 = require('./query-step');
+var query_mode_1 = require('./query-mode');
+var QueryState = (function () {
+    function QueryState() {
+        this.steps = [];
+    }
+    /**
+     * Sets the query state from a string.
+     */
+    QueryState.prototype.setStateFromString = function (newStateString) {
+        try {
+            // state string is json
+            var newState = JSON.parse(newStateString);
+            // state should be list of steps
+            if (!Array.isArray(newState))
+                return;
+            var newSteps_1 = [];
+            newState.forEach(function (elem) {
+                // step is an array [mode, params]
+                if (!Array.isArray(elem))
+                    return;
+                var mode = elem[0];
+                // get QueryMode object
+                var qm = query_mode_1.getQueryModeById(mode);
+                var params = elem[1];
+                if (qm != null && params != null) {
+                    // construct QueryStep
+                    var qs = new query_step_1.QueryStep(qm, params);
+                    newSteps_1.push(qs);
+                }
+            });
+            if (newSteps_1.length > 0) {
+                // set new state
+                this.steps = newSteps_1;
+            }
+        }
+        catch (e) {
+            console.error("Unable to set state from string: " + newStateString);
+        }
+    };
+    QueryState.prototype.getNumSteps = function () {
+        return this.steps.length;
+    };
+    /**
+     * Returns the current query state as a string.
+     */
+    QueryState.prototype.getStateAsString = function () {
+        var stateList = this.steps.map(function (qs) { return [qs.mode.id, qs.params]; });
+        var stateStr = JSON.stringify(stateList);
+        return stateStr;
+    };
+    /**
+     * Returns the cypher query as text for display.
+     */
+    QueryState.prototype.getQueryText = function () {
+        var text = this.resultCypherQuery;
+        var hasParams = false;
+        for (var k in this.cypherQueryParams) {
+            if (!hasParams) {
+                hasParams = true;
+                text += '\n';
+            }
+            text += "[" + k + "='" + this.cypherQueryParams[k] + "'] ";
+        }
+        return text;
+    };
+    return QueryState;
+}());
+exports.QueryState = QueryState;
+//# sourceMappingURL=query-state.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-state.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"query-state.js","sourceRoot":"","sources":["query-state.ts"],"names":[],"mappings":";AAAA,2BAAwB,cAAc,CAAC,CAAA;AAEvC,2BAA0C,cAAc,CAAC,CAAA;AAEzD;IAAA;QACW,UAAK,GAAgB,EAAE,CAAC;IA8EnC,CAAC;IA5DG;;OAEG;IACH,uCAAkB,GAAlB,UAAmB,cAAsB;QACrC,IAAI,CAAC;YACD,uBAAuB;YACvB,IAAI,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAC1C,gCAAgC;YAChC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAC,MAAM,CAAC;YACrC,IAAI,UAAQ,GAAgB,EAAE,CAAC;YAC/B,QAAQ,CAAC,OAAO,CAAC,UAAC,IAAI;gBAClB,kCAAkC;gBAClC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBAAC,MAAM,CAAC;gBACjC,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;gBACnB,uBAAuB;gBACvB,IAAI,EAAE,GAAc,6BAAgB,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;gBACrB,EAAE,CAAC,CAAC,EAAE,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC;oBAC/B,sBAAsB;oBACtB,IAAI,EAAE,GAAG,IAAI,sBAAS,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;oBACnC,UAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACtB,CAAC;YACL,CAAC,CAAC,CAAC;YACH,EAAE,CAAC,CAAC,UAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;gBACtB,gBAAgB;gBAChB,IAAI,CAAC,KAAK,GAAG,UAAQ,CAAC;YAC1B,CAAC;QACL,CAAE;QAAA,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,mCAAmC,GAAC,cAAc,CAAC,CAAC;QACtE,CAAC;IACL,CAAC;IAED,gCAAW,GAAX;QACI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,qCAAgB,GAAhB;QACI,IAAI,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAC,EAAE,IAAK,OAAA,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,EAAvB,CAAuB,CAAC,CAAC;QAChE,IAAI,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,QAAQ,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,iCAAY,GAAZ;QACI,IAAI,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC;QAClC,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;YACnC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;gBACb,SAAS,GAAG,IAAI,CAAC;gBACjB,IAAI,IAAI,IAAI,CAAC;YACjB,CAAC;YACD,IAAI,IAAI,MAAI,CAAC,UAAK,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAK,CAAC;QACrD,CAAC;QACD,MAAM,CAAC,IAAI,CAAC;IAChB,CAAC;IACL,iBAAC;AAAD,CAAC,AA/ED,IA+EC;AA/EY,kBAAU,aA+EtB,CAAA"}
\ No newline at end of file
--- a/src/app/query-state.ts	Mon Mar 20 18:50:31 2017 +0100
+++ b/src/app/query-state.ts	Wed Mar 29 17:19:12 2017 +0200
@@ -1,5 +1,6 @@
 import {QueryStep} from './query-step';
 import {ResultType} from './result-type';
+import {QueryMode, getQueryModeById} from './query-mode';
 
 export class QueryState {
     public steps: QueryStep[] = [];
@@ -15,10 +16,59 @@
     public resultTypes: string;
     public resultType: ResultType;
     public resultInfo: string;
-    public resultAttributes: string[];    
+    public resultAttributes: string[];
     public resultRelations: any[];
     public resultColumns: any[];
     
+
+    /**
+     * Sets the query state from a string.
+     */
+    setStateFromString(newStateString: string) {
+        try {
+            // state string is json
+            let newState = JSON.parse(newStateString);
+            // state should be list of steps
+            if (!Array.isArray(newState)) return;
+            let newSteps: QueryStep[] = [];
+            newState.forEach((elem) => {
+                // step is an array [mode, params]
+                if (!Array.isArray(elem)) return;
+                let mode = elem[0];
+                // get QueryMode object
+                let qm: QueryMode = getQueryModeById(mode);
+                let params = elem[1];
+                if (qm != null && params != null) {
+                    // construct QueryStep
+                    let qs = new QueryStep(qm, params);
+                    newSteps.push(qs);
+                }
+            });
+            if (newSteps.length > 0) {
+                // set new state
+                this.steps = newSteps;
+            }
+        } catch (e) {
+            console.error("Unable to set state from string: "+newStateString);
+        }
+    }
+
+    getNumSteps() {
+        return this.steps.length;
+    }
+    
+    /**
+     * Returns the current query state as a string.
+     */
+    getStateAsString(): string {
+        let stateList = this.steps.map((qs) => [qs.mode.id, qs.params]);
+        let stateStr = JSON.stringify(stateList);
+        return stateStr;
+    }
+
+    /**
+     * Returns the cypher query as text for display.
+     */
     getQueryText() {
         let text = this.resultCypherQuery;
         let hasParams = false;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-step.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,10 @@
+"use strict";
+var QueryStep = (function () {
+    function QueryStep(mode, params) {
+        this.mode = mode;
+        this.params = params;
+    }
+    return QueryStep;
+}());
+exports.QueryStep = QueryStep;
+//# sourceMappingURL=query-step.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query-step.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"query-step.js","sourceRoot":"","sources":["query-step.ts"],"names":[],"mappings":";AAEA;IAOI,mBAAa,IAAe,EAAE,MAAW;QACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IACL,gBAAC;AAAD,CAAC,AAXD,IAWC;AAXY,iBAAS,YAWrB,CAAA"}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query.service.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,359 @@
+"use strict";
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var core_1 = require('@angular/core');
+var http_1 = require('@angular/http');
+require('rxjs/Rx'); // import all RxJS operators
+//import 'rxjs/add/operator/map';
+var app_config_1 = require('./app-config');
+var query_mode_1 = require('./query-mode');
+var query_state_1 = require('./query-state');
+var result_type_1 = require('./result-type');
+var ismi_result_types_1 = require('./ismi-result-types');
+var ismi_relation_types_1 = require('./ismi-relation-types');
+var QueryService = (function () {
+    function QueryService(_http) {
+        this._http = _http;
+        this.typeAttribute = '_type';
+        this.excludedAttributes = {};
+        // init query state
+        this.state = new query_state_1.QueryState();
+    }
+    QueryService.prototype.setup = function (newStateString) {
+        // get list of object types
+        this.setupObjectTypes();
+        // get state from string
+        if (newStateString) {
+            this.state.setStateFromString(newStateString);
+        }
+    };
+    QueryService.prototype.getState = function () {
+        return this.state;
+    };
+    QueryService.prototype.getQueryModes = function (index) {
+        if (index == 0) {
+            return query_mode_1.FIRST_QUERY_MODES;
+        }
+        else {
+            return query_mode_1.QUERY_MODES;
+        }
+    };
+    /**
+     * return the first set of options for the given query mode.
+     */
+    QueryService.prototype.getQueryOptions = function (queryMode) {
+        var options = [];
+        if (queryMode == null)
+            return options;
+        if (queryMode.id === 'type_is') {
+            options = this.objectTypes;
+        }
+        else if (queryMode.id === 'relation_is') {
+            options = this.state.resultRelations;
+        }
+        else if (queryMode.id === 'att_contains') {
+            options = this.filterAttributes(this.state.resultAttributes);
+        }
+        else if (queryMode.id === 'att_contains_norm') {
+            options = this.filterAttributes(this.state.resultAttributes, true);
+        }
+        else if (queryMode.id === 'att_num_range') {
+            options = this.filterAttributes(this.state.resultAttributes);
+        }
+        console.debug("getQueryOptions returns: ", options);
+        return options;
+    };
+    /**
+     * fetch all object types from Neo4j and store in this.objectTypes.
+     */
+    QueryService.prototype.setupObjectTypes = function () {
+        var _this = this;
+        var query = "MATCH (n) WITH DISTINCT labels(n) AS labels\n                UNWIND labels AS label \n                RETURN DISTINCT label ORDER BY label";
+        var res = this.fetchCypherResults([query]);
+        res.subscribe(function (data) {
+            console.debug("neo4j data=", data);
+            _this.objectTypes = data.results[0].data
+                .map(function (elem) { return elem.row[0]; })
+                .filter(function (elem) { return elem[0] != "_"; });
+            console.debug("object types=", _this.objectTypes);
+        }, function (err) { return console.error("neo4j error=", err); }, function () { return console.debug('neo4j query Complete'); });
+    };
+    /**
+     * Set the query step at index.
+     */
+    QueryService.prototype.setQueryStep = function (index, step) {
+        this.state.steps[index] = step;
+    };
+    /**
+     * Create the cypher queries for the current query state.
+     *
+     * Updates the queries for results, attributes and relations.
+     */
+    QueryService.prototype.createCypherQuery = function () {
+        var queryMatch = '';
+        var queryWhere = '';
+        var queryReturn = '';
+        var queryParams = {};
+        var resultQuery = '';
+        var attributesQuery = '';
+        var outRelsQuery = '';
+        var inRelsQuery = '';
+        var returnType = '';
+        var nIdx = 1;
+        this.state.steps.forEach(function (step, stepIdx) {
+            var mode = step.mode.id;
+            var params = step.params;
+            /*
+             * step: object type is
+             */
+            if (mode === 'type_is') {
+                queryMatch = "MATCH (n" + nIdx + ":" + params.objectType + ")";
+                queryWhere = '';
+                queryReturn = "RETURN n" + nIdx;
+                returnType = 'node';
+            }
+            /*
+             * step: object id is
+             */
+            if (mode === 'id_is') {
+                if (!queryMatch) {
+                    // first step - use match clause
+                    queryMatch = "MATCH (n" + nIdx + " {ismi_id: {att_val" + stepIdx + "}})";
+                    queryParams[("att_val" + stepIdx)] = parseInt(params.value, 10);
+                    queryWhere = '';
+                    queryReturn = "RETURN n" + nIdx;
+                    returnType = 'node';
+                }
+                else {
+                    // use where clause
+                    if (!queryWhere) {
+                        queryWhere = 'WHERE ';
+                    }
+                    else {
+                        queryWhere += ' AND ';
+                    }
+                    queryWhere += "n" + nIdx + ".ismi_id = {att_val" + stepIdx + "}";
+                    queryParams[("att_val" + stepIdx)] = parseInt(params.value, 10);
+                }
+            }
+            /*
+             * step: relation type is
+             */
+            if (mode === 'relation_is') {
+                nIdx += 1;
+                var rel = params.relationType;
+                if (rel.isOutgoing()) {
+                    queryMatch += "-[:`" + rel.getRelType() + "`]->(n" + nIdx + ")";
+                }
+                else {
+                    // inverse relation
+                    queryMatch += "<-[:`" + rel.getRelType() + "`]-(n" + nIdx + ")";
+                }
+                queryReturn = "RETURN DISTINCT n" + nIdx;
+                returnType = 'node';
+            }
+            /*
+             * step: attribute contains(_norm)
+             */
+            if (mode === 'att_contains' || mode === 'att_contains_norm') {
+                if (!queryWhere) {
+                    queryWhere = 'WHERE ';
+                }
+                else {
+                    queryWhere += ' AND ';
+                }
+                if (params.attribute === 'ismi_id') {
+                    // ismi_id is integer
+                    queryWhere += "n" + nIdx + ".ismi_id = {att_val" + stepIdx + "}";
+                    queryParams[("att_val" + stepIdx)] = parseInt(params.value, 10);
+                }
+                else {
+                    if (mode === 'att_contains_norm') {
+                        // match _n_attribute with normValue
+                        queryWhere += "lower(n" + nIdx + "._n_" + params.attribute + ") CONTAINS lower({att_val" + stepIdx + "})";
+                        queryParams[("att_val" + stepIdx)] = params.normValue;
+                    }
+                    else {
+                        queryWhere += "lower(n" + nIdx + "." + params.attribute + ") CONTAINS lower({att_val" + stepIdx + "})";
+                        queryParams[("att_val" + stepIdx)] = params.value;
+                    }
+                }
+            }
+            /*
+             * step: attribute number range
+             */
+            if (mode === 'att_num_range') {
+                if (!queryWhere) {
+                    queryWhere = 'WHERE ';
+                }
+                else {
+                    queryWhere += ' AND ';
+                }
+                queryWhere += ("toint(n" + nIdx + "." + params.attribute + ") >= toint({att_nlo" + stepIdx + "})")
+                    + (" AND toint(n" + nIdx + "." + params.attribute + ") <= toint({att_nhi" + stepIdx + "})");
+                queryParams[("att_nlo" + stepIdx)] = params.numLo;
+                queryParams[("att_nhi" + stepIdx)] = params.numHi;
+            }
+        });
+        // compose query
+        resultQuery = queryMatch + (queryWhere ? '\n' + queryWhere : '') + '\n' + queryReturn;
+        // compose query for attributes of result
+        attributesQuery = queryMatch + ' ' + queryWhere + (" WITH DISTINCT keys(n" + nIdx + ") AS atts")
+            + " UNWIND atts AS att RETURN DISTINCT att ORDER BY att";
+        // compose query for relations of result
+        outRelsQuery = queryMatch + '-[r]->() ' + queryWhere + ' RETURN DISTINCT type(r)';
+        inRelsQuery = queryMatch + '<-[r]-() ' + queryWhere + ' RETURN DISTINCT type(r)';
+        this.state.resultCypherQuery = resultQuery;
+        this.state.cypherQueryParams = queryParams;
+        this.state.attributesCypherQuery = attributesQuery;
+        this.state.outRelsCypherQuery = outRelsQuery;
+        this.state.inRelsCypherQuery = inRelsQuery;
+        this.state.resultTypes = returnType;
+    };
+    /**
+     * Create and run the cypher queries for the current query state.
+     *
+     * Updates the results and nextQuery attributes and relations.
+     */
+    QueryService.prototype.runQuery = function () {
+        var _this = this;
+        this.createCypherQuery();
+        this.state.resultInfo = 'loading...';
+        /*
+         * run query for result table
+         */
+        var queries = [this.state.resultCypherQuery];
+        var params = [this.state.cypherQueryParams];
+        if (this.state.attributesCypherQuery) {
+            queries.push(this.state.attributesCypherQuery);
+            params.push(this.state.cypherQueryParams);
+        }
+        if (this.state.outRelsCypherQuery) {
+            queries.push(this.state.outRelsCypherQuery);
+            params.push(this.state.cypherQueryParams);
+        }
+        if (this.state.inRelsCypherQuery) {
+            queries.push(this.state.inRelsCypherQuery);
+            params.push(this.state.cypherQueryParams);
+        }
+        var res = this.fetchCypherResults(queries, params);
+        res.subscribe(function (data) {
+            console.debug("neo4j result data=", data);
+            var resIdx = 0;
+            /*
+             * results for result table
+             */
+            _this.state.results = data.results[resIdx].data.map(function (elem) { return elem.row[0]; });
+            _this.state.numResults = _this.state.results.length;
+            // count all types
+            var resTypes = {};
+            _this.state.results.forEach(function (r) {
+                var t = r[_this.typeAttribute];
+                if (resTypes[t] == null) {
+                    resTypes[t] = 1;
+                }
+                else {
+                    resTypes[t] += 1;
+                }
+            });
+            var info = '';
+            for (var t in resTypes) {
+                info += t + '(' + resTypes[t] + ') ';
+            }
+            info = info.substr(0, info.length - 1);
+            _this.state.resultInfo = info;
+            // save info also in last step
+            _this.state.steps[_this.state.steps.length - 1].resultInfo = info;
+            /*
+             * results for attribute list
+             */
+            if (_this.state.attributesCypherQuery) {
+                resIdx += 1;
+                var atts = data.results[resIdx].data.map(function (elem) { return elem.row[0]; });
+                _this.state.resultAttributes = atts;
+                // the following assumes only one type in the result
+                for (var t in resTypes) {
+                    _this.state.resultType = result_type_1.getResultType(t, ismi_result_types_1.ISMI_RESULT_TYPES);
+                    break;
+                }
+                _this.state.resultColumns = _this.state.resultType.getColumns(atts);
+            }
+            /*
+             * results for relations list
+             */
+            if (_this.state.outRelsCypherQuery) {
+                // outgoing aka forward relations
+                resIdx += 1;
+                var rels = data.results[resIdx].data.map(function (elem) { return elem.row[0]; })
+                    .filter(function (elem) { return elem[0] != "_"; })
+                    .map(function (elem) { return ismi_relation_types_1.getRelationType(elem, true); });
+                _this.state.resultRelations = rels;
+            }
+            if (_this.state.inRelsCypherQuery) {
+                // incoming aka reverse relations
+                resIdx += 1;
+                var rels = data.results[resIdx].data.map(function (elem) { return elem.row[0]; })
+                    .filter(function (elem) { return elem[0] != "_"; })
+                    .map(function (elem) { return ismi_relation_types_1.getRelationType(elem, false); });
+                _this.state.resultRelations = _this.state.resultRelations.concat(rels);
+            }
+        }, function (err) { return console.error("neo4j result error=", err); }, function () { return console.debug('neo4j result query Complete'); });
+    };
+    QueryService.prototype.filterAttributes = function (attributes, normalized) {
+        var _this = this;
+        if (normalized === void 0) { normalized = false; }
+        var atts = [];
+        if (normalized) {
+            attributes.forEach(function (att) {
+                if (att.substr(0, 3) == "_n_") {
+                    atts.push(att.substr(3));
+                }
+            });
+        }
+        else {
+            atts = attributes.filter(function (elem) { return elem[0] != "_" && !_this.excludedAttributes[elem]; });
+        }
+        return atts;
+    };
+    /**
+     * Run the given queries on the Neo4J server.
+     *
+     * Returns an Observable with the results.
+     */
+    QueryService.prototype.fetchCypherResults = function (queries, params) {
+        if (params === void 0) { params = [{}]; }
+        console.debug("fetching cypher queries: ", queries);
+        var headers = new http_1.Headers();
+        var auth = app_config_1.NEO4J_AUTHENTICATION;
+        headers.append('Authorization', 'Basic ' + btoa(auth.user + ":" + auth.password));
+        headers.append('Content-Type', 'application/json');
+        headers.append('Accept', 'application/json');
+        // put headers in options
+        var opts = { 'headers': headers };
+        // unpack queries into statements
+        var statements = queries.map(function (q, i) {
+            return { 'statement': q, 'parameters': (params[i]) ? params[i] : {} };
+        });
+        // create POST data from query
+        var data = JSON.stringify({ 'statements': statements });
+        // make post request asynchronously
+        var resp = this._http.post(app_config_1.NEO4J_BASE_URL + '/transaction/commit', data, opts)
+            .map(function (res) { return res.json(); });
+        // return Observable
+        return resp;
+    };
+    QueryService = __decorate([
+        core_1.Injectable(), 
+        __metadata('design:paramtypes', [http_1.Http])
+    ], QueryService);
+    return QueryService;
+}());
+exports.QueryService = QueryService;
+//# sourceMappingURL=query.service.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/query.service.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"query.service.js","sourceRoot":"","sources":["query.service.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
--- a/src/app/query.service.ts	Mon Mar 20 18:50:31 2017 +0100
+++ b/src/app/query.service.ts	Wed Mar 29 17:19:12 2017 +0200
@@ -25,8 +25,13 @@
         this.state = new QueryState();
     }
     
-    setup() {
+    setup(newStateString: string) {
+        // get list of object types
         this.setupObjectTypes();
+        // get state from string
+        if (newStateString) {
+            this.state.setStateFromString(newStateString);
+        }
     }
     
     getState() {
@@ -74,7 +79,9 @@
         res.subscribe(
             data => {
                 console.debug("neo4j data=", data);
-                this.objectTypes = data.results[0].data.map(elem => elem.row[0]).filter(elem => elem[0] != "_");
+                this.objectTypes = data.results[0].data
+                    .map(elem => elem.row[0])
+                    .filter(elem => elem[0] != "_");
                 console.debug("object types=", this.objectTypes);
                 },
             err => console.error("neo4j error=", err),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/relation-type.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,44 @@
+"use strict";
+exports.invLabelPrefix = '<- ';
+exports.invNamePrefix = '-';
+exports.rawLabelPrefix = '(';
+exports.rawLabelPostfix = ')';
+var RelationType = (function () {
+    function RelationType(relType, isOutgoing, label) {
+        this.outgoing = isOutgoing;
+        this.relType = relType;
+        if (isOutgoing) {
+            this.name = relType;
+        }
+        else {
+            this.name = exports.invNamePrefix + relType;
+        }
+        if (label != null) {
+            this.label = label;
+        }
+        else {
+            // create label using name
+            if (isOutgoing) {
+                this.label = exports.rawLabelPrefix + relType + exports.rawLabelPostfix;
+            }
+            else {
+                this.label = exports.rawLabelPrefix + exports.invLabelPrefix + relType + exports.rawLabelPostfix;
+            }
+        }
+    }
+    RelationType.prototype.getLabel = function () {
+        return this.label;
+    };
+    RelationType.prototype.getName = function () {
+        return this.name;
+    };
+    RelationType.prototype.getRelType = function () {
+        return this.relType;
+    };
+    RelationType.prototype.isOutgoing = function () {
+        return this.outgoing;
+    };
+    return RelationType;
+}());
+exports.RelationType = RelationType;
+//# sourceMappingURL=relation-type.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/relation-type.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"relation-type.js","sourceRoot":"","sources":["relation-type.ts"],"names":[],"mappings":";AACW,sBAAc,GAAG,KAAK,CAAC;AACvB,qBAAa,GAAG,GAAG,CAAC;AACpB,sBAAc,GAAG,GAAG,CAAC;AACrB,uBAAe,GAAG,GAAG,CAAC;AAEjC;IAMI,sBAAa,OAAe,EAAE,UAAmB,EAAE,KAAa;QAC5D,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;YACb,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC;QACxB,CAAC;QAAC,IAAI,CAAC,CAAC;YACJ,IAAI,CAAC,IAAI,GAAG,qBAAa,GAAG,OAAO,CAAC;QACxC,CAAC;QACD,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC;YAChB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACvB,CAAC;QAAC,IAAI,CAAC,CAAC;YACJ,0BAA0B;YAC1B,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;gBACb,IAAI,CAAC,KAAK,GAAG,sBAAc,GAAG,OAAO,GAAG,uBAAe,CAAC;YAC5D,CAAC;YAAC,IAAI,CAAC,CAAC;gBACJ,IAAI,CAAC,KAAK,GAAG,sBAAc,GAAG,sBAAc,GAAG,OAAO,GAAG,uBAAe,CAAC;YAC7E,CAAC;QACL,CAAC;IACL,CAAC;IAED,+BAAQ,GAAR;QACI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,8BAAO,GAAP;QACI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,iCAAU,GAAV;QACI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,iCAAU,GAAV;QACI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IACL,mBAAC;AAAD,CAAC,AAzCD,IAyCC;AAzCY,oBAAY,eAyCxB,CAAA"}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/result-column.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,14 @@
+"use strict";
+var ResultColumn = (function () {
+    function ResultColumn(name, title, sort, show) {
+        if (sort === void 0) { sort = ''; }
+        if (show === void 0) { show = false; }
+        this.name = name;
+        this.title = title;
+        this.sort = sort;
+        this.show = show;
+    }
+    return ResultColumn;
+}());
+exports.ResultColumn = ResultColumn;
+//# sourceMappingURL=result-column.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/result-column.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"result-column.js","sourceRoot":"","sources":["result-column.ts"],"names":[],"mappings":";AAAA;IAMI,sBAAa,IAAY,EAAE,KAAa,EAAE,IAAO,EAAE,IAAU;QAAnB,oBAAO,GAAP,SAAO;QAAE,oBAAU,GAAV,YAAU;QACzD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;IACL,mBAAC;AAAD,CAAC,AAZD,IAYC;AAZY,oBAAY,eAYxB,CAAA"}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/result-type.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,49 @@
+"use strict";
+var result_column_1 = require('./result-column');
+var ResultType = (function () {
+    function ResultType(name, idAttribute, allowedAttributes, deniedAttributes) {
+        if (allowedAttributes === void 0) { allowedAttributes = []; }
+        if (deniedAttributes === void 0) { deniedAttributes = []; }
+        this.name = name;
+        this.idAttribute = idAttribute;
+        this.allowedAttributes = allowedAttributes;
+        this.deniedAttributes = deniedAttributes;
+    }
+    /**
+     * Return columns for the given list of attributes.
+     */
+    ResultType.prototype.getColumns = function (attributes, allAttributes) {
+        var _this = this;
+        if (allAttributes === void 0) { allAttributes = true; }
+        var atts = attributes.slice();
+        var cols = [];
+        // allowed attributes
+        this.allowedAttributes.forEach(function (att) {
+            var idx = atts.indexOf(att);
+            if (idx > -1) {
+                cols.push(new result_column_1.ResultColumn(att, att, '', true));
+                atts[idx] = null;
+            }
+        });
+        // then other attributes
+        if (allAttributes) {
+            atts.forEach(function (att) {
+                if (att != null && att[0] != '_' && _this.deniedAttributes.indexOf(att) < 0) {
+                    cols.push(new result_column_1.ResultColumn(att, att, '', false));
+                }
+            });
+        }
+        return cols;
+    };
+    return ResultType;
+}());
+exports.ResultType = ResultType;
+function getResultType(name, resultTypes) {
+    var rt = resultTypes[name];
+    if (rt == null) {
+        rt = resultTypes['*'];
+    }
+    return rt;
+}
+exports.getResultType = getResultType;
+//# sourceMappingURL=result-type.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/result-type.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"result-type.js","sourceRoot":"","sources":["result-type.ts"],"names":[],"mappings":";AAAA,8BAA2B,iBAAiB,CAAC,CAAA;AAE7C;IAMI,oBAAa,IAAY,EAAE,WAAmB,EAAE,iBAA8B,EAAE,gBAA6B;QAA7D,iCAA8B,GAA9B,sBAA8B;QAAE,gCAA6B,GAA7B,qBAA6B;QACzG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,+BAAU,GAAV,UAAW,UAAoB,EAAE,aAAkB;QAAnD,iBAoBC;QApBgC,6BAAkB,GAAlB,oBAAkB;QAC/C,IAAI,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,qBAAqB;QACrB,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,UAAA,GAAG;YAC9B,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC5B,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACX,IAAI,CAAC,IAAI,CAAC,IAAI,4BAAY,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;gBAChD,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YACrB,CAAC;QACL,CAAC,CAAC,CAAC;QACH,wBAAwB;QACxB,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,UAAA,GAAG;gBACZ,EAAE,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,KAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBACzE,IAAI,CAAC,IAAI,CAAC,IAAI,4BAAY,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;gBACrD,CAAC;YACL,CAAC,CAAC,CAAC;QACP,CAAC;QACD,MAAM,CAAC,IAAI,CAAC;IAChB,CAAC;IAEL,iBAAC;AAAD,CAAC,AAtCD,IAsCC;AAtCY,kBAAU,aAsCtB,CAAA;AAED,uBAA8B,IAAY,EAAE,WAAwC;IAChF,IAAI,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC3B,EAAE,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC;QACb,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,MAAM,CAAC,EAAE,CAAC;AACd,CAAC;AANe,qBAAa,gBAM5B,CAAA"}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main.js	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,5 @@
+"use strict";
+var platform_browser_dynamic_1 = require('@angular/platform-browser-dynamic');
+var app_module_1 = require('./app/app.module');
+platform_browser_dynamic_1.platformBrowserDynamic().bootstrapModule(app_module_1.AppModule);
+//# sourceMappingURL=main.js.map
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main.js.map	Wed Mar 29 17:19:12 2017 +0200
@@ -0,0 +1,1 @@
+{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":";AAAA,yCAAuC,mCAAmC,CAAC,CAAA;AAE3E,2BAA0B,kBAAkB,CAAC,CAAA;AAE7C,iDAAsB,EAAE,CAAC,eAAe,CAAC,sBAAS,CAAC,CAAC"}
\ No newline at end of file
--- a/src/main.ts	Mon Mar 20 18:50:31 2017 +0100
+++ b/src/main.ts	Wed Mar 29 17:19:12 2017 +0200
@@ -1,5 +1,5 @@
 import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 
-import { AppModule } from './app/query-app.module';
+import { AppModule } from './app/app.module';
 
 platformBrowserDynamic().bootstrapModule(AppModule);
--- a/src/systemjs.config.js	Mon Mar 20 18:50:31 2017 +0100
+++ b/src/systemjs.config.js	Wed Mar 29 17:19:12 2017 +0200
@@ -25,7 +25,10 @@
 
       // other libraries
       'rxjs':                      'npm:rxjs',
-      'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
+      'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
+      
+      'ng2-bootstrap': 'npm:ng2-bootstrap',
+      'ng2-table': 'npm:ng2-table'
     },
     // packages tells the System loader how to load when no filename and/or no extension
     packages: {
@@ -34,6 +37,14 @@
       },
       rxjs: {
         defaultExtension: 'js'
+      },
+      'ng2-bootstrap': { 
+          format: 'cjs', 
+          main: 'bundles/ng2-bootstrap.umd.js', 
+          defaultExtension: 'js'
+      },
+      'ng2-table': {
+          defaultExtension: 'js'
       }
     }
   });