mirror of
https://github.com/goharbor/harbor.git
synced 2024-09-28 21:37:31 +02:00
Support adding label to multiple artifacts (#14443)
Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
68d7c91596
commit
fb3b1311d8
@ -107,7 +107,7 @@
|
|||||||
{{'REPOSITORY.COPY_DIGEST_ID' | translate}}</div>
|
{{'REPOSITORY.COPY_DIGEST_ID' | translate}}</div>
|
||||||
<clr-dropdown *ngIf="!withAdmiral">
|
<clr-dropdown *ngIf="!withAdmiral">
|
||||||
<button class="action-dropdown-item" clrDropdownTrigger
|
<button class="action-dropdown-item" clrDropdownTrigger
|
||||||
[disabled]="!(selectedRow.length==1)||!hasAddLabelImagePermission ||depth"
|
[disabled]="!canAddLabel()||!hasAddLabelImagePermission ||depth || inprogress"
|
||||||
(click)="addLabels()">
|
(click)="addLabels()">
|
||||||
{{'REPOSITORY.ADD_LABELS' | translate}}
|
{{'REPOSITORY.ADD_LABELS' | translate}}
|
||||||
</button>
|
</button>
|
||||||
@ -121,7 +121,7 @@
|
|||||||
<div [hidden]='imageStickLabels.length' class="no-labels">
|
<div [hidden]='imageStickLabels.length' class="no-labels">
|
||||||
{{'LABEL.NO_LABELS' | translate }}</div>
|
{{'LABEL.NO_LABELS' | translate }}</div>
|
||||||
<div [hidden]='!imageStickLabels.length' class="has-label">
|
<div [hidden]='!imageStickLabels.length' class="has-label">
|
||||||
<button type="button" class="dropdown-item"
|
<button type="button" class="dropdown-item" clrDropdownItem
|
||||||
*ngFor='let label of imageStickLabels' [hidden]='!label.show'
|
*ngFor='let label of imageStickLabels' [hidden]='!label.show'
|
||||||
(click)="stickLabel(label)">
|
(click)="stickLabel(label)">
|
||||||
<clr-icon shape="check" class='pull-left' [hidden]='!label.iconsShow'>
|
<clr-icon shape="check" class='pull-left' [hidden]='!label.iconsShow'>
|
||||||
|
@ -68,6 +68,7 @@ import { errorHandler } from "../../../../../../../shared/units/shared.utils";
|
|||||||
import { ConfirmationDialogComponent } from "../../../../../../../shared/components/confirmation-dialog";
|
import { ConfirmationDialogComponent } from "../../../../../../../shared/components/confirmation-dialog";
|
||||||
import { ConfirmationMessage } from "../../../../../../global-confirmation-dialog/confirmation-message";
|
import { ConfirmationMessage } from "../../../../../../global-confirmation-dialog/confirmation-message";
|
||||||
import { ConfirmationAcknowledgement } from "../../../../../../global-confirmation-dialog/confirmation-state-message";
|
import { ConfirmationAcknowledgement } from "../../../../../../global-confirmation-dialog/confirmation-state-message";
|
||||||
|
|
||||||
export interface LabelState {
|
export interface LabelState {
|
||||||
iconsShow: boolean;
|
iconsShow: boolean;
|
||||||
label: Label;
|
label: Label;
|
||||||
@ -169,7 +170,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
|
|||||||
// could Pagination filter
|
// could Pagination filter
|
||||||
filters: string[];
|
filters: string[];
|
||||||
|
|
||||||
scanFiinishArtifactLength: number = 0;
|
scanFinishedArtifactLength: number = 0;
|
||||||
onScanArtifactsLength: number = 0;
|
onScanArtifactsLength: number = 0;
|
||||||
constructor(
|
constructor(
|
||||||
private errorHandlerService: ErrorHandler,
|
private errorHandlerService: ErrorHandler,
|
||||||
@ -477,7 +478,20 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
|
|||||||
this.stickName = '';
|
this.stickName = '';
|
||||||
this.labelSelectedChange(this.selectedRow);
|
this.labelSelectedChange(this.selectedRow);
|
||||||
}
|
}
|
||||||
|
canAddLabel(): boolean {
|
||||||
|
if (this.selectedRow && this.selectedRow.length === 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (this.selectedRow && this.selectedRow.length > 1) {
|
||||||
|
for (let i = 0; i < this.selectedRow.length; i ++) {
|
||||||
|
if (this.selectedRow[i].labels && this.selectedRow[i].labels.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
stickLabel(labelInfo: LabelState): void {
|
stickLabel(labelInfo: LabelState): void {
|
||||||
if (labelInfo && !labelInfo.iconsShow) {
|
if (labelInfo && !labelInfo.iconsShow) {
|
||||||
this.selectLabel(labelInfo);
|
this.selectLabel(labelInfo);
|
||||||
@ -488,16 +502,21 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectLabel(labelInfo: LabelState): void {
|
selectLabel(labelInfo: LabelState): void {
|
||||||
if (!this.inprogress) {
|
if (!this.inprogress) { // add label to multiple artifact
|
||||||
this.inprogress = true;
|
const ObservableArr: Array<Observable<null>> = [];
|
||||||
this.selectedRow = this.selectedTag;
|
this.selectedRow.forEach(item => {
|
||||||
let params: NewArtifactService.AddLabelParams = {
|
const params: NewArtifactService.AddLabelParams = {
|
||||||
projectName: this.projectName,
|
projectName: this.projectName,
|
||||||
repositoryName: dbEncodeURIComponent(this.repoName),
|
repositoryName: dbEncodeURIComponent(this.repoName),
|
||||||
reference: this.selectedRow[0].digest,
|
reference: item.digest,
|
||||||
label: labelInfo.label
|
label: labelInfo.label
|
||||||
};
|
};
|
||||||
this.newArtifactService.addLabel(params).subscribe(res => {
|
ObservableArr.push(this.newArtifactService.addLabel(params));
|
||||||
|
});
|
||||||
|
this.inprogress = true;
|
||||||
|
forkJoin(ObservableArr)
|
||||||
|
.pipe(finalize(() => this.inprogress = false))
|
||||||
|
.subscribe(res => {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
// set the selected label in front
|
// set the selected label in front
|
||||||
this.imageStickLabels.splice(this.imageStickLabels.indexOf(labelInfo), 1);
|
this.imageStickLabels.splice(this.imageStickLabels.indexOf(labelInfo), 1);
|
||||||
@ -507,16 +526,13 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// when is the last one
|
// when is the last one
|
||||||
if (this.imageStickLabels.every(data => data.iconsShow === true)) {
|
if (this.imageStickLabels.every(data => data.iconsShow === true)) {
|
||||||
this.imageStickLabels.push(labelInfo);
|
this.imageStickLabels.push(labelInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
labelInfo.iconsShow = true;
|
labelInfo.iconsShow = true;
|
||||||
this.inprogress = false;
|
|
||||||
}, err => {
|
}, err => {
|
||||||
this.inprogress = false;
|
this.refresh();
|
||||||
this.errorHandlerService.error(err);
|
this.errorHandlerService.error(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -882,7 +898,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
|
|||||||
if (!this.selectedRow.length) {
|
if (!this.selectedRow.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.scanFiinishArtifactLength = 0;
|
this.scanFinishedArtifactLength = 0;
|
||||||
this.onScanArtifactsLength = this.selectedRow.length;
|
this.onScanArtifactsLength = this.selectedRow.length;
|
||||||
this.onSendingScanCommand = true;
|
this.onSendingScanCommand = true;
|
||||||
this.selectedRow.forEach((data: any) => {
|
this.selectedRow.forEach((data: any) => {
|
||||||
@ -900,9 +916,9 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
|
|||||||
return !!(artifact && artifact.addition_links && artifact.addition_links[ADDITIONS.VULNERABILITIES]);
|
return !!(artifact && artifact.addition_links && artifact.addition_links[ADDITIONS.VULNERABILITIES]);
|
||||||
}
|
}
|
||||||
submitFinish(e: boolean) {
|
submitFinish(e: boolean) {
|
||||||
this.scanFiinishArtifactLength += 1;
|
this.scanFinishedArtifactLength += 1;
|
||||||
// all selected scan action has start
|
// all selected scan action has start
|
||||||
if (this.scanFiinishArtifactLength === this.onScanArtifactsLength) {
|
if (this.scanFinishedArtifactLength === this.onScanArtifactsLength) {
|
||||||
this.onSendingScanCommand = e;
|
this.onSendingScanCommand = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user