Improve event panel (#14664)

Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
Will Sun 2021-04-15 16:44:58 +08:00 committed by GitHub
parent ba4a6d94ef
commit 45663e002d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 66 deletions

View File

@ -15,7 +15,7 @@
<clr-icon class="clr-validate-icon" shape="exclamation-circle"></clr-icon> <clr-icon class="clr-validate-icon" shape="exclamation-circle"></clr-icon>
</div> </div>
<clr-control-error *ngIf="!getValidationState('newPassword')"> <clr-control-error *ngIf="!getValidationState('newPassword')">
{{ 'TOOLTIP.SIGN_IN_PWD' | translate }} {{ 'TOOLTIP.PASSWORD' | translate }}
</clr-control-error> </clr-control-error>
</div> </div>
</div> </div>

View File

@ -42,9 +42,23 @@
text-decoration: none; text-decoration: none;
} }
.freshIcon{float: right; margin-right: 20px; margin-top: -10px;cursor: pointer;} .freshIcon{float: right; margin-right: 20px; margin-top: -10px;cursor: pointer;}
#contentFailed, #contentAll, #contentRun{ :host::ng-deep#contentAll{
position: absolute; position: absolute;
top: 95px; top: 115px;
bottom: 0;
width: 100%;
overflow-y: auto;
}
:host::ng-deep#contentFailed{
position: absolute;
top: 115px;
bottom: 0;
width: 100%;
overflow-y: auto;
}
:host::ng-deep#contentRun{
position: absolute;
top: 115px;
bottom: 0; bottom: 0;
width: 100%; width: 100%;
overflow-y: auto; overflow-y: auto;

View File

