knox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From su...@apache.org
Subject [7/7] knox git commit: KNOX-749 Initial admin UI source project and productized distribution
Date Wed, 21 Dec 2016 16:37:26 GMT
KNOX-749 Initial admin UI source project and productized distribution


Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/87a7592e
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/87a7592e
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/87a7592e

Branch: refs/heads/master
Commit: 87a7592ea9fd2b3ceb40e7e7ec3aadf3c2b8c087
Parents: 9f08a22
Author: Sumit Gupta <sumit@apache.org>
Authored: Wed Dec 21 11:35:45 2016 -0500
Committer: Sumit Gupta <sumit@apache.org>
Committed: Wed Dec 21 11:35:45 2016 -0500

----------------------------------------------------------------------
 .gitignore                                      |   31 +
 gateway-admin-ui/README.md                      |   48 +
 gateway-admin-ui/angular-cli.json               |   59 +
 gateway-admin-ui/e2e/app.e2e-spec.ts            |   14 +
 gateway-admin-ui/e2e/app.po.ts                  |   11 +
 gateway-admin-ui/e2e/tsconfig.json              |   16 +
 gateway-admin-ui/karma.conf.js                  |   43 +
 gateway-admin-ui/package.json                   |   49 +
 gateway-admin-ui/protractor.conf.js             |   32 +
 gateway-admin-ui/src/app/app.component.css      |    0
 gateway-admin-ui/src/app/app.component.html     |    3 +
 gateway-admin-ui/src/app/app.component.spec.ts  |   37 +
 gateway-admin-ui/src/app/app.component.ts       |   40 +
 gateway-admin-ui/src/app/app.module.ts          |   56 +
 .../src/app/gateway-version.component.ts        |   49 +
 .../src/app/gateway-version.service.ts          |   51 +
 gateway-admin-ui/src/app/gateway-version.ts     |   20 +
 gateway-admin-ui/src/app/index.ts               |   18 +
 gateway-admin-ui/src/app/main.ts                |   21 +
 .../src/app/topology-detail.component.ts        |  139 ++
 gateway-admin-ui/src/app/topology.component.ts  |   70 +
 gateway-admin-ui/src/app/topology.service.ts    |  124 ++
 gateway-admin-ui/src/app/topology.ts            |   23 +
 .../src/app/utils/json-pretty.pipe.ts           |   27 +
 gateway-admin-ui/src/app/utils/tab.component.ts |   34 +
 .../src/app/utils/tabs.component.ts             |   54 +
 gateway-admin-ui/src/app/utils/xml.pipe.ts      |   27 +
 gateway-admin-ui/src/assets/.gitkeep            |    0
 gateway-admin-ui/src/assets/sticky-footer.css   |   22 +
 gateway-admin-ui/src/assets/vkbeautify.js       |  357 +++
 .../src/environments/environment.prod.ts        |   19 +
 .../src/environments/environment.ts             |   24 +
 gateway-admin-ui/src/favicon.ico                |  Bin 0 -> 5430 bytes
 gateway-admin-ui/src/index.html                 |   79 +
 gateway-admin-ui/src/main.ts                    |   28 +
 gateway-admin-ui/src/polyfills.ts               |   35 +
 gateway-admin-ui/src/styles.css                 |    1 +
 gateway-admin-ui/src/test.ts                    |   48 +
 gateway-admin-ui/src/tsconfig.json              |   18 +
 gateway-admin-ui/src/typings.d.ts               |   18 +
 gateway-admin-ui/tslint.json                    |  107 +
 .../admin-ui/app/assets/sticky-footer.css       |   22 +
 .../admin-ui/app/assets/vkbeautify.js           |  357 +++
 .../applications/admin-ui/app/favicon.ico       |  Bin 0 -> 5430 bytes
 .../applications/admin-ui/app/index.html        |   79 +
 .../app/inline.d41d8cd98f00b204e980.bundle.js   |    2 +
 .../app/inline.d41d8cd98f00b204e980.bundle.map  |    1 +
 .../app/main.a62ce79090310dbb7cec.bundle.js     |    2 +
 .../app/main.a62ce79090310dbb7cec.bundle.js.gz  |  Bin 0 -> 3675 bytes
 .../app/main.a62ce79090310dbb7cec.bundle.map    |    1 +
 .../app/styles.b2328beb0372c051d06d.bundle.js   |    2 +
 .../app/styles.b2328beb0372c051d06d.bundle.map  |    1 +
 ....d41d8cd98f00b204e9800998ecf8427e.bundle.css |    2 +
 .../app/vendor.a4f10aaf35e0664cc5fa.bundle.js   | 2035 ++++++++++++++++++
 .../vendor.a4f10aaf35e0664cc5fa.bundle.js.gz    |  Bin 0 -> 459996 bytes
 .../app/vendor.a4f10aaf35e0664cc5fa.bundle.map  |    1 +
 .../resources/applications/admin-ui/service.xml |   49 +
 gateway-release/home/conf/topologies/admin.xml  |   14 +
 pom.xml                                         |    5 +
 59 files changed, 4425 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 35f4d01..61d27c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,3 +36,34 @@ velocity.log
 *.pyc
 *.py~
 *.patch
