GUI2 implementation of device/flow/port/group/meter/host/link/tunnel view
Review comments incorporated.
Change-Id: I45dd6570961cc3e0f4ffddb7acbf02cd7d860de5
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps.module.ts b/web/gui2/src/main/webapp/app/view/apps/apps.module.ts
index 738ee18..0e79a2b 100644
--- a/web/gui2/src/main/webapp/app/view/apps/apps.module.ts
+++ b/web/gui2/src/main/webapp/app/view/apps/apps.module.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-present Open Networking Foundation
+ * 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.
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.css b/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.css
index 3096bae..636fb0c 100644
--- a/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.css
+++ b/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.css
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-present Open Networking Foundation
+ * 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.
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.html b/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.html
index 943e26b..37826fa 100644
--- a/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.html
+++ b/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.html
@@ -36,24 +36,24 @@
<div class="separator"></div>
<div class="active" (click)="triggerForm()">
- <onos-icon classes="{{ 'active upload' }}"
+ <onos-icon classes="{{ 'active-rect upload' }}"
iconId="upload" iconSize="42" toolTip="{{ uploadTip }}"></onos-icon>
</div>
- <div (click)="confirmAction(AppActionEnum.ACTIVATE)">
- <onos-icon classes="{{ ctrlBtnState.installed?'active play':'play' }}"
+ <div (click)="(!!selId) ? confirmAction(AppActionEnum.ACTIVATE) : ''">
+ <onos-icon classes="{{ ctrlBtnState.installed?'active-rect play':'play' }}"
iconId="play" iconSize="42" toolTip="{{ activateTip }}"></onos-icon>
</div>
- <div (click)="confirmAction(AppActionEnum.DEACTIVATE)">
- <onos-icon classes="{{ ctrlBtnState.active?'active stop':'stop' }}"
+ <div (click)="(!!selId) ? confirmAction(AppActionEnum.DEACTIVATE) : ''">
+ <onos-icon classes="{{ ctrlBtnState.active?'active-rect stop':'stop' }}"
iconId="stop" iconSize="42" toolTip="{{ deactivateTip }}"></onos-icon>
</div>
- <div (click)="confirmAction(AppActionEnum.UNINSTALL)">
- <onos-icon classes="{{ ctrlBtnState.selection?'active garbage':'garbage' }}"
+ <div (click)="(!!selId) ? confirmAction(AppActionEnum.UNINSTALL) : ''">
+ <onos-icon classes="{{ ctrlBtnState.selection?'active-rect garbage':'garbage' }}"
iconId="garbage" iconSize="42" toolTip="{{ uninstallTip }}"></onos-icon>
</div>
- <div (click)="downloadApp()">
- <onos-icon classes="{{ ctrlBtnState.selection?'active download':'download' }}"
+ <div (click)="(!!selId) ? downloadApp() : ''">
+ <onos-icon classes="{{ ctrlBtnState.selection?'active-rect download':'download' }}"
iconId="download" iconSize="42" toolTip="{{ downloadTip }}"></onos-icon>
</div>
</div>
@@ -74,34 +74,34 @@
</div>
- <div id="summary-list" class="summary-list">
+ <div id="summary-list" class="summary-list" onosTableResize>
<div class="table-header">
- <table onosTableResize>
+ <table>
<tr>
<th colId="state" [ngStyle]="{width: '32px'}" class="table-icon" (click)="onSort('state')">
- <onos-icon classes="active" [iconId]="sortIcon('state')"></onos-icon>
+ <onos-icon classes="active-sort" [iconSize]="10" [iconId]="sortIcon('state')"></onos-icon>
</th>
<th colId="icon" [ngStyle]="{width: '32px'}" class="table-icon"></th>
<th colId="title" (click)="onSort('title')">{{lionFn('title')}}
- <onos-icon classes="active" [iconId]="sortIcon('title')"></onos-icon>
+ <onos-icon classes="active-sort" [iconSize]="10" [iconId]="sortIcon('title')"></onos-icon>
</th>
<th colId="id" (click)="onSort('id')">{{lionFn('app_id')}}
- <onos-icon classes="active" [iconId]="sortIcon('id')"></onos-icon>
+ <onos-icon classes="active-sort" [iconSize]="10" [iconId]="sortIcon('id')"></onos-icon>
</th>
<th colId="version" (click)="onSort('version')"> {{lionFn('version')}}
- <onos-icon classes="active" [iconId]="sortIcon('version')"></onos-icon>
+ <onos-icon classes="active-sort" [iconSize]="10" [iconId]="sortIcon('version')"></onos-icon>
</th>
<th colId="category" (click)="onSort('category')"> {{lionFn('category')}}
- <onos-icon classes="active" [iconId]="sortIcon('category')"></onos-icon>
+ <onos-icon classes="active-sort" [iconSize]="10" [iconId]="sortIcon('category')"></onos-icon>
</th>
<th colId="origin" (click)="onSort('origin')"> {{lionFn('origin')}}
- <onos-icon classes="active" [iconId]="sortIcon('origin')"></onos-icon>
+ <onos-icon classes="active-sort" [iconSize]="10" [iconId]="sortIcon('origin')"></onos-icon>
</th>
</tr>
</table>
</div>
<div class="table-body">
- <table onosTableResize>
+ <table>
<tr *ngIf="tableData.length === 0" class="no-data">
<td colspan="5">
{{annots.no_rows_msg}}
@@ -137,6 +137,6 @@
The advantage in 2) is that panel can be animated in and out, as it is not
killed every time the selection changes.
-->
- <onos-appsdetails class="floatpanels" id="{{ selId }}"></onos-appsdetails>
+ <onos-appsdetails class="floatpanels" id="{{ selId }}" (closeEvent)="deselectRow($event)"></onos-appsdetails>
</div>
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.spec.ts b/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.spec.ts
index cddf9ae..e022ebc 100644
--- a/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.spec.ts
+++ b/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.spec.ts
@@ -38,6 +38,7 @@
import { UrlFnService } from '../../../fw/remote/urlfn.service';
import { WebSocketService } from '../../../fw/remote/websocket.service';
import { of } from 'rxjs';
+import { } from 'jasmine';
class MockActivatedRoute extends ActivatedRoute {
constructor(params: Params) {
@@ -46,33 +47,33 @@
}
}
-class MockDialogService {}
+class MockDialogService { }
-class MockFnService {}
+class MockFnService { }
class MockHttpClient {}
class MockIconService {
- loadIconDef() {}
+ loadIconDef() { }
}
-class MockKeyService {}
+class MockKeyService { }
class MockLoadingService {
- startAnim() {}
- stop() {}
- waiting() {}
+ startAnim() { }
+ stop() { }
+ waiting() { }
}
-class MockThemeService {}
+class MockThemeService { }
-class MockUrlFnService {}
+class MockUrlFnService { }
class MockWebSocketService {
- createWebSocket() {}
+ createWebSocket() { }
isConnected() { return false; }
- unbindHandlers() {}
- bindHandlers() {}
+ unbindHandlers() { }
+ bindHandlers() { }
}
/**
@@ -90,21 +91,21 @@
test: 'test1'
}
};
- const mockLion = (key) => {
+ const mockLion = (key) => {
return bundleObj[key] || '%' + key + '%';
};
beforeEach(async(() => {
const logSpy = jasmine.createSpyObj('LogService', ['info', 'debug', 'warn', 'error']);
- ar = new MockActivatedRoute({'debug': 'txrx'});
+ ar = new MockActivatedRoute({ 'debug': 'txrx' });
windowMock = <any>{
- location: <any> {
+ location: <any>{
hostname: 'foo',
host: 'foo',
port: '80',
protocol: 'http',
- search: { debug: 'true'},
+ search: { debug: 'true' },
href: 'ws://foo:123/onos/ui/websock/path',
absUrl: 'ws://foo:123/onos/ui/websock/path'
}
@@ -127,7 +128,8 @@
{ provide: HttpClient, useClass: MockHttpClient },
{ provide: IconService, useClass: MockIconService },
{ provide: KeyService, useClass: MockKeyService },
- { provide: LionService, useFactory: (() => {
+ {
+ provide: LionService, useFactory: (() => {
return {
bundle: ((bundleId) => mockLion),
ubercache: new Array(),
@@ -143,7 +145,7 @@
{ provide: 'Window', useValue: windowMock },
]
})
- .compileComponents();
+ .compileComponents();
logServiceSpy = TestBed.get(LogService);
}));
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.ts b/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.ts
index ffd7b37..b2f6231 100644
--- a/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.ts
+++ b/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.ts
@@ -337,4 +337,13 @@
evt.preventDefault();
evt.stopPropagation();
}
+
+ deselectRow(event) {
+ this.log.debug('Details panel close event');
+ this.selId = event;
+ this.ctrlBtnState = <CtrlBtnState>{
+ installed: undefined,
+ active: undefined
+ };
+ }
}
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps/apps.theme.css b/web/gui2/src/main/webapp/app/view/apps/apps/apps.theme.css
index 13f1847..a705d45 100644
--- a/web/gui2/src/main/webapp/app/view/apps/apps/apps.theme.css
+++ b/web/gui2/src/main/webapp/app/view/apps/apps/apps.theme.css
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * 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.
@@ -41,7 +41,6 @@
#ov-app div.summary-list .table-body {
overflow:scroll;
- max-height:70vh;
}
#ov-app h2 {
display: inline-block;
diff --git a/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.css b/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.css
index ce9af3a..90d4b14 100644
--- a/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.css
+++ b/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.css
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-present Open Networking Foundation
+ * 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.
diff --git a/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.html b/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.html
index a78bdd9..d43c264 100644
--- a/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.html
+++ b/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.html
@@ -1,5 +1,5 @@
<!--
-~ Copyright 2014-present Open Networking Foundation
+~ 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.
diff --git a/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.spec.ts b/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.spec.ts
index f890cde..75f5f8e 100644
--- a/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.spec.ts
+++ b/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.spec.ts
@@ -21,10 +21,10 @@
import { LogService } from '../../../log.service';
import { AppsDetailsComponent } from './appsdetails.component';
-import { FnService } from '../../../../app/fw/util/fn.service';
-import { IconComponent } from '../../../../app/fw/svg/icon/icon.component';
-import { IconService } from '../../../../app/fw/svg/icon.service';
-import { LionService } from '../../../../app/fw/util/lion.service';
+import { FnService } from '../../../fw/util/fn.service';
+import { IconComponent } from '../../../fw/svg/icon/icon.component';
+import { IconService } from '../../../fw/svg/icon.service';
+import { LionService } from '../../../fw/util/lion.service';
import { UrlFnService } from '../../../fw/remote/urlfn.service';
import { WebSocketService } from '../../../fw/remote/websocket.service';
import { of } from 'rxjs';
diff --git a/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.ts b/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.ts
index 1e6ed29..c0d2e02 100644
--- a/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.ts
+++ b/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.ts
@@ -101,8 +101,20 @@
this.log.debug('App Details Component destroyed');
}
+ /**
+ * Details Panel Data Request on row selection changes
+ * Should be called whenever id changes
+ * If id is empty, no request is made
+ */
ngOnChanges() {
- this.requestDetailsPanelData(this.id);
+ if (this.id === '') {
+ return '';
+ } else {
+ const query = {
+ 'id': this.id
+ };
+ this.requestDetailsPanelData(query);
+ }
}
iconUrl(appId: string): string {