Fix UI issues

This commit is contained in:
Steven Zou 2017-06-22 16:44:34 +08:00
parent 283792e7c3
commit fde171bcb3
15 changed files with 92 additions and 35 deletions

View File

@ -48,8 +48,8 @@ export const TAG_DETAIL_HTML: string = `
</div>
</div>
<div class="second-column">
<div>{{highCount}} {{'VULNERABILITY.SEVERITY.HIGH' | translate }} {{suffixForHigh | translate }}</div>
<div class="second-row">{{mediumCount}} {{'VULNERABILITY.SEVERITY.MEDIUM' | translate }} {{suffixForMedium | translate }}</div>
<div>{{highCount}} {{getPackageText(highCount) | translate}} {{'VULNERABILITY.SEVERITY.HIGH' | translate }} {{suffixForHigh | translate }}</div>
<div class="second-row">{{mediumCount}} {{getPackageText(mediumCount) | translate}} {{'VULNERABILITY.SEVERITY.MEDIUM' | translate }} {{suffixForMedium | translate }}</div>
</div>
<div class="third-column">
<div>
@ -60,8 +60,8 @@ export const TAG_DETAIL_HTML: string = `
</div>
</div>
<div class="fourth-column">
<div>{{lowCount}} {{'VULNERABILITY.SEVERITY.LOW' | translate }} {{suffixForLow | translate }}</div>
<div class="second-row">{{unknownCount}} {{'VULNERABILITY.SEVERITY.UNKNOWN' | translate }} {{suffixForUnknown | translate }}</div>
<div>{{lowCount}} {{getPackageText(lowCount) | translate}} {{'VULNERABILITY.SEVERITY.LOW' | translate }} {{suffixForLow | translate }}</div>
<div class="second-row">{{unknownCount}} {{getPackageText(unknownCount) | translate}} {{'VULNERABILITY.SEVERITY.UNKNOWN' | translate }} {{suffixForUnknown | translate }}</div>
</div>
</div>
</div>

View File

@ -144,7 +144,7 @@ describe('TagDetailComponent (inline template)', () => {
expect(el).toBeTruthy();
let el2: HTMLElement = el.querySelector('div');
expect(el2).toBeTruthy();
expect(el2.textContent.trim()).toEqual("13 VULNERABILITY.SEVERITY.HIGH VULNERABILITY.PLURAL");
expect(el2.textContent.trim()).toEqual("13 VULNERABILITY.PACKAGES VULNERABILITY.SEVERITY.HIGH VULNERABILITY.PLURAL");
});
}));

View File

