mirror of
https://github.com/goharbor/harbor
synced 2025-04-15 12:36:43 +00:00
Merge pull request #2424 from wknet123/master-stackview-repo-tag
Add stack view repo-tag component.
This commit is contained in:
commit
1d3364c1a3
|
@ -4,6 +4,8 @@ import { LOG_DIRECTIVES } from './log/index';
|
|||
import { FILTER_DIRECTIVES } from './filter/index';
|
||||
import { ENDPOINT_DIRECTIVES } from './endpoint/index';
|
||||
import { REPOSITORY_DIRECTIVES } from './repository/index';
|
||||
import { REPOSITORY_STACKVIEW_DIRECTIVES } from './repository-stackview/index';
|
||||
|
||||
import { LIST_REPOSITORY_DIRECTIVES } from './list-repository/index';
|
||||
import { TAG_DIRECTIVES } from './tag/index';
|
||||
|
||||
|
@ -135,6 +137,7 @@ export function initConfig(translateService: TranslateService, config: IServiceC
|
|||
FILTER_DIRECTIVES,
|
||||
ENDPOINT_DIRECTIVES,
|
||||
REPOSITORY_DIRECTIVES,
|
||||
REPOSITORY_STACKVIEW_DIRECTIVES,
|
||||
LIST_REPOSITORY_DIRECTIVES,
|
||||
TAG_DIRECTIVES,
|
||||
CREATE_EDIT_ENDPOINT_DIRECTIVES,
|
||||
|
@ -151,6 +154,7 @@ export function initConfig(translateService: TranslateService, config: IServiceC
|
|||
FILTER_DIRECTIVES,
|
||||
ENDPOINT_DIRECTIVES,
|
||||
REPOSITORY_DIRECTIVES,
|
||||
REPOSITORY_STACKVIEW_DIRECTIVES,
|
||||
LIST_REPOSITORY_DIRECTIVES,
|
||||
TAG_DIRECTIVES,
|
||||
CREATE_EDIT_ENDPOINT_DIRECTIVES,
|
||||
|
|
|
@ -7,6 +7,7 @@ export * from './log/index';
|
|||
export * from './filter/index';
|
||||
export * from './endpoint/index';
|
||||
export * from './repository/index';
|
||||
export * from './repository-stackview/index';
|
||||
export * from './tag/index';
|
||||
export * from './replication/index';
|
||||
export * from './vulnerability-scanning/index';
|
|
@ -7,7 +7,7 @@ export const LIST_REPOSITORY_TEMPLATE = `
|
|||
<clr-dg-action-overflow [hidden]="!hasProjectAdminRole">
|
||||
<button class="action-item" (click)="deleteRepo(r.name)">{{'REPOSITORY.DELETE' | translate}}</button>
|
||||
</clr-dg-action-overflow>
|
||||
<clr-dg-cell>{{r.name}}</clr-dg-cell>
|
||||
<clr-dg-cell><a href="javascript:void(0)" (click)="gotoLink(projectId || r.project_id, r.name || r.repository_name)">{{r.name}}</a></clr-dg-cell>
|
||||
<clr-dg-cell>{{r.tags_count}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{r.pull_count}}</clr-dg-cell>
|
||||
</clr-dg-row>
|
||||
|
|
|
@ -2,12 +2,18 @@
|
|||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
|
||||
import { ListRepositoryComponent } from './list-repository.component';
|
||||
import { Repository } from '../service/interface';
|
||||
|
||||
|
||||
class RouterStub {
|
||||
navigateByUrl(url: string) { return url; }
|
||||
}
|
||||
|
||||
describe('ListRepositoryComponent (inline template)', ()=> {
|
||||
|
||||
let comp: ListRepositoryComponent;
|
||||
|
@ -43,7 +49,9 @@ describe('ListRepositoryComponent (inline template)', ()=> {
|
|||
ListRepositoryComponent,
|
||||
ConfirmationDialogComponent
|
||||
],
|
||||
providers: []
|
||||
providers: [
|
||||
{ provide: Router, useClass: RouterStub }
|
||||
]
|
||||
});
|
||||
}));
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Component, Input, Output, EventEmitter, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { State, Comparator } from 'clarity-angular';
|
||||
|
||||
|
@ -13,6 +14,7 @@ import { CustomComparator } from '../utils';
|
|||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ListRepositoryComponent {
|
||||
@Input() urlPrefix: string;
|
||||
@Input() projectId: number;
|
||||
@Input() repositories: Repository[];
|
||||
|
||||
|
@ -28,6 +30,7 @@ export class ListRepositoryComponent {
|
|||
tagsCountComparator: Comparator<Repository> = new CustomComparator<Repository>('tags_count', 'number');
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private ref: ChangeDetectorRef) {
|
||||
let hnd = setInterval(()=>ref.markForCheck(), 100);
|
||||
setTimeout(()=>clearInterval(hnd), 1000);
|
||||
|
@ -44,4 +47,9 @@ export class ListRepositoryComponent {
|
|||
this.paginate.emit(state);
|
||||
}
|
||||
}
|
||||
|
||||
public gotoLink(projectId: number, repoName: string): void {
|
||||
let linkUrl = [this.urlPrefix, 'tags', projectId, repoName];
|
||||
this.router.navigate(linkUrl);
|
||||
}
|
||||
}
|
6
src/ui_ng/lib/src/repository-stackview/index.ts
Normal file
6
src/ui_ng/lib/src/repository-stackview/index.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { Type } from '@angular/core';
|
||||
import { RepositoryStackviewComponent } from './repository-stackview.component';
|
||||
|
||||
export const REPOSITORY_STACKVIEW_DIRECTIVES: Type<any>[] = [
|
||||
RepositoryStackviewComponent
|
||||
];
|
|
@ -0,0 +1,26 @@
|
|||
export const REPOSITORY_STACKVIEW_STYLES: string = `
|
||||
.option-right {
|
||||
padding-right: 16px;
|
||||
margin-top: 32px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.sub-grid-custom {
|
||||
position: relative;
|
||||
left: 40px;
|
||||
}
|
||||
|
||||
:host >>> .datagrid .datagrid-body .datagrid-row {
|
||||
overflow-x: hidden;
|
||||
overflow-y: hidden;
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
:host >>> .datagrid-body .datagrid-row .datagrid-row-master{
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
:host >>> .datagrid .datagrid-placeholder-container {
|
||||
display: none;
|
||||
}
|
||||
`;
|
|
@ -0,0 +1,34 @@
|
|||
export const REPOSITORY_STACKVIEW_TEMPLATE: string = `
|
||||
<confirmation-dialog #confirmationDialog (confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<div class="row flex-items-xs-right option-right">
|
||||
<div class="flex-xs-middle">
|
||||
<hbr-filter filterPlaceholder="{{'REPOSITORY.FILTER_FOR_REPOSITORIES' | translate}}" (filter)="doSearchRepoNames($event)"></hbr-filter>
|
||||
<a href="javascript:void(0)" (click)="refresh()"><clr-icon shape="refresh"></clr-icon></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<clr-datagrid>
|
||||
<clr-dg-column [clrDgField]="'name'">{{'REPOSITORY.NAME' | translate}}</clr-dg-column>
|
||||
<clr-dg-column [clrDgSortBy]="tagsCountComparator">{{'REPOSITORY.TAGS_COUNT' | translate}}</clr-dg-column>
|
||||
<clr-dg-column [clrDgSortBy]="pullCountComparator">{{'REPOSITORY.PULL_COUNT' | translate}}</clr-dg-column>
|
||||
<clr-dg-row *clrDgItems="let r of repositories">
|
||||
<clr-dg-action-overflow [hidden]="!hasProjectAdminRole">
|
||||
<button class="action-item" (click)="deleteRepo(r.name)">{{'REPOSITORY.DELETE' | translate}}</button>
|
||||
</clr-dg-action-overflow>
|
||||
<clr-dg-cell>{{r.name}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{r.tags_count}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{r.pull_count}}</clr-dg-cell>
|
||||
<hbr-tag *clrIfExpanded ngProjectAs="clr-dg-row-detail" class="sub-grid-custom" [repoName]="r.name" [sessionInfo]="sessionInfo" [projectId]="projectId" [isEmbedded]="true" (refreshRepo)="refresh($event)"></hbr-tag>
|
||||
</clr-dg-row>
|
||||
<clr-dg-footer>
|
||||
{{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} {{'REPOSITORY.OF' | translate}}
|
||||
{{pagination.totalItems}} {{'REPOSITORY.ITEMS' | translate}}
|
||||
<clr-dg-pagination #pagination [clrDgPageSize]="15"></clr-dg-pagination>
|
||||
</clr-dg-footer>
|
||||
</clr-datagrid>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
|
@ -0,0 +1,152 @@
|
|||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DebugElement } from '@angular/core';
|
||||
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
|
||||
import { RepositoryStackviewComponent } from './repository-stackview.component';
|
||||
import { TagComponent } from '../tag/tag.component';
|
||||
import { FilterComponent } from '../filter/filter.component';
|
||||
|
||||
import { ErrorHandler } from '../error-handler/error-handler';
|
||||
import { Repository, Tag } from '../service/interface';
|
||||
import { SERVICE_CONFIG, IServiceConfig } from '../service.config';
|
||||
import { RepositoryService, RepositoryDefaultService } from '../service/repository.service';
|
||||
import { TagService, TagDefaultService } from '../service/tag.service';
|
||||
|
||||
import { click } from '../utils';
|
||||
|
||||
describe('RepositoryComponentStackview (inline template)', ()=> {
|
||||
|
||||
let compRepo: RepositoryStackviewComponent;
|
||||
let fixtureRepo: ComponentFixture<RepositoryStackviewComponent>;
|
||||
let repositoryService: RepositoryService;
|
||||
let spyRepos: jasmine.Spy;
|
||||
|
||||
let compTag: TagComponent;
|
||||
let fixtureTag: ComponentFixture<TagComponent>;
|
||||
let tagService: TagService;
|
||||
let spyTags: jasmine.Spy;
|
||||
|
||||
let mockRepoData: Repository[] = [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "library/busybox",
|
||||
"project_id": 1,
|
||||
"description": "",
|
||||
"pull_count": 0,
|
||||
"star_count": 0,
|
||||
"tags_count": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "library/nginx",
|
||||
"project_id": 1,
|
||||
"description": "",
|
||||
"pull_count": 0,
|
||||
"star_count": 0,
|
||||
"tags_count": 1
|
||||
}
|
||||
];
|
||||
|
||||
let mockTagData: Tag[] = [
|
||||
{
|
||||
"digest": "sha256:e5c82328a509aeb7c18c1d7fb36633dc638fcf433f651bdcda59c1cc04d3ee55",
|
||||
"name": "1.11.5",
|
||||
"architecture": "amd64",
|
||||
"os": "linux",
|
||||
"docker_version": "1.12.3",
|
||||
"author": "NGINX Docker Maintainers \"docker-maint@nginx.com\"",
|
||||
"created": new Date("2016-11-08T22:41:15.912313785Z"),
|
||||
"signature": null
|
||||
}
|
||||
];
|
||||
|
||||
let config: IServiceConfig = {
|
||||
repositoryBaseEndpoint: '/api/repository/testing'
|
||||
};
|
||||
|
||||
beforeEach(async(()=>{
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
SharedModule
|
||||
],
|
||||
declarations: [
|
||||
RepositoryStackviewComponent,
|
||||
TagComponent,
|
||||
ConfirmationDialogComponent,
|
||||
FilterComponent
|
||||
],
|
||||
providers: [
|
||||
ErrorHandler,
|
||||
{ provide: SERVICE_CONFIG, useValue : config },
|
||||
{ provide: RepositoryService, useClass: RepositoryDefaultService },
|
||||
{ provide: TagService, useClass: TagDefaultService }
|
||||
]
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(()=>{
|
||||
fixtureRepo = TestBed.createComponent(RepositoryStackviewComponent);
|
||||
compRepo = fixtureRepo.componentInstance;
|
||||
compRepo.projectId = 1;
|
||||
compRepo.sessionInfo = {
|
||||
hasProjectAdminRole: true
|
||||
};
|
||||
repositoryService = fixtureRepo.debugElement.injector.get(RepositoryService);
|
||||
|
||||
spyRepos = spyOn(repositoryService, 'getRepositories').and.returnValues(Promise.resolve(mockRepoData));
|
||||
fixtureRepo.detectChanges();
|
||||
});
|
||||
|
||||
beforeEach(()=>{
|
||||
fixtureTag = TestBed.createComponent(TagComponent);
|
||||
compTag = fixtureTag.componentInstance;
|
||||
compTag.projectId = compRepo.projectId;
|
||||
compTag.repoName = 'library/busybox';
|
||||
compTag.sessionInfo = compRepo.sessionInfo;
|
||||
tagService = fixtureTag.debugElement.injector.get(TagService);
|
||||
spyTags = spyOn(tagService, 'getTags').and.returnValues(Promise.resolve(mockTagData));
|
||||
fixtureTag.detectChanges();
|
||||
});
|
||||
|
||||
it('should load and render data', async(()=>{
|
||||
fixtureRepo.detectChanges();
|
||||
fixtureRepo.whenStable().then(()=>{
|
||||
fixtureRepo.detectChanges();
|
||||
let deRepo: DebugElement = fixtureRepo.debugElement.query(By.css('datagrid-cell'));
|
||||
fixtureRepo.detectChanges();
|
||||
expect(deRepo).toBeTruthy();
|
||||
let elRepo: HTMLElement = deRepo.nativeElement;
|
||||
fixtureRepo.detectChanges();
|
||||
expect(elRepo).toBeTruthy();
|
||||
fixtureRepo.detectChanges();
|
||||
expect(elRepo.textContent).toEqual('library/busybox');
|
||||
click(deRepo);
|
||||
fixtureTag.detectChanges();
|
||||
let deTag: DebugElement = fixtureTag.debugElement.query(By.css('datagrid-cell'));
|
||||
expect(deTag).toBeTruthy();
|
||||
let elTag: HTMLElement = deTag.nativeElement;
|
||||
expect(elTag).toBeTruthy();
|
||||
expect(elTag.textContent).toEqual('1.12.5');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should filter data by keyword', async(()=>{
|
||||
fixtureRepo.detectChanges();
|
||||
fixtureRepo.whenStable().then(()=>{
|
||||
fixtureRepo.detectChanges();
|
||||
compRepo.doSearchRepoNames('nginx');
|
||||
fixtureRepo.detectChanges();
|
||||
let de: DebugElement[] = fixtureRepo.debugElement.queryAll(By.css('datagrid-cell'));
|
||||
fixtureRepo.detectChanges();
|
||||
expect(de).toBeTruthy();
|
||||
expect(de.length).toEqual(1);
|
||||
let el: HTMLElement = de[0].nativeElement;
|
||||
fixtureRepo.detectChanges();
|
||||
expect(el).toBeTruthy();
|
||||
expect(el.textContent).toEqual('library/nginx');
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
|
@ -0,0 +1,111 @@
|
|||
import { Component, Input, OnInit, ViewChild, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Comparator } from 'clarity-angular';
|
||||
|
||||
import { REPOSITORY_STACKVIEW_TEMPLATE } from './repository-stackview.component.html';
|
||||
import { REPOSITORY_STACKVIEW_STYLES } from './repository-stackview.component.css';
|
||||
|
||||
import { Repository, SessionInfo } from '../service/interface';
|
||||
import { ErrorHandler } from '../error-handler/error-handler';
|
||||
import { RepositoryService } from '../service/repository.service';
|
||||
import { toPromise, CustomComparator } from '../utils';
|
||||
|
||||
import { ConfirmationState, ConfirmationTargets, ConfirmationButtons } from '../shared/shared.const';
|
||||
|
||||
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
|
||||
import { ConfirmationMessage } from '../confirmation-dialog/confirmation-message';
|
||||
import { ConfirmationAcknowledgement } from '../confirmation-dialog/confirmation-state-message';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
|
||||
@Component({
|
||||
selector: 'hbr-repository-stackview',
|
||||
template: REPOSITORY_STACKVIEW_TEMPLATE,
|
||||
styles: [ REPOSITORY_STACKVIEW_STYLES ],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class RepositoryStackviewComponent implements OnInit {
|
||||
|
||||
@Input() projectId: number;
|
||||
@Input() sessionInfo: SessionInfo;
|
||||
|
||||
lastFilteredRepoName: string;
|
||||
|
||||
hasProjectAdminRole: boolean;
|
||||
|
||||
repositories: Repository[];
|
||||
|
||||
@ViewChild('confirmationDialog')
|
||||
confirmationDialog: ConfirmationDialogComponent;
|
||||
|
||||
pullCountComparator: Comparator<Repository> = new CustomComparator<Repository>('pull_count', 'number');
|
||||
|
||||
tagsCountComparator: Comparator<Repository> = new CustomComparator<Repository>('tags_count', 'number');
|
||||
|
||||
|
||||
constructor(
|
||||
private errorHandler: ErrorHandler,
|
||||
private translateService: TranslateService,
|
||||
private repositoryService: RepositoryService,
|
||||
private ref: ChangeDetectorRef){}
|
||||
|
||||
confirmDeletion(message: ConfirmationAcknowledgement) {
|
||||
if (message &&
|
||||
message.source === ConfirmationTargets.REPOSITORY &&
|
||||
message.state === ConfirmationState.CONFIRMED) {
|
||||
let repoName = message.data;
|
||||
toPromise<number>(this.repositoryService
|
||||
.deleteRepository(repoName))
|
||||
.then(
|
||||
response => {
|
||||
this.refresh();
|
||||
this.translateService.get('REPOSITORY.DELETED_REPO_SUCCESS')
|
||||
.subscribe(res=>this.errorHandler.info(res));
|
||||
}).catch(error => this.errorHandler.error(error));
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if(!this.projectId) {
|
||||
this.errorHandler.error('Project ID cannot be unset.');
|
||||
return;
|
||||
}
|
||||
if(!this.sessionInfo) {
|
||||
this.errorHandler.error('Session info cannot be unset.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.hasProjectAdminRole = this.sessionInfo.hasProjectAdminRole || false;
|
||||
this.lastFilteredRepoName = '';
|
||||
this.retrieve();
|
||||
}
|
||||
|
||||
retrieve() {
|
||||
toPromise<Repository[]>(this.repositoryService
|
||||
.getRepositories(this.projectId, this.lastFilteredRepoName))
|
||||
.then(
|
||||
repos => this.repositories = repos,
|
||||
error => this.errorHandler.error(error));
|
||||
let hnd = setInterval(()=>this.ref.markForCheck(), 100);
|
||||
setTimeout(()=>clearInterval(hnd), 1000);
|
||||
}
|
||||
|
||||
doSearchRepoNames(repoName: string) {
|
||||
this.lastFilteredRepoName = repoName;
|
||||
this.retrieve();
|
||||
}
|
||||
|
||||
deleteRepo(repoName: string) {
|
||||
let message = new ConfirmationMessage(
|
||||
'REPOSITORY.DELETION_TITLE_REPO',
|
||||
'REPOSITORY.DELETION_SUMMARY_REPO',
|
||||
repoName,
|
||||
repoName,
|
||||
ConfirmationTargets.REPOSITORY,
|
||||
ConfirmationButtons.DELETE_CANCEL);
|
||||
this.confirmationDialog.open(message);
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.retrieve();
|
||||
}
|
||||
}
|
|
@ -10,6 +10,6 @@ export const REPOSITORY_TEMPLATE = `
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<hbr-list-repository [projectId]="projectId" [repositories]="changedRepositories" (delete)="deleteRepo($event)" [hasProjectAdminRole]="hasProjectAdminRole" (paginate)="retrieve($event)"></hbr-list-repository>
|
||||
<hbr-list-repository [urlPrefix]="urlPrefix" [projectId]="projectId" [repositories]="changedRepositories" (delete)="deleteRepo($event)" [hasProjectAdminRole]="hasProjectAdminRole" (paginate)="retrieve($event)"></hbr-list-repository>
|
||||
</div>
|
||||
</div>`;
|
|
@ -1,6 +1,7 @@
|
|||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
|
||||
|
@ -13,6 +14,10 @@ import { Repository } from '../service/interface';
|
|||
import { SERVICE_CONFIG, IServiceConfig } from '../service.config';
|
||||
import { RepositoryService, RepositoryDefaultService } from '../service/repository.service';
|
||||
|
||||
class RouterStub {
|
||||
navigateByUrl(url: string) { return url; }
|
||||
}
|
||||
|
||||
describe('RepositoryComponent (inline template)', ()=> {
|
||||
|
||||
let comp: RepositoryComponent;
|
||||
|
@ -59,7 +64,8 @@ describe('RepositoryComponent (inline template)', ()=> {
|
|||
providers: [
|
||||
ErrorHandler,
|
||||
{ provide: SERVICE_CONFIG, useValue : config },
|
||||
{ provide: RepositoryService, useClass: RepositoryDefaultService }
|
||||
{ provide: RepositoryService, useClass: RepositoryDefaultService },
|
||||
{ provide: Router, useClass: RouterStub }
|
||||
]
|
||||
});
|
||||
}));
|
||||
|
|
|
@ -43,6 +43,7 @@ export class RepositoryComponent implements OnInit {
|
|||
|
||||
@Input() projectId: number;
|
||||
@Input() sessionInfo: SessionInfo;
|
||||
@Input() urlPrefix: string;
|
||||
|
||||
lastFilteredRepoName: string;
|
||||
|
||||
|
|
|
@ -1,4 +1,33 @@
|
|||
export const TAG_STYLE = `
|
||||
.sub-header-title {
|
||||
margin-top: 12px;
|
||||
}`;
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
.embeded-datagrid {
|
||||
width: 98%;
|
||||
}
|
||||
|
||||
.hidden-tag {
|
||||
display: block; height: 0;
|
||||
}
|
||||
|
||||
:host >>> .datagrid {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:host >>> .datagrid-placeholder {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:host >>> .datagrid .datagrid-body {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
:host >>> .datagrid .datagrid-head .datagrid-row {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
:host >>> .datagrid .datagrid-body .datagrid-row-master {
|
||||
background-color: #eee;
|
||||
}
|
||||
`;
|
|
@ -1,6 +1,6 @@
|
|||
export const TAG_TEMPLATE = `
|
||||
<confirmation-dialog #confirmationDialog (confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
||||
<clr-modal [(clrModalOpen)]="showTagManifestOpened" [clrModalStaticBackdrop]="staticBackdrop" [clrModalClosable]="closable">
|
||||
<confirmation-dialog class="hidden-tag" #confirmationDialog (confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
||||
<clr-modal class="hidden-tag" [(clrModalOpen)]="showTagManifestOpened" [clrModalStaticBackdrop]="staticBackdrop" [clrModalClosable]="closable">
|
||||
<h3 class="modal-title">{{ manifestInfoTitle | translate }}</h3>
|
||||
<div class="modal-body">
|
||||
<div class="row col-md-12">
|
||||
|
@ -11,8 +11,9 @@ export const TAG_TEMPLATE = `
|
|||
<button type="button" class="btn btn-primary" (click)="showTagManifestOpened = false">{{'BUTTON.OK' | translate}}</button>
|
||||
</div>
|
||||
</clr-modal>
|
||||
<h2 class="sub-header-title">{{repoName}}</h2>
|
||||
<clr-datagrid [clrDgLoading]="loading">
|
||||
|
||||
<h2 *ngIf="!isEmbedded" class="sub-header-title">{{repoName}}</h2>
|
||||
<clr-datagrid [clrDgLoading]="loading" [class.embeded-datagrid]="isEmbedded">
|
||||
<clr-dg-column [clrDgField]="'name'">{{'REPOSITORY.TAG' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'REPOSITORY.PULL_COMMAND' | translate}}</clr-dg-column>
|
||||
<clr-dg-column *ngIf="withNotary">{{'REPOSITORY.SIGNED' | translate}}</clr-dg-column>
|
||||
|
@ -42,9 +43,9 @@ export const TAG_TEMPLATE = `
|
|||
<clr-dg-cell>{{t.architecture}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{t.os}}</clr-dg-cell>
|
||||
</clr-dg-row>
|
||||
<clr-dg-footer>
|
||||
<clr-dg-footer>
|
||||
{{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} {{'REPOSITORY.OF' | translate}}
|
||||
{{pagination.totalItems}} {{'REPOSITORY.ITEMS' | translate}}
|
||||
<clr-dg-pagination #pagination [clrDgPageSize]="10"></clr-dg-pagination>
|
||||
{{pagination.totalItems}} {{'REPOSITORY.ITEMS' | translate}}
|
||||
<clr-dg-pagination #pagination [clrDgPageSize]="5"></clr-dg-pagination>
|
||||
</clr-dg-footer>
|
||||
</clr-datagrid>`;
|
|
@ -11,7 +11,7 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
import { Component, OnInit, ViewChild, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
|
||||
import { Component, OnInit, ViewChild, Input, Output, EventEmitter, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
|
||||
|
||||
import { TagService } from '../service/tag.service';
|
||||
import { ErrorHandler } from '../error-handler/error-handler';
|
||||
|
@ -43,6 +43,9 @@ export class TagComponent implements OnInit {
|
|||
@Input() projectId: number;
|
||||
@Input() repoName: string;
|
||||
@Input() sessionInfo: SessionInfo;
|
||||
@Input() isEmbedded: boolean;
|
||||
|
||||
@Output() refreshRepo = new EventEmitter<boolean>();
|
||||
|
||||
hasProjectAdminRole: boolean;
|
||||
|
||||
|
@ -73,23 +76,23 @@ export class TagComponent implements OnInit {
|
|||
|
||||
confirmDeletion(message: ConfirmationAcknowledgement) {
|
||||
if (message &&
|
||||
message.source === ConfirmationTargets.TAG
|
||||
&& message.state === ConfirmationState.CONFIRMED) {
|
||||
let tag: Tag = message.data;
|
||||
if (tag) {
|
||||
if (tag.signature) {
|
||||
return;
|
||||
} else {
|
||||
toPromise<number>(this.tagService
|
||||
.deleteTag(this.repoName, tag.name))
|
||||
.then(
|
||||
response => {
|
||||
this.retrieve();
|
||||
this.translateService.get('REPOSITORY.DELETED_TAG_SUCCESS')
|
||||
.subscribe(res=>this.errorHandler.info(res));
|
||||
}).catch(error => this.errorHandler.error(error));
|
||||
}
|
||||
message.source === ConfirmationTargets.TAG
|
||||
&& message.state === ConfirmationState.CONFIRMED) {
|
||||
let tag: Tag = message.data;
|
||||
if (tag) {
|
||||
if (tag.signature) {
|
||||
return;
|
||||
} else {
|
||||
toPromise<number>(this.tagService
|
||||
.deleteTag(this.repoName, tag.name))
|
||||
.then(
|
||||
response => {
|
||||
this.retrieve();
|
||||
this.translateService.get('REPOSITORY.DELETED_TAG_SUCCESS')
|
||||
.subscribe(res=>this.errorHandler.info(res));
|
||||
}).catch(error => this.errorHandler.error(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,6 +125,9 @@ export class TagComponent implements OnInit {
|
|||
.then(items => {
|
||||
this.tags = items;
|
||||
this.loading = false;
|
||||
if(this.tags && this.tags.length === 0) {
|
||||
this.refreshRepo.emit(true);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
this.errorHandler.error(error);
|
||||
|
|
Loading…
Reference in New Issue
Block a user