mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-21 08:07:59 +01:00
Merge pull request #9839 from AllForNothing/unexpected
Fix tag select bug in tag component
This commit is contained in:
commit
9367b3f240
@ -55,10 +55,10 @@
|
|||||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||||
<clr-datagrid [clrDgLoading]="loading" class="datagrid-top" [class.embeded-datagrid]="isEmbedded" [(clrDgSelected)]="selectedRow">
|
<clr-datagrid [clrDgLoading]="loading" class="datagrid-top" [class.embeded-datagrid]="isEmbedded" [(clrDgSelected)]="selectedRow">
|
||||||
<clr-dg-action-bar>
|
<clr-dg-action-bar>
|
||||||
<button [clrLoading]="scanBtnState" type="button" class="btn btn-sm btn-secondary" [disabled]="!(canScanNow(selectedRow) && selectedRow.length==1 && hasEnabledScanner)" (click)="scanNow(selectedRow)"><clr-icon shape="shield-check" size="16"></clr-icon> {{'VULNERABILITY.SCAN_NOW' | translate}}</button>
|
<button [clrLoading]="scanBtnState" type="button" class="btn btn-sm btn-secondary" [disabled]="!(canScanNow() && selectedRow.length==1 && hasEnabledScanner)" (click)="scanNow()"><clr-icon shape="shield-check" size="16"></clr-icon> {{'VULNERABILITY.SCAN_NOW' | translate}}</button>
|
||||||
<button type="button" class="btn btn-sm btn-secondary" [disabled]="!(selectedRow.length==1)" (click)="showDigestId(selectedRow)"><clr-icon shape="copy" size="16"></clr-icon> {{'REPOSITORY.COPY_DIGEST_ID' | translate}}</button>
|
<button type="button" class="btn btn-sm btn-secondary" [disabled]="!(selectedRow.length==1)" (click)="showDigestId()"><clr-icon shape="copy" size="16"></clr-icon> {{'REPOSITORY.COPY_DIGEST_ID' | translate}}</button>
|
||||||
<clr-dropdown *ngIf="!withAdmiral">
|
<clr-dropdown *ngIf="!withAdmiral">
|
||||||
<button type="button" class="btn btn-sm btn-secondary" clrDropdownTrigger [disabled]="!(selectedRow.length==1)||!hasAddLabelImagePermission" (click)="addLabels(selectedRow)"><clr-icon shape="plus" size="16"></clr-icon>{{'REPOSITORY.ADD_LABELS' | translate}}</button>
|
<button type="button" class="btn btn-sm btn-secondary" clrDropdownTrigger [disabled]="!(selectedRow.length==1)||!hasAddLabelImagePermission" (click)="addLabels()"><clr-icon shape="plus" size="16"></clr-icon>{{'REPOSITORY.ADD_LABELS' | translate}}</button>
|
||||||
<clr-dropdown-menu clrPosition="bottom-left" *clrIfOpen>
|
<clr-dropdown-menu clrPosition="bottom-left" *clrIfOpen>
|
||||||
<clr-dropdown>
|
<clr-dropdown>
|
||||||
<div class="filter-grid">
|
<div class="filter-grid">
|
||||||
@ -75,8 +75,8 @@
|
|||||||
</clr-dropdown>
|
</clr-dropdown>
|
||||||
</clr-dropdown-menu>
|
</clr-dropdown-menu>
|
||||||
</clr-dropdown>
|
</clr-dropdown>
|
||||||
<button type="button" class="btn btn-sm btn-secondary" *ngIf="!withAdmiral" [disabled]="!(selectedRow.length===1)|| !hasRetagImagePermission" (click)="retag(selectedRow)"><clr-icon shape="copy" size="16"></clr-icon> {{'REPOSITORY.RETAG' | translate}}</button>
|
<button type="button" class="btn btn-sm btn-secondary" *ngIf="!withAdmiral" [disabled]="!(selectedRow.length===1)|| !hasRetagImagePermission" (click)="retag()"><clr-icon shape="copy" size="16"></clr-icon> {{'REPOSITORY.RETAG' | translate}}</button>
|
||||||
<button type="button" class="btn btn-sm btn-secondary" *ngIf="hasDeleteImagePermission" (click)="deleteTags(selectedRow)" [disabled]="!hasDeleteImagePermission||!selectedRow.length"><clr-icon shape="times" size="16"></clr-icon> {{'REPOSITORY.DELETE' | translate}}</button>
|
<button type="button" class="btn btn-sm btn-secondary" *ngIf="hasDeleteImagePermission" (click)="deleteTags()" [disabled]="!hasDeleteImagePermission||!selectedRow.length"><clr-icon shape="times" size="16"></clr-icon> {{'REPOSITORY.DELETE' | translate}}</button>
|
||||||
</clr-dg-action-bar>
|
</clr-dg-action-bar>
|
||||||
<clr-dg-column class="flex-max-width" [clrDgField]="'name'">{{'REPOSITORY.TAG' | translate}}</clr-dg-column>
|
<clr-dg-column class="flex-max-width" [clrDgField]="'name'">{{'REPOSITORY.TAG' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'size'">{{'REPOSITORY.SIZE' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'size'">{{'REPOSITORY.SIZE' | translate}}</clr-dg-column>
|
||||||
@ -109,7 +109,7 @@
|
|||||||
</clr-dg-cell>
|
</clr-dg-cell>
|
||||||
<clr-dg-cell>
|
<clr-dg-cell>
|
||||||
<div class="cell">
|
<div class="cell">
|
||||||
<hbr-vulnerability-bar [repoName]="repoName" [tagId]="t.name" [summary]="handleScanOverview(t.scan_overview)"></hbr-vulnerability-bar>
|
<hbr-vulnerability-bar (submitFinish)="submitFinish($event)" [repoName]="repoName" [tagId]="t.name" [summary]="handleScanOverview(t.scan_overview)"></hbr-vulnerability-bar>
|
||||||
</div>
|
</div>
|
||||||
</clr-dg-cell>
|
</clr-dg-cell>
|
||||||
<clr-dg-cell *ngIf="withNotary" [ngSwitch]="t.signature !== null">
|
<clr-dg-cell *ngIf="withNotary" [ngSwitch]="t.signature !== null">
|
||||||
|
@ -153,6 +153,7 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
hasScanImagePermission: boolean;
|
hasScanImagePermission: boolean;
|
||||||
hasEnabledScanner: boolean;
|
hasEnabledScanner: boolean;
|
||||||
scanBtnState: ClrLoadingState = ClrLoadingState.DEFAULT;
|
scanBtnState: ClrLoadingState = ClrLoadingState.DEFAULT;
|
||||||
|
onSendingScanCommand: boolean;
|
||||||
constructor(
|
constructor(
|
||||||
private errorHandler: ErrorHandler,
|
private errorHandler: ErrorHandler,
|
||||||
private tagService: TagService,
|
private tagService: TagService,
|
||||||
@ -318,11 +319,11 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addLabels(tag: Tag[]): void {
|
addLabels(): void {
|
||||||
this.labelListOpen = true;
|
this.labelListOpen = true;
|
||||||
this.selectedTag = tag;
|
this.selectedTag = this.selectedRow;
|
||||||
this.stickName = '';
|
this.stickName = '';
|
||||||
this.labelSelectedChange(tag);
|
this.labelSelectedChange(this.selectedRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
stickLabel(labelInfo: LabelState): void {
|
stickLabel(labelInfo: LabelState): void {
|
||||||
@ -558,10 +559,10 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retag(tags: Tag[]) {
|
retag() {
|
||||||
if (tags && tags.length) {
|
if (this.selectedRow && this.selectedRow.length) {
|
||||||
this.retagDialogOpened = true;
|
this.retagDialogOpened = true;
|
||||||
this.retagSrcImage = this.repoName + ":" + tags[0].digest;
|
this.retagSrcImage = this.repoName + ":" + this.selectedRow[0].digest;
|
||||||
} else {
|
} else {
|
||||||
this.errorHandler.error("One tag should be selected before retag.");
|
this.errorHandler.error("One tag should be selected before retag.");
|
||||||
}
|
}
|
||||||
@ -588,10 +589,10 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteTags(tags: Tag[]) {
|
deleteTags() {
|
||||||
if (tags && tags.length) {
|
if (this.selectedRow && this.selectedRow.length) {
|
||||||
let tagNames: string[] = [];
|
let tagNames: string[] = [];
|
||||||
tags.forEach(tag => {
|
this.selectedRow.forEach(tag => {
|
||||||
tagNames.push(tag.name);
|
tagNames.push(tag.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -604,7 +605,7 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
titleKey,
|
titleKey,
|
||||||
summaryKey,
|
summaryKey,
|
||||||
content,
|
content,
|
||||||
tags,
|
this.selectedRow,
|
||||||
ConfirmationTargets.TAG,
|
ConfirmationTargets.TAG,
|
||||||
buttons);
|
buttons);
|
||||||
this.confirmationDialog.open(message);
|
this.confirmationDialog.open(message);
|
||||||
@ -670,10 +671,10 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showDigestId(tag: Tag[]) {
|
showDigestId() {
|
||||||
if (tag && (tag.length === 1)) {
|
if (this.selectedRow && (this.selectedRow.length === 1)) {
|
||||||
this.manifestInfoTitle = "REPOSITORY.COPY_DIGEST_ID";
|
this.manifestInfoTitle = "REPOSITORY.COPY_DIGEST_ID";
|
||||||
this.digestId = tag[0].digest;
|
this.digestId = this.selectedRow[0].digest;
|
||||||
this.showTagManifestOpened = true;
|
this.showTagManifestOpened = true;
|
||||||
this.copyFailed = false;
|
this.copyFailed = false;
|
||||||
}
|
}
|
||||||
@ -716,9 +717,10 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
return VULNERABILITY_SCAN_STATUS.NOT_SCANNED;
|
return VULNERABILITY_SCAN_STATUS.NOT_SCANNED;
|
||||||
}
|
}
|
||||||
// Whether show the 'scan now' menu
|
// Whether show the 'scan now' menu
|
||||||
canScanNow(t: Tag[]): boolean {
|
canScanNow(): boolean {
|
||||||
if (!this.hasScanImagePermission) { return false; }
|
if (!this.hasScanImagePermission) { return false; }
|
||||||
let st: string = this.scanStatus(t[0]);
|
if (this.onSendingScanCommand) { return false; }
|
||||||
|
let st: string = this.scanStatus(this.selectedRow[0]);
|
||||||
return st !== VULNERABILITY_SCAN_STATUS.RUNNING;
|
return st !== VULNERABILITY_SCAN_STATUS.RUNNING;
|
||||||
}
|
}
|
||||||
getImagePermissionRule(projectId: number): void {
|
getImagePermissionRule(projectId: number): void {
|
||||||
@ -742,15 +744,18 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
}, error => this.errorHandler.error(error));
|
}, error => this.errorHandler.error(error));
|
||||||
}
|
}
|
||||||
// Trigger scan
|
// Trigger scan
|
||||||
scanNow(t: Tag[]): void {
|
scanNow(): void {
|
||||||
if (t && t.length) {
|
if (this.selectedRow && this.selectedRow.length) {
|
||||||
t.forEach((data: any) => {
|
this.selectedRow.forEach((data: any) => {
|
||||||
let tagId = data.name;
|
let tagId = data.name;
|
||||||
|
this.onSendingScanCommand = true;
|
||||||
this.channel.publishScanEvent(this.repoName + "/" + tagId);
|
this.channel.publishScanEvent(this.repoName + "/" + tagId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
submitFinish(e: boolean) {
|
||||||
|
this.onSendingScanCommand = e;
|
||||||
|
}
|
||||||
// pull command
|
// pull command
|
||||||
onCpError($event: any): void {
|
onCpError($event: any): void {
|
||||||
this.copyInput.setPullCommendShow();
|
this.copyInput.setPullCommendShow();
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
OnInit,
|
OnInit,
|
||||||
OnDestroy,
|
OnDestroy,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef, Output, EventEmitter,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { Subscription , timer} from "rxjs";
|
import { Subscription , timer} from "rxjs";
|
||||||
|
|
||||||
@ -17,6 +17,7 @@ import {
|
|||||||
import { ErrorHandler } from '../error-handler/index';
|
import { ErrorHandler } from '../error-handler/index';
|
||||||
import { ChannelService } from '../channel/index';
|
import { ChannelService } from '../channel/index';
|
||||||
import { JobLogService } from "../service/index";
|
import { JobLogService } from "../service/index";
|
||||||
|
import { finalize } from "rxjs/operators";
|
||||||
|
|
||||||
const STATE_CHECK_INTERVAL: number = 3000; // 3s
|
const STATE_CHECK_INTERVAL: number = 3000; // 3s
|
||||||
const RETRY_TIMES: number = 3;
|
const RETRY_TIMES: number = 3;
|
||||||
@ -35,6 +36,8 @@ export class ResultBarChartComponent implements OnInit, OnDestroy {
|
|||||||
stateCheckTimer: Subscription;
|
stateCheckTimer: Subscription;
|
||||||
scanSubscription: Subscription;
|
scanSubscription: Subscription;
|
||||||
timerHandler: any;
|
timerHandler: any;
|
||||||
|
@Output()
|
||||||
|
submitFinish: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private tagService: TagService,
|
private tagService: TagService,
|
||||||
@ -114,6 +117,7 @@ export class ResultBarChartComponent implements OnInit, OnDestroy {
|
|||||||
this.onSubmitting = true;
|
this.onSubmitting = true;
|
||||||
|
|
||||||
this.scanningService.startVulnerabilityScanning(this.repoName, this.tagId)
|
this.scanningService.startVulnerabilityScanning(this.repoName, this.tagId)
|
||||||
|
.pipe(finalize(() => this.submitFinish.emit(false)))
|
||||||
.subscribe(() => {
|
.subscribe(() => {
|
||||||
this.onSubmitting = false;
|
this.onSubmitting = false;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<span class="margin-left-10 font-weight-800 color-green font-size-12">{{fixableCount}}</span>
|
<span class="margin-left-10 font-weight-800 color-green font-size-12">{{fixableCount}}</span>
|
||||||
<span class="margin-left-5 color-green font-size-12">{{'SCANNER.FIXABLE' | translate}}</span>
|
<span class="margin-left-5 color-green font-size-12">{{'SCANNER.FIXABLE' | translate}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="isNone" class="margin-left-5 tip-wrapper bar-block-none shadow-none width-150">{{'VULNERABILITY.NO_VULNERABILITY' | translate }}</div>
|
<div *ngIf="isNone" class="pl-1 margin-left-5 tip-wrapper bar-block-none shadow-none width-150">{{'VULNERABILITY.NO_VULNERABILITY' | translate }}</div>
|
||||||
</div>
|
</div>
|
||||||
<clr-tooltip-content class="w-800" [clrPosition]="'right'" [clrSize]="'lg'" *clrIfOpen>
|
<clr-tooltip-content class="w-800" [clrPosition]="'right'" [clrSize]="'lg'" *clrIfOpen>
|
||||||
<div class="bar-tooltip-font-larger">
|
<div class="bar-tooltip-font-larger">
|
||||||
|
@ -288,8 +288,6 @@ hr {
|
|||||||
color: green;
|
color: green;
|
||||||
}
|
}
|
||||||
.tip-block {
|
.tip-block {
|
||||||
height: $thirty-pixel;
|
|
||||||
line-height: $thirty-pixel;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.font-size-14 {
|
.font-size-14 {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
.bar-wrapper {
|
.bar-wrapper {
|
||||||
width: 210px;
|
width: 210px;
|
||||||
height: 15px;
|
|
||||||
}
|
}
|
||||||
.bar-state {
|
.bar-state {
|
||||||
text-align: center !important;
|
text-align: center !important;
|
||||||
@ -10,7 +9,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bar-state-chart {
|
.bar-state-chart {
|
||||||
margin-top: 2px;
|
|
||||||
.loop-height {
|
.loop-height {
|
||||||
height: 2px;
|
height: 2px;
|
||||||
}
|
}
|
||||||
@ -18,7 +16,6 @@
|
|||||||
|
|
||||||
.bar-state-error {
|
.bar-state-error {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.error-text {
|
.error-text {
|
||||||
|
Loading…
Reference in New Issue
Block a user