Merge pull request #12701 from AllForNothing/artifact-icon

get artifact icon from backend API
This commit is contained in:
Will Sun 2020-08-18 10:29:15 +08:00 committed by GitHub
commit 9671ff1f10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 112 additions and 69 deletions

View File

@ -151,11 +151,6 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
this.tags = null;
this.labels = null;
this.cron = null;
this.currentForm.reset({
triggerType: "manual",
severity: PROJECT_SEVERITY_LEVEL_MAP[this.projectSeverity],
onlySignedImages: this.enableContentTrust
});
if (this.providers && this.providers.length) {
this.providers.forEach(item => {
if (item.default) {
@ -163,6 +158,12 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
}
});
}
this.currentForm.reset({
triggerType: "manual",
severity: PROJECT_SEVERITY_LEVEL_MAP[this.projectSeverity],
onlySignedImages: this.enableContentTrust,
provider: this.policy.provider_id
});
}
setCron(event: any) {

View File

@ -40,7 +40,7 @@
<div class="execution-select">
<div class="select filter-tag" [hidden]="!openSelectFilterPiece">
<clr-select-container>
<select clrSelect [(ngModel)]="filterByType" (change)="selectFilterType($event)" >
<select clrSelect [(ngModel)]="filterByType" (change)="selectFilterType()" >
<option *ngFor="let filter of mutipleFilter" value="{{filter.filterBy}}">{{ filter.filterByShowText | translate}}</option>
</select>
</clr-select-container>
@ -161,25 +161,16 @@
<clr-dg-row *ngFor="let artifact of artifactList" [clrDgItem]="artifact" >
<clr-dg-cell class="truncated flex-max-width">
<div class="cell white-normal">
<img *ngIf="artifact?.type !== 'IMAGE';else elseBlock" class="artifact-icon" [title]="artifact.type"
[src]="artifact.type | selectArtifactIcon" />
<ng-template #elseBlock>
<clr-tooltip>
<div clrTooltipTrigger class="level-border">
<img class="artifact-icon" [title]="artifact.type"
[src]="artifact.type | selectArtifactIcon" />
</div>
<clr-tooltip-content clrPosition="top-right" clrSize="lg" *clrIfOpen>
<span>Docker and the Docker logo are trademarks or registered trademarks of Docker, Inc. in the United States and/or other countries.</span>
</clr-tooltip-content>
</clr-tooltip>
</ng-template>
<div class="artifact-icon clr-display-inline-block" *ngIf="artifact.icon">
<img *ngIf="getIcon(artifact.icon)" class="artifact-icon" [title]="artifact.type"
[src]="getIcon(artifact.icon)" (error)="showDefaultIcon($event)" />
</div>
<a href="javascript:void(0)" class="max-width-100 margin-left-5" (click)="goIntoArtifactSummaryPage(artifact)"
title="{{artifact.digest}}">
{{ artifact.digest | slice:0:15}}</a>
<clr-tooltip *ngIf="artifact?.references && artifact?.references?.length">
<div clrTooltipTrigger class="level-border">
<div class="inner truncated ">
<div class="inner truncated">
<a href="javascript:void(0)" (click)="goIntoIndexArtifact(artifact)">
<clr-icon class="icon-folder" shape="folder"></clr-icon>
</a>
@ -256,7 +247,7 @@
</clr-dg-cell>
<clr-dg-cell>
<div class="cell">
{{artifact.size?sizeTransform(artifact.size): ""}}
{{artifact.size?sizeTransform(artifact.size+''): ""}}
</div>
</clr-dg-cell>
<clr-dg-cell>

View File

@ -282,8 +282,13 @@ describe("ArtifactListTabComponent (inline template)", () => {
).pipe(delay(0));
}
},
deleteArtifact: () => of (null)
deleteArtifact: () => of (null),
getIconsFromBackEnd() {
return undefined;
},
getIcon() {
return undefined;
}
};
beforeEach(async(() => {
TestBed.configureTestingModule({

View File

@ -54,11 +54,18 @@ import {
} from "../../../../../../lib/entities/shared.const";
import { operateChanges, OperateInfo, OperationState } from "../../../../../../lib/components/operation/operate";
import { errorHandler } from "../../../../../../lib/utils/shared/shared.utils";
import { ArtifactFront as Artifact, mutipleFilter, artifactPullCommands } from "../../../artifact/artifact";
import {
ArtifactFront as Artifact,
mutipleFilter,
artifactPullCommands,
artifactDefault
} from '../../../artifact/artifact';
import { Project } from "../../../../project";
import { ArtifactService as NewArtifactService } from "../../../../../../../ng-swagger-gen/services/artifact.service";
import { ADDITIONS } from "../../../artifact/artifact-additions/models";
import { Platform } from "../../../../../../../ng-swagger-gen/models/platform";
import { IconService } from '../../../../../../../ng-swagger-gen/services/icon.service';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
export interface LabelState {
iconsShow: boolean;
label: Label;
@ -161,7 +168,6 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
scanFiinishArtifactLength: number = 0;
onScanArtifactsLength: number = 0;
constructor(
private errorHandlerService: ErrorHandler,
private userPermissionService: UserPermissionService,
@ -374,6 +380,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
artifact.platform = clone(platFormAttr[index].platform);
});
this.getPullCommand(this.artifactList);
this.getIconsFromBackEnd();
}, error => {
this.errorHandlerService.error(error);
});
@ -403,6 +410,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
this.artifactList = doSorting<Artifact>(this.artifactList, state);
this.getPullCommand(this.artifactList);
this.getIconsFromBackEnd();
}, error => {
// error
this.errorHandlerService.error(error);
@ -992,4 +1000,17 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
}
}
}
getIconsFromBackEnd() {
if (this.artifactList && this.artifactList.length) {
this.artifactService.getIconsFromBackEnd(this.artifactList);
}
}
showDefaultIcon(event: any) {
if (event && event.target) {
event.target.src = artifactDefault;
}
}
getIcon(icon: string): SafeUrl {
return this.artifactService.getIcon(icon);
}
}

