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>
</div>
<clr-control-error *ngIf="!getValidationState('newPassword')">
{{ 'TOOLTIP.SIGN_IN_PWD' | translate }}
{{ 'TOOLTIP.PASSWORD' | translate }}
</clr-control-error>
</div>
</div>

View File

@ -42,9 +42,23 @@
text-decoration: none;
}
.freshIcon{float: right; margin-right: 20px; margin-top: -10px;cursor: pointer;}
#contentFailed, #contentAll, #contentRun{
:host::ng-deep#contentAll{
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;
width: 100%;
overflow-y: auto;

View File

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

View File

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