mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-22 18:25:56 +01:00
Improve global search component (#15462)
Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
a8562b2934
commit
eca3d82d9c
@ -1,5 +1,5 @@
|
|||||||
<form class="search">
|
<form class="search">
|
||||||
<label for="search_input">
|
<label for="search_input">
|
||||||
<input #globalSearchBox name="globalSearchBox" [(ngModel)]="searchTerm" id="search_input" type="text" (keyup)="search(globalSearchBox.value)" placeholder='{{placeholderText | translate}}'>
|
<input autocomplete="off" #globalSearchBox name="globalSearchBox" [(ngModel)]="searchTerm" id="search_input" type="text" (keyup)="search(globalSearchBox.value)" placeholder='{{placeholderText | translate}}'>
|
||||||
</label>
|
</label>
|
||||||
</form>
|
</form>
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
||||||
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||||
//
|
//
|
||||||
@ -13,20 +12,17 @@ import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { Subject , Subscription } from "rxjs";
|
import { Subject, Subscription } from "rxjs";
|
||||||
|
|
||||||
import { SearchTriggerService } from './search-trigger.service';
|
import { SearchTriggerService } from './search-trigger.service';
|
||||||
|
|
||||||
import { AppConfigService } from '../../../services/app-config.service';
|
import { AppConfigService } from '../../../services/app-config.service';
|
||||||
|
import { TranslateService } from "@ngx-translate/core";
|
||||||
|
import { SkinableConfig } from "../../../services/skinable-config.service";
|
||||||
|
import { Location } from '@angular/common';
|
||||||
import {TranslateService} from "@ngx-translate/core";
|
|
||||||
import {SkinableConfig} from "../../../services/skinable-config.service";
|
|
||||||
|
|
||||||
const deBounceTime = 500; // ms
|
const deBounceTime = 500; // ms
|
||||||
|
const SEARCH_KEY: string = 'globalSearch';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'global-search',
|
selector: 'global-search',
|
||||||
@ -43,13 +39,13 @@ export class GlobalSearchComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
// To indicate if the result panel is opened
|
// To indicate if the result panel is opened
|
||||||
isResPanelOpened: boolean = false;
|
isResPanelOpened: boolean = false;
|
||||||
searchTerm: string = "";
|
|
||||||
|
|
||||||
placeholderText: string;
|
placeholderText: string;
|
||||||
|
private _searchTerm = "";
|
||||||
constructor(
|
constructor(
|
||||||
private searchTrigger: SearchTriggerService,
|
private searchTrigger: SearchTriggerService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private activatedRoute: ActivatedRoute,
|
||||||
|
private location: Location,
|
||||||
private appConfigService: AppConfigService,
|
private appConfigService: AppConfigService,
|
||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
private skinableConfig: SkinableConfig) {
|
private skinableConfig: SkinableConfig) {
|
||||||
@ -71,8 +67,7 @@ export class GlobalSearchComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.searchSub = this.searchTerms.pipe(
|
this.searchSub = this.searchTerms.pipe(
|
||||||
debounceTime(deBounceTime),
|
debounceTime(deBounceTime))
|
||||||
distinctUntilChanged())
|
|
||||||
.subscribe(term => {
|
.subscribe(term => {
|
||||||
this.searchTrigger.triggerSearch(term);
|
this.searchTrigger.triggerSearch(term);
|
||||||
});
|
});
|
||||||
@ -83,6 +78,11 @@ export class GlobalSearchComponent implements OnInit, OnDestroy {
|
|||||||
if (this.appConfigService.isIntegrationMode()) {
|
if (this.appConfigService.isIntegrationMode()) {
|
||||||
this.placeholderText = "GLOBAL_SEARCH.PLACEHOLDER_VIC";
|
this.placeholderText = "GLOBAL_SEARCH.PLACEHOLDER_VIC";
|
||||||
}
|
}
|
||||||
|
// init _searchTerm from queryParams
|
||||||
|
this._searchTerm = this.activatedRoute.snapshot.queryParams[SEARCH_KEY];
|
||||||
|
if (this._searchTerm) {
|
||||||
|
this.searchTerms.next(this._searchTerm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
@ -98,7 +98,24 @@ export class GlobalSearchComponent implements OnInit, OnDestroy {
|
|||||||
// Handle the term inputting event
|
// Handle the term inputting event
|
||||||
search(term: string): void {
|
search(term: string): void {
|
||||||
// Send event even term is empty
|
// Send event even term is empty
|
||||||
|
|
||||||
this.searchTerms.next(term.trim());
|
this.searchTerms.next(term.trim());
|
||||||
}
|
}
|
||||||
|
get searchTerm(): string {
|
||||||
|
return this._searchTerm;
|
||||||
|
}
|
||||||
|
set searchTerm(s) {
|
||||||
|
let url: string;
|
||||||
|
if (s) {
|
||||||
|
url = this.router.createUrlTree([], {
|
||||||
|
relativeTo: this.activatedRoute,
|
||||||
|
queryParams: {[SEARCH_KEY]: s}
|
||||||
|
}).toString();
|
||||||
|
} else {
|
||||||
|
url = this.router.createUrlTree([], {
|
||||||
|
relativeTo: this.activatedRoute,
|
||||||
|
}).toString();
|
||||||
|
}
|
||||||
|
this.location.replaceState(url);
|
||||||
|
this._searchTerm = s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Component, OnInit, Input } from '@angular/core';
|
import { Component, OnInit, Input, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { HelmChartSearchResultItem, HelmChartVersion, HelmChartMaintainer } from '../../../base/project/helm-chart/helm-chart-detail/helm-chart.interface.service';
|
import { HelmChartSearchResultItem, HelmChartVersion, HelmChartMaintainer } from '../../../base/project/helm-chart/helm-chart-detail/helm-chart.interface.service';
|
||||||
import { SearchTriggerService } from '../global-search/search-trigger.service';
|
import { SearchTriggerService } from '../global-search/search-trigger.service';
|
||||||
import { ProjectService } from "../../services";
|
import { ProjectService } from "../../services";
|
||||||
@ -7,11 +7,10 @@ import { ProjectService } from "../../services";
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'list-chart-version-ro',
|
selector: 'list-chart-version-ro',
|
||||||
templateUrl: './list-chart-version-ro.component.html'
|
templateUrl: './list-chart-version-ro.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class ListChartVersionRoComponent implements OnInit {
|
export class ListChartVersionRoComponent implements OnInit {
|
||||||
|
|
||||||
@Input() projectId: number;
|
|
||||||
@Input() charts: HelmChartSearchResultItem[];
|
@Input() charts: HelmChartSearchResultItem[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
<clr-datagrid (clrDgRefresh)="refresh($event)">
|
<clr-datagrid>
|
||||||
<clr-dg-column>{{'PROJECT.NAME' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'PROJECT.NAME' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'PROJECT.ACCESS_LEVEL' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'PROJECT.ACCESS_LEVEL' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'PROJECT.REPO_COUNT'| translate}}</clr-dg-column>
|
<clr-dg-column>{{'PROJECT.REPO_COUNT'| translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'PROJECT.CREATION_TIME' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'PROJECT.CREATION_TIME' | translate}}</clr-dg-column>
|
||||||
<clr-dg-row *clrDgItems="let p of projects" [clrDgItem]="p">
|
<clr-dg-row *clrDgItems="let p of projects" [clrDgItem]="p">
|
||||||
<clr-dg-cell><a href="javascript:void(0)" (click)="goToLink(p.project_id)">{{p.name}}</a></clr-dg-cell>
|
<clr-dg-cell><a href="javascript:void(0)" [routerLink]="getLink(p.project_id)">{{p.name}}</a></clr-dg-cell>
|
||||||
<clr-dg-cell>{{ (p.metadata.public === 'true' ? 'PROJECT.PUBLIC' : 'PROJECT.PRIVATE') | translate}}</clr-dg-cell>
|
<clr-dg-cell>{{ (p.metadata.public === 'true' ? 'PROJECT.PUBLIC' : 'PROJECT.PRIVATE') | translate}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{p.repo_count}}</clr-dg-cell>
|
<clr-dg-cell>{{p.repo_count}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{p.creation_time | harborDatetime: 'short'}}</clr-dg-cell>
|
<clr-dg-cell>{{p.creation_time | harborDatetime: 'short'}}</clr-dg-cell>
|
||||||
</clr-dg-row>
|
</clr-dg-row>
|
||||||
|
<clr-dg-placeholder>{{'PROJECT.NO_PROJECT' | translate }}</clr-dg-placeholder>
|
||||||
<clr-dg-footer>
|
<clr-dg-footer>
|
||||||
<span *ngIf="projects?.length">{{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'PROJECT.OF' | translate}} </span> {{projects?.length}} {{'PROJECT.ITEMS' | translate}}
|
<span *ngIf="projects?.length">{{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'PROJECT.OF' | translate}} </span> {{projects?.length}} {{'PROJECT.ITEMS' | translate}}
|
||||||
<clr-dg-pagination #pagination [clrDgPageSize]="5"></clr-dg-pagination>
|
<clr-dg-pagination #pagination [clrDgPageSize]="5"></clr-dg-pagination>
|
||||||
|
@ -1,47 +1,50 @@
|
|||||||
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
|
||||||
import { ListProjectROComponent } from './list-project-ro.component';
|
import { ListProjectROComponent } from './list-project-ro.component';
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
import { SharedTestingModule } from "../../shared.module";
|
||||||
import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { Project } from "../../../../../ng-swagger-gen/models/project";
|
||||||
import { ClarityModule } from '@clr/angular';
|
import { Component } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
// mock a TestHostComponent for ListProjectROComponent
|
||||||
import { of } from 'rxjs';
|
@Component({
|
||||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
template: `
|
||||||
import { SearchTriggerService } from '../global-search/search-trigger.service';
|
<list-project-ro [projects]="projects">
|
||||||
|
</list-project-ro>`
|
||||||
|
})
|
||||||
|
class TestHostComponent {
|
||||||
|
projects: Project[] = [];
|
||||||
|
}
|
||||||
|
|
||||||
describe('ListProjectROComponent', () => {
|
describe('ListProjectROComponent', () => {
|
||||||
let component: ListProjectROComponent;
|
let component: TestHostComponent;
|
||||||
let fixture: ComponentFixture<ListProjectROComponent>;
|
let fixture: ComponentFixture<TestHostComponent>;
|
||||||
const mockSearchTriggerService = {
|
const mockedProjects: Project[] = [
|
||||||
closeSearch: () => { }
|
{
|
||||||
};
|
chart_count: 0,
|
||||||
|
name: "test1",
|
||||||
|
metadata: {},
|
||||||
|
project_id: 1,
|
||||||
|
repo_count: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chart_count: 0,
|
||||||
|
name: "test2",
|
||||||
|
metadata: {},
|
||||||
|
project_id: 2,
|
||||||
|
repo_count: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
schemas: [
|
|
||||||
CUSTOM_ELEMENTS_SCHEMA
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
BrowserAnimationsModule,
|
SharedTestingModule
|
||||||
ClarityModule,
|
|
||||||
TranslateModule.forRoot(),
|
|
||||||
FormsModule,
|
|
||||||
RouterTestingModule,
|
|
||||||
NoopAnimationsModule,
|
|
||||||
HttpClientTestingModule
|
|
||||||
],
|
],
|
||||||
declarations: [ListProjectROComponent],
|
declarations: [ListProjectROComponent,
|
||||||
providers: [
|
TestHostComponent],
|
||||||
TranslateService,
|
}).compileComponents();
|
||||||
{ provide: SearchTriggerService, useValue: mockSearchTriggerService }
|
|
||||||
|
|
||||||
]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(ListProjectROComponent);
|
fixture = TestBed.createComponent(TestHostComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
@ -49,4 +52,12 @@ describe('ListProjectROComponent', () => {
|
|||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should render project list', async () => {
|
||||||
|
component.projects = mockedProjects;
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const rows = fixture.nativeElement.querySelectorAll('clr-dg-row');
|
||||||
|
expect(rows.length).toEqual(2);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,12 +11,8 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
import { Component, EventEmitter, Output, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Project } from "../../../../../ng-swagger-gen/models/project";
|
||||||
import { State } from '../../services/interface';
|
|
||||||
|
|
||||||
import { SearchTriggerService } from '../global-search/search-trigger.service';
|
|
||||||
import { Project } from '../../../base/project/project';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'list-project-ro',
|
selector: 'list-project-ro',
|
||||||
@ -25,21 +21,11 @@ import { Project } from '../../../base/project/project';
|
|||||||
})
|
})
|
||||||
export class ListProjectROComponent {
|
export class ListProjectROComponent {
|
||||||
@Input() projects: Project[];
|
@Input() projects: Project[];
|
||||||
@Output() paginate = new EventEmitter<State>();
|
|
||||||
|
|
||||||
|
constructor() {
|
||||||
constructor(
|
|
||||||
private searchTrigger: SearchTriggerService,
|
|
||||||
private router: Router) {}
|
|
||||||
|
|
||||||
goToLink(proId: number): void {
|
|
||||||
this.searchTrigger.closeSearch(true);
|
|
||||||
|
|
||||||
let linkUrl = ['harbor', 'projects', proId, 'repositories'];
|
|
||||||
this.router.navigate(linkUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh(state: State) {
|
getLink(proId: number) {
|
||||||
this.paginate.emit(state);
|
return `/harbor/projects/${proId}/repositories`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
<clr-datagrid (clrDgRefresh)="refresh($event)">
|
<clr-datagrid>
|
||||||
<clr-dg-column>{{'REPOSITORY.NAME' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'REPOSITORY.NAME' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'REPOSITORY.ARTIFACTS_COUNT' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'REPOSITORY.ARTIFACTS_COUNT' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'REPOSITORY.PULL_COUNT' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'REPOSITORY.PULL_COUNT' | translate}}</clr-dg-column>
|
||||||
<clr-dg-row *clrDgItems="let r of repositories" [clrDgItem]='r'>
|
<clr-dg-row *clrDgItems="let r of repositories" [clrDgItem]='r'>
|
||||||
<clr-dg-cell><a href="javascript:void(0)" (click)="gotoLink(projectId || r.project_id, r.name || r.repository_name)">{{r.name || r.repository_name}}</a></clr-dg-cell>
|
<clr-dg-cell><a href="javascript:void(0)" [routerLink]="getLink(r.project_id, r.name || r.repository_name)" [queryParams]="getQueryParams()">{{r.name || r.repository_name}}</a></clr-dg-cell>
|
||||||
<clr-dg-cell>{{r.artifact_count}}</clr-dg-cell>
|
<clr-dg-cell>{{r.artifact_count}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{r.pull_count}}</clr-dg-cell>
|
<clr-dg-cell>{{r.pull_count}}</clr-dg-cell>
|
||||||
</clr-dg-row>
|
</clr-dg-row>
|
||||||
|
<clr-dg-placeholder>{{'REPOSITORY.PLACEHOLDER' | translate }}</clr-dg-placeholder>
|
||||||
<clr-dg-footer>
|
<clr-dg-footer>
|
||||||
<span *ngIf="repositories?.length">{{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'REPOSITORY.OF' | translate}} </span> {{repositories?.length }} {{'REPOSITORY.ITEMS' | translate}}
|
<span *ngIf="repositories?.length">{{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'REPOSITORY.OF' | translate}} </span> {{repositories?.length }} {{'REPOSITORY.ITEMS' | translate}}
|
||||||
<clr-dg-pagination #pagination [clrDgPageSize]="5"></clr-dg-pagination>
|
<clr-dg-pagination #pagination [clrDgPageSize]="5"></clr-dg-pagination>
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
import {filter} from 'rxjs/operators';
|
|
||||||
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -13,72 +11,39 @@ import {filter} from 'rxjs/operators';
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
import { Component, Input, Output, OnDestroy, EventEmitter, ChangeDetectionStrategy, ChangeDetectorRef, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
import { Router, NavigationEnd } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { State } from '../../services/interface';
|
|
||||||
import { Repository } from '../../../../../ng-swagger-gen/models/repository';
|
import { Repository } from '../../../../../ng-swagger-gen/models/repository';
|
||||||
|
|
||||||
import { SearchTriggerService } from '../global-search/search-trigger.service';
|
import { SearchTriggerService } from '../global-search/search-trigger.service';
|
||||||
import {Subscription} from "rxjs";
|
|
||||||
import { SessionService } from "../../services/session.service";
|
import { SessionService } from "../../services/session.service";
|
||||||
import { UN_LOGGED_PARAM } from "../../../account/sign-in/sign-in.service";
|
import { UN_LOGGED_PARAM } from "../../../account/sign-in/sign-in.service";
|
||||||
|
|
||||||
const YES: string = 'yes';
|
const YES: string = 'yes';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'list-repository-ro',
|
selector: 'list-repository-ro',
|
||||||
templateUrl: 'list-repository-ro.component.html',
|
templateUrl: 'list-repository-ro.component.html',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class ListRepositoryROComponent implements OnInit, OnDestroy {
|
export class ListRepositoryROComponent {
|
||||||
|
|
||||||
@Input() projectId: number;
|
|
||||||
@Input() repositories: Repository[];
|
@Input() repositories: Repository[];
|
||||||
|
|
||||||
@Output() paginate = new EventEmitter<State>();
|
|
||||||
|
|
||||||
routerSubscription: Subscription;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private searchTrigger: SearchTriggerService,
|
private searchTrigger: SearchTriggerService,
|
||||||
private ref: ChangeDetectorRef,
|
|
||||||
private sessionService: SessionService) {
|
private sessionService: SessionService) {
|
||||||
this.router.routeReuseStrategy.shouldReuseRoute = function() {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
this.routerSubscription = this.router.events.pipe(filter(event => event instanceof NavigationEnd))
|
|
||||||
.subscribe((event) => {
|
|
||||||
// trick the Router into believing it's last link wasn't previously loaded
|
|
||||||
this.router.navigated = false;
|
|
||||||
// if you need to scroll back to top, here is the right place
|
|
||||||
window.scrollTo(0, 0);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
getLink(projectId: number, repoName: string) {
|
||||||
let hnd = setInterval(() => this.ref.markForCheck(), 100);
|
|
||||||
setTimeout(() => clearInterval(hnd), 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
|
||||||
this.routerSubscription.unsubscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh(state: State) {
|
|
||||||
if (this.repositories) {
|
|
||||||
this.paginate.emit(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public gotoLink(projectId: number, repoName: string): void {
|
|
||||||
this.searchTrigger.closeSearch(true);
|
|
||||||
let projectName = repoName.split('/')[0];
|
let projectName = repoName.split('/')[0];
|
||||||
let repositorieName = projectName ? repoName.substr(projectName.length + 1) : repoName;
|
let repositorieName = projectName ? repoName.substr(projectName.length + 1) : repoName;
|
||||||
let linkUrl = ['harbor', 'projects', projectId, 'repositories', repositorieName ];
|
return `/harbor/projects/${projectId}/repositories/${repositorieName}`;
|
||||||
|
}
|
||||||
|
getQueryParams() {
|
||||||
if (this.sessionService.getCurrentUser()) {
|
if (this.sessionService.getCurrentUser()) {
|
||||||
this.router.navigate(linkUrl);
|
return null;
|
||||||
} else {// if not logged in and it's a public project, add param 'publicAndNotLogged'
|
|
||||||
this.router.navigate(linkUrl, {queryParams: {[UN_LOGGED_PARAM]: YES}});
|
|
||||||
}
|
}
|
||||||
|
return {[UN_LOGGED_PARAM]: YES};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,8 @@
|
|||||||
"PROXY_CACHE": "Proxy Cache",
|
"PROXY_CACHE": "Proxy Cache",
|
||||||
"PROXY_CACHE_TOOLTIP": "Die Aktivierung der Funktion erlaubt es dem Projekt, als Cache für eine andere Registry Instanz zu dienen. Harbor unterstützt die Proxy Funktion nur für DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay und Google GCR.",
|
"PROXY_CACHE_TOOLTIP": "Die Aktivierung der Funktion erlaubt es dem Projekt, als Cache für eine andere Registry Instanz zu dienen. Harbor unterstützt die Proxy Funktion nur für DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay und Google GCR.",
|
||||||
"ENDPOINT": "Endpunkt",
|
"ENDPOINT": "Endpunkt",
|
||||||
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpunkt"
|
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpunkt",
|
||||||
|
"NO_PROJECT": "We couldn't find any projects"
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "Zusammenfassung",
|
"SUMMARY": "Zusammenfassung",
|
||||||
|
@ -254,7 +254,8 @@
|
|||||||
"PROXY_CACHE": "Proxy Cache",
|
"PROXY_CACHE": "Proxy Cache",
|
||||||
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
||||||
"ENDPOINT": "Endpoint",
|
"ENDPOINT": "Endpoint",
|
||||||
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
|
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint",
|
||||||
|
"NO_PROJECT": "We couldn't find any projects"
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "Summary",
|
"SUMMARY": "Summary",
|
||||||
|
@ -255,7 +255,8 @@
|
|||||||
"PROXY_CACHE": "Proxy Cache",
|
"PROXY_CACHE": "Proxy Cache",
|
||||||
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
||||||
"ENDPOINT": "Endpoint",
|
"ENDPOINT": "Endpoint",
|
||||||
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
|
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint",
|
||||||
|
"NO_PROJECT": "We couldn't find any projects"
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "Summary",
|
"SUMMARY": "Summary",
|
||||||
|
@ -248,7 +248,8 @@
|
|||||||
"PROXY_CACHE": "Proxy Cache",
|
"PROXY_CACHE": "Proxy Cache",
|
||||||
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
||||||
"ENDPOINT": "Endpoint",
|
"ENDPOINT": "Endpoint",
|
||||||
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
|
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint",
|
||||||
|
"NO_PROJECT": "We couldn't find any projects"
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "Summary",
|
"SUMMARY": "Summary",
|
||||||
|
@ -252,7 +252,8 @@
|
|||||||
"PROXY_CACHE": "Proxy Cache",
|
"PROXY_CACHE": "Proxy Cache",
|
||||||
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
||||||
"ENDPOINT": "Endpoint",
|
"ENDPOINT": "Endpoint",
|
||||||
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
|
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint",
|
||||||
|
"NO_PROJECT": "We couldn't find any projects"
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "Summary",
|
"SUMMARY": "Summary",
|
||||||
|
@ -254,7 +254,8 @@
|
|||||||
"PROXY_CACHE": "Proxy Cache",
|
"PROXY_CACHE": "Proxy Cache",
|
||||||
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
||||||
"ENDPOINT": "Endpoint",
|
"ENDPOINT": "Endpoint",
|
||||||
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
|
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint",
|
||||||
|
"NO_PROJECT": "We couldn't find any projects"
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "Özet",
|
"SUMMARY": "Özet",
|
||||||
|
@ -253,7 +253,8 @@
|
|||||||
"PROXY_CACHE": "镜像代理",
|
"PROXY_CACHE": "镜像代理",
|
||||||
"PROXY_CACHE_TOOLTIP": "开启此项,以使得该项目成为目标仓库的镜像代理.仅支持 DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay 和 Google GCR 类型的仓库",
|
"PROXY_CACHE_TOOLTIP": "开启此项,以使得该项目成为目标仓库的镜像代理.仅支持 DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay 和 Google GCR 类型的仓库",
|
||||||
"ENDPOINT": "地址",
|
"ENDPOINT": "地址",
|
||||||
"PROXY_CACHE_ENDPOINT": "镜像代理地址"
|
"PROXY_CACHE_ENDPOINT": "镜像代理地址",
|
||||||
|
"NO_PROJECT": "未发现任何项目"
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "概要",
|
"SUMMARY": "概要",
|
||||||
|
@ -251,7 +251,8 @@
|
|||||||
"PROXY_CACHE": "Proxy Cache",
|
"PROXY_CACHE": "Proxy Cache",
|
||||||
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
"PROXY_CACHE_TOOLTIP": "Enable this to allow this project to act as a pull-through cache for a particular target registry instance. Harbor can only act a proxy for DockerHub, Docker Registry, Harbor, Aws ECR, Azure ACR, Quay and Google GCR registries.",
|
||||||
"ENDPOINT": "Endpoint",
|
"ENDPOINT": "Endpoint",
|
||||||
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint"
|
"PROXY_CACHE_ENDPOINT": "Proxy Cache Endpoint",
|
||||||
|
"NO_PROJECT": "We couldn't find any projects"
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL":{
|
"PROJECT_DETAIL":{
|
||||||
"SUMMARY": "概要",
|
"SUMMARY": "概要",
|
||||||
|
Loading…
Reference in New Issue
Block a user