Added actions to the Apps view of web/gui2

Change-Id: I3d96a324590bee4de0875d4f533cc723c7f6ba52
diff --git a/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.css b/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.css
index 829d5e2..66b8f3b 100644
--- a/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.css
+++ b/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.css
@@ -15,33 +15,54 @@
  */
 
 /*
- ONOS GUI -- Flash Service (layout) -- CSS file
+ ONOS GUI -- Flash Component (layout) -- CSS file
  */
 
 #flash {
-    z-index: 1400;
-}
-
-#flash svg {
-    /*position: absolute;*/
-    bottom: 0;
-    opacity: 0.8;
-}
-
-#flash svg g.flashItem text {
-    stroke: none;
-    text-anchor: middle;
-    alignment-baseline: middle;
-    font-size: 16pt;
-}
-
-/* Used for temp div */
-.centered {
     position: fixed;
     top: 50%;
     left: 50%;
-    -webkit-transform: translate(-50%, -50%);
     transform: translate(-50%, -50%);
-    margin: 0;
+    z-index: 1400;
+}
+
+#flash.warning div#flashBox {
+    border: 2px solid #222222;
+    border-radius: 10px;
+    background: #FFFFFF;
     padding: 10px;
 }
+
+#flash div#flashBox {
+    background: #CCCCCC;
+    border-radius: 10px;
+    padding: 1px;
+}
+
+#flash div#flashBox div.dialog-button {
+    transform :translateY(-32px);
+}
+
+#flash.warning p#flashText {
+    stroke: #FF0000;
+    color: #FF0000;
+    text-anchor: middle;
+    alignment-baseline: middle;
+    text-align: center;
+    font-size: 16pt;
+    border-radius: 10px;
+    background: #FFFFFF;
+    padding: 10px;
+}
+
+#flash p#flashText {
+    stroke: none;
+    color: #222222;
+    text-anchor: middle;
+    alignment-baseline: middle;
+    text-align: center;
+    font-size: 16pt;
+    border-radius: 10px;
+    background: #CCCCCC;
+    padding: 5px;
+}
diff --git a/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.html b/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.html
index 5566013..46b6de9 100644
--- a/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.html
+++ b/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.html
@@ -13,15 +13,9 @@
 ~ See the License for the specific language governing permissions and
 ~ limitations under the License.
 -->
-<div id="flash">
-    <svg *ngIf="enabled" [attr.width]="width" [attr.height]="height" [attr.viewBox]="vbox" >
-        <g class="flashItem" [@flashState]="enabled?'active':'inactive'">
-            <text #flashtext>{{ message }}</text>
-            <rect [attr.opacity]="0.5" [attr.rx]="rx"
-                      [attr.x]="-flashtext.getBBox().width/2-xpad"
-                      [attr.y]="flashtext.getBBox().y-ypad"
-                      [attr.height]="flashtext.getBBox().height+ypad*2"
-                      [attr.width]="flashtext.getBBox().width+xpad*2"></rect>
-        </g>
-    </svg>
+<div id="flash" class="dialog" [ngClass]="warning?'warning':''" [@flashState]="visible">
+    <div id="flashBox" *ngIf="visible">
+        <p id="flashText">{{ message }}</p>
+        <div class="dialog-button" *ngIf="dwell>1200" (click)="closeNow()">Dismiss</div>
+    </div>
 </div>
