Added native Bazel build to GUI2. Reduced a lot of the unused Angular CLI structures

Reviewers should look at the changes in WORKSPACE, BUILD, BUILD.bazel, README.md files
This is only possible now as rules_nodejs went to 1.0.0 on December 20
gui2 has now been made the entry point (rather than gui2-fw-lib)
No tests or linting are functional yet for Typescript
Each NgModule now has its own BUILD.bazel file with ng_module
gui2-fw-lib is all one module and has been refactored to simplify the directory structure
gui2-topo-lib is also all one module - its directory structure has had 3 layers removed
The big bash script in web/gui2/BUILD has been removed - all is done through ng_module rules
in web/gui2/src/main/webapp/BUILD.bazel and web/gui2/src/main/webapp/app/BUILD.bazel

Change-Id: Ifcfcc23a87be39fe6d6c8324046cc8ebadb90551
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.css b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.css
new file mode 100644
index 0000000..e5f12ae
--- /dev/null
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.css
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed 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.
+ */
+
+
+/*
+ ONOS GUI -- Topology View (forces link svg) -- CSS file
+ */
+/* --- Topo Links --- */
+line {
+    stroke: #888888;
+    stroke-width: 2px;
+}
+
+.link {
+    opacity: .9;
+}
+
+.link.selected {
+    stroke: #009fdb;
+}
+.link.enhanced {
+    stroke: #009fdb;
+    stroke-width: 4px;
+    cursor: pointer;
+}
+
+.link.inactive {
+    opacity: .5;
+    stroke-dasharray: 4 2;
+}
+/* TODO: Review for not-permitted links */
+.link.not-permitted {
+    stroke: rgb(255,0,0);
+    stroke-dasharray: 8 4;
+}
+
+.link.secondary {
+    stroke: rgba(0,153,51,0.5);
+}
+
+.link.secondary.port-traffic-green {
+    stroke: rgb(0,153,51);
+}
+
+.link.secondary.port-traffic-yellow {
+    stroke: rgb(128,145,27);
+}
+
+.link.secondary.port-traffic-orange {
+    stroke: rgb(255, 137, 3);
+}
+
+.link.secondary.port-traffic-red {
+    stroke: rgb(183, 30, 21);
+}
+
+/* Port traffic color visualization for Kbps, Mbps, and Gbps */
+
+.link.secondary.port-traffic-Kbps {
+    stroke: rgb(0,153,51);
+}
+
+.link.secondary.port-traffic-Mbps {
+    stroke: rgb(128,145,27);
+}
+
+.link.secondary.port-traffic-Gbps {
+    stroke: rgb(255, 137, 3);
+}
+
+.link.secondary.port-traffic-Gbps-choked {
+    stroke: rgb(183, 30, 21);
+}
+
+.link.animated {
+    stroke-dasharray: 8;
+    animation: ants 5s infinite linear;
+    /* below line could be added via Javascript, based on path, if we cared
+     * enough about the direction of ant-flow
+     */
+    /*animation-direction: reverse;*/
+}
+@keyframes ants {
+    from {
+        stroke-dashoffset: 0;
+    }
+    to {
+        stroke-dashoffset: 400;
+    }
+}
+
+.link.primary {
+    stroke-width: 4px;
+    stroke: #ffA300;
+}
+
+.link.secondary.optical {
+    stroke-width: 4px;
+    stroke: rgba(128,64,255,0.5);
+}
+
+.link.primary.optical {
+    stroke-width: 6px;
+    stroke: #74f;
+}
+
+/* Link Labels */
+.linkLabel rect {
+    stroke: none;
+    fill: #ffffff;
+}
+
+.linkLabel text {
+    fill: #444;
+    text-anchor: middle;
+}
+
+
+/* Port Labels */
+.portLabel rect {
+    stroke: #a3a596;
+    fill: #ffffff;
+}
+
+.portLabel {
+    fill: #444;
+    alignment-baseline: middle;
+    dominant-baseline: middle;
+}
+
+/* Number of Links Labels */
+
+
+#ov-topo2 text.numLinkText {
+    fill: #444;
+}
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.html b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.html
new file mode 100644
index 0000000..ec3afae
--- /dev/null
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.html
@@ -0,0 +1,101 @@
+<!--
+~ Copyright 2018-present Open Networking Foundation
+~
+~ Licensed 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.
+-->
+<svg:defs xmlns:svg="http://www.w3.org/2000/svg">
+    <svg:filter id="glow">
+        <svg:feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0.9 0 0 0 0 0.9 0 0 0 0 1 0" />
+        <svg:feGaussianBlur stdDeviation="2.5" result="coloredBlur" />
+        <svg:feMerge>
+            <svg:feMergeNode in="coloredBlur" />
+            <svg:feMergeNode in="SourceGraphic"/>
+        </svg:feMerge>
+    </svg:filter>
+</svg:defs>
+<!-- Template explanation: Creates an SVG Line and in
+    line 1) transform end A to the position calculated by the d3 force graph engine
+    line 2) transform end B to the position calculated by the d3 force graph engine
+    line 3) Give it various CSS styles depending on attributes
+    ling 4) Change the line width depending on the scale
+    line 4) When it is clicked, call the method that toggles the selection and
+        emits an event.
+    line 5) When the mouse is moved over call on enhance() function. This will
+        flash up the port labels, and display the link in blue for 1 second
+    Other child objects have their own description
+-->
+<svg:line xmlns:svg="http://www.w3.org/2000/svg"
+        [attr.x1]="link.source?.x" [attr.y1]="link.source?.y"
+        [attr.x2]="link.target?.x" [attr.y2]="link.target?.y"
+        [ngClass]="['link', selected?'selected':'', enhanced?'enhanced':'', highlightAsString()]"
+        [ngStyle]="{'stroke-width': (enhanced ? 4 : 2) * scale + 'px'}"
+        (click)="toggleSelected(link, $event)"
+        (mouseover)="enhance()">
+<!--        [attr.filter]="highlighted?'url(#glow)':'none'">-->
+    <svg:desc>{{link.id}} {{linkHighlight?.css}} {{isHighlighted}}</svg:desc>
+</svg:line>
+<svg:g xmlns:svg="http://www.w3.org/2000/svg"
+       [ngClass]="['linkLabel']"
+       [attr.transform]="'scale(' + scale + ')'">
+    <!-- Template explanation: Creates SVG Text in the middle of the link to
+          show traffic and in:
+        line 1) Performs the animation 'linkLabelVisible' whenever the isHighlighted
+            boolean value changes
+        line 2 & 3) Sets the text at half way between the 2 end points of the line
+        Note: we do not use an *ngIf to enable or disable this, because that would
+        cause the fade out of the text to not work
+    -->
+    <svg:text xmlns:svg="http://www.w3.org/2000/svg"
+              [@linkLabelVisible]="isHighlighted"
+              [attr.x]="link.source?.x + (link.target?.x - link.source?.x)/2"
+              [attr.y]="link.source?.y + (link.target?.y - link.source?.y)/2"
+    >{{ linkHighlight?.label }}</svg:text>
+</svg:g>
+<!-- Template explanation: Creates an SVG Group if
+    line 1) 'enhanced' is active and port text exists
+    line 2) assigns classes to it
+-->
+<svg:g xmlns:svg="http://www.w3.org/2000/svg"
+       *ngIf="enhanced && link.portA"
+       class="portLabel"
+       [attr.transform]="'translate(' + labelPosSrc.x + ',' + labelPosSrc.y + '),scale(' + scale + ')'">
+    <!-- Template explanation: Creates an SVG Rectangle and in
+        line 1) transform end A to the position calculated by the d3 force graph engine
+        line 2) assigns classes to it
+    -->
+    <svg:rect
+            [attr.x]="2 - textLength(link.portA)/2" y="-8"
+            [attr.width]="4 + textLength(link.portA)" height="16" >
+    </svg:rect>
+    <!-- Template explanation: Creates SVG Text and in
+        line 1) transform it to the position calculated by the method labelPosSrc()
+        line 2) centre aligns it
+        line 3) ensures that the text fills the rectangle by adjusting spacing
+    -->
+    <svg:text y="2" text-anchor="middle"
+            [attr.textLength]= "textLength(link.portA)" lengthAdjust="spacing"
+    >{{ link.portA }}</svg:text>
+</svg:g>
+<!-- A repeat of the above, but for the other end of the line -->
+<svg:g xmlns:svg="http://www.w3.org/2000/svg"
+       *ngIf="enhanced && link.portB"
+       class="portLabel"
+       [attr.transform]="'translate(' + labelPosTgt.x + ',' + labelPosTgt.y + '),scale(' + scale + ')'">
+    <svg:rect
+            [attr.x]="2 - textLength(link.portB)/2" y="-8"
+            [attr.width]="4 + textLength(link.portB)" height="16">
+    </svg:rect>
+    <svg:text x="2" y="2" text-anchor="middle"
+            [attr.textLength]= "textLength(link.portB)" lengthAdjust="spacing"
+    >{{ link.portB }}</svg:text>
+</svg:g>
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.spec.ts b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.spec.ts
new file mode 100644
index 0000000..6418fb4
--- /dev/null
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.spec.ts
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed 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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { LinkSvgComponent } from './linksvg.component';
+import {LogService} from '../../../../../../gui2-fw-lib/public_api';
+import {ActivatedRoute, Params} from '@angular/router';
+import {of} from 'rxjs';
+import {Device, Link, RegionLink, LinkType} from '../../models';
+import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
+
+class MockActivatedRoute extends ActivatedRoute {
+    constructor(params: Params) {
+        super();
+        this.queryParams = of(params);
+    }
+}
+
+describe('LinkVisualComponent', () => {
+    let logServiceSpy: jasmine.SpyObj<LogService>;
+    let component: LinkSvgComponent;
+    let fixture: ComponentFixture<LinkSvgComponent>;
+    let ar: MockActivatedRoute;
+    let testLink: Link;
+    let testDeviceA: Device;
+    let testDeviceB: Device;
+
+    beforeEach(async(() => {
+        const logSpy = jasmine.createSpyObj('LogService', ['info', 'debug', 'warn', 'error']);
+        ar = new MockActivatedRoute({ 'debug': 'txrx' });
+
+        testDeviceA = new Device('test:A');
+        testDeviceA.online = true;
+
+        testDeviceB = new Device('test:B');
+        testDeviceB.online = true;
+
+        testLink = new RegionLink(LinkType.UiDeviceLink, testDeviceA, testDeviceB);
+        testLink.id = 'test:A/1-test:B/1';
+
+        TestBed.configureTestingModule({
+            imports: [ BrowserAnimationsModule ],
+            declarations: [ LinkSvgComponent ],
+            providers: [
+                { provide: LogService, useValue: logSpy },
+                { provide: ActivatedRoute, useValue: ar },
+            ]
+        })
+        .compileComponents();
+        logServiceSpy = TestBed.get(LogService);
+    }));
+
+    beforeEach(() => {
+        fixture = TestBed.createComponent(LinkSvgComponent);
+        component = fixture.componentInstance;
+        component.link = testLink;
+        fixture.detectChanges();
+    });
+
+    it('should create', () => {
+        expect(component).toBeTruthy();
+    });
+});
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
new file mode 100644
index 0000000..9997897
--- /dev/null
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed 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 {
+    ChangeDetectorRef,
+    Component, EventEmitter,
+    Input, OnChanges, Output, SimpleChanges,
+} from '@angular/core';
+import {Link, LinkHighlight, UiElement} from '../../models';
+import {LogService} from '../../../../../../gui2-fw-lib/public_api';
+import {NodeVisual, SelectedEvent} from '../nodevisual';
+import {animate, state, style, transition, trigger} from '@angular/animations';
+
+interface Point {
+    x: number;
+    y: number;
+}
+
+/*
+ * LinkSvgComponent gets its data from 2 sources - the force SVG regionData (which
+ * gives the Link below), and other state data here.
+ */
+@Component({
+    selector: '[onos-linksvg]',
+    templateUrl: './linksvg.component.html',
+    styleUrls: ['./linksvg.component.css'],
+    animations: [
+        trigger('linkLabelVisible', [
+            state('true', style( {
+                opacity: 1.0,
+            })),
+            state( 'false', style({
+                opacity: 0
+            })),
+            transition('false => true', animate('500ms ease-in')),
+            transition('true => false', animate('1000ms ease-out'))
+        ])
+    ]
+})
+export class LinkSvgComponent extends NodeVisual implements OnChanges {
+    @Input() link: Link;
+    @Input() linkHighlight: LinkHighlight;
+    @Input() highlightsEnabled: boolean = true;
+    @Input() scale = 1.0;
+    isHighlighted: boolean = false;
+    @Output() selectedEvent = new EventEmitter<SelectedEvent>();
+    @Output() enhancedEvent = new EventEmitter<Link>();
+    enhanced: boolean = false;
+    labelPosSrc: Point = {x: 0, y: 0};
+    labelPosTgt: Point = {x: 0, y: 0};
+    lastTimer: any;
+
+    constructor(
+        protected log: LogService,
+        private ref: ChangeDetectorRef
+    ) {
+        super();
+    }
+
+    ngOnChanges(changes: SimpleChanges) {
+        if (changes['linkHighlight']) {
+            const hl: LinkHighlight = changes['linkHighlight'].currentValue;
+            clearTimeout(this.lastTimer);
+            this.isHighlighted = true;
+            this.log.debug('Link highlighted', this.link.id);
+
+            if (hl.fadems > 0) {
+                this.lastTimer = setTimeout(() => {
+                    this.isHighlighted = false;
+                    this.linkHighlight = <LinkHighlight>{};
+                    this.ref.markForCheck();
+                }, this.linkHighlight.fadems); // Disappear slightly before next one comes in
+            }
+        }
+
+        this.ref.markForCheck();
+    }
+
+    highlightAsString(): string {
+        if (this.linkHighlight && this.linkHighlight.css) {
+            return this.linkHighlight.css;
+        }
+        return '';
+    }
+
+    enhance() {
+        if (!this.highlightsEnabled) {
+            return;
+        }
+        this.enhancedEvent.emit(this.link);
+        this.enhanced = true;
+        this.repositionLabels();
+        setTimeout(() => {
+            this.enhanced = false;
+            this.ref.markForCheck();
+        }, 1000);
+    }
+
+    /**
+     * We want to place the label for the port about 40 px from the node.
+     * If the distance between the nodes is less than 100, then just place the
+     * label 1/3 of the way from the node
+     */
+    repositionLabels(): void {
+        const x1: number = this.link.source.x;
+        const y1: number = this.link.source.y;
+        const x2: number = this.link.target.x;
+        const y2: number = this.link.target.y;
+
+        const dist = Math.sqrt(Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2));
+        const offset = dist > 100 ? 40 : dist / 3;
+        this.labelPosSrc = <Point>{
+            x: x1 + (x2 - x1) * offset / dist,
+            y: y1 + (y2 - y1) * offset / dist
+        };
+
+        this.labelPosTgt = <Point>{
+            x: x2 - (x2 - x1) * offset / dist,
+            y: y2 - (y2 - y1) * offset / dist
+        };
+    }
+
+    /**
+     * For the 14pt font we are using, the average width seems to be about 8px
+     * @param text The string we want to calculate a width for
+     */
+    textLength(text: string) {
+        return text.length * 8;
+    }
+}