@ -75,8 +75,12 @@ export class TagDetailComponent implements OnInit {
this.backEvt.emit(this.tagId);
}
getPackageText(count: number): string {
return count > 1 ? "VULNERABILITY.PACKAGES" : "VULNERABILITY.PACKAGE";
}
public get author(): string {
return this.tagDetails && this.tagDetails.author? this.tagDetails.author: 'TAG.ANONYMITY';
return this.tagDetails && this.tagDetails.author ? this.tagDetails.author : 'TAG.ANONYMITY';
}
public get highCount(): number {

View File

@ -37,4 +37,9 @@ export const TAG_STYLE = `
white-space: nowrap;
text-overflow:ellipsis;
}
.copy-failed {
color: red;
margin-right: 6px;
}
`;

View File

@ -4,11 +4,12 @@ export const TAG_TEMPLATE = `
<h3 class="modal-title">{{ manifestInfoTitle | translate }}</h3>
<div class="modal-body">
<div class="row col-md-12">
<textarea rows="3" (click)="selectAndCopy($event)">{{digestId}}</textarea>
<textarea rows="2" #digestTarget>{{digestId}}</textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" (click)="showTagManifestOpened = false">{{'BUTTON.OK' | translate}}</button>
<span class="copy-failed" [hidden]="!copyFailed">{{'TAG.COPY_ERROR' | translate}}</span>
<button type="button" class="btn btn-primary" [ngxClipboard]="digestTarget" (cbOnSuccess)="onSuccess($event)" (cbOnError)="onError($event)">{{'BUTTON.COPY' | translate}}</button>
</div>
</clr-modal>
@ -54,6 +55,6 @@ export const TAG_TEMPLATE = `
<clr-dg-footer>
{{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} {{'REPOSITORY.OF' | translate}}
{{pagination.totalItems}} {{'REPOSITORY.ITEMS' | translate}}&nbsp;&nbsp;&nbsp;&nbsp;
<clr-dg-pagination #pagination [clrDgPageSize]="5"></clr-dg-pagination>
<clr-dg-pagination #pagination [clrDgPageSize]="10"></clr-dg-pagination>
</clr-dg-footer>
</clr-datagrid>`;

View File

@ -20,6 +20,7 @@ import {
EventEmitter,
ChangeDetectionStrategy,
ChangeDetectorRef,
ElementRef,
OnDestroy
} from '@angular/core';
@ -87,9 +88,13 @@ export class TagComponent implements OnInit, OnDestroy {
tagsInScanning: { [key: string]: any } = {};
scanningTagCount: number = 0;
copyFailed: boolean = false;
@ViewChild('confirmationDialog')
confirmationDialog: ConfirmationDialogComponent;
@ViewChild('digestTarget') textInput: ElementRef;
constructor(
private errorHandler: ErrorHandler,
private tagService: TagService,
@ -195,13 +200,10 @@ export class TagComponent implements OnInit, OnDestroy {
this.manifestInfoTitle = 'REPOSITORY.COPY_DIGEST_ID';
this.digestId = tag.digest;
this.showTagManifestOpened = true;
this.copyFailed = false;
}
}
selectAndCopy($event: any) {
$event.target.select();
}
onTagClick(tag: Tag): void {
if (tag) {
let evt: TagClickEvent = {
@ -255,4 +257,19 @@ export class TagComponent implements OnInit, OnDestroy {
let hnd = setInterval(() => this.ref.markForCheck(), 100);
setTimeout(() => clearInterval(hnd), 1000);
}
onSuccess($event: any): void {
this.copyFailed = false;
//Directly close dialog
this.showTagManifestOpened = false;
}
onError($event: any): void {
//Show error
this.copyFailed = true;
//Select all text
if(this.textInput){
this.textInput.nativeElement.select();
}
}
}

View File

@ -1,16 +1,34 @@
export const SCANNING_STYLES: string = `
.bar-wrapper {
width: 120px;
height: 12px;
}
.bar-state {
text-align: center !important;
}
.bar-state-chart {
position: relative;
top: 2px;
}
.bar-state-error {
position: relative;
top: -3px;
}
.error-text {
position: relative;
top: 1px;
margin-left: -5px;
}
.scanning-button {
height: 24px;
margin-top: 0px;
margin-bottom: 0px;
vertical-align: middle;
top: -6px;
top: -12px;
position: relative;
}
.tip-wrapper {

View File

@ -56,7 +56,7 @@ export const GRID_COMPONENT_HTML: string = `
<clr-dg-column [clrDgField]="'id'">{{'VULNERABILITY.GRID.COLUMN_ID' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'severity'">{{'VULNERABILITY.GRID.COLUMN_SEVERITY' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'package'">{{'VULNERABILITY.GRID.COLUMN_PACKAGE' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'version'">{{'VULNERABILITY.GRID.COLUMN_VERSION' | translate}} version</clr-dg-column>
<clr-dg-column [clrDgField]="'version'">{{'VULNERABILITY.GRID.COLUMN_VERSION' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'fixedVersion'">{{'VULNERABILITY.GRID.COLUMN_FIXED' | translate}}</clr-dg-column>
<clr-dg-placeholder>{{'VULNERABILITY.GRID.PLACEHOLDER' | translate}}</clr-dg-placeholder>
@ -94,15 +94,15 @@ export const BAR_CHART_COMPONENT_HTML: string = `
<div *ngIf="queued" class="bar-state">
<span>{{'VULNERABILITY.STATE.QUEUED' | translate}}</span>
</div>
<div *ngIf="error" class="bar-state">
<div *ngIf="error" class="bar-state bar-state-error">
<clr-icon shape="info-circle" class="is-error" size="24"></clr-icon>
<span style="margin-left:-5px;">{{'VULNERABILITY.STATE.ERROR' | translate}}</span>
<span class="error-text">{{'VULNERABILITY.STATE.ERROR' | translate}}</span>
</div>
<div *ngIf="scanning" class="bar-state">
<div *ngIf="scanning" class="bar-state bar-state-chart">
<div>{{'VULNERABILITY.STATE.SCANNING' | translate}}</div>
<div class="progress loop" style="height:2px;min-height:2px;"><progress></progress></div>
</div>
<div *ngIf="completed" class="bar-state">
<div *ngIf="completed" class="bar-state bar-state-chart" style="z-index:1020;">
<hbr-vulnerability-summary-chart [summary]="summary"></hbr-vulnerability-summary-chart>
</div>
<div *ngIf="unknown" class="bar-state">

View File

@ -31,7 +31,7 @@
"clarity-icons": "^0.9.8",
"clarity-ui": "^0.9.8",
"core-js": "^2.4.1",
"harbor-ui": "^0.2.13",
"harbor-ui": "^0.2.19",
"intl": "^1.2.5",
"mutationobserver-shim": "^0.3.2",
"ngx-cookie": "^1.0.0",

View File

@ -11,6 +11,6 @@
</clr-dg-row>
<clr-dg-footer>
{{(projects ? projects.length : 0)}} {{'PROJECT.ITEMS' | translate}}
<clr-dg-pagination [clrDgPageSize]="5"></clr-dg-pagination>
<clr-dg-pagination [clrDgPageSize]="15"></clr-dg-pagination>
</clr-dg-footer>
</clr-datagrid>

View File

@ -9,6 +9,6 @@
</clr-dg-row>
<clr-dg-footer>
{{(repositories ? repositories.length : 0)}} {{'REPOSITORY.ITEMS' | translate}}
<clr-dg-pagination [clrDgPageSize]="3"></clr-dg-pagination>
<clr-dg-pagination [clrDgPageSize]="15"></clr-dg-pagination>
</clr-dg-footer>
</clr-datagrid>

View File

@ -63,8 +63,8 @@ const uiLibConfig: IServiceConfig = {
enablei18Support: true,
langCookieKey: "harbor-lang",
langMessageLoader: "http",
langMessagePathForHttpLoader: "src/i18n/lang/",
langMessageFileSuffixForHttpLoader: "-lang.json",
langMessagePathForHttpLoader: "i18n/lang/",
langMessageFileSuffixForHttpLoader: "-lang.json"
};
@NgModule({

View File

@ -31,7 +31,8 @@
"MORE_INFO": "More info...",
"YES": "YES",
"NO": "NO",
"NEGATIVE": "NEGATIVE"
"NEGATIVE": "NEGATIVE",
"COPY": "COPY"
},
"TOOLTIP": {
"EMAIL": "Email should be a valid email address like name@example.com.",
@ -477,7 +478,9 @@
},
"SINGULAR": "Vulnerability",
"PLURAL": "Vulnerabilities",
"PLACEHOLDER": "Filter Vulnerabilities"
"PLACEHOLDER": "Filter Vulnerabilities",
"PACKAGE": "Package with",
"PACKAGES": "Packages with"
},
"PUSH_IMAGE": {
"TITLE": "Push Image",
@ -496,7 +499,8 @@
"OS": "OS",
"SCAN_COMPLETION_TIME": "Scan Completed",
"IMAGE_VULNERABILITIES": "Image Vulnerabilities",
"PLACEHOLDER": "We couldn't find any tags!"
"PLACEHOLDER": "We couldn't find any tags!",
"COPY_ERROR": "Copy failed, please try to manually copy."
},
"UNKNOWN_ERROR": "Unknown errors have occurred. Please try again later.",
"UNAUTHORIZED_ERROR": "Your session is invalid or has expired. You need to sign in to continue your action.",

View File

@ -31,7 +31,8 @@
"MORE_INFO": "Más información...",
"YES": "SI",
"NO": "NO",
"NEGATIVE": "NEGATIVO"
"NEGATIVE": "NEGATIVO",
"COPY": "COPY"
},
"TOOLTIP": {
"EMAIL": "El email debe ser una dirección válida como nombre@ejemplo.com.",
@ -476,7 +477,9 @@
},
"SINGULAR": "Vulnerability",
"PLURAL": "Vulnerabilities",
"PLACEHOLDER": "Filter Vulnerabilities"
"PLACEHOLDER": "Filter Vulnerabilities",
"PACKAGE": "Package with",
"PACKAGES": "Packages with"
},
"PUSH_IMAGE": {
"TITLE": "Push Image",
@ -495,7 +498,8 @@
"OS": "OS",
"SCAN_COMPLETION_TIME": "Scan Completed",
"IMAGE_VULNERABILITIES": "Image Vulnerabilities",
"PLACEHOLDER": "We couldn't find any tags!"
"PLACEHOLDER": "We couldn't find any tags!",
"COPY_ERROR": "Copy failed, please try to manually copy."
},
"UNKNOWN_ERROR": "Ha ocurrido un error desconocido. Por favor, inténtelo de nuevo más tarde.",
"UNAUTHORIZED_ERROR": "La sesión no es válida o ha caducado. Necesita identificarse de nuevo para llevar a cabo esa acción.",

View File

@ -31,7 +31,8 @@
"MORE_INFO": "更多信息...",
"YES": "是",
"NO": "否",
"NEGATIVE": "否"
"NEGATIVE": "否",
"COPY": "拷贝"
},
"TOOLTIP": {
"EMAIL": "请使用正确的邮箱地址比如name@example.com。",
@ -456,7 +457,7 @@
"PLACEHOLDER": "没有扫描结果!",
"COLUMN_ID": "缺陷码",
"COLUMN_SEVERITY": "严重度",
"COLUMN_PACKAGE": "组",
"COLUMN_PACKAGE": "组",
"COLUMN_VERSION": "当前版本",
"COLUMN_FIXED": "修复版本",
"COLUMN_DESCRIPTION": "简介",
@ -477,7 +478,9 @@
},
"SINGULAR": "缺陷",
"PLURAL": "缺陷",
"PLACEHOLDER": "过滤缺陷"
"PLACEHOLDER": "过滤缺陷",
"PACKAGE": "个组件有",
"PACKAGES": "个组件有"
},
"PUSH_IMAGE": {
"TITLE": "推送镜像",
@ -496,7 +499,8 @@
"OS": "操作系统",
"SCAN_COMPLETION_TIME": "扫描完成时间",
"IMAGE_VULNERABILITIES": "镜像缺陷",
"PLACEHOLDER": "未发现任何标签!"
"PLACEHOLDER": "未发现任何标签!",
"COPY_ERROR": "拷贝失败,请尝试手动拷贝。"
},
"UNKNOWN_ERROR": "发生未知错误,请稍后再试。",
"UNAUTHORIZED_ERROR": "会话无效或者已经过期, 请重新登录以继续。",