View File

@ -15,19 +15,10 @@
</div>
<div class="title-block">
<h2 class="custom-h2 center-align-items">
<img *ngIf="artifact?.type !== 'IMAGE';else elseBlock" class="artifact-icon" [title]="artifact.type"
[src]="artifact.type | selectArtifactIcon" />
<ng-template #elseBlock>
<clr-tooltip>
<div clrTooltipTrigger class="level-border">
<img class="artifact-icon" [title]="artifact.type"
[src]="artifact.type | selectArtifactIcon" />
</div>
<clr-tooltip-content clrPosition="top-right" clrSize="lg" *clrIfOpen>
<span>Docker and the Docker logo are trademarks or registered trademarks of Docker, Inc. in the United States and/or other countries.</span>
</clr-tooltip-content>
</clr-tooltip>
</ng-template>
<div class="artifact-icon clr-display-inline-block" *ngIf="artifact.icon">
<img *ngIf="getIcon(artifact.icon)" class="artifact-icon" [title]="artifact.type"
[src]="getIcon(artifact.icon)" (error)="showDefaultIcon($event)" />
</div>
<span class="margin-left-10px">{{artifact?.digest | slice:0:15}}</span>
<clr-icon size="25" *ngIf="artifact?.references && artifact?.references?.length" class="icon-folder margin-left-10px" shape="folder"></clr-icon>
</h2>

View File

