Added in panel support - details panels

Change-Id: I2803edd6fe12cb0d97a2d3c45a692ea701786dd2
diff --git a/web/gui2/src/main/webapp/app/fw/widget/detailspanel.base.ts b/web/gui2/src/main/webapp/app/fw/widget/detailspanel.base.ts
new file mode 100644
index 0000000..d7cf7b8
--- /dev/null
+++ b/web/gui2/src/main/webapp/app/fw/widget/detailspanel.base.ts
@@ -0,0 +1,113 @@
+/*
+ * 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 { FnService } from '../util/fn.service';
+import { LoadingService } from '../layer/loading.service';
+import { LogService } from '../../log.service';
+import { WebSocketService } from '../remote/websocket.service';
+
+import { PanelBaseImpl } from './panel.base';
+
+/**
+ * A generic model of the data returned from the *DetailsResponse
+ */
+interface DetailsResponse {
+    details: any;
+}
+
+/**
+ * Extends the PanelBase abstract class specifically for showing details
+ *
+ * This makes another call through WSS to the server for specific
+ * details to fill the panel with
+ *
+ * This replaces the detailspanel service in the old gui
+ */
+export abstract class DetailsPanelBaseImpl extends PanelBaseImpl {
+
+    private root: string;
+    private req: string;
+    private resp: string;
+    private handlers: string[] = [];
+    public detailsData: any = {};
+    public closed: boolean = false;
+
+    constructor(
+        protected fs: FnService,
+        protected ls: LoadingService,
+        protected log: LogService,
+        protected wss: WebSocketService,
+        protected tag: string,
+    ) {
+        super(fs, ls, log, wss, {});
+        this.root = tag + 's';
+        this.req = tag + 'DetailsRequest';
+        this.resp = tag + 'DetailsResponse';
+    }
+
+    /**
+     * When the details panel is created set up a listener on
+     * Web Socket for details responses
+     */
+    init() {
+        this.wss.bindHandlers(new Map<string, (data) => void>([
+            [this.resp, (data) => this.detailsPanelResponseCb(data)]
+        ]));
+        this.handlers.push(this.resp);
+    }
+
+    /**
+     * When the details panel is destroyed this should be called to
+     * de-register from the WebSocket
+     */
+    destroy() {
+        this.wss.unbindHandlers(this.handlers);
+    }
+
+    /**
+     * A callback that executes when the details data that was requested
+     * on WebSocketService arrives.
+     */
+    detailsPanelResponseCb(data: DetailsResponse) {
+        this.detailsData = data['details'];
+    }
+
+    /**
+     * Details Panel Data Request - should be called whenever id changes
+     * If id is empty, no request is made
+     */
+    requestDetailsPanelData(id: string) {
+        if (id === '') {
+            return;
+        }
+        this.closed = false;
+        const query = {'id': id};
+
+        // Do not send if the Web Socket hasn't opened
+        if (this.wss.isConnected()) {
+            if (this.fs.debugOn('panel')) {
+                this.log.debug('Details panel data REQUEST:', this.req, query);
+            }
+            this.wss.sendEvent(this.req, query);
+        }
+    }
+
+    /**
+     * this should be called when the details panel close button is clicked
+     */
+    close(): void {
+        this.closed = true;
+    }
+}