+
+# ui compiled output
+dist
+tmp
+
+# ui dependencies
+node_modules
+bower_components
+
+# other IDEs and editors
+.vscode
+.c9/
+*.launch
+
+# ui misc
+.sass-cache
+connect.lock
+coverage/*
+libpeerconnection.log
+npm-debug.log
+testem.log
+typings
+
+# e2e and app
+e2e/*.js
+e2e/*.map
+gateway-admin-ui/src/app/**/*.js
+gateway-admin-ui/src/app/**/*.map
+
+#System Files
+Thumbs.db

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/README.md
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/README.md b/gateway-admin-ui/README.md
new file mode 100644
index 0000000..40a5d3d
--- /dev/null
+++ b/gateway-admin-ui/README.md
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+# NgKnoxUi
+
+This project was generated with [angular-cli](https://github.com/angular/angular-cli) version 1.0.0-beta.22-1.
+
+## Development server
+Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
+
+## Code scaffolding
+
+Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/class`.
+
+## Build
+
+Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
+
+## Running unit tests
+
+Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
+
+## Running end-to-end tests
+
+Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
+Before running the tests make sure you are serving the app via `ng serve`.
+
+## Deploying to Github Pages
+
+Run `ng github-pages:deploy` to deploy to Github Pages.
+
+## Further help
+
+To get more help on the `angular-cli` use `ng --help` or go check out the [Angular-CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/angular-cli.json
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/angular-cli.json b/gateway-admin-ui/angular-cli.json
new file mode 100644
index 0000000..832c4f0
--- /dev/null
+++ b/gateway-admin-ui/angular-cli.json
@@ -0,0 +1,59 @@
+{
+  "project": {
+    "version": "1.0.0-beta.22-1",
+    "name": "ng-knox-ui"
+  },
+  "apps": [
+    {
+      "root": "src",
+      "outDir": "dist",
+      "assets": [
+        "assets",
+        "favicon.ico"
+      ],
+      "index": "index.html",
+      "main": "main.ts",
+      "test": "test.ts",
+      "tsconfig": "tsconfig.json",
+      "prefix": "app",
+      "mobile": false,
+      "styles": [
+        "styles.css"
+      ],
+      "scripts": [],
+      "environments": {
+        "source": "environments/environment.ts",
+        "dev": "environments/environment.ts",
+        "prod": "environments/environment.prod.ts"
+      }
+    }
+  ],
+  "addons": [],
+  "packages": [],
+  "e2e": {
+    "protractor": {
+      "config": "./protractor.conf.js"
+    }
+  },
+  "test": {
+    "karma": {
+      "config": "./karma.conf.js"
+    }
+  },
+  "defaults": {
+    "styleExt": "css",
+    "prefixInterfaces": false,
+    "inline": {
+      "style": false,
+      "template": false
+    },
+    "spec": {
+      "class": false,
+      "component": true,
+      "directive": true,
+      "module": false,
+      "pipe": true,
+      "service": true
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/e2e/app.e2e-spec.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/e2e/app.e2e-spec.ts b/gateway-admin-ui/e2e/app.e2e-spec.ts
new file mode 100644
index 0000000..62d7181
--- /dev/null
+++ b/gateway-admin-ui/e2e/app.e2e-spec.ts
@@ -0,0 +1,14 @@
+import { NgKnoxUiPage } from './app.po';
+
+describe('ng-knox-ui App', function() {
+  let page: NgKnoxUiPage;
+
+  beforeEach(() => {
+    page = new NgKnoxUiPage();
+  });
+
+  it('should display message saying app works', () => {
+    page.navigateTo();
+    expect(page.getParagraphText()).toEqual('app works!');
+  });
+});

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/e2e/app.po.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/e2e/app.po.ts b/gateway-admin-ui/e2e/app.po.ts
new file mode 100644
index 0000000..bd3458e
--- /dev/null
+++ b/gateway-admin-ui/e2e/app.po.ts
@@ -0,0 +1,11 @@
+import { browser, element, by } from 'protractor';
+
+export class NgKnoxUiPage {
+  navigateTo() {
+    return browser.get('/');
+  }
+
+  getParagraphText() {
+    return element(by.css('app-root h1')).getText();
+  }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/e2e/tsconfig.json
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/e2e/tsconfig.json b/gateway-admin-ui/e2e/tsconfig.json
new file mode 100644
index 0000000..656bdb1
--- /dev/null
+++ b/gateway-admin-ui/e2e/tsconfig.json
@@ -0,0 +1,16 @@
+{
+  "compileOnSave": false,
+  "compilerOptions": {
+    "declaration": false,
+    "emitDecoratorMetadata": true,
+    "experimentalDecorators": true,
+    "module": "commonjs",
+    "moduleResolution": "node",
+    "outDir": "../dist/out-tsc-e2e",
+    "sourceMap": true,
+    "target": "es5",
+    "typeRoots": [
+      "../node_modules/@types"
+    ]
+  }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/karma.conf.js
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/karma.conf.js b/gateway-admin-ui/karma.conf.js
new file mode 100644
index 0000000..1f2613a
--- /dev/null
+++ b/gateway-admin-ui/karma.conf.js
@@ -0,0 +1,43 @@
+// Karma configuration file, see link for more information
+// https://karma-runner.github.io/0.13/config/configuration-file.html
+
+module.exports = function (config) {
+  config.set({
+    basePath: '',
+    frameworks: ['jasmine', 'angular-cli'],
+    plugins: [
+      require('karma-jasmine'),
+      require('karma-chrome-launcher'),
+      require('karma-remap-istanbul'),
+      require('angular-cli/plugins/karma')
+    ],
+    files: [
+      { pattern: './src/test.ts', watched: false }
+    ],
+    preprocessors: {
+      './src/test.ts': ['angular-cli']
+    },
+    mime: {
+      'text/x-typescript': ['ts','tsx']
+    },
+    remapIstanbulReporter: {
+      reports: {
+        html: 'coverage',
+        lcovonly: './coverage/coverage.lcov'
+      }
+    },
+    angularCli: {
+      config: './angular-cli.json',
+      environment: 'dev'
+    },
+    reporters: config.angularCli && config.angularCli.codeCoverage
+              ? ['progress', 'karma-remap-istanbul']
+              : ['progress'],
+    port: 9876,
+    colors: true,
+    logLevel: config.LOG_INFO,
+    autoWatch: true,
+    browsers: ['Chrome'],
+    singleRun: false
+  });
+};

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/package.json
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/package.json b/gateway-admin-ui/package.json
new file mode 100644
index 0000000..0d7fdd7
--- /dev/null
+++ b/gateway-admin-ui/package.json
@@ -0,0 +1,49 @@
+{
+  "name": "ng-knox-ui",
+  "version": "0.0.0",
+  "license": "MIT",
+  "angular-cli": {},
+  "scripts": {
+    "start": "ng serve",
+    "lint": "tslint \"src/**/*.ts\"",
+    "test": "ng test",
+    "pree2e": "webdriver-manager update",
+    "e2e": "protractor"
+  },
+  "private": true,
+  "dependencies": {
+    "@angular/common": "2.2.3",
+    "@angular/compiler": "2.2.3",
+    "@angular/core": "2.2.3",
+    "@angular/forms": "2.2.3",
+    "@angular/http": "2.2.3",
+    "@angular/platform-browser": "2.2.3",
+    "@angular/platform-browser-dynamic": "2.2.3",
+    "@angular/router": "3.2.3",
+    "core-js": "^2.4.1",
+    "ng2-bs3-modal": "^0.10.4",
+    "ng2-ace-editor": "0.1.3",
+    "rxjs": "5.0.0-beta.12",
+    "ts-helpers": "^1.1.1",
+    "zone.js": "^0.6.23"
+  },
+  "devDependencies": {
+    "@angular/compiler-cli": "2.2.3",
+    "@types/jasmine": "2.5.38",
+    "@types/node": "^6.0.42",
+    "angular-cli": "1.0.0-beta.22-1",
+    "codelyzer": "~2.0.0-beta.1",
+    "jasmine-core": "2.5.2",
+    "jasmine-spec-reporter": "2.5.0",
+    "karma": "1.2.0",
+    "karma-chrome-launcher": "^2.0.0",
+    "karma-cli": "^1.0.1",
+    "karma-jasmine": "^1.0.2",
+    "karma-remap-istanbul": "^0.2.1",
+    "protractor": "4.0.9",
+    "ts-node": "1.2.1",
+    "tslint": "^4.0.2",
+    "typescript": "~2.0.3",
+    "webdriver-manager": "10.2.5"
+  }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/protractor.conf.js
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/protractor.conf.js b/gateway-admin-ui/protractor.conf.js
new file mode 100644
index 0000000..169743b
--- /dev/null
+++ b/gateway-admin-ui/protractor.conf.js
@@ -0,0 +1,32 @@
+// Protractor configuration file, see link for more information
+// https://github.com/angular/protractor/blob/master/docs/referenceConf.js
+
+/*global jasmine */
+var SpecReporter = require('jasmine-spec-reporter');
+
+exports.config = {
+  allScriptsTimeout: 11000,
+  specs: [
+    './e2e/**/*.e2e-spec.ts'
+  ],
+  capabilities: {
+    'browserName': 'chrome'
+  },
+  directConnect: true,
+  baseUrl: 'http://localhost:4200/',
+  framework: 'jasmine',
+  jasmineNodeOpts: {
+    showColors: true,
+    defaultTimeoutInterval: 30000,
+    print: function() {}
+  },
+  useAllAngular2AppRoots: true,
+  beforeLaunch: function() {
+    require('ts-node').register({
+      project: 'e2e'
+    });
+  },
+  onPrepare: function() {
+    jasmine.getEnv().addReporter(new SpecReporter());
+  }
+};

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/app.component.css
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/app.component.css b/gateway-admin-ui/src/app/app.component.css
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/app.component.html
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/app.component.html b/gateway-admin-ui/src/app/app.component.html
new file mode 100644
index 0000000..b6931b5
--- /dev/null
+++ b/gateway-admin-ui/src/app/app.component.html
@@ -0,0 +1,3 @@
+<h1>
+  {{title}}
+</h1>

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/app.component.spec.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/app.component.spec.ts b/gateway-admin-ui/src/app/app.component.spec.ts
new file mode 100644
index 0000000..211fadf
--- /dev/null
+++ b/gateway-admin-ui/src/app/app.component.spec.ts
@@ -0,0 +1,37 @@
+/* tslint:disable:no-unused-variable */
+import { AppComponent } from './app.component';
+
+import { TestBed } from '@angular/core/testing';
+
+import { By }             from '@angular/platform-browser';
+
+////////  SPECS  /////////////
+
+/// Delete this
+describe('Smoke test', () => {
+  it('should run a passing test', () => {
+    expect(true).toEqual(true, 'should pass');
+  });
+});
+
+describe('AppComponent with TCB', function () {
+  beforeEach(() => {
+    TestBed.configureTestingModule({declarations: [AppComponent]});
+  });
+
+  it('should instantiate component', () => {
+    let fixture = TestBed.createComponent(AppComponent);
+    expect(fixture.componentInstance instanceof AppComponent).toBe(true, 'should create AppComponent');
+  });
+
+  it('should have expected <h1> text', () => {
+    let fixture = TestBed.createComponent(AppComponent);
+    fixture.detectChanges();
+
+    let h1 = fixture.debugElement.query(el => el.name === 'h1').nativeElement;  // it works
+
+        h1 = fixture.debugElement.query(By.css('h1')).nativeElement;            // preferred
+
+    expect(h1.innerText).toMatch(/angular 2 app/i, '<h1> should say something about "Angular 2 App"');
+  });
+});

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/app.component.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/app.component.ts b/gateway-admin-ui/src/app/app.component.ts
new file mode 100644
index 0000000..cee1178
--- /dev/null
+++ b/gateway-admin-ui/src/app/app.component.ts
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Component } from '@angular/core';
+import {TopologyService} from "./topology.service";
+
+@Component({
+    selector: 'topology-management',
+    template: `
+      <div class="container">
+        <div class="row">
+          <div class="col-md-5">
+            <topology></topology>
+         </div>
+          <div class="col-md-7">
+            <topology-detail></topology-detail>
+          </div>
+        </div>
+      </div>
+  `,
+    providers: [TopologyService]
+})
+
+export class AppComponent {
+    constructor(private topologyService : TopologyService) {
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/app.module.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/app.module.ts b/gateway-admin-ui/src/app/app.module.ts
new file mode 100644
index 0000000..afa8f4b
--- /dev/null
+++ b/gateway-admin-ui/src/app/app.module.ts
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { NgModule }      from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { HttpModule }    from '@angular/http';
+import { FormsModule } from '@angular/forms';
+
+import { AppComponent }  from './app.component';
+import {TopologyService} from "./topology.service";
+import {GatewayVersionService} from "./gateway-version.service";
+import {GatewayVersionComponent} from "./gateway-version.component";
+import {TopologyComponent} from "./topology.component";
+import {TopologyDetailComponent} from "./topology-detail.component";
+import {XmlPipe} from "./utils/xml.pipe";
+import {JsonPrettyPipe} from "./utils/json-pretty.pipe";
+import { TabComponent } from './utils/tab.component';
+import { TabsComponent } from './utils/tabs.component';
+
+import { AceEditorDirective } from 'ng2-ace-editor'; 
+import { Ng2Bs3ModalModule } from 'ng2-bs3-modal/ng2-bs3-modal'
+
+@NgModule({
+  imports: [ BrowserModule,
+    HttpModule,
+    FormsModule,
+    Ng2Bs3ModalModule
+    ],
+  declarations: [ AppComponent,
+    TopologyComponent,
+      TopologyDetailComponent,
+    GatewayVersionComponent,
+    AceEditorDirective,
+    XmlPipe,
+    JsonPrettyPipe,
+    TabsComponent,
+    TabComponent ],
+  providers: [ TopologyService,
+    GatewayVersionService ],
+  bootstrap: [ AppComponent,
+    GatewayVersionComponent]
+})
+export class AppModule { }

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/gateway-version.component.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/gateway-version.component.ts b/gateway-admin-ui/src/app/gateway-version.component.ts
new file mode 100644
index 0000000..d31c87f
--- /dev/null
+++ b/gateway-admin-ui/src/app/gateway-version.component.ts
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {Component, OnInit} from '@angular/core';
+import {GatewayVersion} from './gateway-version';
+import {GatewayVersionService} from "./gateway-version.service";
+
+
+@Component({
+    selector: 'gateway-version',
+    template: `
+        <div *ngIf="gatewayVersion">
+            <span class="small"><cite>Knox Gateway Version</cite> {{this.gatewayVersion.version}}</span>
+            <span class="small"><cite>Hash</cite> {{this.gatewayVersion.hash}}</span>
+</div>`,
+    providers: [GatewayVersionService]
+})
+
+export class GatewayVersionComponent implements OnInit {
+
+    gatewayVersion : GatewayVersion;
+
+    constructor(private gatewayVersionService : GatewayVersionService) {
+    }
+
+    getVersion(): void {
+        this.gatewayVersionService.getVersion().then( gatewayVersion => this.gatewayVersion = gatewayVersion);
+    }
+
+    ngOnInit(): void {
+        this.getVersion();
+    }
+
+
+}
+

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/gateway-version.service.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/gateway-version.service.ts b/gateway-admin-ui/src/app/gateway-version.service.ts
new file mode 100644
index 0000000..b242ce3
--- /dev/null
+++ b/gateway-admin-ui/src/app/gateway-version.service.ts
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Injectable }    from '@angular/core';
+import { Headers, Http } from '@angular/http';
+
+import 'rxjs/add/operator/toPromise';
+
+import { GatewayVersion } from './gateway-version';
+
+@Injectable()
+export class GatewayVersionService {
+
+    private apiUrl = '/gateway/admin/api/v1/version';
+
+    constructor(private http: Http) { }
+
+    getVersion(): Promise<GatewayVersion> {
+        let headers = new Headers();
+        this.addHeaders(headers);
+        return this.http.get(this.apiUrl, {
+            headers: headers
+        } )
+            .toPromise()
+            .then(response => response.json().ServerVersion as GatewayVersion)
+            .catch(this.handleError);
+    }
+
+    addHeaders(headers: Headers) {
+        headers.append('Accept', 'application/json');
+        headers.append('Content-Type', 'application/json');
+    }
+
+    private handleError(error: any): Promise<any> {
+        console.error('An error occurred', error); // for demo purposes only
+        return Promise.reject(error.message || error);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/gateway-version.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/gateway-version.ts b/gateway-admin-ui/src/app/gateway-version.ts
new file mode 100644
index 0000000..a674080
--- /dev/null
+++ b/gateway-admin-ui/src/app/gateway-version.ts
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export class GatewayVersion {
+    version: string;
+    hash: string;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/index.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/index.ts b/gateway-admin-ui/src/app/index.ts
new file mode 100644
index 0000000..d7b550c
--- /dev/null
+++ b/gateway-admin-ui/src/app/index.ts
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export * from './app.component';
+export * from './app.module';

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/main.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/main.ts b/gateway-admin-ui/src/app/main.ts
new file mode 100644
index 0000000..df4b6a7
--- /dev/null
+++ b/gateway-admin-ui/src/app/main.ts
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/topology-detail.component.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/topology-detail.component.ts b/gateway-admin-ui/src/app/topology-detail.component.ts
new file mode 100644
index 0000000..6fa118a
--- /dev/null
+++ b/gateway-admin-ui/src/app/topology-detail.component.ts
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Component, OnInit, ViewChild, ViewEncapsulation} from '@angular/core';
+import { Topology } from './topology';
+import {TopologyService} from "./topology.service";
+import { ModalComponent } from 'ng2-bs3-modal/ng2-bs3-modal';
+
+@Component({
+    selector: 'topology-detail',
+    template: `
+     <div class="panel panel-default">
+        <div class="panel-heading">
+            <h4 class="panel-title">{{title}} <span class="label label-default pull-right">{{titleSuffix}}</span></h4>
+         </div>
+     <div *ngIf="topologyContent" class="panel-body">
+      <div ace-editor
+       [readOnly]="false" [text]="topologyContent | xml" [mode]="'xml'" [options]="options" 
+        [theme]="'monokai'"
+         style="min-height: 300px; width:100%; overflow: auto;" (textChanged)="onChange($event)">
+      </div>
+       <div class="panel-footer">
+        <button (click)="duplicateModal.open('sm')" class="btn btn-default btn-sm" type="submit">
+            <span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span>
+        </button>
+        <button (click)="deleteConfirmModal.open('sm')" class="btn btn-default btn-sm" type="submit">
+            <span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
+        </button>
+       <button (click)="saveTopology()" class="btn btn-default btn-sm pull-right" [disabled]="!changedTopology" type="submit">
+            <span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>
+        </button>
+       </div>
+         
+    </div>
+    <modal (onClose)="createTopology()" #duplicateModal>
+
+        <modal-header [show-close]="true">
+            <h4 class="modal-title">Create a copy</h4>
+        </modal-header>
+        <modal-body>
+            <div class="form-group">
+                <label for="textbox">Name the new topology</label>
+                <input autofocus type="text" class="form-control" required [(ngModel)]="newTopologyName" id="textbox">
+            </div> 
+        </modal-body>
+        <modal-footer>
+            <button type="button" class="btn btn-default btn-sm" data-dismiss="duplicateModal" (click)="duplicateModal.dismiss()">Cancel</button>
+            <button type="button" class="btn btn-primary btn-sm" [disabled]="!newTopologyName" (click)="duplicateModal.close()">Ok</button>
+        </modal-footer>
+    </modal>
+    <modal (onClose)="deleteTopology()" #deleteConfirmModal>
+        <modal-header [show-close]="true">
+            <h4 class="modal-title">Deleting Topology</h4>
+        </modal-header>
+        <modal-body>
+            Are you sure you want to delete the topology?
+        </modal-body>
+        <modal-footer>
+            <button type="button" class="btn btn-default btn-sm" data-dismiss="deleteConfirmModal" (click)="deleteConfirmModal.dismiss()">Cancel</button>
+            <button type="button" class="btn btn-primary btn-sm" (click)="deleteConfirmModal.close()">Ok</button>
+        </modal-footer>
+    </modal>
+   `
+})
+export class TopologyDetailComponent implements OnInit {
+
+    title = 'Topology Detail';
+    titleSuffix: string;
+    topology: Topology;
+    topologyContent: string;
+    changedTopology: string;
+    newTopologyName: string;
+    options:any = {useWorker: false, printMargin: false};
+
+    @ViewChild('duplicateModal')
+    duplicateModal: ModalComponent;
+
+    @ViewChild('deleteConfirmModal')
+    deleteConfirmModal: ModalComponent;
+
+    constructor(private topologyService : TopologyService) {
+    }
+
+    ngOnInit(): void {
+        this.topologyService.selectedTopology$.subscribe(value => this.populateContent(value));
+    }
+
+    setTitle(value : string) {
+        this.titleSuffix = value;
+    }
+
+    onChange(code: any) {
+        this.changedTopology = code;
+    }
+
+    saveTopology() {
+        this.topologyService.saveTopology(this.topology.href, this.changedTopology)
+        .then(value => this.topologyService.changedTopology(this.topology.name));
+    }
+
+    createTopology() {
+        if (this.changedTopology) {
+            this.topologyService.createTopology(this.newTopologyName, this.changedTopology)
+            .then(value => this.topologyService.changedTopology(this.newTopologyName));
+        } else {
+            this.topologyService.createTopology(this.newTopologyName, this.topologyContent)
+            .then(value => this.topologyService.changedTopology(this.newTopologyName));
+        }
+    }
+
+    deleteTopology() {
+        this.topologyService.deleteTopology(this.topology.href).then(value => this.topologyService.changedTopology(this.topology.name));
+    }
+
+    populateContent(topology: Topology) {
+        this.topology = topology;
+        this.setTitle(topology.name);
+        if (this.topology) {
+            if (this.topology.href) {
+                this.topologyService.getTopology(this.topology.href).then( content => this.topologyContent = content);
+            }
+        }
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/topology.component.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/topology.component.ts b/gateway-admin-ui/src/app/topology.component.ts
new file mode 100644
index 0000000..3878425
--- /dev/null
+++ b/gateway-admin-ui/src/app/topology.component.ts
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {Component, OnInit} from '@angular/core';
+import {Topology} from './topology';
+import {TopologyService} from "./topology.service";
+import { Subscription }   from 'rxjs/Subscription';
+
+
+@Component({
+    selector: 'topology',
+    template: `
+        <div class="table-responsive" style="max-height: 400px; width:100%; overflow: auto;">
+            <table class="table table-striped table-hover">
+              <thead>
+                <tr>
+                  <th>Topology Name</th>
+                  <th>Timestamp</th>
+                </tr>
+              </thead>
+         <tbody>
+         <tr *ngFor="let topology of topologies"
+          [class.selected]="topology === selectedTopology"
+        (click)="onSelect(topology)">
+         <td>{{topology.name}}</td> 
+         <td>{{topology.timestamp | date:'yMMMdjms'}}</td> 
+         </tr>
+        </tbody>
+        </table>
+        </div>
+       `
+})
+export class TopologyComponent implements OnInit {
+
+    value :any;
+    topologies: Topology[];
+    selectedTopology: Topology;
+
+
+    constructor(private topologyService : TopologyService) {
+    }
+
+    getTopologies(): void {
+        this.topologyService.getTopologies().then(topologies => this.topologies = topologies);
+    }
+
+    ngOnInit(): void {
+        this.getTopologies();
+        this.topologyService.changedTopology$.subscribe(value => this.getTopologies());
+    }
+
+    onSelect(topology: Topology): void {
+        this.selectedTopology = topology;
+        this.topologyService.selectedTopology(topology);
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/topology.service.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/topology.service.ts b/gateway-admin-ui/src/app/topology.service.ts
new file mode 100644
index 0000000..bf97ce7
--- /dev/null
+++ b/gateway-admin-ui/src/app/topology.service.ts
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Injectable }    from '@angular/core';
+import { Headers, Http } from '@angular/http';
+
+import 'rxjs/add/operator/toPromise';
+import { Subject }    from 'rxjs/Subject';
+import { Observable }    from 'rxjs/Observable';
+
+import { Topology } from './topology';
+
+@Injectable()
+export class TopologyService {
+
+    apiUrl = '/gateway/admin/api/v1/';
+    topologiesUrl = this.apiUrl + 'topologies';
+    selectedTopologySource = new Subject<Topology>();
+    selectedTopology$ = this.selectedTopologySource.asObservable();
+    changedTopologySource = new Subject<string>();
+    changedTopology$ = this.changedTopologySource.asObservable();
+
+    constructor(private http: Http) { }
+
+    getTopologies(): Promise<Topology[]> {
+        let headers = new Headers();
+        this.addJsonHeaders(headers);
+        return this.http.get(this.topologiesUrl, {
+            headers: headers
+        } )
+            .toPromise()
+            .then(response => response.json().topologies.topology as Topology[])
+            .catch(this.handleError);
+    }
+
+    getTopology(href : string): Promise<string> {
+        let headers = new Headers();
+        this.addXmlHeaders(headers);
+        return this.http.get(href, {
+            headers: headers
+        } )
+            .toPromise()
+            .then(response => response.text())
+            .catch(this.handleError);
+
+    }
+
+    saveTopology(url: string, xml : string): Promise<string> {
+        let xheaders = new Headers();
+        this.addXmlHeaders(xheaders);
+        this.addCsrfHeaders(xheaders);
+        return this.http
+            .put(url, xml, {headers: xheaders})
+            .toPromise()
+            .then(() => xml)
+            .catch(this.handleError);
+
+    }
+
+    createTopology(name: string, xml : string): Promise<string> {
+        let xheaders = new Headers();
+        this.addXmlHeaders(xheaders);
+        this.addCsrfHeaders(xheaders);
+        let url = this.topologiesUrl + "/" + name;
+        return this.http
+            .put(url, xml, {headers: xheaders})
+            .toPromise()
+            .then(() => xml)
+            .catch(this.handleError);
+    }
+
+    deleteTopology(href: string): Promise<string> {
+        let headers = new Headers();
+        this.addJsonHeaders(headers);
+        this.addCsrfHeaders(headers);
+        return this.http.delete(href, {
+            headers: headers
+        } )
+            .toPromise()
+            .then(response => response.text())
+            .catch(this.handleError);
+    }
+
+    addJsonHeaders(headers: Headers) {
+        headers.append('Accept', 'application/json');
+        headers.append('Content-Type', 'application/json');
+    }
+
+    addXmlHeaders(headers: Headers) {
+        headers.append('Accept', 'application/xml');
+        headers.append('Content-Type', 'application/xml');
+    }
+
+    addCsrfHeaders(headers: Headers) {
+        headers.append('X-XSRF-Header', 'admin-ui');
+    }
+
+    selectedTopology(value: Topology) {
+        this.selectedTopologySource.next(value);
+    }
+
+    changedTopology(value: string) {
+        this.changedTopologySource.next(value);
+    }
+
+
+    private handleError(error: any): Promise<any> {
+        console.error('An error occurred', error); // for demo purposes only
+        return Promise.reject(error.message || error);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/topology.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/topology.ts b/gateway-admin-ui/src/app/topology.ts
new file mode 100644
index 0000000..95db774
--- /dev/null
+++ b/gateway-admin-ui/src/app/topology.ts
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export class Topology {
+    timestamp: number;
+    name: string;
+    uri: string;
+    href: string;
+    content: string;
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/utils/json-pretty.pipe.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/utils/json-pretty.pipe.ts b/gateway-admin-ui/src/app/utils/json-pretty.pipe.ts
new file mode 100644
index 0000000..6bbf49f
--- /dev/null
+++ b/gateway-admin-ui/src/app/utils/json-pretty.pipe.ts
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Pipe, PipeTransform } from '@angular/core';
+
+declare var vkbeautify: any;
+
+@Pipe({name: 'jsonpretty'})
+export class JsonPrettyPipe implements PipeTransform {
+
+  transform(value: string): string {
+    return vkbeautify.json(value);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/utils/tab.component.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/utils/tab.component.ts b/gateway-admin-ui/src/app/utils/tab.component.ts
new file mode 100644
index 0000000..bfe3a34
--- /dev/null
+++ b/gateway-admin-ui/src/app/utils/tab.component.ts
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'tab',
+  styles: [`
+    .pane{
+      padding: 1em;
+    }
+  `],
+  template: `
+    <div [hidden]="!active" class="pane">
+    </div>
+  `
+})
+export class TabComponent {
+  @Input('tabTitle') title: string;
+  @Input() active = false;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/utils/tabs.component.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/utils/tabs.component.ts b/gateway-admin-ui/src/app/utils/tabs.component.ts
new file mode 100644
index 0000000..e246796
--- /dev/null
+++ b/gateway-admin-ui/src/app/utils/tabs.component.ts
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Component, ContentChildren, QueryList, AfterContentInit } from '@angular/core';
+import { TabComponent } from './tab.component';
+
+@Component({
+  selector: 'tabs',
+  template:`
+    <ul class="nav nav-tabs">
+      <li *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active">
+        <a>{{tab.title}}</a>
+      </li>
+    </ul>
+    
+  `
+})
+export class TabsComponent implements AfterContentInit {
+  
+  @ContentChildren(TabComponent) tabs: QueryList<TabComponent>;
+  
+  // contentChildren are set
+  ngAfterContentInit() {
+    // get all active tabs
+    let activeTabs = this.tabs.filter((tab)=>tab.active);
+    
+    // if there is no active tab set, activate the first
+    if(activeTabs.length === 0) {
+      this.selectTab(this.tabs.first);
+    }
+  }
+  
+  selectTab(tab: TabComponent){
+    // deactivate all tabs
+    this.tabs.toArray().forEach(tab => tab.active = false);
+    
+    // activate the tab the user has clicked on.
+    tab.active = true;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/app/utils/xml.pipe.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/utils/xml.pipe.ts b/gateway-admin-ui/src/app/utils/xml.pipe.ts
new file mode 100644
index 0000000..17a6a8d
--- /dev/null
+++ b/gateway-admin-ui/src/app/utils/xml.pipe.ts
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Pipe, PipeTransform } from '@angular/core';
+
+declare var vkbeautify: any;
+
+@Pipe({name: 'xml'})
+export class XmlPipe implements PipeTransform {
+
+  transform(value: string): string {
+    return vkbeautify.xml(value);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/assets/.gitkeep
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/assets/.gitkeep b/gateway-admin-ui/src/assets/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/assets/sticky-footer.css
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/assets/sticky-footer.css b/gateway-admin-ui/src/assets/sticky-footer.css
new file mode 100644
index 0000000..52d570c
--- /dev/null
+++ b/gateway-admin-ui/src/assets/sticky-footer.css
@@ -0,0 +1,22 @@
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+    position: relative;
+    min-height: 100%;
+}
+body {
+    /* Margin bottom by footer height */
+    margin-bottom: 60px;
+}
+.footer {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    /* Set the fixed height of the footer here */
+    height: 60px;
+    background-color: #f5f5f5;
+}
+
+.jumbotron {
+    padding: 0.5em 0.6em;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/assets/vkbeautify.js
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/assets/vkbeautify.js b/gateway-admin-ui/src/assets/vkbeautify.js
new file mode 100644
index 0000000..076c3d5
--- /dev/null
+++ b/gateway-admin-ui/src/assets/vkbeautify.js
@@ -0,0 +1,357 @@
+/**
+* vkBeautify - javascript plugin to pretty-print or minify text in XML, JSON, CSS and SQL formats.
+*  
+* Version - 0.99.00.beta 
+* Copyright (c) 2012 Vadim Kiryukhin
+* vkiryukhin @ gmail.com
+* http://www.eslinstructor.net/vkbeautify/
+* 
+* MIT license:
+*   http://www.opensource.org/licenses/mit-license.php
+*
+*   Pretty print
+*
+*        vkbeautify.xml(text [,indent_pattern]);
+*        vkbeautify.json(text [,indent_pattern]);
+*        vkbeautify.css(text [,indent_pattern]);
+*        vkbeautify.sql(text [,indent_pattern]);
+*
+*        @text - String; text to beatufy;
+*        @indent_pattern - Integer | String;
+*                Integer:  number of white spaces;
+*                String:   character string to visualize indentation ( can also be a set of white spaces )
+*   Minify
+*
+*        vkbeautify.xmlmin(text [,preserve_comments]);
+*        vkbeautify.jsonmin(text);
+*        vkbeautify.cssmin(text [,preserve_comments]);
+*        vkbeautify.sqlmin(text);
+*
+*        @text - String; text to minify;
+*        @preserve_comments - Bool; [optional];
+*                Set this flag to true to prevent removing comments from @text ( minxml and mincss functions only. )
+*
+*   Examples:
+*        vkbeautify.xml(text); // pretty print XML
+*        vkbeautify.json(text, 4 ); // pretty print JSON
+*        vkbeautify.css(text, '. . . .'); // pretty print CSS
+*        vkbeautify.sql(text, '----'); // pretty print SQL
+*
+*        vkbeautify.xmlmin(text, true);// minify XML, preserve comments
+*        vkbeautify.jsonmin(text);// minify JSON
+*        vkbeautify.cssmin(text);// minify CSS, remove comments ( default )
+*        vkbeautify.sqlmin(text);// minify SQL
+*
+*/
+
+(function() {
+
+function createShiftArr(step) {
+
+	var space = '    ';
+	
+	if ( isNaN(parseInt(step)) ) {  // argument is string
+		space = step;
+	} else { // argument is integer
+		switch(step) {
+			case 1: space = ' '; break;
+			case 2: space = '  '; break;
+			case 3: space = '   '; break;
+			case 4: space = '    '; break;
+			case 5: space = '     '; break;
+			case 6: space = '      '; break;
+			case 7: space = '       '; break;
+			case 8: space = '        '; break;
+			case 9: space = '         '; break;
+			case 10: space = '          '; break;
+			case 11: space = '           '; break;
+			case 12: space = '            '; break;
+		}
+	}
+
+	var shift = ['\n']; // array of shifts
+	for(ix=0;ix<100;ix++){
+		shift.push(shift[ix]+space); 
+	}
+	return shift;
+}
+
+function vkbeautify(){
+	this.step = '\t'; // 4 spaces
+	this.shift = createShiftArr(this.step);
+};
+
+vkbeautify.prototype.xml = function(text,step) {
+
+	var ar = text.replace(/>\s{0,}</g,"><")
+				 .replace(/</g,"~::~<")
+				 .replace(/\s*xmlns\:/g,"~::~xmlns:")
+				 .replace(/\s*xmlns\=/g,"~::~xmlns=")
+				 .split('~::~'),
+		len = ar.length,
+		inComment = false,
+		deep = 0,
+		str = '',
+		ix = 0,
+		shift = step ? createShiftArr(step) : this.shift;
+
+		for(ix=0;ix<len;ix++) {
+			// start comment or <![CDATA[...]]> or <!DOCTYPE //
+			if(ar[ix].search(/<!/) > -1) { 
+				str += shift[deep]+ar[ix];
+				inComment = true; 
+				// end comment  or <![CDATA[...]]> //
+				if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1 || ar[ix].search(/!DOCTYPE/) > -1 ) { 
+					inComment = false; 
+				}
+			} else 
+			// end comment  or <![CDATA[...]]> //
+			if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1) { 
+				str += ar[ix];
+				inComment = false; 
+			} else 
+			// <elm></elm> //
+			if( /^<\w/.exec(ar[ix-1]) && /^<\/\w/.exec(ar[ix]) &&
+				/^<[\w:\-\.\,]+/.exec(ar[ix-1]) == /^<\/[\w:\-\.\,]+/.exec(ar[ix])[0].replace('/','')) { 
+				str += ar[ix];
+				if(!inComment) deep--;
+			} else
+			 // <elm> //
+			if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) == -1 && ar[ix].search(/\/>/) == -1 ) {
+				str = !inComment ? str += shift[deep++]+ar[ix] : str += ar[ix];
+			} else 
+			 // <elm>...</elm> //
+			if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) > -1) {
+				str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];
+			} else 
+			// </elm> //
+			if(ar[ix].search(/<\//) > -1) { 
+				str = !inComment ? str += shift[--deep]+ar[ix] : str += ar[ix];
+			} else 
+			// <elm/> //
+			if(ar[ix].search(/\/>/) > -1 ) { 
+				str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];
+			} else 
+			// <? xml ... ?> //
+			if(ar[ix].search(/<\?/) > -1) { 
+				str += shift[deep]+ar[ix];
+			} else 
+			// xmlns //
+			if( ar[ix].search(/xmlns\:/) > -1  || ar[ix].search(/xmlns\=/) > -1) { 
+				str += shift[deep]+ar[ix];
+			} 
+			
+			else {
+				str += ar[ix];
+			}
+		}
+		
+	return  (str[0] == '\n') ? str.slice(1) : str;
+}
+
+vkbeautify.prototype.json = function(text,step) {
+
+	var step = step ? step : this.step;
+	
+	if (typeof JSON === 'undefined' ) return text; 
+	
+	if ( typeof text === "string" ) return JSON.stringify(JSON.parse(text), null, step);
+	if ( typeof text === "object" ) return JSON.stringify(text, null, step);
+		
+	return text; // text is not string nor object
+}
+
+vkbeautify.prototype.css = function(text, step) {
+
+	var ar = text.replace(/\s{1,}/g,' ')
+				.replace(/\{/g,"{~::~")
+				.replace(/\}/g,"~::~}~::~")
+				.replace(/\;/g,";~::~")
+				.replace(/\/\*/g,"~::~/*")
+				.replace(/\*\//g,"*/~::~")
+				.replace(/~::~\s{0,}~::~/g,"~::~")
+				.split('~::~'),
+		len = ar.length,
+		deep = 0,
+		str = '',
+		ix = 0,
+		shift = step ? createShiftArr(step) : this.shift;
+		
+		for(ix=0;ix<len;ix++) {
+
+			if( /\{/.exec(ar[ix]))  { 
+				str += shift[deep++]+ar[ix];
+			} else 
+			if( /\}/.exec(ar[ix]))  { 
+				str += shift[--deep]+ar[ix];
+			} else
+			if( /\*\\/.exec(ar[ix]))  { 
+				str += shift[deep]+ar[ix];
+			}
+			else {
+				str += shift[deep]+ar[ix];
+			}
+		}
+		return str.replace(/^\n{1,}/,'');
+}
+
+//----------------------------------------------------------------------------
+
+function isSubquery(str, parenthesisLevel) {
+	return  parenthesisLevel - (str.replace(/\(/g,'').length - str.replace(/\)/g,'').length )
+}
+
+function split_sql(str, tab) {
+
+	return str.replace(/\s{1,}/g," ")
+
+				.replace(/ AND /ig,"~::~"+tab+tab+"AND ")
+				.replace(/ BETWEEN /ig,"~::~"+tab+"BETWEEN ")
+				.replace(/ CASE /ig,"~::~"+tab+"CASE ")
+				.replace(/ ELSE /ig,"~::~"+tab+"ELSE ")
+				.replace(/ END /ig,"~::~"+tab+"END ")
+				.replace(/ FROM /ig,"~::~FROM ")
+				.replace(/ GROUP\s{1,}BY/ig,"~::~GROUP BY ")
+				.replace(/ HAVING /ig,"~::~HAVING ")
+				//.replace(/ SET /ig," SET~::~")
+				.replace(/ IN /ig," IN ")
+				
+				.replace(/ JOIN /ig,"~::~JOIN ")
+				.replace(/ CROSS~::~{1,}JOIN /ig,"~::~CROSS JOIN ")
+				.replace(/ INNER~::~{1,}JOIN /ig,"~::~INNER JOIN ")
+				.replace(/ LEFT~::~{1,}JOIN /ig,"~::~LEFT JOIN ")
+				.replace(/ RIGHT~::~{1,}JOIN /ig,"~::~RIGHT JOIN ")
+				
+				.replace(/ ON /ig,"~::~"+tab+"ON ")
+				.replace(/ OR /ig,"~::~"+tab+tab+"OR ")
+				.replace(/ ORDER\s{1,}BY/ig,"~::~ORDER BY ")
+				.replace(/ OVER /ig,"~::~"+tab+"OVER ")
+
+				.replace(/\(\s{0,}SELECT /ig,"~::~(SELECT ")
+				.replace(/\)\s{0,}SELECT /ig,")~::~SELECT ")
+				
+				.replace(/ THEN /ig," THEN~::~"+tab+"")
+				.replace(/ UNION /ig,"~::~UNION~::~")
+				.replace(/ USING /ig,"~::~USING ")
+				.replace(/ WHEN /ig,"~::~"+tab+"WHEN ")
+				.replace(/ WHERE /ig,"~::~WHERE ")
+				.replace(/ WITH /ig,"~::~WITH ")
+				
+				//.replace(/\,\s{0,}\(/ig,",~::~( ")
+				//.replace(/\,/ig,",~::~"+tab+tab+"")
+
+				.replace(/ ALL /ig," ALL ")
+				.replace(/ AS /ig," AS ")
+				.replace(/ ASC /ig," ASC ")	
+				.replace(/ DESC /ig," DESC ")	
+				.replace(/ DISTINCT /ig," DISTINCT ")
+				.replace(/ EXISTS /ig," EXISTS ")
+				.replace(/ NOT /ig," NOT ")
+				.replace(/ NULL /ig," NULL ")
+				.replace(/ LIKE /ig," LIKE ")
+				.replace(/\s{0,}SELECT /ig,"SELECT ")
+				.replace(/\s{0,}UPDATE /ig,"UPDATE ")
+				.replace(/ SET /ig," SET ")
+							
+				.replace(/~::~{1,}/g,"~::~")
+				.split('~::~');
+}
+
+vkbeautify.prototype.sql = function(text,step) {
+
+	var ar_by_quote = text.replace(/\s{1,}/g," ")
+							.replace(/\'/ig,"~::~\'")
+							.split('~::~'),
+		len = ar_by_quote.length,
+		ar = [],
+		deep = 0,
+		tab = this.step,//+this.step,
+		inComment = true,
+		inQuote = false,
+		parenthesisLevel = 0,
+		str = '',
+		ix = 0,
+		shift = step ? createShiftArr(step) : this.shift;;
+
+		for(ix=0;ix<len;ix++) {
+			if(ix%2) {
+				ar = ar.concat(ar_by_quote[ix]);
+			} else {
+				ar = ar.concat(split_sql(ar_by_quote[ix], tab) );
+			}
+		}
+		
+		len = ar.length;
+		for(ix=0;ix<len;ix++) {
+			
+			parenthesisLevel = isSubquery(ar[ix], parenthesisLevel);
+			
+			if( /\s{0,}\s{0,}SELECT\s{0,}/.exec(ar[ix]))  { 
+				ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
+			} 
+			
+			if( /\s{0,}\s{0,}SET\s{0,}/.exec(ar[ix]))  { 
+				ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
+			} 
+			
+			if( /\s{0,}\(\s{0,}SELECT\s{0,}/.exec(ar[ix]))  { 
+				deep++;
+				str += shift[deep]+ar[ix];
+			} else 
+			if( /\'/.exec(ar[ix]) )  { 
+				if(parenthesisLevel<1 && deep) {
+					deep--;
+				}
+				str += ar[ix];
+			}
+			else  { 
+				str += shift[deep]+ar[ix];
+				if(parenthesisLevel<1 && deep) {
+					deep--;
+				}
+			} 
+			var junk = 0;
+		}
+
+		str = str.replace(/^\n{1,}/,'').replace(/\n{1,}/g,"\n");
+		return str;
+}
+
+
+vkbeautify.prototype.xmlmin = function(text, preserveComments) {
+
+	var str = preserveComments ? text
+							   : text.replace(/\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/g,"")
+									 .replace(/[ \r\n\t]{1,}xmlns/g, ' xmlns');
+	return  str.replace(/>\s{0,}</g,"><"); 
+}
+
+vkbeautify.prototype.jsonmin = function(text) {
+
+	if (typeof JSON === 'undefined' ) return text; 
+	
+	return JSON.stringify(JSON.parse(text), null, 0); 
+				
+}
+
+vkbeautify.prototype.cssmin = function(text, preserveComments) {
+	
+	var str = preserveComments ? text
+							   : text.replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\//g,"") ;
+
+	return str.replace(/\s{1,}/g,' ')
+			  .replace(/\{\s{1,}/g,"{")
+			  .replace(/\}\s{1,}/g,"}")
+			  .replace(/\;\s{1,}/g,";")
+			  .replace(/\/\*\s{1,}/g,"/*")
+			  .replace(/\*\/\s{1,}/g,"*/");
+}
+
+vkbeautify.prototype.sqlmin = function(text) {
+	return text.replace(/\s{1,}/g," ").replace(/\s{1,}\(/,"(").replace(/\s{1,}\)/,")");
+}
+
+window.vkbeautify = new vkbeautify();
+
+})();
+

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/environments/environment.prod.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/environments/environment.prod.ts b/gateway-admin-ui/src/environments/environment.prod.ts
new file mode 100644
index 0000000..67e0aa8
--- /dev/null
+++ b/gateway-admin-ui/src/environments/environment.prod.ts
@@ -0,0 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export const environment = {
+  production: true
+};

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/environments/environment.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/environments/environment.ts b/gateway-admin-ui/src/environments/environment.ts
new file mode 100644
index 0000000..1e9b09d
--- /dev/null
+++ b/gateway-admin-ui/src/environments/environment.ts
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// The file contents for the current environment will overwrite these during build.
+// The build system defaults to the dev environment which uses `environment.ts`, but if you do
+// `ng build --env=prod` then `environment.prod.ts` will be used instead.
+// The list of which env maps to which file can be found in `angular-cli.json`.
+
+export const environment = {
+  production: false
+};

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/favicon.ico
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/favicon.ico b/gateway-admin-ui/src/favicon.ico
new file mode 100644
index 0000000..8081c7c
Binary files /dev/null and b/gateway-admin-ui/src/favicon.ico differ

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/index.html
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/index.html b/gateway-admin-ui/src/index.html
new file mode 100644
index 0000000..2d1d24b
--- /dev/null
+++ b/gateway-admin-ui/src/index.html
@@ -0,0 +1,79 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!doctype html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Apache Knox Manager</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <link rel="icon" type="image/x-icon" href="favicon.ico">
+      <meta name="viewport" content="width=device-width, initial-scale=1">
+    <!-- Latest compiled and minified CSS -->
+    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
+
+    <!-- Optional theme -->
+    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
+    <!-- Custom styles for this template -->
+    <link href="assets/sticky-footer.css" rel="stylesheet">
+
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
+    <!-- Latest compiled and minified JavaScript -->
+    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
+    <script src="assets/vkbeautify.js"></script>
+
+</head>
+<body>
+  <div class="navbar-wrapper">
+    <div class="container-fluid">
+
+      <nav class="navbar navbar-inverse navbar-static-top">
+        <div class="container-fluid">
+          <div class="navbar-header">
+            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
+              <span class="sr-only">Toggle navigation</span>
+              <span class="icon-bar"></span>
+              <span class="icon-bar"></span>
+              <span class="icon-bar"></span>
+            </button>
+            <a class="navbar-brand" href="#">Apache Knox Manager</a>
+          </div>
+          <!--<div id="navbar" class="navbar-collapse collapse">
+            <ul class="nav navbar-nav  navbar-right">
+              <li><a href="./">Logout</a></li>
+            </ul>
+          </div>-->
+        </div>
+      </nav>
+
+  </div>
+  <div class="container">
+
+    <!-- Main component for a primary marketing message or call to action -->
+    <div class="jumbotron">
+      <h3>Topology Management</h3>
+      <p>Protecting cluster resources through Knox</p>
+    </div>
+  </div>
+
+
+  <!-- Content -->
+  <topology-management></topology-management>
+
+  <footer class="footer">
+    <div>Knox Manager Version 0.0.1</div>
+    <gateway-version></gateway-version>
+  </footer>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/main.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/main.ts b/gateway-admin-ui/src/main.ts
new file mode 100644
index 0000000..c0e53eb
--- /dev/null
+++ b/gateway-admin-ui/src/main.ts
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import './polyfills.ts';
+
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { enableProdMode } from '@angular/core';
+import { environment } from './environments/environment';
+import { AppModule } from './app/';
+
+if (environment.production) {
+  enableProdMode();
+}
+
+platformBrowserDynamic().bootstrapModule(AppModule);

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/polyfills.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/polyfills.ts b/gateway-admin-ui/src/polyfills.ts
new file mode 100644
index 0000000..78cba47
--- /dev/null
+++ b/gateway-admin-ui/src/polyfills.ts
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// This file includes polyfills needed by Angular 2 and is loaded before
+// the app. You can add your own extra polyfills to this file.
+import 'core-js/es6/symbol';
+import 'core-js/es6/object';
+import 'core-js/es6/function';
+import 'core-js/es6/parse-int';
+import 'core-js/es6/parse-float';
+import 'core-js/es6/number';
+import 'core-js/es6/math';
+import 'core-js/es6/string';
+import 'core-js/es6/date';
+import 'core-js/es6/array';
+import 'core-js/es6/regexp';
+import 'core-js/es6/map';
+import 'core-js/es6/set';
+import 'core-js/es6/reflect';
+
+import 'core-js/es7/reflect';
+import 'zone.js/dist/zone';

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/styles.css
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/styles.css b/gateway-admin-ui/src/styles.css
new file mode 100644
index 0000000..90d4ee0
--- /dev/null
+++ b/gateway-admin-ui/src/styles.css
@@ -0,0 +1 @@
+/* You can add global styles to this file, and also import other style files */

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/test.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/test.ts b/gateway-admin-ui/src/test.ts
new file mode 100644
index 0000000..89cf2fe
--- /dev/null
+++ b/gateway-admin-ui/src/test.ts
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import './polyfills.ts';
+
+import 'zone.js/dist/long-stack-trace-zone';
+import 'zone.js/dist/proxy.js';
+import 'zone.js/dist/sync-test';
+import 'zone.js/dist/jasmine-patch';
+import 'zone.js/dist/async-test';
+import 'zone.js/dist/fake-async-test';
+import { getTestBed } from '@angular/core/testing';
+import {
+  BrowserDynamicTestingModule,
+  platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+
+// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
+declare var __karma__: any;
+declare var require: any;
+
+// Prevent Karma from running prematurely.
+__karma__.loaded = function () {};
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+  BrowserDynamicTestingModule,
+  platformBrowserDynamicTesting()
+);
+// Then we find all the tests.
+let context = require.context('./', true, /\.spec\.ts/);
+// And load the modules.
+context.keys().map(context);
+// Finally, start Karma to run the tests.
+__karma__.start();

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/tsconfig.json
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/tsconfig.json b/gateway-admin-ui/src/tsconfig.json
new file mode 100644
index 0000000..1cf713a
--- /dev/null
+++ b/gateway-admin-ui/src/tsconfig.json
@@ -0,0 +1,18 @@
+{
+  "compilerOptions": {
+    "baseUrl": "",
+    "declaration": false,
+    "emitDecoratorMetadata": true,
+    "experimentalDecorators": true,
+    "lib": ["es6", "dom"],
+    "mapRoot": "./",
+    "module": "es6",
+    "moduleResolution": "node",
+    "outDir": "../dist/out-tsc",
+    "sourceMap": true,
+    "target": "es5",
+    "typeRoots": [
+      "../node_modules/@types"
+    ]
+  }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/src/typings.d.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/typings.d.ts b/gateway-admin-ui/src/typings.d.ts
new file mode 100644
index 0000000..32bf19d
--- /dev/null
+++ b/gateway-admin-ui/src/typings.d.ts
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Typings reference file, you can add your own global typings here
+// https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-admin-ui/tslint.json
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/tslint.json b/gateway-admin-ui/tslint.json
new file mode 100644
index 0000000..640d02c
--- /dev/null
+++ b/gateway-admin-ui/tslint.json
@@ -0,0 +1,107 @@
+{
+  "rulesDirectory": [
+    "node_modules/codelyzer"
+  ],
+  "rules": {
+    "class-name": true,
+    "comment-format": [
+      true,
+      "check-space"
+    ],
+    "curly": true,
+    "eofline": true,
+    "forin": true,
+    "indent": [
+      true,
+      "spaces"
+    ],
+    "label-position": true,
+    "max-line-length": [
+      true,
+      140
+    ],
+    "member-access": false,
+    "member-ordering": [
+      true,
+      "static-before-instance",
+      "variables-before-functions"
+    ],
+    "no-arg": true,
+    "no-bitwise": true,
+    "no-console": [
+      true,
+      "debug",
+      "info",
+      "time",
+      "timeEnd",
+      "trace"
+    ],
+    "no-construct": true,
+    "no-debugger": true,
+    "no-duplicate-variable": true,
+    "no-empty": false,
+    "no-eval": true,
+    "no-inferrable-types": true,
+    "no-shadowed-variable": true,
+    "no-string-literal": false,
+    "no-switch-case-fall-through": true,
+    "no-trailing-whitespace": true,
+    "no-unused-expression": true,
+    "no-use-before-declare": true,
+    "no-var-keyword": true,
+    "object-literal-sort-keys": false,
+    "one-line": [
+      true,
+      "check-open-brace",
+      "check-catch",
+      "check-else",
+      "check-whitespace"
+    ],
+    "quotemark": [
+      true,
+      "single"
+    ],
+    "radix": true,
+    "semicolon": [
+      "always"
+    ],
+    "triple-equals": [
+      true,
+      "allow-null-check"
+    ],
+    "typedef-whitespace": [
+      true,
+      {
+        "call-signature": "nospace",
+        "index-signature": "nospace",
+        "parameter": "nospace",
+        "property-declaration": "nospace",
+        "variable-declaration": "nospace"
+      }
+    ],
+    "variable-name": false,
+    "whitespace": [
+      true,
+      "check-branch",
+      "check-decl",
+      "check-operator",
+      "check-separator",
+      "check-type"
+    ],
+
+    "directive-selector": [true, "attribute", "app", "camelCase"],
+    "component-selector": [true, "element", "app", "kebab-case"],
+    "use-input-property-decorator": true,
+    "use-output-property-decorator": true,
+    "use-host-property-decorator": true,
+    "no-input-rename": true,
+    "no-output-rename": true,
+    "use-life-cycle-interface": true,
+    "use-pipe-transform-interface": true,
+    "component-class-suffix": true,
+    "directive-class-suffix": true,
+    "no-access-missing-member": true,
+    "templates-use-public": true,
+    "invoke-injectable": true
+  }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/87a7592e/gateway-applications/src/main/resources/applications/admin-ui/app/assets/sticky-footer.css
----------------------------------------------------------------------
diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/assets/sticky-footer.css b/gateway-applications/src/main/resources/applications/admin-ui/app/assets/sticky-footer.css
new file mode 100644
index 0000000..52d570c
--- /dev/null
+++ b/gateway-applications/src/main/resources/applications/admin-ui/app/assets/sticky-footer.css
@@ -0,0 +1,22 @@
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+    position: relative;
+    min-height: 100%;
+}
+body {
+    /* Margin bottom by footer height */
+    margin-bottom: 60px;
+}
+.footer {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    /* Set the fixed height of the footer here */
+    height: 60px;
+    background-color: #f5f5f5;
+}
+
+.jumbotron {
+    padding: 0.5em 0.6em;
+}
\ No newline at end of file


Mime
View raw message