Added in summary panel of GUI 2 topo view

Change-Id: I5d325ff1dc2940e08ab9e6f970768b5fd0885e10
diff --git a/web/gui2/src/main/webapp/app/view/topology/panel/topopanel.base.ts b/web/gui2/src/main/webapp/app/view/topology/panel/topopanel.base.ts
new file mode 100644
index 0000000..48aa2ed
--- /dev/null
+++ b/web/gui2/src/main/webapp/app/view/topology/panel/topopanel.base.ts
@@ -0,0 +1,109 @@
+/*
+ * 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,
+    LoadingService,
+    LogService,
+    PanelBaseImpl
+} from 'gui2-fw-lib';
+
+/**
+ * Base model of panel view - implemented by Topology Panel components
+ */
+export abstract class TopoPanelBaseImpl extends PanelBaseImpl {
+
+    protected header: any;
+    protected body: any;
+    protected footer: any;
+
+    protected constructor(
+        protected fs: FnService,
+        protected ls: LoadingService,
+        protected log: LogService,
+        protected id: string
+    ) {
+        super(fs, ls, log);
+    }
+
+    protected init(el: any) {
+        this.header = el.append('div').classed('header', true);
+        this.body = el.append('div').classed('body', true);
+        this.footer = el.append('div').classed('footer', true);
+    }
+
+    /**
+     * Decode lists of props sent back through Web Socket
+     *
+     * Means that panels do not have to know property names in advance
+     * Driven by PropertyPanel on Server side
+     */
+    listProps(el, data) {
+        let sepLast: boolean = false;
+
+        // note: track whether we end with a separator or not...
+        data.propOrder.forEach((p) => {
+            if (p === '-') {
+                this.addSep(el);
+                sepLast = true;
+            } else {
+                this.addProp(el, data.propLabels[p], data.propValues[p]);
+                sepLast = false;
+            }
+        });
+        return sepLast;
+    }
+
+    addProp(el, label, value) {
+        const tr = el.append('tr');
+        let lab;
+
+        if (typeof label === 'string') {
+            lab = label.replace(/_/g, ' ');
+        } else {
+            lab = label;
+        }
+
+        function addCell(cls, txt) {
+            tr.append('td').attr('class', cls).text(txt);
+        }
+
+        addCell('label', lab + ' :');
+        addCell('value', value);
+    }
+
+    addSep(el) {
+        el.append('tr').append('td').attr('colspan', 2).append('hr');
+    }
+
+    appendToHeader(x) {
+        return this.header.append(x);
+    }
+
+    appendToBody(x) {
+        return this.body.append(x);
+    }
+
+    appendToFooter(x) {
+        return this.footer.append(x);
+    }
+
+    emptyRegions() {
+        this.header.selectAll('*').remove();
+        this.body.selectAll('*').remove();
+        this.footer.selectAll('*').remove();
+    }
+
+}