Implemented table building functions
Change-Id: Ie4003080b13725561df22de41ec85f8c3f31c794
diff --git a/web/gui2/src/main/webapp/app/fw/widget/tablebase.ts b/web/gui2/src/main/webapp/app/fw/widget/tablebase.ts
new file mode 100644
index 0000000..807a014
--- /dev/null
+++ b/web/gui2/src/main/webapp/app/fw/widget/tablebase.ts
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2015-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 { Injectable } from '@angular/core';
+import { FnService } from '../util/fn.service';
+import { LoadingService } from '../layer/loading.service';
+import { LogService } from '../../log.service';
+import { WebSocketService } from '../remote/websocket.service';
+
+const REFRESH_INTERVAL = 2000;
+
+/**
+ * Base model of table view - implemented by Table components
+ */
+export interface TableBase {
+ annots: TableAnnots;
+ autoRefresh: boolean;
+ autoRefreshTip: string;
+ changedData: any;
+ payloadParams: any;
+ selId: string;
+ sortParams: any;
+ tableData: any[];
+ toggleRefresh(): void;
+ selectCallback(event: any, selRow: any): void;
+ parentSelCb(event: any, selRow: any): void;
+ sortCallback(): void;
+ responseCallback(): void;
+}
+
+interface TableAnnots {
+ noRowsMsg: string;
+}
+
+/**
+ * A model of data returned in a TableResponse
+ *
+ * There is an interface extending from this one in the parent component
+ */
+export interface TableResponse {
+ annots: any;
+ // There will be other parts to the response depending on table type
+ // Expect one called tag+'s' e.g. devices or apps
+}
+
+/**
+ * ONOS GUI -- Widget -- Table Base class
+ */
+export class TableBaseImpl implements TableBase {
+ // attributes from the interface
+ public annots: TableAnnots;
+ autoRefresh: boolean = true;
+ autoRefreshTip: string = 'Toggle auto refresh'; // TODO: get LION string
+ changedData: string[] = [];
+ payloadParams: any;
+ selId: string = undefined;
+ sortParams: any;
+ tableData: any[] = [];
+ toggleRefresh; // Function
+ selectCallback; // Function
+ parentSelCb = null;
+ sortCallback; // Function
+ responseCallback; // Function
+
+ private root: string;
+ private req: string;
+ private resp: string;
+ private refreshPromise: any = null;
+ private handlers: string[] = [];
+
+ constructor(
+ protected fs: FnService,
+ protected ls: LoadingService,
+ protected log: LogService,
+ protected wss: WebSocketService,
+ protected tag: string,
+ protected idKey: string = 'id',
+ protected query: string = '',
+ protected selCb = () => ({}) // Function
+ ) {
+ this.root = tag + 's';
+ this.req = tag + 'DataRequest';
+ this.resp = tag + 'DataResponse';
+
+ this.sortCallback = this.requestTableData;
+ this.selectCallback = this.rowSelectionCb;
+ this.toggleRefresh = () => {
+ this.autoRefresh = !this.autoRefresh;
+ this.autoRefresh ? this.startRefresh() : this.stopRefresh();
+ };
+ }
+
+ init() {
+ this.wss.bindHandlers(new Map<string, (data) => void>([
+ [this.resp, (data) => this.tableDataResponseCb(data)]
+ ]));
+ this.handlers.push(this.resp);
+
+ this.annots = <TableAnnots>{
+ noRowsMsg: ''
+ };
+
+ // Now send the WebSocket request and make it repeat every 2 seconds
+ this.requestTableData();
+ this.startRefresh();
+
+ this.log.debug('TableBase initialized');
+ }
+
+ destroy() {
+ this.wss.unbindHandlers(this.handlers);
+ this.stopRefresh();
+ this.ls.stop();
+ }
+
+ /**
+ * A callback that executes when the table data that was requested
+ * on WebSocketService arrives.
+ *
+ * Happens every 2 seconds
+ */
+ tableDataResponseCb(data: TableResponse) {
+ this.ls.stop();
+
+ const newTableData: any[] = Array.from(data[this.root]);
+ this.annots.noRowsMsg = data.annots.no_rows_msg;
+
+ // If the onResp() function is set then call it
+ if (this.responseCallback) {
+ this.responseCallback(data);
+ }
+ this.changedData = [];
+
+ // checks if data changed for row flashing
+ if (JSON.stringify(newTableData) !== JSON.stringify(this.tableData)) {
+ this.log.debug('table data has changed');
+ const oldTableData: any[] = this.tableData;
+ this.tableData = [ ...newTableData ]; // ES6 spread syntax
+ // only flash the row if the data already exists
+ if (oldTableData.length > 0) {
+ for (const idx in newTableData) {
+ if (!this.fs.containsObj(oldTableData, newTableData[idx])) {
+ this.changedData.push(newTableData[idx][this.idKey]);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Table Data Request
+ */
+ requestTableData() {
+ const p = Object.assign({}, this.sortParams, this.payloadParams, this.query);
+
+ // Allow it to sit in pending events
+ if (this.wss.isConnected()) {
+ if (this.fs.debugOn('table')) {
+ this.log.debug('Table data REQUEST:', this.req, p);
+ }
+ this.wss.sendEvent(this.req, p);
+ this.ls.start();
+ }
+ }
+
+ /**
+ * Row Selected
+ */
+ rowSelectionCb(event: any, selRow: any) {
+ const selId: string = selRow[this.idKey];
+ this.selId = (this.selId === selId) ? undefined : selId;
+ if (this.parentSelCb) {
+ this.log.debug('Parent called on Row', selId, 'selected');
+ this.parentSelCb(event, selRow);
+ }
+ }
+
+ /**
+ * autoRefresh functions
+ */
+ startRefresh() {
+ this.refreshPromise =
+ setInterval(() => {
+ if (!this.ls.waiting()) {
+ if (this.fs.debugOn('table')) {
+ this.log.debug('Refreshing ' + this.root + ' page');
+ }
+ this.requestTableData();
+ }
+ }, REFRESH_INTERVAL);
+ }
+
+ stopRefresh() {
+ if (this.refreshPromise) {
+ clearInterval(this.refreshPromise);
+ this.refreshPromise = null;
+ }
+ }
+
+ isChanged(id: string): boolean {
+ return (this.fs.inArray(id, this.changedData) === -1) ? false : true;
+ }
+}