@ -12,6 +12,7 @@ import { ActivatedRoute, Router } from "@angular/router";
import { AppConfigService } from "../../../services/app-config.service";
import { Project } from "../../project";
import { AllPipesModule } from "../../../all-pipes/all-pipes.module";
import { ArtifactDefaultService } from './artifact.service';
describe('ArtifactSummaryComponent', () => {
@ -26,9 +27,12 @@ describe('ArtifactSummaryComponent', () => {
}
};
const fakedArtifactService = {
getArtifact() {
return of(mockedArtifact);
const fakedArtifactDefaultService = {
getIconsFromBackEnd() {
return undefined;
},
getIcon() {
return undefined;
}
};
let component: ArtifactSummaryComponent;
@ -86,7 +90,7 @@ describe('ArtifactSummaryComponent', () => {
{ provide: Router, useValue: mockRouter },
{ provide: ActivatedRoute, useValue: mockActivatedRoute },
{ provide: ProjectService, useValue: fakedProjectService },
{ provide: ArtifactService, useValue: fakedArtifactService },
{ provide: ArtifactDefaultService, useValue: fakedArtifactDefaultService },
ErrorHandler
]
})

View File

@ -1,14 +1,14 @@
import { Component, Output, EventEmitter, OnInit } from "@angular/core";
import { Artifact } from "../../../../../ng-swagger-gen/models/artifact";
import { ArtifactService } from "../../../../../ng-swagger-gen/services/artifact.service";
import { ErrorHandler } from "../../../../lib/utils/error-handler";
import { Label } from "../../../../../ng-swagger-gen/models/label";
import { ProjectService } from "../../../../lib/services";
import { ActivatedRoute, Router } from "@angular/router";
import { AppConfigService } from "../../../services/app-config.service";
import { Project } from "../../project";
import { finalize } from "rxjs/operators";
import { dbEncodeURIComponent } from "../../../../lib/utils/utils";
import { artifactDefault } from './artifact';
import { SafeUrl } from '@angular/platform-browser';
import { ArtifactDefaultService } from './artifact.service';
@Component({
selector: "artifact-summary",
@ -34,11 +34,11 @@ export class ArtifactSummaryComponent implements OnInit {
constructor(
private projectService: ProjectService,
private artifactService: ArtifactService,
private errorHandler: ErrorHandler,
private route: ActivatedRoute,
private appConfigService: AppConfigService,
private router: Router
private router: Router,
private frontEndArtifactService: ArtifactDefaultService,
) {
}
@ -81,27 +81,24 @@ export class ArtifactSummaryComponent implements OnInit {
const pro: Project = <Project>(resolverData['artifactResolver'][1]);
this.projectName = pro.name;
this.artifact = <Artifact>(resolverData['artifactResolver'][0]);
this.getIconFromBackEnd();
}
}
}
getArtifactDetails(): void {
this.loading = true;
this.artifactService.getArtifact({
repositoryName: dbEncodeURIComponent(this.repositoryName),
reference: this.artifactDigest,
projectName: this.projectName,
withLabel: true,
withScanOverview: true
}).pipe(finalize(() => this.loading = false))
.subscribe(response => {
this.artifact = response;
}, error => {
this.errorHandler.error(error);
});
}
onBack(): void {
this.backEvt.emit(this.repositoryName);
}
showDefaultIcon(event: any) {
if (event && event.target) {
event.target.src = artifactDefault;
}
}
getIcon(icon: string): SafeUrl {
return this.frontEndArtifactService.getIcon(icon);
}
getIconFromBackEnd() {
if (this.artifact && this.artifact.icon) {
this.frontEndArtifactService.getIconsFromBackEnd([this.artifact]);
}
}
}

View File

@ -3,6 +3,8 @@ import { IServiceConfig, SERVICE_CONFIG } from "../../../../lib/entities/service
import { SharedModule } from "../../../../lib/utils/shared/shared.module";
import { ArtifactDefaultService, ArtifactService } from "../artifact/artifact.service";
import { CURRENT_BASE_HREF } from "../../../../lib/utils/utils";
import { IconService } from '../../../../../ng-swagger-gen/services/icon.service';
import { DomSanitizer } from '@angular/platform-browser';
describe('ArtifactService', () => {
@ -16,7 +18,10 @@ describe('ArtifactService', () => {
{
provide: ArtifactService,
useClass: ArtifactDefaultService
}]
},
IconService,
DomSanitizer
]
});
});

View File

@ -1,6 +1,9 @@
import { Injectable, Inject } from "@angular/core";
import { Subject } from "rxjs";
import { IServiceConfig, SERVICE_CONFIG } from "../../../../lib/entities/service.config";
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { Artifact } from '../../../../../ng-swagger-gen/models/artifact';
import { IconService } from '../../../../../ng-swagger-gen/services/icon.service';
/**
* Define the service methods to handle the repository tag related things.
@ -13,15 +16,39 @@ export abstract class ArtifactService {
reference: string[];
triggerUploadArtifact = new Subject<string>();
TriggerArtifactChan$ = this.triggerUploadArtifact.asObservable();
abstract getIcon(digest: string): SafeUrl;
abstract setIcon(digest: string, url: SafeUrl);
abstract getIconsFromBackEnd(artifactList: Artifact[]);
}
@Injectable()
export class ArtifactDefaultService extends ArtifactService {
triggerUploadArtifact = new Subject<string>();
TriggerArtifactChan$ = this.triggerUploadArtifact.asObservable();
constructor() {
private _iconMap: {[key: string]: SafeUrl} = {};
constructor(private iconService: IconService,
private domSanitizer: DomSanitizer) {
super();
}
getIcon(icon: string): SafeUrl {
return this._iconMap[icon];
}
setIcon(icon: string, url: SafeUrl) {
if (!this._iconMap[icon]) {
this._iconMap[icon] = url;
}
}
getIconsFromBackEnd(artifactList: Artifact[]) {
if (artifactList && artifactList.length) {
artifactList.forEach(item => {
if (item.icon && !this.getIcon(item.icon)) {
this.iconService.getIcon({digest: item.icon})
.subscribe(res => {
this.setIcon(item.icon, this.domSanitizer
.bypassSecurityTrustUrl(`data:${res['content-type']};charset=utf-8;base64,${res.content}`));
});
}
});
}
}
}

View File

@ -5,6 +5,7 @@ export interface ArtifactFront extends Artifact {
platform?: Platform;
showImage?: string;
pullCommand?: string;
annotationsArray?: Array<{[key: string]: any}>;
}
export const mutipleFilter = [