\ No newline at end of file
diff --git a/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.spec.ts b/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.spec.ts
new file mode 100644
index 0000000..14efa19
--- /dev/null
+++ b/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.spec.ts
@@ -0,0 +1,60 @@
+/*
+ * 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 { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { DebugElement } from '@angular/core';
+import { By } from '@angular/platform-browser';
+
+import { ConsoleLoggerService } from '../../../consolelogger.service';
+import { LogService } from '../../../log.service';
+import { FlashComponent } from './flash.component';
+
+/**
+ * ONOS GUI -- Layer -- Flash Component - Unit Tests
+ */
+describe('FlashComponent', () => {
+    let log: LogService;
+    let component: FlashComponent;
+    let fixture: ComponentFixture<FlashComponent>;
+
+    beforeEach(async(() => {
+        log = new ConsoleLoggerService();
+        TestBed.configureTestingModule({
+            imports: [ BrowserAnimationsModule ],
+            declarations: [ FlashComponent ],
+            providers: [
+                { provide: LogService, useValue: log },
+            ]
+        });
+    }));
+
+    beforeEach(() => {
+        fixture = TestBed.createComponent(FlashComponent);
+        component = fixture.debugElement.componentInstance;
+        fixture.detectChanges();
+    });
+
+    it('should create', () => {
+        expect(component).toBeTruthy();
+    });
+
+//    it('should have a div#flash', () => {
+//        component.enabled = true;
+//        const appDe: DebugElement = fixture.debugElement;
+//        const divDe = appDe.query(By.css('div#flash'));
+//        expect(divDe).toBeTruthy();
+//    });
+});
diff --git a/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.ts b/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.ts
index 3a70c35..df08a96 100644
--- a/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.ts
+++ b/web/gui2/src/main/webapp/app/fw/layer/flash/flash.component.ts
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { Component } from '@angular/core';
+import { Component, Input, Output, OnChanges, SimpleChange, EventEmitter } from '@angular/core';
 import { LogService } from '../../../log.service';
 import { trigger, state, style, animate, transition } from '@angular/animations';
 
@@ -24,55 +24,68 @@
  * Provides a mechanism to flash short informational messages to the screen
  * to alert the user of something, e.g. "Hosts visible" or "Hosts hidden".
  *
+ * It can be used in a warning mode, where text will appear in red
+ * The dwell time (milliseconds) can be controlled or the default is 1200ms
+ *
  * To use add an element to the template like
- *   <onos-flash #flashComponent (click)="flashComponent.flash('Hosts visible')"></onos-flash>
- * 1) The (click) can be removed and the call to flash() can be called from anywhere else in the template.
- * 2) This whole element can be disabled until needed with an ngIf
+ *   <onos-flash message="Hosts visible" dwell="2000" warning="true"></onos-flash>
+ * This whole element can be disabled until needed with an ngIf, but if this is done
+ * the animated fade-in and fade-out will not happen
+ * There is also a (closed) event that tells you when the message is closed, or
+ * fades-out
  */
 @Component({
     selector: 'onos-flash',
     templateUrl: './flash.component.html',
-    styleUrls: ['./flash.component.css'],
+    styleUrls: [
+        './flash.component.css',
+        '../dialog.css',
+        '../dialog.theme.css',
+    ],
     animations: [
         trigger('flashState', [
-            state('inactive', style({
+            state('false', style({
+//                transform: 'translateY(-400%)',
                 opacity: '0.0',
             })),
-            state('active', style({
+            state('true', style({
+//                transform: 'translateY(0%)',
                 opacity: '1.0',
             })),
-            transition('inactive => active', animate('200ms ease-in')),
-            transition('active => inactive', animate('200ms ease-out'))
+            transition('0 => 1', animate('200ms ease-in')),
+            transition('1 => 0', animate('200ms ease-out'))
         ])
     ]
 })
-export class FlashComponent {
-    public message: string;
+export class FlashComponent implements OnChanges {
+    @Input() message: string;
+    @Input() dwell: number = 1200; // milliseconds
+    @Input() warning: boolean = false;
+    @Output() closed: EventEmitter<boolean> = new EventEmitter();
 
-    public width: string = '100%';
-    public height: number = 200;
-    public rx: number = 10;
-    public vbox: string = '-200 -' + (this.height / 2) + ' 400 ' + this.height;
-    public xpad: number = 20;
-    public ypad: number = 10;
-    public enabled: boolean = false;
-
-    constructor(
-        private log: LogService,
-    ) {
-        this.log.debug('FlashComponent constructed');
-    }
+    public visible: boolean = false;
 
     /**
      * Flash a message up for 1200ms then disappear again.
      * See animation parameter for the ease in and ease out params
      */
-    flash(message: string): void {
-        this.message = message;
-        this.enabled = true;
+    ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
+        if (changes['message'] && this.message && this.message !== '') {
+            this.visible = true;
 
-        setTimeout(() => {
-            this.enabled = false;
-        }, 1200);
+            setTimeout(() => {
+                this.visible = false;
+                this.closed.emit(false);
+            }, this.dwell);
+        }
+    }
+
+    /**
+     * The message will flash up for 'dwell' milliseconds
+     * If dwell is > 2000ms, then there will be a button that allows it to be dismissed now
+     */
+    closeNow() {
+        this.visible = false;
+        this.closed.emit(false);
     }
 }