@ -1,10 +1,7 @@
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { TranslateService } from "@ngx-translate/core";
import { OperationComponent } from './operation.component'; import { OperationComponent } from './operation.component';
import { OperationService } from './operation.service'; import { OperationService } from './operation.service';
import { OperateInfo } from './operate'; import { OperateInfo } from './operate';
import { CURRENT_BASE_HREF } from "../../units/utils";
import { SharedTestingModule } from "../../shared.module"; import { SharedTestingModule } from "../../shared.module";
describe('OperationComponent', () => { describe('OperationComponent', () => {
@ -15,11 +12,6 @@ describe('OperationComponent', () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [
SharedTestingModule, SharedTestingModule,
BrowserAnimationsModule,
],
providers: [
OperationService,
TranslateService,
] ]
}); });
}); });
@ -47,9 +39,9 @@ describe('OperationComponent', () => {
const right: string = getComputedStyle(fixture.nativeElement.querySelector(".operDiv")).right; const right: string = getComputedStyle(fixture.nativeElement.querySelector(".operDiv")).right;
expect(right).toEqual("-325px"); expect(right).toEqual("-325px");
})); }));
it("should show '50+' after pushing 60 new operateInfos", fakeAsync(() => { it("should show '500+' after pushing 60 new operateInfos", fakeAsync(() => {
const operationService: OperationService = TestBed.get(OperationService); const operationService: OperationService = TestBed.inject(OperationService);
for (let i = 0; i < 60; i++) { for (let i = 0; i < 520; i++) {
let operateInfo = new OperateInfo(); let operateInfo = new OperateInfo();
if (i > 19) { if (i > 19) {
operateInfo.state = "progressing"; operateInfo.state = "progressing";
@ -62,7 +54,7 @@ describe('OperationComponent', () => {
} }
fixture.detectChanges(); fixture.detectChanges();
const toolBar: HTMLAnchorElement = fixture.nativeElement.querySelector(".toolBar"); const toolBar: HTMLAnchorElement = fixture.nativeElement.querySelector(".toolBar");
expect(toolBar.textContent).toContain('50+'); expect(toolBar.textContent).toContain('500+');
})); }));
it('check toggleTitle function', () => { it('check toggleTitle function', () => {
const errorSpan: HTMLSpanElement = document.createElement('span'); const errorSpan: HTMLSpanElement = document.createElement('span');

View File

@ -1,10 +1,14 @@
import {Component, OnInit, OnDestroy, HostListener} from '@angular/core'; import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
import {OperationService} from "./operation.service"; import { OperationService } from "./operation.service";
import {Subscription} from "rxjs"; import { Subscription } from "rxjs";
import {OperateInfo, OperationState} from "./operate"; import { OperateInfo, OperationState } from "./operate";
import {SlideInOutAnimation} from "../../_animations/slide-in-out.animation"; import { SlideInOutAnimation } from "../../_animations/slide-in-out.animation";
import {TranslateService} from "@ngx-translate/core"; import { TranslateService } from "@ngx-translate/core";
import { SessionService } from "../../services/session.service";
const OPERATION_KEY: string = 'operation';
const MAX_NUMBER: number = 500;
const MAX_SAVING_TIME: number = 1000 * 60 * 60 * 24 * 30; // 30 days
@Component({ @Component({
selector: 'hbr-operation-model', selector: 'hbr-operation-model',
@ -21,13 +25,21 @@ export class OperationComponent implements OnInit, OnDestroy {
@HostListener('window:beforeunload', ['$event']) @HostListener('window:beforeunload', ['$event'])
beforeUnloadHander(event) { beforeUnloadHander(event) {
// storage to localStorage if (this.session.getCurrentUser()) {
let timp = new Date().getTime(); // storage to localStorage
localStorage.setItem('operaion', JSON.stringify({timp: timp, data: this.resultLists})); const timp = new Date().getTime();
localStorage.setItem('newMessageCount', this._newMessageCount.toString()); // group by user id
localStorage.setItem(`${OPERATION_KEY}-${this.session.getCurrentUser().user_id}`,
JSON.stringify({
timp: timp,
data: this.resultLists,
newMessageCount: this._newMessageCount
}));
}
} }
constructor( constructor(
private session: SessionService,
private operationService: OperationService, private operationService: OperationService,
private translate: TranslateService) { private translate: TranslateService) {
@ -36,8 +48,8 @@ export class OperationComponent implements OnInit, OnDestroy {
this._newMessageCount += 1; this._newMessageCount += 1;
} }
if (data) { if (data) {
if (this.resultLists.length >= 50) { if (this.resultLists.length >= MAX_NUMBER) {
this.resultLists.splice(49, this.resultLists.length - 49); this.resultLists.splice(MAX_NUMBER - 1, this.resultLists.length + 1 - MAX_NUMBER);
} }
this.resultLists.unshift(data); this.resultLists.unshift(data);
} }
@ -46,29 +58,33 @@ export class OperationComponent implements OnInit, OnDestroy {
getNewMessageCountStr(): string { getNewMessageCountStr(): string {
if (this._newMessageCount) { if (this._newMessageCount) {
if (this._newMessageCount > 50) { if (this._newMessageCount > MAX_NUMBER) {
return 50 + '+'; return MAX_NUMBER + '+';
} }
return this._newMessageCount.toString(); return this._newMessageCount.toString();
} }
return ''; return '';
} }
resetNewMessageCount() { resetNewMessageCount() {
this._newMessageCount = 0; this._newMessageCount = 0;
} }
mouseover() { mouseover() {
if (this._timeoutInterval) { if (this._timeoutInterval) {
clearInterval(this._timeoutInterval); clearInterval(this._timeoutInterval);
this._timeoutInterval = null; this._timeoutInterval = null;
} }
} }
mouseleave() { mouseleave() {
if (!this._timeoutInterval) { if (!this._timeoutInterval) {
this._timeoutInterval = setTimeout(() => { this._timeoutInterval = setTimeout(() => {
this.animationState = 'out'; this.animationState = 'out';
}, 5000); }, 5000);
} }
} }
public get runningLists(): OperateInfo[] { public get runningLists(): OperateInfo[] {
let runningList: OperateInfo[] = []; let runningList: OperateInfo[] = [];
this.resultLists.forEach(data => { this.resultLists.forEach(data => {
@ -89,29 +105,38 @@ export class OperationComponent implements OnInit, OnDestroy {
return failedList; return failedList;
} }
ngOnInit() { init() {
this._newMessageCount = +localStorage.getItem('newMessageCount'); if (this.session.getCurrentUser()) {
let requestCookie = localStorage.getItem('operaion'); let requestCookie = localStorage.getItem(`${OPERATION_KEY}-${this.session.getCurrentUser().user_id}`);
if (requestCookie) { if (requestCookie) {
let operInfors: any = JSON.parse(requestCookie); let operInfors: any = JSON.parse(requestCookie);
if (operInfors) { if (operInfors) {
if ((new Date().getTime() - operInfors.timp) > 1000 * 60 * 60 * 24) { if (operInfors.newMessageCount) {
localStorage.removeItem('operaion'); this._newMessageCount = operInfors.newMessageCount;
} else { }
if (operInfors.data) { if ((new Date().getTime() - operInfors.timp) > MAX_SAVING_TIME) {
operInfors.data.forEach(operInfo => { localStorage.removeItem(`${OPERATION_KEY}-${this.session.getCurrentUser().user_id}`);
if (operInfo.state === OperationState.progressing) { } else {
operInfo.state = OperationState.interrupt; if (operInfors.data) {
operInfo.data.errorInf = 'operation been interrupted'; operInfors.data.forEach(operInfo => {
} if (operInfo.state === OperationState.progressing) {
}); operInfo.state = OperationState.interrupt;
this.resultLists = operInfors.data; operInfo.data.errorInf = 'operation been interrupted';
}
});
this.resultLists = operInfors.data;
}
} }
} }
}
}
} }
} }
ngOnInit() {
this.init();
}
ngOnDestroy(): void { ngOnDestroy(): void {
if (this.batchInfoSubscription) { if (this.batchInfoSubscription) {
this.batchInfoSubscription.unsubscribe(); this.batchInfoSubscription.unsubscribe();
@ -144,8 +169,8 @@ export class OperationComponent implements OnInit, OnDestroy {
TabEvent(): void { TabEvent(): void {
let timp: any; let timp: any;
this.resultLists.forEach(data => { this.resultLists.forEach(data => {
timp = new Date().getTime() - +data.timeStamp; timp = new Date().getTime() - +data.timeStamp;
data.timeDiff = this.calculateTime(timp); data.timeDiff = this.calculateTime(timp);
}); });
} }
@ -155,29 +180,15 @@ export class OperationComponent implements OnInit, OnDestroy {
return Math.floor(dist) + ' minute(s) ago'; return Math.floor(dist) + ' minute(s) ago';
} else if (dist >= 60 && Math.floor(dist / 60) < 24) { } else if (dist >= 60 && Math.floor(dist / 60) < 24) {
return Math.floor(dist / 60) + ' hour(s) ago'; return Math.floor(dist / 60) + ' hour(s) ago';
} else if (Math.floor(dist / 60) >= 24) { } else if (Math.floor(dist / 60) >= 24) {
return Math.floor(dist / 60 / 24) + ' day(s) ago'; return Math.floor(dist / 60 / 24) + ' day(s) ago';
} else { } else {
return 'less than 1 minute'; return 'less than 1 minute';
} }
} }
/*calculateTime(timp: number) {
let dist = Math.floor(timp / 1000 / 60); // change to minute;
if (dist > 0 && dist < 60) {
return this.translateTime('OPERATION.MINUTE_AGO', Math.floor(dist));
}else if (dist > 60 && Math.floor(dist / 60) < 24) {
return this.translateTime('OPERATION.HOUR_AGO', Math.floor(dist / 60));
} else if (Math.floor(dist / 60) >= 24 && Math.floor(dist / 60) <= 48) {
return this.translateTime('OPERATION.DAY_AGO', Math.floor(dist / 60 / 24));
} else {
return this.translateTime('OPERATION.SECOND_AGO');
}
}*/
translateTime(tim: string, param?: number) { translateTime(tim: string, param?: number) {
this.translate.get(tim, { 'param': param }).subscribe((res: string) => { this.translate.get(tim, {'param': param}).subscribe((res: string) => {
return res; return res;
}); });
} }