mirror of
https://github.com/goharbor/harbor.git
synced 2024-06-24 13:55:05 +02:00
Remove helm chart UI (#18099)
1.Remove all helm chart v2 related code Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
9d30955607
commit
ff9dcd5483
|
@ -118,13 +118,6 @@ export class SignInComponent implements AfterViewChecked, OnInit {
|
||||||
|
|
||||||
// App title
|
// App title
|
||||||
public get appTitle(): string {
|
public get appTitle(): string {
|
||||||
if (
|
|
||||||
this.appConfigService.getConfig() &&
|
|
||||||
this.appConfigService.getConfig().with_admiral
|
|
||||||
) {
|
|
||||||
return 'APP_TITLE.VIC';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'APP_TITLE.VMW_HARBOR';
|
return 'APP_TITLE.VMW_HARBOR';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,10 +50,6 @@ export class AppComponent {
|
||||||
this.initLanguage();
|
this.initLanguage();
|
||||||
// Override page title
|
// Override page title
|
||||||
let key: string = 'APP_TITLE.HARBOR';
|
let key: string = 'APP_TITLE.HARBOR';
|
||||||
if (this.appConfigService.isIntegrationMode()) {
|
|
||||||
key = 'APP_TITLE.REG';
|
|
||||||
}
|
|
||||||
|
|
||||||
translate.get(key).subscribe((res: string) => {
|
translate.get(key).subscribe((res: string) => {
|
||||||
const customSkinData: CustomStyle =
|
const customSkinData: CustomStyle =
|
||||||
this.skinableConfig.getSkinConfig();
|
this.skinableConfig.getSkinConfig();
|
||||||
|
|
|
@ -161,17 +161,6 @@ const routes: Routes = [
|
||||||
projectResolver: ProjectRoutingResolver,
|
projectResolver: ProjectRoutingResolver,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'projects/:id/helm-charts',
|
|
||||||
canActivate: [MemberGuard],
|
|
||||||
resolve: {
|
|
||||||
projectResolver: ProjectRoutingResolver,
|
|
||||||
},
|
|
||||||
loadChildren: () =>
|
|
||||||
import(
|
|
||||||
'./project/helm-chart/helm-chart-detail/helm-chart-detail.module'
|
|
||||||
).then(m => m.HelmChartListModule),
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -129,7 +129,6 @@
|
||||||
{{ 'SIDE_NAV.DISTRIBUTIONS.NAME' | translate }}
|
{{ 'SIDE_NAV.DISTRIBUTIONS.NAME' | translate }}
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
*ngIf="!withAdmiral"
|
|
||||||
clrVerticalNavLink
|
clrVerticalNavLink
|
||||||
routerLink="/harbor/labels"
|
routerLink="/harbor/labels"
|
||||||
routerLinkActive="active">
|
routerLinkActive="active">
|
||||||
|
|
|
@ -242,9 +242,6 @@ export class HarborShellComponent implements OnInit, OnDestroy {
|
||||||
this.session.getCurrentUser().has_admin_role
|
this.session.getCurrentUser().has_admin_role
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public get withAdmiral(): boolean {
|
|
||||||
return this.appConfigService.getConfig().with_admiral;
|
|
||||||
}
|
|
||||||
// Open modal dialog
|
// Open modal dialog
|
||||||
openModal(event: ModalEvent): void {
|
openModal(event: ModalEvent): void {
|
||||||
switch (event.modalName) {
|
switch (event.modalName) {
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
type="button"
|
type="button"
|
||||||
routerLink="security"
|
routerLink="security"
|
||||||
routerLinkActive="active">
|
routerLinkActive="active">
|
||||||
{{ 'HELM_CHART.SECURITY' | translate }}
|
{{ 'CONFIG.SECURITY' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li role="presentation" class="nav-item">
|
<li role="presentation" class="nav-item">
|
||||||
|
|
|
@ -53,9 +53,6 @@
|
||||||
<clr-dg-column>{{ 'PROJECT.ROLE' | translate }}</clr-dg-column>
|
<clr-dg-column>{{ 'PROJECT.ROLE' | translate }}</clr-dg-column>
|
||||||
<clr-dg-column>{{ 'PROJECT.TYPE' | translate }}</clr-dg-column>
|
<clr-dg-column>{{ 'PROJECT.TYPE' | 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 *ngIf="withChartMuseum">{{
|
|
||||||
'PROJECT.CHART_COUNT' | translate
|
|
||||||
}}</clr-dg-column>
|
|
||||||
<clr-dg-column [clrDgSortBy]="'creation_time'">{{
|
<clr-dg-column [clrDgSortBy]="'creation_time'">{{
|
||||||
'PROJECT.CREATION_TIME' | translate
|
'PROJECT.CREATION_TIME' | translate
|
||||||
}}</clr-dg-column>
|
}}</clr-dg-column>
|
||||||
|
@ -83,7 +80,6 @@
|
||||||
projectTypeMap[p.registry_id ? 1 : 0] | translate
|
projectTypeMap[p.registry_id ? 1 : 0] | translate
|
||||||
}}</clr-dg-cell>
|
}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{ p.repo_count }}</clr-dg-cell>
|
<clr-dg-cell>{{ p.repo_count }}</clr-dg-cell>
|
||||||
<clr-dg-cell *ngIf="withChartMuseum">{{ p.chart_count }}</clr-dg-cell>
|
|
||||||
<clr-dg-cell>{{
|
<clr-dg-cell>{{
|
||||||
p.creation_time | harborDatetime: 'short'
|
p.creation_time | harborDatetime: 'short'
|
||||||
}}</clr-dg-cell>
|
}}</clr-dg-cell>
|
||||||
|
|
|
@ -132,11 +132,6 @@ export class ListProjectComponent implements OnDestroy {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
get withChartMuseum(): boolean {
|
|
||||||
return this.appConfigService.getConfig().with_chartmuseum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get isSystemAdmin(): boolean {
|
public get isSystemAdmin(): boolean {
|
||||||
let account = this.session.getCurrentUser();
|
let account = this.session.getCurrentUser();
|
||||||
return account != null && account.has_admin_role;
|
return account != null && account.has_admin_role;
|
||||||
|
|
|
@ -101,12 +101,10 @@ export class CreateEditEndpointComponent
|
||||||
this.endpointService.getAdapters().subscribe(
|
this.endpointService.getAdapters().subscribe(
|
||||||
adapters => {
|
adapters => {
|
||||||
this.adapterList = adapters || [];
|
this.adapterList = adapters || [];
|
||||||
if (!this.appConfigService.getConfig().with_chartmuseum) {
|
// disable helm-hub
|
||||||
// disable helm-hub
|
for (let i = 0; i < this.adapterList.length; i++) {
|
||||||
for (let i = 0; i < this.adapterList.length; i++) {
|
if (this.adapterList[i] === HELM_HUB) {
|
||||||
if (this.adapterList[i] === HELM_HUB) {
|
this.adapterList.splice(i, 1);
|
||||||
this.adapterList.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -246,12 +246,7 @@
|
||||||
?.values
|
?.values
|
||||||
"
|
"
|
||||||
value="{{ value }}">
|
value="{{ value }}">
|
||||||
{{ value
|
{{ value }}
|
||||||
}}{{
|
|
||||||
value === 'chart'
|
|
||||||
? ' (chartmuseum)'
|
|
||||||
: ''
|
|
||||||
}}
|
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -610,7 +605,6 @@
|
||||||
| translate
|
| translate
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div>{{ 'REPLICATION.NOTE' | translate }}</div>
|
|
||||||
</clr-tooltip-content>
|
</clr-tooltip-content>
|
||||||
</clr-tooltip>
|
</clr-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -111,7 +111,6 @@ export class ReplicationComponent implements OnInit, OnDestroy {
|
||||||
@Input() projectId: number | string;
|
@Input() projectId: number | string;
|
||||||
@Input() projectName: string;
|
@Input() projectName: string;
|
||||||
@Input() isSystemAdmin: boolean;
|
@Input() isSystemAdmin: boolean;
|
||||||
@Input() withAdmiral: boolean;
|
|
||||||
@Input() withReplicationJob: boolean;
|
@Input() withReplicationJob: boolean;
|
||||||
@Input() hasCreateReplicationPermission: boolean;
|
@Input() hasCreateReplicationPermission: boolean;
|
||||||
@Input() hasUpdateReplicationPermission: boolean;
|
@Input() hasUpdateReplicationPermission: boolean;
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
<hbr-replication
|
<hbr-replication
|
||||||
[withReplicationJob]="true"
|
[withReplicationJob]="true"
|
||||||
[isSystemAdmin]="isSystemAdmin"
|
[isSystemAdmin]="isSystemAdmin"
|
||||||
[withAdmiral]="withAdmiral"
|
|
||||||
(goToRegistry)="goRegistry()"
|
(goToRegistry)="goRegistry()"
|
||||||
[hasCreateReplicationPermission]="true"
|
[hasCreateReplicationPermission]="true"
|
||||||
[hasUpdateReplicationPermission]="true"
|
[hasUpdateReplicationPermission]="true"
|
||||||
|
|
|
@ -80,8 +80,4 @@ export class TotalReplicationPageComponent implements OnInit, OnDestroy {
|
||||||
let account = this.session.getCurrentUser();
|
let account = this.session.getCurrentUser();
|
||||||
return account != null && account.has_admin_role;
|
return account != null && account.has_admin_role;
|
||||||
}
|
}
|
||||||
|
|
||||||
get withAdmiral(): boolean {
|
|
||||||
return this.appConfigService.getConfig().with_admiral;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,6 @@ export enum PermissionsKinds {
|
||||||
|
|
||||||
export enum Resource {
|
export enum Resource {
|
||||||
REPO = 'repository',
|
REPO = 'repository',
|
||||||
HELM_CHART = 'helm-chart',
|
|
||||||
HELM_CHART_VERSION = 'helm-chart-version',
|
|
||||||
ARTIFACT = 'artifact',
|
ARTIFACT = 'artifact',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,31 +114,6 @@ export const INITIAL_ACCESSES: FrontAccess[] = [
|
||||||
action: 'stop',
|
action: 'stop',
|
||||||
checked: true,
|
checked: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
resource: 'helm-chart',
|
|
||||||
action: 'read',
|
|
||||||
checked: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resource: 'helm-chart-version',
|
|
||||||
action: 'create',
|
|
||||||
checked: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resource: 'helm-chart-version',
|
|
||||||
action: 'delete',
|
|
||||||
checked: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resource: 'helm-chart-version-label',
|
|
||||||
action: 'create',
|
|
||||||
checked: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resource: 'helm-chart-version-label',
|
|
||||||
action: 'delete',
|
|
||||||
checked: true,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ACTION_RESOURCE_I18N_MAP = {
|
export const ACTION_RESOURCE_I18N_MAP = {
|
||||||
|
@ -151,11 +124,8 @@ export const ACTION_RESOURCE_I18N_MAP = {
|
||||||
delete: 'SYSTEM_ROBOT.DELETE',
|
delete: 'SYSTEM_ROBOT.DELETE',
|
||||||
repository: 'SYSTEM_ROBOT.REPOSITORY',
|
repository: 'SYSTEM_ROBOT.REPOSITORY',
|
||||||
artifact: 'SYSTEM_ROBOT.ARTIFACT',
|
artifact: 'SYSTEM_ROBOT.ARTIFACT',
|
||||||
'helm-chart': 'SYSTEM_ROBOT.HELM',
|
|
||||||
'helm-chart-version': 'SYSTEM_ROBOT.HELM_VERSION',
|
|
||||||
tag: 'REPLICATION.TAG',
|
tag: 'REPLICATION.TAG',
|
||||||
'artifact-label': 'SYSTEM_ROBOT.ARTIFACT_LABEL',
|
'artifact-label': 'SYSTEM_ROBOT.ARTIFACT_LABEL',
|
||||||
'helm-chart-version-label': 'SYSTEM_ROBOT.HELM_LABEL',
|
|
||||||
scan: 'SYSTEM_ROBOT.SCAN',
|
scan: 'SYSTEM_ROBOT.SCAN',
|
||||||
'scanner-pull': 'SYSTEM_ROBOT.SCANNER_PULL',
|
'scanner-pull': 'SYSTEM_ROBOT.SCANNER_PULL',
|
||||||
stop: 'SYSTEM_ROBOT.STOP',
|
stop: 'SYSTEM_ROBOT.STOP',
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
<div>
|
|
||||||
<div class="breadcrumb">
|
|
||||||
<span class="back-icon"><</span>
|
|
||||||
<a (click)="gotoProjectList()">{{ 'SIDE_NAV.PROJECTS' | translate }}</a>
|
|
||||||
<span class="back-icon"><</span>
|
|
||||||
<a (click)="gotoChartList()">{{ projectName }}</a>
|
|
||||||
<span class="back-icon"><</span>
|
|
||||||
<a (click)="gotoChartVersion()">{{
|
|
||||||
'HELM_CHART.CHARTVERSIONS' | translate
|
|
||||||
}}</a>
|
|
||||||
</div>
|
|
||||||
<hbr-chart-detail
|
|
||||||
[projectId]="projectId"
|
|
||||||
[project]="project"
|
|
||||||
[chartName]="chartName"
|
|
||||||
[chartVersion]="chartVersion"
|
|
||||||
[roleName]="roleName"></hbr-chart-detail>
|
|
||||||
</div>
|
|
|
@ -1,16 +0,0 @@
|
||||||
.breadcrumb a {
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #007cbb;
|
|
||||||
font-size: 16px;
|
|
||||||
margin: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.breadcrumb {
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-icon {
|
|
||||||
color: #007cbb;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
|
||||||
import { SessionService } from '../../../../shared/services/session.service';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { HelmChartDetailComponent } from './chart-detail.component';
|
|
||||||
import { SharedTestingModule } from '../../../../shared/shared.module';
|
|
||||||
|
|
||||||
describe('ChartDetailComponent', () => {
|
|
||||||
let component: HelmChartDetailComponent;
|
|
||||||
let fixture: ComponentFixture<HelmChartDetailComponent>;
|
|
||||||
let fakeRouter = null;
|
|
||||||
let fakeSessionService = {
|
|
||||||
getCurrentUser: function () {
|
|
||||||
return { has_admin_role: true };
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [HelmChartDetailComponent],
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
imports: [SharedTestingModule],
|
|
||||||
providers: [
|
|
||||||
{
|
|
||||||
provide: ActivatedRoute,
|
|
||||||
useValue: {
|
|
||||||
paramMap: of({ get: key => 'value' }),
|
|
||||||
snapshot: {
|
|
||||||
parent: {
|
|
||||||
data: {
|
|
||||||
projectResolver: {
|
|
||||||
role_name: 'admin',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
params: { id: 1 },
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
chart: 'chart',
|
|
||||||
version: 1.0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ provide: Router, useValue: fakeRouter },
|
|
||||||
{ provide: SessionService, useValue: fakeSessionService },
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(HelmChartDetailComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,59 +0,0 @@
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
|
||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
import { Project } from '../../project';
|
|
||||||
import { SessionService } from '../../../../shared/services/session.service';
|
|
||||||
import { SessionUser } from '../../../../shared/entities/session-user';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'project-chart-detail',
|
|
||||||
templateUrl: './chart-detail.component.html',
|
|
||||||
styleUrls: ['./chart-detail.component.scss'],
|
|
||||||
})
|
|
||||||
export class HelmChartDetailComponent implements OnInit {
|
|
||||||
projectId: number | string;
|
|
||||||
project: Project;
|
|
||||||
projectName: string;
|
|
||||||
chartName: string;
|
|
||||||
chartVersion: string;
|
|
||||||
currentUser: SessionUser;
|
|
||||||
hasProjectAdminRole: boolean;
|
|
||||||
roleName: string;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private route: ActivatedRoute,
|
|
||||||
private router: Router,
|
|
||||||
private session: SessionService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
// Get projectId from router-guard params snapshot.
|
|
||||||
this.projectId = +this.route.snapshot.parent.params['id'];
|
|
||||||
this.chartName = this.route.snapshot.params['chart'];
|
|
||||||
this.chartVersion = this.route.snapshot.params['version'];
|
|
||||||
// Get current user from registered resolver.
|
|
||||||
this.currentUser = this.session.getCurrentUser();
|
|
||||||
let resolverData = this.route.snapshot.parent.data;
|
|
||||||
if (resolverData) {
|
|
||||||
this.project = <Project>resolverData['projectResolver'];
|
|
||||||
this.roleName = this.project.role_name;
|
|
||||||
this.projectName = this.project.name;
|
|
||||||
this.hasProjectAdminRole = this.project.has_project_admin_role;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gotoProjectList() {
|
|
||||||
this.router.navigateByUrl('/harbor/projects');
|
|
||||||
}
|
|
||||||
|
|
||||||
gotoChartList() {
|
|
||||||
this.router.navigateByUrl(
|
|
||||||
`/harbor/projects/${this.projectId}/helm-charts`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
gotoChartVersion() {
|
|
||||||
this.router.navigateByUrl(
|
|
||||||
`/harbor/projects/${this.projectId}/helm-charts/${this.chartName}/versions`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
<div class="row flex-items-xs-center dep-container">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="left">{{ 'HELM_CHART.NAME' | translate }}</th>
|
|
||||||
<th class="left">{{ 'HELM_CHART.VERSION' | translate }}</th>
|
|
||||||
<th class="left">{{ 'HELM_CHART.REPO' | translate }}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr *ngFor="let dep of dependencies">
|
|
||||||
<td class="left">{{ dep.name }}</td>
|
|
||||||
<td class="left">{{ dep.version }}</td>
|
|
||||||
<td class="left">
|
|
||||||
<a href="{{ dep.repository }}">{{ dep.repository }}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,3 +0,0 @@
|
||||||
.dep-container {
|
|
||||||
margin-top: 30px;
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { ChartDetailDependencyComponent } from './chart-detail-dependency.component';
|
|
||||||
import { SharedTestingModule } from '../../../../../shared/shared.module';
|
|
||||||
|
|
||||||
describe('ChartDetailDependencyComponent', () => {
|
|
||||||
let component: ChartDetailDependencyComponent;
|
|
||||||
let fixture: ComponentFixture<ChartDetailDependencyComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [SharedTestingModule],
|
|
||||||
declarations: [ChartDetailDependencyComponent],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ChartDetailDependencyComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
|
||||||
|
|
||||||
import { HelmChartDependency } from '../helm-chart.interface.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hbr-chart-detail-dependency',
|
|
||||||
templateUrl: './chart-detail-dependency.component.html',
|
|
||||||
styleUrls: ['./chart-detail-dependency.component.scss'],
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
})
|
|
||||||
export class ChartDetailDependencyComponent {
|
|
||||||
@Input() dependencies: HelmChartDependency;
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
}
|
|
|
@ -1,224 +0,0 @@
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<p>{{ summary.description }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row content-wrapper">
|
|
||||||
<div class="col-md-8 md-container pl-1">
|
|
||||||
<div
|
|
||||||
*ngIf="readme"
|
|
||||||
class="md-div"
|
|
||||||
[innerHTML]="readme | markdown"></div>
|
|
||||||
<div *ngIf="!readme">{{ 'HELM_CHART.NO_README' | translate }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4 summary-container mt-1">
|
|
||||||
<div class="col-md-12 content-group">
|
|
||||||
<div>
|
|
||||||
<label>{{ 'HELM_CHART.OVERVIEW' | translate }}</label>
|
|
||||||
</div>
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="left">
|
|
||||||
{{ 'HELM_CHART.HOME' | translate }}
|
|
||||||
</td>
|
|
||||||
<td class="left text-wrapper">
|
|
||||||
<a href="{{ summary.home }}">{{ summary.home }}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr *ngFor="let src of summary.sources; let i = index">
|
|
||||||
<td class="left" *ngIf="i === 0">
|
|
||||||
{{ 'HELM_CHART.SRC_REPO' | translate }}
|
|
||||||
</td>
|
|
||||||
<td class="left" *ngIf="i !== 0"></td>
|
|
||||||
<td class="left text-wrapper">
|
|
||||||
<a href="{{ src }}">{{ src }}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left">
|
|
||||||
{{ 'HELM_CHART.CREATED' | translate }}
|
|
||||||
</td>
|
|
||||||
<td class="left">
|
|
||||||
{{ summary.created | harborDatetime }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr
|
|
||||||
*ngFor="
|
|
||||||
let maintainer of summary.maintainers;
|
|
||||||
let i = index
|
|
||||||
">
|
|
||||||
<td class="left" *ngIf="i === 0">
|
|
||||||
{{ 'HELM_CHART.MAINTAINERS' | translate }}
|
|
||||||
</td>
|
|
||||||
<td class="left" *ngIf="i !== 0"></td>
|
|
||||||
<td class="left">
|
|
||||||
<a href="mailto:{{ maintainer.email }}">{{
|
|
||||||
maintainer.name
|
|
||||||
}}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left">
|
|
||||||
{{ 'HELM_CHART.APP_VERSION' | translate }}
|
|
||||||
</td>
|
|
||||||
<td class="left">{{ summary.appVersion }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-12 content-group">
|
|
||||||
<div>
|
|
||||||
<label>{{ 'HELM_CHART.COMMAND' | translate }}</label>
|
|
||||||
</div>
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="left cmd-title">
|
|
||||||
{{ 'HELM_CHART.ADD_REPO' | translate }}
|
|
||||||
</td>
|
|
||||||
<td class="left cmd-content">
|
|
||||||
<input
|
|
||||||
class="cmd-content clr-input"
|
|
||||||
type="text"
|
|
||||||
[(ngModel)]="addCMD"
|
|
||||||
#addCMDInput
|
|
||||||
readonly />
|
|
||||||
</td>
|
|
||||||
<td class="left">
|
|
||||||
<span>
|
|
||||||
<clr-icon
|
|
||||||
shape="copy"
|
|
||||||
size="24"
|
|
||||||
[class.is-success]="isCopied('add')"
|
|
||||||
[ngxClipboard]="addCMDInput"
|
|
||||||
(cbOnSuccess)="
|
|
||||||
onCopySuccess($event, 'add')
|
|
||||||
"></clr-icon>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left cmd-title">
|
|
||||||
{{ 'HELM_CHART.INSTALL_CHART' | translate }}
|
|
||||||
</td>
|
|
||||||
<td class="left">
|
|
||||||
<input
|
|
||||||
class="cmd-content clr-input"
|
|
||||||
type="text"
|
|
||||||
[(ngModel)]="installCMD"
|
|
||||||
#installCMDInput
|
|
||||||
readonly />
|
|
||||||
</td>
|
|
||||||
<td class="left">
|
|
||||||
<span>
|
|
||||||
<clr-icon
|
|
||||||
shape="copy"
|
|
||||||
size="24"
|
|
||||||
[class.is-success]="isCopied('install')"
|
|
||||||
[ngxClipboard]="installCMDInput"
|
|
||||||
(cbOnSuccess)="
|
|
||||||
onCopySuccess($event, 'install')
|
|
||||||
"></clr-icon>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr *ngIf="prov_ready">
|
|
||||||
<td class="left cmd-title">
|
|
||||||
{{ 'HELM_CHART.VERIFY_CHART' | translate }}
|
|
||||||
</td>
|
|
||||||
<td class="left">
|
|
||||||
<input
|
|
||||||
class="cmd-content clr-input"
|
|
||||||
type="text"
|
|
||||||
[(ngModel)]="verifyCMD"
|
|
||||||
#verifyCMDInput
|
|
||||||
readonly />
|
|
||||||
</td>
|
|
||||||
<td class="left">
|
|
||||||
<span>
|
|
||||||
<clr-icon
|
|
||||||
shape="copy"
|
|
||||||
size="24"
|
|
||||||
[class.is-success]="isCopied('verify')"
|
|
||||||
[ngxClipboard]="verifyCMDInput"
|
|
||||||
(cbOnSuccess)="
|
|
||||||
onCopySuccess($event, 'verify')
|
|
||||||
"></clr-icon>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-12 content-group">
|
|
||||||
<div>
|
|
||||||
<label>{{ 'HELM_CHART.SECURITY' | translate }}</label>
|
|
||||||
</div>
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="left">
|
|
||||||
{{ 'HELM_CHART.PROV_FILE' | translate }}
|
|
||||||
</td>
|
|
||||||
<div
|
|
||||||
*ngIf="
|
|
||||||
prov_ready;
|
|
||||||
then signedContent;
|
|
||||||
else unsignedContent
|
|
||||||
"></div>
|
|
||||||
<ng-template #signedContent>
|
|
||||||
<td class="left">
|
|
||||||
<span class="content-icon">
|
|
||||||
<clr-icon
|
|
||||||
shape="shield-check"
|
|
||||||
class="is-success"></clr-icon> </span
|
|
||||||
> <a
|
|
||||||
href="javascript:void(0)"
|
|
||||||
(click)="downloadChart()"
|
|
||||||
>{{ 'HELM_CHART.READY' | translate }}</a
|
|
||||||
>
|
|
||||||
</td>
|
|
||||||
</ng-template>
|
|
||||||
<ng-template #unsignedContent>
|
|
||||||
<td class="left">
|
|
||||||
<span class="content-icon">
|
|
||||||
<clr-icon
|
|
||||||
shape="shield-x"
|
|
||||||
class="is-error"></clr-icon> </span
|
|
||||||
> {{ 'HELM_CHART.NOT_READY' | translate }}
|
|
||||||
</td>
|
|
||||||
</ng-template>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-12 content-group">
|
|
||||||
<div>
|
|
||||||
<label>{{ 'HELM_CHART.LABELS' | translate }}</label>
|
|
||||||
</div>
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="left">
|
|
||||||
{{ 'HELM_CHART.LABELS' | translate }}
|
|
||||||
</td>
|
|
||||||
<td class="left">{{ labels?.length }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr *ngIf="labels?.length > 0">
|
|
||||||
<td></td>
|
|
||||||
<td class="left">
|
|
||||||
<hbr-label-piece
|
|
||||||
*ngFor="let label of labels"
|
|
||||||
[label]="label"
|
|
||||||
[labelWidth]="90">
|
|
||||||
</hbr-label-piece>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,45 +0,0 @@
|
||||||
.content-wrapper {
|
|
||||||
margin-top: 20px;
|
|
||||||
padding: 0 0 0 15px;
|
|
||||||
|
|
||||||
.md-container {
|
|
||||||
border: solid 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-container {
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
table {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-group {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-icon {
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-wrapper {
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmd-title {
|
|
||||||
white-space: nowrap;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmd-content {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin align-text-mixin($values...) {
|
|
||||||
@each $var in $values {
|
|
||||||
&[align="$var"] {
|
|
||||||
text-align: $var;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
import { ChartDetailSummaryComponent } from './chart-detail-summary.component';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, SecurityContext } from '@angular/core';
|
|
||||||
import { MarkdownModule, MarkedOptions } from 'ngx-markdown';
|
|
||||||
import { HelmChartService } from '../helm-chart.service';
|
|
||||||
import { ErrorHandler } from '../../../../../shared/units/error-handler';
|
|
||||||
import { MessageHandlerService } from '../../../../../shared/services/message-handler.service';
|
|
||||||
import { SharedTestingModule } from '../../../../../shared/shared.module';
|
|
||||||
|
|
||||||
describe('ChartDetailSummaryComponent', () => {
|
|
||||||
let component: ChartDetailSummaryComponent;
|
|
||||||
let fixture: ComponentFixture<ChartDetailSummaryComponent>;
|
|
||||||
const mockHelmChartService = {
|
|
||||||
downloadChart: function () {},
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
imports: [
|
|
||||||
SharedTestingModule,
|
|
||||||
MarkdownModule.forRoot({ sanitize: SecurityContext.HTML }),
|
|
||||||
],
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
declarations: [ChartDetailSummaryComponent],
|
|
||||||
providers: [
|
|
||||||
TranslateService,
|
|
||||||
{ provide: MarkedOptions, useValue: {} },
|
|
||||||
{ provide: ErrorHandler, useValue: MessageHandlerService },
|
|
||||||
{ provide: HelmChartService, useValue: mockHelmChartService },
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ChartDetailSummaryComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
component.summary = {
|
|
||||||
name: 'string',
|
|
||||||
home: 'string',
|
|
||||||
sources: [],
|
|
||||||
version: 'string',
|
|
||||||
description: 'string',
|
|
||||||
keywords: [],
|
|
||||||
maintainers: [],
|
|
||||||
engine: 'string',
|
|
||||||
icon: 'string',
|
|
||||||
appVersion: 'string',
|
|
||||||
urls: [],
|
|
||||||
created: new Date().toDateString(),
|
|
||||||
digest: 'string',
|
|
||||||
};
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,87 +0,0 @@
|
||||||
import {
|
|
||||||
ChangeDetectionStrategy,
|
|
||||||
Component,
|
|
||||||
Input,
|
|
||||||
OnInit,
|
|
||||||
} from '@angular/core';
|
|
||||||
import {
|
|
||||||
HelmChartMetaData,
|
|
||||||
HelmChartSecurity,
|
|
||||||
} from '../helm-chart.interface.service';
|
|
||||||
import { HelmChartService } from '../helm-chart.service';
|
|
||||||
import { Label } from '../../../../../shared/services';
|
|
||||||
import { ErrorHandler } from '../../../../../shared/units/error-handler';
|
|
||||||
import { downloadFile } from '../../../../../shared/units/utils';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hbr-chart-detail-summary',
|
|
||||||
templateUrl: './chart-detail-summary.component.html',
|
|
||||||
styleUrls: ['./chart-detail-summary.component.scss'],
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
})
|
|
||||||
export class ChartDetailSummaryComponent implements OnInit {
|
|
||||||
@Input() summary: HelmChartMetaData;
|
|
||||||
@Input() security: HelmChartSecurity;
|
|
||||||
@Input() repoURL: string;
|
|
||||||
@Input() projectName: string;
|
|
||||||
@Input() chartName: string;
|
|
||||||
@Input() chartVersion: string;
|
|
||||||
@Input() readme: string;
|
|
||||||
@Input() labels: Label[];
|
|
||||||
|
|
||||||
copiedCMD = '';
|
|
||||||
addCMD: string;
|
|
||||||
installCMD: string;
|
|
||||||
verifyCMD: string;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private errorHandler: ErrorHandler,
|
|
||||||
private helmChartService: HelmChartService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.addCMD = `helm repo add --ca-file <ca file> --cert-file <cert file> --key-file <key file> \
|
|
||||||
--username <username> --password <password> <repo name> ${this.repoURL}/chartrepo/${this.projectName}`;
|
|
||||||
this.installCMD = `helm install --ca-file <ca file> --cert-file <cert file> --key-file <key file> \
|
|
||||||
--username=<username> --password=<password> --version ${this.chartVersion} <repo name>/${this.chartName}`;
|
|
||||||
this.verifyCMD = `helm verify --keyring <key path> ${this.chartName}-${this.chartVersion}.tgz`;
|
|
||||||
}
|
|
||||||
|
|
||||||
isCopied(cmd: string) {
|
|
||||||
return this.copiedCMD === cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
onCopySuccess(e: Event, cmd: string) {
|
|
||||||
this.copiedCMD = cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get prov_ready() {
|
|
||||||
return (
|
|
||||||
this.security &&
|
|
||||||
this.security.signature &&
|
|
||||||
this.security.signature.signed
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadChart() {
|
|
||||||
if (
|
|
||||||
!this.summary ||
|
|
||||||
!this.summary.urls ||
|
|
||||||
this.summary.urls.length < 1
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let filename = `${this.summary.urls[0]}.prov`;
|
|
||||||
|
|
||||||
this.helmChartService
|
|
||||||
.downloadChart(this.projectName, filename)
|
|
||||||
.subscribe(
|
|
||||||
res => {
|
|
||||||
downloadFile(res);
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
this.errorHandler.error(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
<div class="row flex-items-xs-between values-header">
|
|
||||||
<div *ngIf="valueMode" class="title-container">
|
|
||||||
<label>{{ 'HELM_CHART.SHOW_KV' | translate }}</label>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="!valueMode" class="title-container">
|
|
||||||
<label>{{ 'HELM_CHART.SHOW_YAML' | translate }}</label>
|
|
||||||
</div>
|
|
||||||
<div class="switch-container">
|
|
||||||
<span
|
|
||||||
class="card-btn"
|
|
||||||
(click)="showYamlFile(false)"
|
|
||||||
(mouseenter)="mouseEnter('value')"
|
|
||||||
(mouseleave)="mouseLeave('value')">
|
|
||||||
<clr-icon
|
|
||||||
size="24"
|
|
||||||
shape="view-list"
|
|
||||||
title="list values"
|
|
||||||
[ngClass]="{
|
|
||||||
'is-highlight': isValueMode || isHovering('value')
|
|
||||||
}"></clr-icon>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="list-btn"
|
|
||||||
(click)="showYamlFile(true)"
|
|
||||||
(mouseenter)="mouseEnter('yaml')"
|
|
||||||
(mouseleave)="mouseLeave('yaml')">
|
|
||||||
<clr-icon
|
|
||||||
size="24"
|
|
||||||
shape="file"
|
|
||||||
title="yaml file"
|
|
||||||
[ngClass]="{
|
|
||||||
'is-highlight': !isValueMode || isHovering('yaml')
|
|
||||||
}"></clr-icon>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row value-container">
|
|
||||||
<div class="col-xs-8" *ngIf="valueMode">
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr *ngFor="let key of objKeys(values)">
|
|
||||||
<td class="left">{{ key }}</td>
|
|
||||||
<td class="left">{{ values[key] }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-8" *ngIf="!valueMode">
|
|
||||||
<div
|
|
||||||
class="yaml-container"
|
|
||||||
[innerHTML]="yaml | language: 'yaml' | markdown"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,24 +0,0 @@
|
||||||
.value-container {
|
|
||||||
::ng-deep pre {
|
|
||||||
min-height: fit-content;
|
|
||||||
max-height: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.values-header {
|
|
||||||
margin-top: 12px;
|
|
||||||
|
|
||||||
.title-container {
|
|
||||||
margin-left: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-container {
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* stylelint-disable */
|
|
||||||
pre {
|
|
||||||
max-height: max-content;
|
|
||||||
padding-left: 21px;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
|
||||||
import { ChartDetailValueComponent } from './chart-detail-value.component';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA, SecurityContext } from '@angular/core';
|
|
||||||
import { ClarityModule } from '@clr/angular';
|
|
||||||
import { FormsModule } from '@angular/forms';
|
|
||||||
import { MarkdownModule, MarkedOptions } from 'ngx-markdown';
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
describe('ChartDetailValueComponent', () => {
|
|
||||||
let component: ChartDetailValueComponent;
|
|
||||||
let fixture: ComponentFixture<ChartDetailValueComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [
|
|
||||||
TranslateModule.forRoot(),
|
|
||||||
ClarityModule,
|
|
||||||
FormsModule,
|
|
||||||
BrowserModule,
|
|
||||||
MarkdownModule.forRoot({ sanitize: SecurityContext.HTML }),
|
|
||||||
],
|
|
||||||
declarations: [ChartDetailValueComponent],
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
providers: [
|
|
||||||
TranslateService,
|
|
||||||
{ provide: MarkedOptions, useValue: {} },
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ChartDetailValueComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
component.yaml = 'rfrf';
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,53 +0,0 @@
|
||||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hbr-chart-detail-value',
|
|
||||||
templateUrl: './chart-detail-value.component.html',
|
|
||||||
styleUrls: ['./chart-detail-value.component.scss'],
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
})
|
|
||||||
export class ChartDetailValueComponent {
|
|
||||||
@Input() values;
|
|
||||||
@Input() yaml;
|
|
||||||
|
|
||||||
// Default set to yaml file
|
|
||||||
valueMode = false;
|
|
||||||
valueHover = false;
|
|
||||||
yamlHover = true;
|
|
||||||
|
|
||||||
objKeys = Object.keys;
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
public get isValueMode() {
|
|
||||||
return this.valueMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
isHovering(view: string) {
|
|
||||||
if (view === 'value') {
|
|
||||||
return this.valueHover;
|
|
||||||
} else {
|
|
||||||
return this.yamlHover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
showYamlFile(showYaml: boolean) {
|
|
||||||
this.valueMode = !showYaml;
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseEnter(mode: string) {
|
|
||||||
if (mode === 'value') {
|
|
||||||
this.valueHover = true;
|
|
||||||
} else {
|
|
||||||
this.yamlHover = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseLeave(mode: string) {
|
|
||||||
if (mode === 'value') {
|
|
||||||
this.valueHover = false;
|
|
||||||
} else {
|
|
||||||
this.yamlHover = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
<div>
|
|
||||||
<div class="flex-container">
|
|
||||||
<div class="title-container">
|
|
||||||
<div class="chart-name">
|
|
||||||
{{ chartNameWithVersion | translate }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ roleName | translate }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button class="btn btn-secondary" (click)="downloadChart()">
|
|
||||||
{{ 'HELM_CHART.DOWNLOAD' | translate }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span *ngIf="loading" class="spinner spinner-lg detail-loading">
|
|
||||||
Loading...
|
|
||||||
</span>
|
|
||||||
<div *ngIf="!loading && isChartExist">
|
|
||||||
<clr-tabs>
|
|
||||||
<clr-tab>
|
|
||||||
<button clrTabLink id="summary-link">
|
|
||||||
{{ 'HELM_CHART.SUMMARY' | translate }}
|
|
||||||
</button>
|
|
||||||
<clr-tab-content id="summary-content" *clrIfActive>
|
|
||||||
<hbr-chart-detail-summary
|
|
||||||
[summary]="chartDetail.metadata"
|
|
||||||
[chartName]="chartName"
|
|
||||||
[repoURL]="repoURL"
|
|
||||||
[projectName]="project.name"
|
|
||||||
[chartVersion]="chartVersion"
|
|
||||||
[security]="chartDetail.security"
|
|
||||||
[readme]="chartDetail.files['README.md']"
|
|
||||||
[labels]="
|
|
||||||
chartDetail.labels
|
|
||||||
"></hbr-chart-detail-summary>
|
|
||||||
</clr-tab-content>
|
|
||||||
</clr-tab>
|
|
||||||
<clr-tab>
|
|
||||||
<button clrTabLink id="depend-link">
|
|
||||||
{{ 'HELM_CHART.DEPENDENCIES' | translate }}
|
|
||||||
</button>
|
|
||||||
<clr-tab-content id="depend-content">
|
|
||||||
<hbr-chart-detail-dependency
|
|
||||||
[dependencies]="
|
|
||||||
chartDetail.dependencies
|
|
||||||
"></hbr-chart-detail-dependency>
|
|
||||||
</clr-tab-content>
|
|
||||||
</clr-tab>
|
|
||||||
<clr-tab>
|
|
||||||
<button clrTabLink id="value-link">
|
|
||||||
{{ 'HELM_CHART.VALUES' | translate }}
|
|
||||||
</button>
|
|
||||||
<clr-tab-content id="value-content">
|
|
||||||
<hbr-chart-detail-value
|
|
||||||
[values]="chartDetail.values"
|
|
||||||
[yaml]="
|
|
||||||
chartDetail.files['values.yaml']
|
|
||||||
"></hbr-chart-detail-value>
|
|
||||||
</clr-tab-content>
|
|
||||||
</clr-tab>
|
|
||||||
</clr-tabs>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="!loading && !isChartExist">
|
|
||||||
<h6>{{ 'HELM_CHART.NO_DETAIL' | translate }}</h6>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,28 +0,0 @@
|
||||||
@import "../../../../../shared/mixin";
|
|
||||||
|
|
||||||
.title-container {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.chart-name {
|
|
||||||
border-right: 1px solid gray;
|
|
||||||
font-size: 27px;
|
|
||||||
font-weight: normal;
|
|
||||||
padding-right: 9px;
|
|
||||||
margin-right: 9px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-loading {
|
|
||||||
@include absolute-center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex-container {
|
|
||||||
display: flex;
|
|
||||||
-webkit-display:flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.title-container {
|
|
||||||
display: flex;
|
|
||||||
align-items:center;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,143 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
|
||||||
import { ChartDetailComponent } from './chart-detail.component';
|
|
||||||
import { ClarityModule } from '@clr/angular';
|
|
||||||
import { FormsModule } from '@angular/forms';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
||||||
import { HelmChartService } from '../helm-chart.service';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { ErrorHandler } from '../../../../../shared/units/error-handler';
|
|
||||||
import { SystemInfoService } from '../../../../../shared/services';
|
|
||||||
|
|
||||||
describe('ChartDetailComponent', () => {
|
|
||||||
let component: ChartDetailComponent;
|
|
||||||
let fixture: ComponentFixture<ChartDetailComponent>;
|
|
||||||
const mockErrorHandler = {
|
|
||||||
error: function () {},
|
|
||||||
};
|
|
||||||
const mockSystemInfoService = {
|
|
||||||
getSystemInfo: function () {
|
|
||||||
return of({
|
|
||||||
with_notary: false,
|
|
||||||
with_admiral: false,
|
|
||||||
admiral_endpoint: '',
|
|
||||||
auth_mode: 'oidc_auth',
|
|
||||||
registry_url: 'nightly-oidc.harbor.io',
|
|
||||||
external_url: 'https://nightly-oidc.harbor.io',
|
|
||||||
project_creation_restriction: 'everyone',
|
|
||||||
self_registration: false,
|
|
||||||
has_ca_root: false,
|
|
||||||
harbor_version: 'dev',
|
|
||||||
registry_storage_provider_name: 'filesystem',
|
|
||||||
read_only: false,
|
|
||||||
with_chartmuseum: true,
|
|
||||||
notification_enable: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const mockHelmChartService = {
|
|
||||||
getChartDetail: function () {
|
|
||||||
return of({
|
|
||||||
metadata: {
|
|
||||||
name: 'harbor',
|
|
||||||
home: 'https://github.com/vmware/harbor',
|
|
||||||
sources: [
|
|
||||||
'https://github.com/vmware/harbor/tree/master/contrib/helm/harbor',
|
|
||||||
],
|
|
||||||
version: '0.2.0',
|
|
||||||
description: 'Ane',
|
|
||||||
keywords: ['vmware', 'docker', 'registry', 'harbor'],
|
|
||||||
maintainers: [
|
|
||||||
{
|
|
||||||
name: 'Jessde Hu',
|
|
||||||
email: 'huh@qq.com',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'paulczar',
|
|
||||||
email: 'username@qq.com',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
engine: '',
|
|
||||||
icon: 'ht',
|
|
||||||
appVersion: '1.5.0',
|
|
||||||
urls: [''],
|
|
||||||
created: '201940492141Z',
|
|
||||||
digest: '',
|
|
||||||
},
|
|
||||||
dependencies: [
|
|
||||||
{
|
|
||||||
name: 'redis',
|
|
||||||
version: '3.2.5',
|
|
||||||
repository: '',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
values: {
|
|
||||||
'adminserver.image.pullPolicy': 'IfNotPresent',
|
|
||||||
},
|
|
||||||
files: {
|
|
||||||
'README.md': '',
|
|
||||||
'values.yaml': '',
|
|
||||||
},
|
|
||||||
security: {
|
|
||||||
signature: {
|
|
||||||
signed: false,
|
|
||||||
prov_file: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
labels: [],
|
|
||||||
});
|
|
||||||
},
|
|
||||||
downloadChart: function () {},
|
|
||||||
};
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
imports: [TranslateModule.forRoot(), ClarityModule, FormsModule],
|
|
||||||
declarations: [ChartDetailComponent],
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
providers: [
|
|
||||||
TranslateService,
|
|
||||||
{ provide: ErrorHandler, useValue: mockErrorHandler },
|
|
||||||
{ provide: SystemInfoService, useValue: mockSystemInfoService },
|
|
||||||
{ provide: HelmChartService, useValue: mockHelmChartService },
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ChartDetailComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
component.chartName = 'chart';
|
|
||||||
component.chartVersion = 'chart-version';
|
|
||||||
component.project = {
|
|
||||||
project_id: 1,
|
|
||||||
owner_id: 1,
|
|
||||||
name: 'library',
|
|
||||||
creation_time: new Date(),
|
|
||||||
creation_time_str: '123',
|
|
||||||
update_time: new Date(),
|
|
||||||
deleted: 1,
|
|
||||||
owner_name: '',
|
|
||||||
togglable: true,
|
|
||||||
current_user_role_id: 1,
|
|
||||||
has_project_admin_role: true,
|
|
||||||
is_member: true,
|
|
||||||
role_name: 'maintainer',
|
|
||||||
repo_count: 0,
|
|
||||||
chart_count: 1,
|
|
||||||
registry_id: 0,
|
|
||||||
metadata: {
|
|
||||||
public: 'true',
|
|
||||||
enable_content_trust: 'string',
|
|
||||||
prevent_vul: 'string',
|
|
||||||
severity: 'string',
|
|
||||||
auto_scan: true,
|
|
||||||
retention_id: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,109 +0,0 @@
|
||||||
import { Component, Input, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
import { Project } from '../../../project';
|
|
||||||
import { HelmChartService } from '../helm-chart.service';
|
|
||||||
import { HelmChartDetail } from '../helm-chart.interface.service';
|
|
||||||
import { finalize } from 'rxjs/operators';
|
|
||||||
import { SystemInfo, SystemInfoService } from '../../../../../shared/services';
|
|
||||||
import { ErrorHandler } from '../../../../../shared/units/error-handler';
|
|
||||||
import { downloadFile } from '../../../../../shared/units/utils';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hbr-chart-detail',
|
|
||||||
templateUrl: './chart-detail.component.html',
|
|
||||||
styleUrls: ['./chart-detail.component.scss'],
|
|
||||||
})
|
|
||||||
export class ChartDetailComponent implements OnInit {
|
|
||||||
@Input() projectId: number;
|
|
||||||
@Input() project: Project;
|
|
||||||
@Input() chartName: string;
|
|
||||||
@Input() chartVersion: string;
|
|
||||||
@Input() roleName: string;
|
|
||||||
@Input() hasSignedIn: boolean;
|
|
||||||
@Input() hasProjectAdminRole: boolean;
|
|
||||||
|
|
||||||
loading = true;
|
|
||||||
isMember = false;
|
|
||||||
chartDetail: HelmChartDetail;
|
|
||||||
systemInfo: SystemInfo;
|
|
||||||
|
|
||||||
repoURL = '';
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private errorHandler: ErrorHandler,
|
|
||||||
private systemInfoService: SystemInfoService,
|
|
||||||
private helmChartService: HelmChartService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.systemInfoService.getSystemInfo().subscribe(
|
|
||||||
systemInfo => {
|
|
||||||
this.systemInfo = systemInfo;
|
|
||||||
if (this.systemInfo.external_url) {
|
|
||||||
this.repoURL = `${this.systemInfo.external_url}`;
|
|
||||||
} else {
|
|
||||||
let scheme = 'http://';
|
|
||||||
if (this.systemInfo.has_ca_root) {
|
|
||||||
scheme = 'https://';
|
|
||||||
}
|
|
||||||
this.repoURL = `${scheme}${this.systemInfo.registry_url}`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error => this.errorHandler.error(error)
|
|
||||||
);
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
public get chartNameWithVersion() {
|
|
||||||
return `${this.chartName}:${this.chartVersion}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get isChartExist() {
|
|
||||||
return !!this.chartDetail;
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh() {
|
|
||||||
this.loading = true;
|
|
||||||
this.helmChartService
|
|
||||||
.getChartDetail(
|
|
||||||
this.project.name,
|
|
||||||
this.chartName,
|
|
||||||
this.chartVersion
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
finalize(() => {
|
|
||||||
this.loading = false;
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(
|
|
||||||
chartDetail => {
|
|
||||||
this.chartDetail = chartDetail;
|
|
||||||
},
|
|
||||||
err => {
|
|
||||||
this.errorHandler.error(err);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadChart() {
|
|
||||||
if (
|
|
||||||
!this.chartDetail ||
|
|
||||||
!this.chartDetail.metadata ||
|
|
||||||
!this.chartDetail.metadata.urls ||
|
|
||||||
this.chartDetail.metadata.urls.length < 1
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let filename = this.chartDetail.metadata.urls[0];
|
|
||||||
|
|
||||||
this.helmChartService
|
|
||||||
.downloadChart(this.project.name, filename)
|
|
||||||
.subscribe(
|
|
||||||
res => {
|
|
||||||
downloadFile(res);
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
this.errorHandler.error(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
// Copyright Project Harbor Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// 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 { NgModule } from '@angular/core';
|
|
||||||
import { LabelFilterComponent } from './label-filter/label-filter.component';
|
|
||||||
import { LabelMarkerComponent } from './label-marker/label-marker.component';
|
|
||||||
import { ListChartVersionsComponent } from './list-chart-versions/list-chart-versions.component';
|
|
||||||
import { ChartVersionComponent } from './list-chart-versions/helm-chart-versions-detail/helm-chart-version.component';
|
|
||||||
import { ChartDetailDependencyComponent } from './chart-detail/chart-detail-dependency.component';
|
|
||||||
import { ChartDetailSummaryComponent } from './chart-detail/chart-detail-summary.component';
|
|
||||||
import { ChartDetailValueComponent } from './chart-detail/chart-detail-value.component';
|
|
||||||
import { ChartDetailComponent } from './chart-detail/chart-detail.component';
|
|
||||||
import { HelmChartDetailComponent } from './chart-detail.component';
|
|
||||||
import { SharedModule } from '../../../../shared/shared.module';
|
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
|
||||||
|
|
||||||
const routes: Routes = [
|
|
||||||
{
|
|
||||||
path: ':chart/versions',
|
|
||||||
component: ListChartVersionsComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: ':chart/versions/:version',
|
|
||||||
component: HelmChartDetailComponent,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
@NgModule({
|
|
||||||
imports: [SharedModule, RouterModule.forChild(routes)],
|
|
||||||
declarations: [
|
|
||||||
LabelFilterComponent,
|
|
||||||
LabelMarkerComponent,
|
|
||||||
ListChartVersionsComponent,
|
|
||||||
ChartVersionComponent,
|
|
||||||
ChartDetailDependencyComponent,
|
|
||||||
ChartDetailSummaryComponent,
|
|
||||||
ChartDetailValueComponent,
|
|
||||||
ChartDetailComponent,
|
|
||||||
HelmChartDetailComponent,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
export class HelmChartListModule {}
|
|
|
@ -1,89 +0,0 @@
|
||||||
import { Label } from '../../../../shared/services';
|
|
||||||
|
|
||||||
export interface HelmChartSearchResultItem {
|
|
||||||
Name: string;
|
|
||||||
Score: number;
|
|
||||||
Chart: HelmChartVersion;
|
|
||||||
}
|
|
||||||
export interface HelmChartItem {
|
|
||||||
name: string;
|
|
||||||
total_versions: number;
|
|
||||||
latest_version: string;
|
|
||||||
created: string;
|
|
||||||
updated: string;
|
|
||||||
icon: string;
|
|
||||||
home: string;
|
|
||||||
deprecated?: boolean;
|
|
||||||
status?: string;
|
|
||||||
pulls?: number;
|
|
||||||
maintainer?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HelmChartVersion {
|
|
||||||
name: string;
|
|
||||||
home: string;
|
|
||||||
sources: string[];
|
|
||||||
version: string;
|
|
||||||
description: string;
|
|
||||||
keywords: string[];
|
|
||||||
maintainers: HelmChartMaintainer[];
|
|
||||||
engine: string;
|
|
||||||
icon: string;
|
|
||||||
appVersion: string;
|
|
||||||
apiVersion: string;
|
|
||||||
urls: string[];
|
|
||||||
created: string;
|
|
||||||
digest: string;
|
|
||||||
labels: Label[];
|
|
||||||
deprecated?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HelmChartDetail {
|
|
||||||
metadata: HelmChartMetaData;
|
|
||||||
dependencies: HelmChartDependency[];
|
|
||||||
values: any;
|
|
||||||
files: HelmchartFile;
|
|
||||||
security: HelmChartSecurity;
|
|
||||||
labels: Label[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HelmChartMetaData {
|
|
||||||
name: string;
|
|
||||||
home: string;
|
|
||||||
sources: string[];
|
|
||||||
version: string;
|
|
||||||
description: string;
|
|
||||||
keywords: string[];
|
|
||||||
maintainers: HelmChartMaintainer[];
|
|
||||||
engine: string;
|
|
||||||
icon: string;
|
|
||||||
appVersion: string;
|
|
||||||
urls: string[];
|
|
||||||
created?: string;
|
|
||||||
digest: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HelmChartMaintainer {
|
|
||||||
name: string;
|
|
||||||
email: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HelmChartDependency {
|
|
||||||
name: string;
|
|
||||||
version: string;
|
|
||||||
repository: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HelmchartFile {
|
|
||||||
'README.MD': string;
|
|
||||||
'values.yaml': string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HelmChartSecurity {
|
|
||||||
signature: HelmChartSignature;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HelmChartSignature {
|
|
||||||
signed: boolean;
|
|
||||||
prov_file: string;
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
import { inject, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { HelmChartService } from './helm-chart.service';
|
|
||||||
|
|
||||||
describe('HelmChartService', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
providers: [HelmChartService],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be created', inject(
|
|
||||||
[HelmChartService],
|
|
||||||
(service: HelmChartService) => {
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
}
|
|
||||||
));
|
|
||||||
});
|
|
|
@ -1,266 +0,0 @@
|
||||||
import { Observable, throwError as observableThrowError } from 'rxjs';
|
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
|
||||||
import { catchError, map } from 'rxjs/operators';
|
|
||||||
import {
|
|
||||||
HelmChartDetail,
|
|
||||||
HelmChartItem,
|
|
||||||
HelmChartVersion,
|
|
||||||
} from './helm-chart.interface.service';
|
|
||||||
import { RequestQueryParams } from '../../../../shared/services';
|
|
||||||
import {
|
|
||||||
HTTP_GET_OPTIONS,
|
|
||||||
HTTP_JSON_OPTIONS,
|
|
||||||
V1_BASE_HREF,
|
|
||||||
} from '../../../../shared/units/utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define service methods for handling the helmchart related things.
|
|
||||||
* Loose couple with project module.
|
|
||||||
*
|
|
||||||
**
|
|
||||||
* @abstract
|
|
||||||
* class HelmChartService
|
|
||||||
*/
|
|
||||||
export abstract class HelmChartService {
|
|
||||||
/**
|
|
||||||
* Get all helm charts info
|
|
||||||
* ** deprecated param projectName Id of the project
|
|
||||||
* ** deprecated param queryParams options params for query data
|
|
||||||
*/
|
|
||||||
abstract getHelmCharts(
|
|
||||||
projectName: string,
|
|
||||||
queryParams?: RequestQueryParams
|
|
||||||
): Observable<HelmChartItem[]>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete an helmchart
|
|
||||||
* ** deprecated param projectId Id of the project
|
|
||||||
* ** deprecated param chartId ID of helmChart in this specific project
|
|
||||||
*/
|
|
||||||
abstract deleteHelmChart(
|
|
||||||
projectId: number | string,
|
|
||||||
chartName: string
|
|
||||||
): Observable<any>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all the versions of helmchart
|
|
||||||
* ** deprecated param projectName Id of the project
|
|
||||||
* ** deprecated param chartName ID of the helm chart
|
|
||||||
* ** deprecated param queryParams option params for query
|
|
||||||
*/
|
|
||||||
abstract getChartVersions(
|
|
||||||
projectName: string,
|
|
||||||
chartName: string
|
|
||||||
): Observable<HelmChartVersion[]>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a version of helmchart
|
|
||||||
* ** deprecated param projectName ID of the project
|
|
||||||
* ** deprecated param chartName ID of the chart you want to delete
|
|
||||||
* ** deprecated param version name of the version
|
|
||||||
*/
|
|
||||||
abstract deleteChartVersion(
|
|
||||||
projectName: string,
|
|
||||||
chartName: string,
|
|
||||||
version: string
|
|
||||||
): Observable<any>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the all details of an helmchart
|
|
||||||
* ** deprecated param projectName ID of the project
|
|
||||||
* ** deprecated param chartname ID of the chart
|
|
||||||
* ** deprecated param version name of the chart's version
|
|
||||||
* ** deprecated param queryParams options
|
|
||||||
*/
|
|
||||||
abstract getChartDetail(
|
|
||||||
projectName: string,
|
|
||||||
chartname: string,
|
|
||||||
version: string
|
|
||||||
): Observable<HelmChartDetail>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Download an specific verison
|
|
||||||
* ** deprecated param projectName ID of the project
|
|
||||||
* ** deprecated param filename ID of the helm chart
|
|
||||||
* ** deprecated param version Name of version
|
|
||||||
* ** deprecated param queryParams options
|
|
||||||
*/
|
|
||||||
abstract downloadChart(
|
|
||||||
projectName: string,
|
|
||||||
filename: string
|
|
||||||
): Observable<any>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload chart and prov files to chartmuseam
|
|
||||||
* ** deprecated param projectName Name of the project
|
|
||||||
* ** deprecated param chart chart file
|
|
||||||
* ** deprecated param prov prov file
|
|
||||||
*/
|
|
||||||
abstract uploadChart(
|
|
||||||
projectName: string,
|
|
||||||
chart: File,
|
|
||||||
prov: File
|
|
||||||
): Observable<any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implement default service for helm chart.
|
|
||||||
*/
|
|
||||||
@Injectable()
|
|
||||||
export class HelmChartDefaultService extends HelmChartService {
|
|
||||||
constructor(private http: HttpClient) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleErrorObservable(error: HttpErrorResponse) {
|
|
||||||
return observableThrowError(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getHelmCharts(projectName: string): Observable<HelmChartItem[]> {
|
|
||||||
if (!projectName) {
|
|
||||||
return observableThrowError(
|
|
||||||
'Bad argument, No project id to get helm charts'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.http
|
|
||||||
.get<HelmChartItem[]>(
|
|
||||||
`${V1_BASE_HREF + '/chartrepo'}/${projectName}/charts`,
|
|
||||||
HTTP_GET_OPTIONS
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
map(response => response || []),
|
|
||||||
catchError(error => this.handleErrorObservable(error))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public deleteHelmChart(
|
|
||||||
projectId: number | string,
|
|
||||||
chartName: string
|
|
||||||
): Observable<any> {
|
|
||||||
if (!chartName) {
|
|
||||||
observableThrowError('Bad argument');
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.http
|
|
||||||
.delete(
|
|
||||||
`${
|
|
||||||
V1_BASE_HREF + '/chartrepo'
|
|
||||||
}/${projectId}/charts/${chartName}`
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
map(response => {
|
|
||||||
return response || [];
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.pipe(catchError(this.handleErrorObservable));
|
|
||||||
}
|
|
||||||
|
|
||||||
public getChartVersions(
|
|
||||||
projectName: string,
|
|
||||||
chartName: string
|
|
||||||
): Observable<HelmChartVersion[]> {
|
|
||||||
return this.http
|
|
||||||
.get<HelmChartVersion[]>(
|
|
||||||
`${
|
|
||||||
V1_BASE_HREF + '/chartrepo'
|
|
||||||
}/${projectName}/charts/${chartName}`,
|
|
||||||
HTTP_GET_OPTIONS
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
map(response => response || []),
|
|
||||||
catchError(this.handleErrorObservable)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public deleteChartVersion(
|
|
||||||
projectName: string,
|
|
||||||
chartName: string,
|
|
||||||
version: string
|
|
||||||
): any {
|
|
||||||
return this.http
|
|
||||||
.delete(
|
|
||||||
`${
|
|
||||||
V1_BASE_HREF + '/chartrepo'
|
|
||||||
}/${projectName}/charts/${chartName}/${version}`,
|
|
||||||
HTTP_JSON_OPTIONS
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
map(response => {
|
|
||||||
return response || [];
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.pipe(catchError(this.handleErrorObservable));
|
|
||||||
}
|
|
||||||
|
|
||||||
public getChartDetail(
|
|
||||||
projectName: string,
|
|
||||||
chartName: string,
|
|
||||||
version: string
|
|
||||||
): Observable<HelmChartDetail> {
|
|
||||||
return this.http
|
|
||||||
.get<HelmChartDetail>(
|
|
||||||
`${
|
|
||||||
V1_BASE_HREF + '/chartrepo'
|
|
||||||
}/${projectName}/charts/${chartName}/${version}`
|
|
||||||
)
|
|
||||||
.pipe(catchError(this.handleErrorObservable));
|
|
||||||
}
|
|
||||||
|
|
||||||
public downloadChart(
|
|
||||||
projectName: string,
|
|
||||||
filename: string
|
|
||||||
): Observable<any> {
|
|
||||||
let url: string;
|
|
||||||
let chartFileRegexPattern = new RegExp('^http.*/chartrepo/(.*)');
|
|
||||||
if (chartFileRegexPattern.test(filename)) {
|
|
||||||
let match = filename.match('^http.*/chartrepo/(.*)');
|
|
||||||
url = `${DOWNLOAD_CHART_ENDPOINT}/${match[1]}`;
|
|
||||||
} else {
|
|
||||||
url = `${DOWNLOAD_CHART_ENDPOINT}/${projectName}/${filename}`;
|
|
||||||
}
|
|
||||||
return this.http
|
|
||||||
.get(url, {
|
|
||||||
responseType: 'blob',
|
|
||||||
})
|
|
||||||
.pipe(
|
|
||||||
map(response => {
|
|
||||||
let parts = filename.split('/');
|
|
||||||
return {
|
|
||||||
filename: parts[parts.length - 1],
|
|
||||||
data: response,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.pipe(catchError(this.handleErrorObservable));
|
|
||||||
}
|
|
||||||
|
|
||||||
public uploadChart(
|
|
||||||
projectName: string,
|
|
||||||
chart?: File,
|
|
||||||
prov?: File
|
|
||||||
): Observable<any> {
|
|
||||||
let formData = new FormData();
|
|
||||||
let uploadURL = `${V1_BASE_HREF + '/chartrepo'}/${projectName}/charts`;
|
|
||||||
if (chart) {
|
|
||||||
formData.append('chart', chart);
|
|
||||||
}
|
|
||||||
if (prov) {
|
|
||||||
formData.append('prov', prov);
|
|
||||||
if (!chart) {
|
|
||||||
uploadURL = `${
|
|
||||||
V1_BASE_HREF + '/chartrepo'
|
|
||||||
}/${projectName}/prov`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.http
|
|
||||||
.post(uploadURL, formData, {
|
|
||||||
responseType: 'json',
|
|
||||||
})
|
|
||||||
.pipe(map(response => response || []))
|
|
||||||
.pipe(catchError(this.handleErrorObservable));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DOWNLOAD_CHART_ENDPOINT: string = '/chartrepo';
|
|
|
@ -1,32 +0,0 @@
|
||||||
<div>
|
|
||||||
<div class="form-group filter-div">
|
|
||||||
<input
|
|
||||||
#filterInput
|
|
||||||
class="clr-input"
|
|
||||||
type="text"
|
|
||||||
placeholder="{{ 'LABEL.FILTER_LABEL_PLACEHOLDER' | translate }}"
|
|
||||||
[(ngModel)]="labelFilter" />
|
|
||||||
</div>
|
|
||||||
<div class="label-items-container">
|
|
||||||
<div class="dropdown-item" *ngFor="let label of filteredLabels">
|
|
||||||
<div class="cur-pointer" (click)="selectLabel(label)">
|
|
||||||
<span class="check-label-span">
|
|
||||||
<clr-icon
|
|
||||||
*ngIf="isSelected(label)"
|
|
||||||
shape="check"></clr-icon>
|
|
||||||
</span>
|
|
||||||
<span class="cur-pointer">
|
|
||||||
<hbr-label-piece
|
|
||||||
[label]="label"
|
|
||||||
[labelWidth]="90"></hbr-label-piece>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
*ngIf="isSelected(label)"
|
|
||||||
class="x-label-span"
|
|
||||||
(click)="$event.stopPropagation(); unselectLabel(label)">
|
|
||||||
<clr-icon shape="times-circle"></clr-icon>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,37 +0,0 @@
|
||||||
@mixin icon-span {
|
|
||||||
width: 12px;
|
|
||||||
min-height: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-div {
|
|
||||||
margin-left: 9px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cur-pointer {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label-items-container {
|
|
||||||
max-height: 300px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.dropdown-item {
|
|
||||||
padding-left: 12px;
|
|
||||||
padding-right: 12px;
|
|
||||||
|
|
||||||
.x-label-span {
|
|
||||||
@include icon-span;
|
|
||||||
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.check-label-span {
|
|
||||||
@include icon-span;
|
|
||||||
|
|
||||||
float: left;
|
|
||||||
margin-right: 9px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { LabelFilterComponent } from './label-filter.component';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
||||||
import { SharedTestingModule } from '../../../../../shared/shared.module';
|
|
||||||
|
|
||||||
describe('LabelFilterComponent', () => {
|
|
||||||
let component: LabelFilterComponent;
|
|
||||||
let fixture: ComponentFixture<LabelFilterComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
imports: [SharedTestingModule],
|
|
||||||
declarations: [LabelFilterComponent],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(LabelFilterComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,84 +0,0 @@
|
||||||
import {
|
|
||||||
ChangeDetectorRef,
|
|
||||||
Component,
|
|
||||||
ElementRef,
|
|
||||||
EventEmitter,
|
|
||||||
Input,
|
|
||||||
OnInit,
|
|
||||||
ViewChild,
|
|
||||||
} from '@angular/core';
|
|
||||||
import { ClrDatagridFilterInterface } from '@clr/angular';
|
|
||||||
import { fromEvent } from 'rxjs';
|
|
||||||
import { debounceTime } from 'rxjs/operators';
|
|
||||||
import { HelmChartVersion } from '../helm-chart.interface.service';
|
|
||||||
import { Label } from '../../../../../shared/services';
|
|
||||||
import { Artifact } from '../../../../../../../ng-swagger-gen/models/artifact';
|
|
||||||
import { ResourceType } from '../../../../../shared/entities/shared.const';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hbr-chart-version-label-filter',
|
|
||||||
templateUrl: './label-filter.component.html',
|
|
||||||
styleUrls: ['./label-filter.component.scss'],
|
|
||||||
})
|
|
||||||
export class LabelFilterComponent
|
|
||||||
implements ClrDatagridFilterInterface<any>, OnInit
|
|
||||||
{
|
|
||||||
@Input() labels: Label[] = [];
|
|
||||||
@Input() resourceType: ResourceType;
|
|
||||||
|
|
||||||
@ViewChild('filterInput', { static: true }) filterInputRef: ElementRef;
|
|
||||||
|
|
||||||
selectedLabels: Map<number, boolean> = new Map<number, boolean>();
|
|
||||||
|
|
||||||
changes: EventEmitter<any> = new EventEmitter<any>(false);
|
|
||||||
|
|
||||||
labelFilter = '';
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
fromEvent(this.filterInputRef.nativeElement, 'keyup')
|
|
||||||
.pipe(debounceTime(500))
|
|
||||||
.subscribe(() => {
|
|
||||||
let hnd = setInterval(() => this.cdr.markForCheck(), 100);
|
|
||||||
setTimeout(() => clearInterval(hnd), 2000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
constructor(private cdr: ChangeDetectorRef) {}
|
|
||||||
|
|
||||||
get filteredLabels() {
|
|
||||||
return this.labels.filter(label =>
|
|
||||||
label.name.includes(this.labelFilter)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
isActive(): boolean {
|
|
||||||
return this.selectedLabels.size > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
accepts(cv: any): boolean {
|
|
||||||
if (this.resourceType === ResourceType.CHART_VERSION) {
|
|
||||||
return (cv as HelmChartVersion).labels.some(label =>
|
|
||||||
this.selectedLabels.get(label.id)
|
|
||||||
);
|
|
||||||
} else if (this.resourceType === ResourceType.REPOSITORY_TAG) {
|
|
||||||
return (cv as Artifact).labels.some(label =>
|
|
||||||
this.selectedLabels.get(label.id)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
selectLabel(label: Label) {
|
|
||||||
this.selectedLabels.set(label.id, true);
|
|
||||||
this.changes.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
unselectLabel(label: Label) {
|
|
||||||
this.selectedLabels.delete(label.id);
|
|
||||||
this.changes.emit(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
isSelected(label: Label) {
|
|
||||||
return this.selectedLabels.has(label.id);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
<div>
|
|
||||||
<label class="dropdown-header">{{ addLabelHeaders | translate }}</label>
|
|
||||||
<div class="form-group filter-div">
|
|
||||||
<input
|
|
||||||
class="clr-input"
|
|
||||||
#filterInput
|
|
||||||
type="text"
|
|
||||||
placeholder="Filter labels"
|
|
||||||
[(ngModel)]="labelFilter" />
|
|
||||||
</div>
|
|
||||||
<div class="label-items-container">
|
|
||||||
<div class="dropdown-item" *ngFor="let label of sortedLabels">
|
|
||||||
<div (click)="markLabel(label)">
|
|
||||||
<div *ngIf="!isMarkOngoing(label)" class="mark-label-div">
|
|
||||||
<clr-icon *ngIf="isMarked(label)" shape="check"></clr-icon>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="isMarkOngoing(label)" class="spinner spinner-sm">
|
|
||||||
Loading...
|
|
||||||
</div>
|
|
||||||
<div class="label-div">
|
|
||||||
<hbr-label-piece
|
|
||||||
[label]="label"
|
|
||||||
[labelWidth]="130"></hbr-label-piece>
|
|
||||||
</div>
|
|
||||||
<div class="unmark-label-div" (click)="unmarkLabel(label)">
|
|
||||||
<clr-icon
|
|
||||||
*ngIf="isMarked(label)"
|
|
||||||
shape="times-circle"></clr-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,53 +0,0 @@
|
||||||
@mixin icon-span {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
|
|
||||||
clr-icon {
|
|
||||||
margin-bottom: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin flex-item {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-div {
|
|
||||||
margin-left: 9px;
|
|
||||||
margin-right: 9px;
|
|
||||||
margin-bottom: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label-items-container {
|
|
||||||
max-height: 300px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.dropdown-item {
|
|
||||||
padding-left: 12px;
|
|
||||||
padding-right: 12px;
|
|
||||||
|
|
||||||
.mark-label-div {
|
|
||||||
@include icon-span;
|
|
||||||
@include flex-item;
|
|
||||||
|
|
||||||
float: left;
|
|
||||||
margin-right: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner {
|
|
||||||
@include flex-item;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label-div {
|
|
||||||
@include flex-item;
|
|
||||||
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unmark-label-div {
|
|
||||||
@include icon-span;
|
|
||||||
@include flex-item;
|
|
||||||
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
|
||||||
import { LabelMarkerComponent } from './label-marker.component';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
||||||
import { ClarityModule } from '@clr/angular';
|
|
||||||
import { FormsModule } from '@angular/forms';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { LabelService } from '../../../../../shared/services';
|
|
||||||
import { ErrorHandler } from '../../../../../shared/units/error-handler';
|
|
||||||
|
|
||||||
describe('LabelMarkerComponent', () => {
|
|
||||||
const mockErrorHandler = null;
|
|
||||||
|
|
||||||
const mockLabelService = {
|
|
||||||
getChartVersionLabels: () => {
|
|
||||||
return of({
|
|
||||||
name: '111',
|
|
||||||
description: 'string',
|
|
||||||
color: 'string',
|
|
||||||
scope: 'string',
|
|
||||||
project_id: 1,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
markChartLabel: () => {},
|
|
||||||
unmarkChartLabel: () => {},
|
|
||||||
};
|
|
||||||
let component: LabelMarkerComponent;
|
|
||||||
let fixture: ComponentFixture<LabelMarkerComponent>;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
imports: [ClarityModule, TranslateModule.forRoot(), FormsModule],
|
|
||||||
declarations: [LabelMarkerComponent],
|
|
||||||
providers: [
|
|
||||||
TranslateService,
|
|
||||||
{ provide: LabelService, useValue: mockLabelService },
|
|
||||||
{ provide: ErrorHandler, useValue: mockErrorHandler },
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(LabelMarkerComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,171 +0,0 @@
|
||||||
import {
|
|
||||||
ChangeDetectorRef,
|
|
||||||
Component,
|
|
||||||
ElementRef,
|
|
||||||
EventEmitter,
|
|
||||||
Input,
|
|
||||||
OnInit,
|
|
||||||
Output,
|
|
||||||
ViewChild,
|
|
||||||
} from '@angular/core';
|
|
||||||
import { fromEvent, Subject } from 'rxjs';
|
|
||||||
import { debounceTime, finalize } from 'rxjs/operators';
|
|
||||||
import { HelmChartVersion } from '../helm-chart.interface.service';
|
|
||||||
import { Label, LabelService } from '../../../../../shared/services';
|
|
||||||
import { ErrorHandler } from '../../../../../shared/units/error-handler';
|
|
||||||
import { ResourceType } from '../../../../../shared/entities/shared.const';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hbr-resource-label-marker',
|
|
||||||
templateUrl: './label-marker.component.html',
|
|
||||||
styleUrls: ['./label-marker.component.scss'],
|
|
||||||
})
|
|
||||||
export class LabelMarkerComponent implements OnInit {
|
|
||||||
@Input() labels: Label[] = [];
|
|
||||||
@Input() projectName: string;
|
|
||||||
@Input() resource: HelmChartVersion;
|
|
||||||
@Input() resourceType: ResourceType;
|
|
||||||
@Input() addLabelHeaders: string;
|
|
||||||
@Output() changeEvt = new EventEmitter<any>();
|
|
||||||
|
|
||||||
labelFilter = '';
|
|
||||||
markedMap: Map<number, boolean> = new Map<number, boolean>();
|
|
||||||
markingMap: Map<number, boolean> = new Map<number, boolean>();
|
|
||||||
sortedLabels: Label[] = [];
|
|
||||||
|
|
||||||
loading = false;
|
|
||||||
|
|
||||||
labelChangeDebouncer: Subject<any> = new Subject();
|
|
||||||
|
|
||||||
@ViewChild('filterInput', { static: true }) filterInputRef: ElementRef;
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.sortedLabels = this.labels;
|
|
||||||
this.refresh();
|
|
||||||
fromEvent(this.filterInputRef.nativeElement, 'keyup')
|
|
||||||
.pipe(debounceTime(500))
|
|
||||||
.subscribe(() => this.refresh());
|
|
||||||
|
|
||||||
this.labelChangeDebouncer
|
|
||||||
.pipe(debounceTime(1000))
|
|
||||||
.subscribe(() => this.changeEvt.emit());
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private labelService: LabelService,
|
|
||||||
private errorHandler: ErrorHandler,
|
|
||||||
private cdr: ChangeDetectorRef
|
|
||||||
) {}
|
|
||||||
|
|
||||||
refresh() {
|
|
||||||
this.loading = true;
|
|
||||||
if (this.resourceType === ResourceType.CHART_VERSION) {
|
|
||||||
this.labelService
|
|
||||||
.getChartVersionLabels(
|
|
||||||
this.projectName,
|
|
||||||
this.resource.name,
|
|
||||||
(this.resource as HelmChartVersion).version
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
finalize(() => {
|
|
||||||
this.loading = false;
|
|
||||||
let hnd = setInterval(
|
|
||||||
() => this.cdr.markForCheck(),
|
|
||||||
100
|
|
||||||
);
|
|
||||||
setTimeout(() => clearInterval(hnd), 2000);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(chartVersionLabels => {
|
|
||||||
for (let label of chartVersionLabels) {
|
|
||||||
this.markedMap.set(label.id, true);
|
|
||||||
}
|
|
||||||
this.sortedLabels = this.getSortedLabels();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
markLabel(label: Label) {
|
|
||||||
if (this.markedMap.get(label.id) || this.isMarkOngoing(label)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.markingMap.set(label.id, true);
|
|
||||||
this.labelService
|
|
||||||
.markChartLabel(
|
|
||||||
this.projectName,
|
|
||||||
this.resource.name,
|
|
||||||
(this.resource as HelmChartVersion).version,
|
|
||||||
label
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
finalize(() => {
|
|
||||||
this.markingMap.set(label.id, false);
|
|
||||||
let hnd = setInterval(() => this.cdr.markForCheck(), 100);
|
|
||||||
setTimeout(() => clearInterval(hnd), 5000);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(
|
|
||||||
() => {
|
|
||||||
this.markedMap.set(label.id, true);
|
|
||||||
this.refresh();
|
|
||||||
this.labelChangeDebouncer.next(null);
|
|
||||||
let hnd = setInterval(() => this.cdr.markForCheck(), 100);
|
|
||||||
setTimeout(() => clearInterval(hnd), 5000);
|
|
||||||
},
|
|
||||||
err => this.errorHandler.error(err)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
unmarkLabel(label: Label) {
|
|
||||||
if (!this.isMarked(label) || this.isMarkOngoing(label)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.markingMap.set(label.id, true);
|
|
||||||
this.labelService
|
|
||||||
.unmarkChartLabel(
|
|
||||||
this.projectName,
|
|
||||||
this.resource.name,
|
|
||||||
(this.resource as HelmChartVersion).version,
|
|
||||||
label
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
finalize(() => {
|
|
||||||
this.markingMap.set(label.id, false);
|
|
||||||
let hnd = setInterval(() => this.cdr.markForCheck(), 100);
|
|
||||||
setTimeout(() => clearInterval(hnd), 5000);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(
|
|
||||||
() => {
|
|
||||||
this.markedMap.set(label.id, false);
|
|
||||||
this.refresh();
|
|
||||||
this.labelChangeDebouncer.next(null);
|
|
||||||
let hnd = setInterval(() => this.cdr.markForCheck(), 100);
|
|
||||||
setTimeout(() => clearInterval(hnd), 5000);
|
|
||||||
},
|
|
||||||
err => this.errorHandler.error(err)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
isMarked(label: Label) {
|
|
||||||
return this.markedMap.get(label.id) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
isMarkOngoing(label: Label) {
|
|
||||||
return this.markingMap.get(label.id) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSortedLabels(): Label[] {
|
|
||||||
return this.labels
|
|
||||||
.filter(l => l.name.includes(this.labelFilter))
|
|
||||||
.sort((a, b) => {
|
|
||||||
if (this.isMarked(a) && !this.isMarked(b)) {
|
|
||||||
return -1;
|
|
||||||
} else if (!this.isMarked(a) && this.isMarked(b)) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,276 +0,0 @@
|
||||||
<div class="version-position">
|
|
||||||
<div class="row flex-items-xs-between">
|
|
||||||
<div class="col-xs-4">
|
|
||||||
<div class="title-container">
|
|
||||||
<div class="chart-name-span">
|
|
||||||
{{ chartName | translate }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ roleName | translate }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row version-tool">
|
|
||||||
<div class="toolbar">
|
|
||||||
<div class="row flex-items-xs-right option-right rightPos">
|
|
||||||
<div class="flex-xs-middle">
|
|
||||||
<hbr-filter
|
|
||||||
[withDivider]="true"
|
|
||||||
filterPlaceholder="{{
|
|
||||||
'HELM_CHART.FILTER_FOR_CHARTS' | translate
|
|
||||||
}}"
|
|
||||||
[currentValue]="lastFilteredVersionName"
|
|
||||||
(filterEvt)="updateFilterValue($event)"></hbr-filter>
|
|
||||||
<span
|
|
||||||
class="card-btn"
|
|
||||||
(click)="showCard(true)"
|
|
||||||
(mouseenter)="mouseEnter('card')"
|
|
||||||
(mouseleave)="mouseLeave('card')">
|
|
||||||
<clr-icon
|
|
||||||
[ngClass]="{
|
|
||||||
'is-highlight': isCardView || isHovering('card')
|
|
||||||
}"
|
|
||||||
shape="view-cards"></clr-icon>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="list-btn"
|
|
||||||
(click)="showCard(false)"
|
|
||||||
(mouseenter)="mouseEnter('list')"
|
|
||||||
(mouseleave)="mouseLeave('list')">
|
|
||||||
<clr-icon
|
|
||||||
[ngClass]="{
|
|
||||||
'is-highlight':
|
|
||||||
!isCardView || isHovering('list')
|
|
||||||
}"
|
|
||||||
shape="view-list"></clr-icon>
|
|
||||||
</span>
|
|
||||||
<span class="filter-divider"></span>
|
|
||||||
<span class="refresh-btn" (click)="refresh()">
|
|
||||||
<clr-icon shape="refresh"></clr-icon>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div
|
|
||||||
*ngIf="!isCardView"
|
|
||||||
class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
|
||||||
<clr-datagrid
|
|
||||||
(clrDgRefresh)="refresh($event)"
|
|
||||||
[clrDgLoading]="loading"
|
|
||||||
[(clrDgSelected)]="selectedRows">
|
|
||||||
<clr-dg-action-bar>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-secondary"
|
|
||||||
[disabled]="
|
|
||||||
!(selectedRows.length === 1) ||
|
|
||||||
!hasDownloadHelmChartVersionPermission
|
|
||||||
"
|
|
||||||
(click)="versionDownload()">
|
|
||||||
<clr-icon shape="download" size="16"></clr-icon> {{
|
|
||||||
'HELM_CHART.DOWNLOAD' | translate
|
|
||||||
}}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-secondary"
|
|
||||||
[disabled]="
|
|
||||||
selectedRows.length <= 0 ||
|
|
||||||
!hasDeleteHelmChartVersionPermission
|
|
||||||
"
|
|
||||||
(click)="openVersionDeleteModal()">
|
|
||||||
<clr-icon shape="times" size="16"></clr-icon> {{
|
|
||||||
'BUTTON.DELETE' | translate
|
|
||||||
}}
|
|
||||||
</button>
|
|
||||||
<clr-dropdown>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-secondary"
|
|
||||||
clrDropdownTrigger
|
|
||||||
[disabled]="
|
|
||||||
!(selectedRows.length === 1) ||
|
|
||||||
!hasAddRemoveHelmChartVersionPermission
|
|
||||||
">
|
|
||||||
<clr-icon shape="plus" size="16"></clr-icon
|
|
||||||
>{{ 'REPOSITORY.ADD_LABELS' | translate }}
|
|
||||||
</button>
|
|
||||||
<clr-dropdown-menu clrPosition="bottom-left" *clrIfOpen>
|
|
||||||
<hbr-resource-label-marker
|
|
||||||
[labels]="labels"
|
|
||||||
[projectName]="projectName"
|
|
||||||
[resource]="selectedRows[0]"
|
|
||||||
[resourceType]="resourceType"
|
|
||||||
[addLabelHeaders]="addLabelHeaders"
|
|
||||||
(changeEvt)="onLabelChange(selectedRows[0])">
|
|
||||||
</hbr-resource-label-marker>
|
|
||||||
</clr-dropdown-menu>
|
|
||||||
</clr-dropdown>
|
|
||||||
</clr-dg-action-bar>
|
|
||||||
<clr-dg-column>{{
|
|
||||||
'HELM_CHART.VERSION' | translate
|
|
||||||
}}</clr-dg-column>
|
|
||||||
<clr-dg-column>{{
|
|
||||||
'HELM_CHART.STATUS' | translate
|
|
||||||
}}</clr-dg-column>
|
|
||||||
<clr-dg-column>{{
|
|
||||||
'HELM_CHART.ENGINE' | translate
|
|
||||||
}}</clr-dg-column>
|
|
||||||
|
|
||||||
<clr-dg-column>{{
|
|
||||||
'HELM_CHART.MAINTAINERS' | translate
|
|
||||||
}}</clr-dg-column>
|
|
||||||
<clr-dg-column>{{
|
|
||||||
'HELM_CHART.CREATED' | translate
|
|
||||||
}}</clr-dg-column>
|
|
||||||
<clr-dg-column>
|
|
||||||
{{ 'REPOSITORY.LABELS' | translate }}
|
|
||||||
<clr-dg-filter [clrDgFilter]="labelFilter">
|
|
||||||
<hbr-chart-version-label-filter
|
|
||||||
#labelFilter
|
|
||||||
class="label-filter"
|
|
||||||
[labels]="labels"
|
|
||||||
[resourceType]="resourceType">
|
|
||||||
</hbr-chart-version-label-filter>
|
|
||||||
</clr-dg-filter>
|
|
||||||
</clr-dg-column>
|
|
||||||
<clr-dg-placeholder>{{
|
|
||||||
'HELM_CHART.NO_VERSION_PLACEHOLDER' | translate
|
|
||||||
}}</clr-dg-placeholder>
|
|
||||||
<clr-dg-row
|
|
||||||
*clrDgItems="let v of chartVersions"
|
|
||||||
[clrDgItem]="v">
|
|
||||||
<clr-dg-cell>
|
|
||||||
<span class="list-img">
|
|
||||||
<img
|
|
||||||
[src]="v.icon ? v.icon : chartDefaultIcon"
|
|
||||||
(error)="getDefaultIcon(v)" />
|
|
||||||
</span>
|
|
||||||
<a
|
|
||||||
href="javascript:void(0)"
|
|
||||||
(click)="onVersionClick(v)"
|
|
||||||
>{{ v.version }}</a
|
|
||||||
>
|
|
||||||
</clr-dg-cell>
|
|
||||||
<clr-dg-cell>{{
|
|
||||||
getStatusString(v) | translate
|
|
||||||
}}</clr-dg-cell>
|
|
||||||
<clr-dg-cell>{{ v.engine }}</clr-dg-cell>
|
|
||||||
<clr-dg-cell>{{
|
|
||||||
getMaintainerString(v.maintainers)
|
|
||||||
}}</clr-dg-cell>
|
|
||||||
<clr-dg-cell>{{ v.created | harborDatetime }}</clr-dg-cell>
|
|
||||||
<clr-dg-cell>
|
|
||||||
<div>
|
|
||||||
<hbr-label-piece
|
|
||||||
*ngIf="v.labels?.length"
|
|
||||||
[label]="v.labels[0]"
|
|
||||||
[labelWidth]="130">
|
|
||||||
</hbr-label-piece>
|
|
||||||
<hbr-resource-label-signpost
|
|
||||||
*ngIf="v.labels?.length > 1"
|
|
||||||
[labels]="
|
|
||||||
v.labels
|
|
||||||
"></hbr-resource-label-signpost>
|
|
||||||
</div>
|
|
||||||
</clr-dg-cell>
|
|
||||||
</clr-dg-row>
|
|
||||||
<clr-dg-footer>
|
|
||||||
<clr-dg-pagination
|
|
||||||
#pagination
|
|
||||||
[clrDgPageSize]="pageSize"
|
|
||||||
[clrDgTotalItems]="totalCount">
|
|
||||||
<clr-dg-page-size [clrPageSizeOptions]="[15, 25, 50]">{{
|
|
||||||
'PAGINATION.PAGE_SIZE' | translate
|
|
||||||
}}</clr-dg-page-size>
|
|
||||||
<span *ngIf="totalCount">
|
|
||||||
{{ pagination.firstItem + 1 }} -
|
|
||||||
{{ pagination.lastItem + 1 }}
|
|
||||||
{{ 'HELM_CHART.OF' | translate }}
|
|
||||||
</span>
|
|
||||||
{{ totalCount }} {{ 'HELM_CHART.ITEMS' | translate }}
|
|
||||||
</clr-dg-pagination>
|
|
||||||
</clr-dg-footer>
|
|
||||||
</clr-datagrid>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="isCardView" class="row card-container">
|
|
||||||
<div
|
|
||||||
*ngFor="let item of chartVersions"
|
|
||||||
class="col-lg-3 col-md-4 col-sm-6">
|
|
||||||
<a
|
|
||||||
let
|
|
||||||
i="index;"
|
|
||||||
class="card clickable"
|
|
||||||
(click)="onVersionClick(item)">
|
|
||||||
<div class="card-header">
|
|
||||||
<div class="card-media-block">
|
|
||||||
<img
|
|
||||||
[src]="item.icon ? item.icon : chartDefaultIcon"
|
|
||||||
(error)="getDefaultIcon(item)" />
|
|
||||||
<div class="card-media-description">
|
|
||||||
<span class="card-media-title">{{
|
|
||||||
item.name
|
|
||||||
}}</span>
|
|
||||||
<a class="card-media-text">{{ item.home }}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-block">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="card-label">{{
|
|
||||||
'HELM_CHART.STATUS' | translate
|
|
||||||
}}</label>
|
|
||||||
<div>{{ getStatusString(item) | translate }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="card-label">{{
|
|
||||||
'HELM_CHART.ENGINE' | translate
|
|
||||||
}}</label>
|
|
||||||
<div>{{ item.engine }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="card-label">{{
|
|
||||||
'HELM_CHART.MAINTAINERS' | translate
|
|
||||||
}}</label>
|
|
||||||
<div>{{ getMaintainerString(item.maintainers) }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="card-label">{{
|
|
||||||
'HELM_CHART.VERSION' | translate
|
|
||||||
}}</label>
|
|
||||||
<div>{{ item.version }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<clr-dropdown [clrCloseMenuOnItemClick]="false">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-link"
|
|
||||||
(click)="versionDownload($event, item)">
|
|
||||||
{{ 'HELM_CHART.DOWNLOAD' | translate }}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-link"
|
|
||||||
[disabled]="!hasDeleteHelmChartVersionPermission"
|
|
||||||
(click)="deleteVersionCard($event, item)">
|
|
||||||
{{ 'BUTTON.DELETE' | translate }}
|
|
||||||
</button>
|
|
||||||
</clr-dropdown>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="loading" class="center-x">
|
|
||||||
<span class="vertical-helper"></span>
|
|
||||||
<span class="spinner"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<confirmation-dialog
|
|
||||||
#confirmationDialog
|
|
||||||
(confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
|
||||||
</div>
|
|
|
@ -1,131 +0,0 @@
|
||||||
@import "../../../../../../shared/mixin";
|
|
||||||
|
|
||||||
.title-container {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.chart-name-span {
|
|
||||||
border-right: 1px solid gray;
|
|
||||||
font-size: 27px;
|
|
||||||
font-weight: normal;
|
|
||||||
padding-right: 9px;
|
|
||||||
margin-right: 9px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.version-tool {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.toolbar {
|
|
||||||
overflow: hidden;
|
|
||||||
/* stylelint-disable */
|
|
||||||
.rightPos {
|
|
||||||
@include grid-right-top-pos;
|
|
||||||
|
|
||||||
.filter-divider {
|
|
||||||
display: inline-block;
|
|
||||||
height: 16px;
|
|
||||||
width: 1px;
|
|
||||||
padding-top: 12px;
|
|
||||||
padding-bottom: 12px;
|
|
||||||
position: relative;
|
|
||||||
top: 9px;
|
|
||||||
margin-right: 6px;
|
|
||||||
margin-left: 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clr-dg-action-bar {
|
|
||||||
clr-dropdown {
|
|
||||||
.btn {
|
|
||||||
@include dropdown-as-action-button;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hbr-resource-label-signpost {
|
|
||||||
display: inline-block;
|
|
||||||
max-height: 24px;
|
|
||||||
margin-left: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-container {
|
|
||||||
margin-top: 40px;
|
|
||||||
|
|
||||||
.card-header {
|
|
||||||
.card-media-block {
|
|
||||||
img {
|
|
||||||
height: 45px;
|
|
||||||
width: 45px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-media-description {
|
|
||||||
width:80%;
|
|
||||||
height: 45px;
|
|
||||||
|
|
||||||
.card-media-title {
|
|
||||||
overflow: hidden;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-media-text {
|
|
||||||
font-size:0.8em;
|
|
||||||
color:#007cbb;
|
|
||||||
@include text-overflow;
|
|
||||||
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-block {
|
|
||||||
font-size:0.9em;
|
|
||||||
margin-top: 24px;
|
|
||||||
min-height: 100px;
|
|
||||||
|
|
||||||
.form-group {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
label {
|
|
||||||
width: 100px;
|
|
||||||
color:#aaa;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-footer {
|
|
||||||
padding-top: 6px;
|
|
||||||
padding-bottom: 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-img {
|
|
||||||
img {
|
|
||||||
height: 24px;
|
|
||||||
width: 24px;
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical-helper {
|
|
||||||
display: inline-block;
|
|
||||||
height: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.center-x {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
position: absolute;
|
|
||||||
top: 6.5rem;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.version-position {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { ChartVersionComponent } from './helm-chart-version.component';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
||||||
import { HelmChartService } from '../../helm-chart.service';
|
|
||||||
import { LabelFilterComponent } from '../../label-filter/label-filter.component';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
import {
|
|
||||||
LabelService,
|
|
||||||
SystemInfoService,
|
|
||||||
UserPermissionService,
|
|
||||||
} from '../../../../../../shared/services';
|
|
||||||
import { ErrorHandler } from '../../../../../../shared/units/error-handler';
|
|
||||||
import { OperationService } from '../../../../../../shared/components/operation/operation.service';
|
|
||||||
import { delay } from 'rxjs/operators';
|
|
||||||
import { SharedTestingModule } from '../../../../../../shared/shared.module';
|
|
||||||
|
|
||||||
describe('ChartVersionComponent', () => {
|
|
||||||
let component: ChartVersionComponent;
|
|
||||||
let fixture: ComponentFixture<ChartVersionComponent>;
|
|
||||||
const mockSystemInfoService = {
|
|
||||||
getSystemInfo: () => {
|
|
||||||
return of({
|
|
||||||
with_notary: false,
|
|
||||||
with_admiral: false,
|
|
||||||
admiral_endpoint: '',
|
|
||||||
auth_mode: 'oidc_auth',
|
|
||||||
registry_url: 'nightly-oidc.harbor.io',
|
|
||||||
external_url: 'https://nightly-oidc.harbor.io',
|
|
||||||
project_creation_restriction: 'everyone',
|
|
||||||
self_registration: false,
|
|
||||||
has_ca_root: false,
|
|
||||||
harbor_version: 'dev',
|
|
||||||
registry_storage_provider_name: 'filesystem',
|
|
||||||
read_only: false,
|
|
||||||
with_chartmuseum: true,
|
|
||||||
notification_enable: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const mockLabelService = {
|
|
||||||
getLabels: () => {
|
|
||||||
return of([]);
|
|
||||||
},
|
|
||||||
getProjectLabels: () => {
|
|
||||||
return of([]);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const mockErrorHandler = null;
|
|
||||||
const mockOperationService = {
|
|
||||||
publishInfo: () => {
|
|
||||||
return of([]);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const mockUserPermissionService = {
|
|
||||||
getPermission() {
|
|
||||||
return of(true);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const mockHelmChartService = {
|
|
||||||
getChartVersions() {
|
|
||||||
return of([
|
|
||||||
{
|
|
||||||
name: 'string',
|
|
||||||
home: 'string',
|
|
||||||
sources: [],
|
|
||||||
version: 'string',
|
|
||||||
description: 'string',
|
|
||||||
keywords: [],
|
|
||||||
maintainers: [],
|
|
||||||
engine: 'string',
|
|
||||||
icon: 'string',
|
|
||||||
appVersion: 'string',
|
|
||||||
apiVersion: 'string',
|
|
||||||
urls: [],
|
|
||||||
created: 'string',
|
|
||||||
digest: 'string',
|
|
||||||
labels: [],
|
|
||||||
},
|
|
||||||
]).pipe(delay(0));
|
|
||||||
},
|
|
||||||
};
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
imports: [SharedTestingModule],
|
|
||||||
declarations: [ChartVersionComponent, LabelFilterComponent],
|
|
||||||
providers: [
|
|
||||||
{ provide: SystemInfoService, useValue: mockSystemInfoService },
|
|
||||||
{ provide: LabelService, useValue: mockLabelService },
|
|
||||||
{
|
|
||||||
provide: UserPermissionService,
|
|
||||||
useValue: mockUserPermissionService,
|
|
||||||
},
|
|
||||||
{ provide: ErrorHandler, useValue: mockErrorHandler },
|
|
||||||
{ provide: HelmChartService, useValue: mockHelmChartService },
|
|
||||||
{ provide: OperationService, useValue: mockOperationService },
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ChartVersionComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,504 +0,0 @@
|
||||||
import {
|
|
||||||
Component,
|
|
||||||
EventEmitter,
|
|
||||||
Input,
|
|
||||||
OnInit,
|
|
||||||
Output,
|
|
||||||
ViewChild,
|
|
||||||
} from '@angular/core';
|
|
||||||
import { forkJoin, Observable, throwError as observableThrowError } from 'rxjs';
|
|
||||||
import { catchError, finalize, map } from 'rxjs/operators';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
import {
|
|
||||||
HelmChartMaintainer,
|
|
||||||
HelmChartVersion,
|
|
||||||
} from '../../helm-chart.interface.service';
|
|
||||||
import { HelmChartService } from '../../helm-chart.service';
|
|
||||||
import {
|
|
||||||
LabelService as OldLabelService,
|
|
||||||
State,
|
|
||||||
SystemInfo,
|
|
||||||
SystemInfoService,
|
|
||||||
UserPermissionService,
|
|
||||||
USERSTATICPERMISSION,
|
|
||||||
} from '../../../../../../shared/services';
|
|
||||||
import {
|
|
||||||
downloadFile,
|
|
||||||
getPageSizeFromLocalStorage,
|
|
||||||
PageSizeMapKeys,
|
|
||||||
setPageSizeToLocalStorage,
|
|
||||||
} from '../../../../../../shared/units/utils';
|
|
||||||
import { ErrorHandler } from '../../../../../../shared/units/error-handler';
|
|
||||||
import { OperationService } from '../../../../../../shared/components/operation/operation.service';
|
|
||||||
import {
|
|
||||||
operateChanges,
|
|
||||||
OperateInfo,
|
|
||||||
OperationState,
|
|
||||||
} from '../../../../../../shared/components/operation/operate';
|
|
||||||
import {
|
|
||||||
ConfirmationButtons,
|
|
||||||
ConfirmationState,
|
|
||||||
ConfirmationTargets,
|
|
||||||
DefaultHelmIcon,
|
|
||||||
ResourceType,
|
|
||||||
} from '../../../../../../shared/entities/shared.const';
|
|
||||||
import { errorHandler } from '../../../../../../shared/units/shared.utils';
|
|
||||||
import { ConfirmationDialogComponent } from '../../../../../../shared/components/confirmation-dialog';
|
|
||||||
import { ConfirmationMessage } from '../../../../../global-confirmation-dialog/confirmation-message';
|
|
||||||
import { ConfirmationAcknowledgement } from '../../../../../global-confirmation-dialog/confirmation-state-message';
|
|
||||||
import { Label } from '../../../../../../../../ng-swagger-gen/models/label';
|
|
||||||
import { LabelService } from '../../../../../../../../ng-swagger-gen/services/label.service';
|
|
||||||
import { ClrDatagridStateInterface } from '@clr/angular';
|
|
||||||
|
|
||||||
const PAGE_SIZE: number = 100;
|
|
||||||
@Component({
|
|
||||||
selector: 'hbr-helm-chart-version',
|
|
||||||
templateUrl: './helm-chart-version.component.html',
|
|
||||||
styleUrls: ['./helm-chart-version.component.scss'],
|
|
||||||
})
|
|
||||||
export class ChartVersionComponent implements OnInit {
|
|
||||||
signedCon: { [key: string]: any | string[] } = {};
|
|
||||||
@Input() projectId: number;
|
|
||||||
@Input() projectName: string;
|
|
||||||
@Input() chartName: string;
|
|
||||||
@Input() roleName: string;
|
|
||||||
@Input() hasSignedIn: boolean;
|
|
||||||
@Input() chartDefaultIcon: string = DefaultHelmIcon;
|
|
||||||
@Output() versionClickEvt = new EventEmitter<string>();
|
|
||||||
@Output() backEvt = new EventEmitter<any>();
|
|
||||||
|
|
||||||
lastFilteredVersionName: string;
|
|
||||||
chartVersions: HelmChartVersion[] = [];
|
|
||||||
systemInfo: SystemInfo;
|
|
||||||
selectedRows: HelmChartVersion[] = [];
|
|
||||||
labels: Label[] = [];
|
|
||||||
loading = true;
|
|
||||||
resourceType = ResourceType.CHART_VERSION;
|
|
||||||
|
|
||||||
isCardView: boolean;
|
|
||||||
cardHover = false;
|
|
||||||
listHover = false;
|
|
||||||
|
|
||||||
pageSize: number = getPageSizeFromLocalStorage(
|
|
||||||
PageSizeMapKeys.CHART_VERSION_COMPONENT
|
|
||||||
);
|
|
||||||
currentPage = 1;
|
|
||||||
totalCount = 0;
|
|
||||||
currentState: State;
|
|
||||||
|
|
||||||
chartFile: File;
|
|
||||||
provFile: File;
|
|
||||||
|
|
||||||
addLabelHeaders = 'HELM_CHART.ADD_LABEL_TO_CHART_VERSION';
|
|
||||||
|
|
||||||
@ViewChild('confirmationDialog')
|
|
||||||
confirmationDialog: ConfirmationDialogComponent;
|
|
||||||
hasAddRemoveHelmChartVersionPermission: boolean;
|
|
||||||
hasDownloadHelmChartVersionPermission: boolean;
|
|
||||||
hasDeleteHelmChartVersionPermission: boolean;
|
|
||||||
constructor(
|
|
||||||
private errorHandlerEntity: ErrorHandler,
|
|
||||||
private systemInfoService: SystemInfoService,
|
|
||||||
private helmChartService: HelmChartService,
|
|
||||||
private labelService: LabelService,
|
|
||||||
private resrouceLabelService: OldLabelService,
|
|
||||||
public userPermissionService: UserPermissionService,
|
|
||||||
private operationService: OperationService,
|
|
||||||
private translateService: TranslateService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public get registryUrl(): string {
|
|
||||||
return this.systemInfo ? this.systemInfo.registry_url : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
// Get system info for tag views
|
|
||||||
this.systemInfoService.getSystemInfo().subscribe(
|
|
||||||
systemInfo => (this.systemInfo = systemInfo),
|
|
||||||
error => this.errorHandlerEntity.error(error)
|
|
||||||
);
|
|
||||||
this.refresh();
|
|
||||||
this.getLabels();
|
|
||||||
this.lastFilteredVersionName = '';
|
|
||||||
this.getHelmChartVersionPermission(this.projectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateFilterValue(value: string) {
|
|
||||||
this.lastFilteredVersionName = value;
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
getLabels() {
|
|
||||||
// get all project labels
|
|
||||||
this.labelService
|
|
||||||
.ListLabelsResponse({
|
|
||||||
pageSize: PAGE_SIZE,
|
|
||||||
page: 1,
|
|
||||||
scope: 'p',
|
|
||||||
projectId: this.projectId,
|
|
||||||
})
|
|
||||||
.subscribe(res => {
|
|
||||||
if (res.headers) {
|
|
||||||
const xHeader: string = res.headers.get('X-Total-Count');
|
|
||||||
const totalCount = parseInt(xHeader, 0);
|
|
||||||
let arr = res.body || [];
|
|
||||||
if (totalCount <= PAGE_SIZE) {
|
|
||||||
// already gotten all project labels
|
|
||||||
if (arr && arr.length) {
|
|
||||||
this.labels = this.labels.concat(arr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// get all the project labels in specified times
|
|
||||||
const times: number = Math.ceil(totalCount / PAGE_SIZE);
|
|
||||||
const observableList: Observable<Label[]>[] = [];
|
|
||||||
for (let i = 2; i <= times; i++) {
|
|
||||||
observableList.push(
|
|
||||||
this.labelService.ListLabels({
|
|
||||||
page: i,
|
|
||||||
pageSize: PAGE_SIZE,
|
|
||||||
scope: 'p',
|
|
||||||
projectId: this.projectId,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
forkJoin(observableList).subscribe(response => {
|
|
||||||
if (response && response.length) {
|
|
||||||
response.forEach(item => {
|
|
||||||
arr = arr.concat(item);
|
|
||||||
});
|
|
||||||
this.labels = this.labels.concat(arr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// get all global labels
|
|
||||||
this.labelService
|
|
||||||
.ListLabelsResponse({
|
|
||||||
pageSize: PAGE_SIZE,
|
|
||||||
page: 1,
|
|
||||||
scope: 'g',
|
|
||||||
})
|
|
||||||
.subscribe(res => {
|
|
||||||
if (res.headers) {
|
|
||||||
const xHeader: string = res.headers.get('X-Total-Count');
|
|
||||||
const totalCount = parseInt(xHeader, 0);
|
|
||||||
let arr = res.body || [];
|
|
||||||
if (totalCount <= PAGE_SIZE) {
|
|
||||||
// already gotten all global labels
|
|
||||||
if (arr && arr.length) {
|
|
||||||
this.labels = this.labels.concat(arr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// get all the global labels in specified times
|
|
||||||
const times: number = Math.ceil(totalCount / PAGE_SIZE);
|
|
||||||
const observableList: Observable<Label[]>[] = [];
|
|
||||||
for (let i = 2; i <= times; i++) {
|
|
||||||
observableList.push(
|
|
||||||
this.labelService.ListLabels({
|
|
||||||
page: i,
|
|
||||||
pageSize: PAGE_SIZE,
|
|
||||||
scope: 'g',
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
forkJoin(observableList).subscribe(response => {
|
|
||||||
if (response && response.length) {
|
|
||||||
response.forEach(item => {
|
|
||||||
arr = arr.concat(item);
|
|
||||||
});
|
|
||||||
this.labels = this.labels.concat(arr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh(state?: ClrDatagridStateInterface) {
|
|
||||||
if (state?.page?.size) {
|
|
||||||
setPageSizeToLocalStorage(
|
|
||||||
PageSizeMapKeys.CHART_VERSION_COMPONENT,
|
|
||||||
state.page.size
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this.loading = true;
|
|
||||||
this.helmChartService
|
|
||||||
.getChartVersions(this.projectName, this.chartName)
|
|
||||||
.pipe(
|
|
||||||
finalize(() => {
|
|
||||||
this.selectedRows = [];
|
|
||||||
this.loading = false;
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(
|
|
||||||
versions => {
|
|
||||||
this.chartVersions = versions.filter(x =>
|
|
||||||
x?.version?.includes(this.lastFilteredVersionName)
|
|
||||||
);
|
|
||||||
this.totalCount = versions.length;
|
|
||||||
},
|
|
||||||
err => {
|
|
||||||
this.errorHandlerEntity.error(err);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getMaintainerString(maintainers: HelmChartMaintainer[]) {
|
|
||||||
if (!maintainers || maintainers.length < 1) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
let maintainer_string = maintainers[0].name;
|
|
||||||
if (maintainers.length > 1) {
|
|
||||||
maintainer_string = `${maintainer_string} (${
|
|
||||||
maintainers.length - 1
|
|
||||||
} others)`;
|
|
||||||
}
|
|
||||||
return maintainer_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
onVersionClick(version: HelmChartVersion) {
|
|
||||||
this.versionClickEvt.emit(version.version);
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteVersion(version: HelmChartVersion): Observable<any> {
|
|
||||||
// init operation info
|
|
||||||
let operateMsg = new OperateInfo();
|
|
||||||
operateMsg.name = 'OPERATION.DELETE_CHART_VERSION';
|
|
||||||
operateMsg.data.id = version.digest;
|
|
||||||
operateMsg.state = OperationState.progressing;
|
|
||||||
operateMsg.data.name = `${version.name}:${version.version}`;
|
|
||||||
this.operationService.publishInfo(operateMsg);
|
|
||||||
|
|
||||||
return this.helmChartService
|
|
||||||
.deleteChartVersion(
|
|
||||||
this.projectName,
|
|
||||||
this.chartName,
|
|
||||||
version.version
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
map(() => operateChanges(operateMsg, OperationState.success)),
|
|
||||||
catchError(error => {
|
|
||||||
const message = errorHandler(error);
|
|
||||||
this.translateService
|
|
||||||
.get(message)
|
|
||||||
.subscribe(res =>
|
|
||||||
operateChanges(
|
|
||||||
operateMsg,
|
|
||||||
OperationState.failure,
|
|
||||||
res
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return observableThrowError(error);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteVersions(versions: HelmChartVersion[]) {
|
|
||||||
if (versions && versions.length < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let successCount: number;
|
|
||||||
let totalCount = this.chartVersions.length;
|
|
||||||
let versionObs = versions.map(v => this.deleteVersion(v));
|
|
||||||
forkJoin(versionObs)
|
|
||||||
.pipe(
|
|
||||||
finalize(() => {
|
|
||||||
if (totalCount !== successCount) {
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(
|
|
||||||
res => {
|
|
||||||
successCount = res.filter(
|
|
||||||
r => r.state === OperationState.success
|
|
||||||
).length;
|
|
||||||
if (totalCount === successCount) {
|
|
||||||
this.backEvt.emit();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
this.errorHandlerEntity.error(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
versionDownload(evt?: Event, item?: HelmChartVersion) {
|
|
||||||
if (evt) {
|
|
||||||
evt.stopPropagation();
|
|
||||||
}
|
|
||||||
let selectedVersion: HelmChartVersion;
|
|
||||||
|
|
||||||
if (item) {
|
|
||||||
selectedVersion = item;
|
|
||||||
} else {
|
|
||||||
// return if selected version less then 1
|
|
||||||
if (this.selectedRows.length < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
selectedVersion = this.selectedRows[0];
|
|
||||||
}
|
|
||||||
if (!selectedVersion) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let filename = selectedVersion.urls[0];
|
|
||||||
this.helmChartService
|
|
||||||
.downloadChart(this.projectName, filename)
|
|
||||||
.subscribe(
|
|
||||||
res => {
|
|
||||||
downloadFile(res);
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
this.errorHandlerEntity.error(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
showCard(cardView: boolean) {
|
|
||||||
if (this.isCardView === cardView) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.isCardView = cardView;
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseEnter(itemName: string) {
|
|
||||||
if (itemName === 'card') {
|
|
||||||
this.cardHover = true;
|
|
||||||
} else {
|
|
||||||
this.listHover = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseLeave(itemName: string) {
|
|
||||||
if (itemName === 'card') {
|
|
||||||
this.cardHover = false;
|
|
||||||
} else {
|
|
||||||
this.listHover = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isHovering(itemName: string) {
|
|
||||||
if (itemName === 'card') {
|
|
||||||
return this.cardHover;
|
|
||||||
} else {
|
|
||||||
return this.listHover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onChartFileChangeEvent(event) {
|
|
||||||
if (event.target.files && event.target.files.length > 0) {
|
|
||||||
this.chartFile = event.target.files[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onProvFileChangeEvent(event) {
|
|
||||||
if (event.target.files && event.target.files.length > 0) {
|
|
||||||
this.provFile = event.target.files[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteVersionCard(env: Event, version: HelmChartVersion) {
|
|
||||||
env.stopPropagation();
|
|
||||||
this.openVersionDeleteModal([version]);
|
|
||||||
}
|
|
||||||
|
|
||||||
openVersionDeleteModal(versions?: HelmChartVersion[]) {
|
|
||||||
if (!versions) {
|
|
||||||
versions = this.selectedRows;
|
|
||||||
}
|
|
||||||
let versionNames = versions.map(v => v.version).join(',');
|
|
||||||
let message = new ConfirmationMessage(
|
|
||||||
'HELM_CHART.DELETE_CHART_VERSION_TITLE',
|
|
||||||
'HELM_CHART.DELETE_CHART_VERSION',
|
|
||||||
versionNames,
|
|
||||||
versions,
|
|
||||||
ConfirmationTargets.HELM_CHART_VERSION,
|
|
||||||
ConfirmationButtons.DELETE_CANCEL
|
|
||||||
);
|
|
||||||
this.confirmationDialog.open(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
confirmDeletion(message: ConfirmationAcknowledgement) {
|
|
||||||
if (
|
|
||||||
message &&
|
|
||||||
message.source === ConfirmationTargets.HELM_CHART_VERSION &&
|
|
||||||
message.state === ConfirmationState.CONFIRMED
|
|
||||||
) {
|
|
||||||
let versions = message.data;
|
|
||||||
this.deleteVersions(versions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getImgLink(v: HelmChartVersion) {
|
|
||||||
if (v.icon) {
|
|
||||||
return v.icon;
|
|
||||||
} else {
|
|
||||||
return DefaultHelmIcon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultIcon(v: HelmChartVersion) {
|
|
||||||
v.icon = this.chartDefaultIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
getStatusString(chartVersion: HelmChartVersion) {
|
|
||||||
if (chartVersion.deprecated) {
|
|
||||||
return 'HELM_CHART.DEPRECATED';
|
|
||||||
} else {
|
|
||||||
return 'HELM_CHART.ACTIVE';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onLabelChange(version: HelmChartVersion) {
|
|
||||||
this.resrouceLabelService
|
|
||||||
.getChartVersionLabels(
|
|
||||||
this.projectName,
|
|
||||||
this.chartName,
|
|
||||||
version.version
|
|
||||||
)
|
|
||||||
.subscribe(labels => {
|
|
||||||
let versionIdx = this.chartVersions.findIndex(
|
|
||||||
v => v.name === version.name
|
|
||||||
);
|
|
||||||
this.chartVersions[versionIdx].labels = labels;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getHelmChartVersionPermission(projectId: number): void {
|
|
||||||
let hasAddRemoveHelmChartVersionPermission =
|
|
||||||
this.userPermissionService.getPermission(
|
|
||||||
projectId,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART_VERSION_LABEL.KEY,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART_VERSION_LABEL.VALUE.CREATE
|
|
||||||
);
|
|
||||||
let hasDownloadHelmChartVersionPermission =
|
|
||||||
this.userPermissionService.getPermission(
|
|
||||||
projectId,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART_VERSION.KEY,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART_VERSION.VALUE.READ
|
|
||||||
);
|
|
||||||
let hasDeleteHelmChartVersionPermission =
|
|
||||||
this.userPermissionService.getPermission(
|
|
||||||
projectId,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART_VERSION.KEY,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART_VERSION.VALUE.DELETE
|
|
||||||
);
|
|
||||||
forkJoin(
|
|
||||||
hasAddRemoveHelmChartVersionPermission,
|
|
||||||
hasDownloadHelmChartVersionPermission,
|
|
||||||
hasDeleteHelmChartVersionPermission
|
|
||||||
).subscribe(
|
|
||||||
permissions => {
|
|
||||||
this.hasAddRemoveHelmChartVersionPermission =
|
|
||||||
permissions[0] as boolean;
|
|
||||||
this.hasDownloadHelmChartVersionPermission =
|
|
||||||
permissions[1] as boolean;
|
|
||||||
this.hasDeleteHelmChartVersionPermission =
|
|
||||||
permissions[2] as boolean;
|
|
||||||
},
|
|
||||||
error => this.errorHandlerEntity.error(error)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
<div>
|
|
||||||
<div class="breadcrumb">
|
|
||||||
<span class="back-icon"><</span>
|
|
||||||
<a href="javascript:void(0)" (click)="gotoProjectList()">{{
|
|
||||||
'SIDE_NAV.PROJECTS' | translate
|
|
||||||
}}</a>
|
|
||||||
<span class="back-icon"><</span>
|
|
||||||
<a href="javascript:void(0)" (click)="gotoChartList()">{{
|
|
||||||
projectName
|
|
||||||
}}</a>
|
|
||||||
</div>
|
|
||||||
<hbr-helm-chart-version
|
|
||||||
[projectId]="projectId"
|
|
||||||
[projectName]="projectName"
|
|
||||||
[chartName]="chartName"
|
|
||||||
[roleName]="roleName"
|
|
||||||
[hasSignedIn]="hasSignedIn"
|
|
||||||
(versionClickEvt)="onVersionClick($event)"
|
|
||||||
(backEvt)="gotoChartList()">
|
|
||||||
</hbr-helm-chart-version>
|
|
||||||
</div>
|
|
|
@ -1,16 +0,0 @@
|
||||||
.breadcrumb a {
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #007cbb;
|
|
||||||
font-size: 16px;
|
|
||||||
margin: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.breadcrumb {
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-icon {
|
|
||||||
color: #007cbb;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { ClarityModule } from '@clr/angular';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
|
||||||
import { SessionService } from '../../../../../shared/services/session.service';
|
|
||||||
import { ListChartVersionsComponent } from './list-chart-versions.component';
|
|
||||||
|
|
||||||
describe('ListChartVersionsComponent', () => {
|
|
||||||
let component: ListChartVersionsComponent;
|
|
||||||
let fixture: ComponentFixture<ListChartVersionsComponent>;
|
|
||||||
let fakeSessionService = {
|
|
||||||
getCurrentUser: function () {
|
|
||||||
return 'admin';
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [ListChartVersionsComponent],
|
|
||||||
imports: [ClarityModule, TranslateModule.forRoot()],
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
providers: [
|
|
||||||
TranslateService,
|
|
||||||
{
|
|
||||||
provide: ActivatedRoute,
|
|
||||||
useValue: {
|
|
||||||
snapshot: {
|
|
||||||
parent: {
|
|
||||||
params: {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
data: null,
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
chart: 'chart',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ provide: Router, useValue: null },
|
|
||||||
{ provide: SessionService, useValue: fakeSessionService },
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ListChartVersionsComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,57 +0,0 @@
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
|
||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
import { Project } from '../../../project';
|
|
||||||
import { SessionUser } from '../../../../../shared/entities/session-user';
|
|
||||||
import { SessionService } from '../../../../../shared/services/session.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'list-chart-version',
|
|
||||||
templateUrl: './list-chart-versions.component.html',
|
|
||||||
styleUrls: ['./list-chart-versions.component.scss'],
|
|
||||||
})
|
|
||||||
export class ListChartVersionsComponent implements OnInit {
|
|
||||||
loading = false;
|
|
||||||
|
|
||||||
projectId: number;
|
|
||||||
projectName: string;
|
|
||||||
chartName: string;
|
|
||||||
roleName: string;
|
|
||||||
|
|
||||||
hasSignedIn: boolean;
|
|
||||||
currentUser: SessionUser;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private route: ActivatedRoute,
|
|
||||||
private router: Router,
|
|
||||||
private session: SessionService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
// Get projectId from router-guard params snapshot.
|
|
||||||
this.projectId = +this.route.snapshot.parent.params['id'];
|
|
||||||
this.chartName = this.route.snapshot.params['chart'];
|
|
||||||
// Get current user from registered resolver.
|
|
||||||
this.currentUser = this.session.getCurrentUser();
|
|
||||||
let resolverData = this.route.snapshot.parent.data;
|
|
||||||
if (resolverData) {
|
|
||||||
let project = <Project>resolverData['projectResolver'];
|
|
||||||
this.roleName = project.role_name;
|
|
||||||
this.projectName = project.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onVersionClick(version: string) {
|
|
||||||
this.router.navigateByUrl(`${this.router.url}/${version}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
gotoProjectList() {
|
|
||||||
this.router.navigateByUrl('/harbor/projects');
|
|
||||||
}
|
|
||||||
|
|
||||||
gotoChartList() {
|
|
||||||
this.router.navigateByUrl(
|
|
||||||
`/harbor/projects/${this.projectId}/helm-charts`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
// Copyright Project Harbor Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// 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 { NgModule } from '@angular/core';
|
|
||||||
import { ListChartsComponent } from './list-charts.component';
|
|
||||||
import { HelmChartComponent } from './list-charts-detail/helm-chart.component';
|
|
||||||
import { SharedModule } from '../../../../shared/shared.module';
|
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
|
||||||
|
|
||||||
const routes: Routes = [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: ListChartsComponent,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
@NgModule({
|
|
||||||
imports: [SharedModule, RouterModule.forChild(routes)],
|
|
||||||
declarations: [ListChartsComponent, HelmChartComponent],
|
|
||||||
})
|
|
||||||
export class HelmChartListModule {}
|
|
|
@ -1,290 +0,0 @@
|
||||||
<div>
|
|
||||||
<div class="row chart-tool">
|
|
||||||
<div class="toolbar">
|
|
||||||
<div class="row flex-items-xs-right option-right rightPos">
|
|
||||||
<div class="flex-xs-middle">
|
|
||||||
<hbr-filter
|
|
||||||
[withDivider]="true"
|
|
||||||
filterPlaceholder="{{
|
|
||||||
'HELM_CHART.FILTER_FOR_CHARTS' | translate
|
|
||||||
}}"
|
|
||||||
[currentValue]="lastFilteredChartName"
|
|
||||||
(filterEvt)="updateFilterValue($event)"></hbr-filter>
|
|
||||||
<span
|
|
||||||
class="card-btn"
|
|
||||||
(click)="showCard(true)"
|
|
||||||
(mouseenter)="mouseEnter('card')"
|
|
||||||
(mouseleave)="mouseLeave('card')">
|
|
||||||
<clr-icon
|
|
||||||
[ngClass]="{
|
|
||||||
'is-highlight': isCardView || isHovering('card')
|
|
||||||
}"
|
|
||||||
shape="view-cards"></clr-icon>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="list-btn"
|
|
||||||
(click)="showCard(false)"
|
|
||||||
(mouseenter)="mouseEnter('list')"
|
|
||||||
(mouseleave)="mouseLeave('list')">
|
|
||||||
<clr-icon
|
|
||||||
[ngClass]="{
|
|
||||||
'is-highlight':
|
|
||||||
!isCardView || isHovering('list')
|
|
||||||
}"
|
|
||||||
shape="view-list"></clr-icon>
|
|
||||||
</span>
|
|
||||||
<span class="filter-divider"></span>
|
|
||||||
<span class="refresh-btn" (click)="refresh()">
|
|
||||||
<clr-icon shape="refresh"></clr-icon>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div
|
|
||||||
*ngIf="!isCardView"
|
|
||||||
class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
|
||||||
<clr-datagrid
|
|
||||||
(clrDgRefresh)="clrLoad($event)"
|
|
||||||
[clrDgLoading]="loading"
|
|
||||||
[(clrDgSelected)]="selectedRows">
|
|
||||||
<clr-dg-action-bar>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
id="helm-chart-upload"
|
|
||||||
class="btn btn-secondary"
|
|
||||||
[disabled]="!hasUploadHelmChartsPermission"
|
|
||||||
(click)="onChartUpload()">
|
|
||||||
<clr-icon shape="upload" size="16"></clr-icon
|
|
||||||
>{{ 'HELM_CHART.UPLOAD' | translate }}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-secondary"
|
|
||||||
[disabled]="
|
|
||||||
!hasDeleteHelmChartsPermission ||
|
|
||||||
selectedRows.length < 1
|
|
||||||
"
|
|
||||||
(click)="openChartDeleteModal()">
|
|
||||||
<clr-icon shape="trash" size="16"></clr-icon
|
|
||||||
>{{ 'BUTTON.DELETE' | translate }}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-secondary"
|
|
||||||
[disabled]="
|
|
||||||
!hasDownloadHelmChartsPermission ||
|
|
||||||
selectedRows.length !== 1
|
|
||||||
"
|
|
||||||
(click)="downloadLatestVersion()">
|
|
||||||
<clr-icon shape="download" size="16"></clr-icon
|
|
||||||
>{{ 'HELM_CHART.DOWNLOAD' | translate }}
|
|
||||||
</button>
|
|
||||||
</clr-dg-action-bar>
|
|
||||||
<clr-dg-column>{{
|
|
||||||
'HELM_CHART.NAME' | translate
|
|
||||||
}}</clr-dg-column>
|
|
||||||
<clr-dg-column>{{
|
|
||||||
'HELM_CHART.STATUS' | translate
|
|
||||||
}}</clr-dg-column>
|
|
||||||
<clr-dg-column>{{
|
|
||||||
'HELM_CHART.CHARTVERSIONS' | translate
|
|
||||||
}}</clr-dg-column>
|
|
||||||
<clr-dg-column>{{
|
|
||||||
'HELM_CHART.CREATED' | translate
|
|
||||||
}}</clr-dg-column>
|
|
||||||
<clr-dg-placeholder>{{
|
|
||||||
'HELM_CHART.PLACEHOLDER' | translate
|
|
||||||
}}</clr-dg-placeholder>
|
|
||||||
<clr-dg-row
|
|
||||||
*clrDgItems="let chart of charts"
|
|
||||||
[clrDgItem]="chart">
|
|
||||||
<clr-dg-cell>
|
|
||||||
<span class="list-img">
|
|
||||||
<img
|
|
||||||
class="size-24 margin-right-12"
|
|
||||||
[src]="
|
|
||||||
chart.icon ? chart.icon : chartDefaultIcon
|
|
||||||
"
|
|
||||||
(error)="getDefaultIcon(chart)" />
|
|
||||||
</span>
|
|
||||||
<a
|
|
||||||
href="javascript:void(0)"
|
|
||||||
(click)="onChartClick(chart)"
|
|
||||||
>{{ chart.name }}</a
|
|
||||||
>
|
|
||||||
</clr-dg-cell>
|
|
||||||
<clr-dg-cell class="table-center">{{
|
|
||||||
getStatusString(chart) | translate
|
|
||||||
}}</clr-dg-cell>
|
|
||||||
<clr-dg-cell class="table-center">{{
|
|
||||||
chart.total_versions
|
|
||||||
}}</clr-dg-cell>
|
|
||||||
<clr-dg-cell class="table-center">{{
|
|
||||||
chart.created | harborDatetime
|
|
||||||
}}</clr-dg-cell>
|
|
||||||
</clr-dg-row>
|
|
||||||
<clr-dg-footer>
|
|
||||||
<clr-dg-pagination
|
|
||||||
#pagination
|
|
||||||
[clrDgPageSize]="pageSize"
|
|
||||||
[clrDgTotalItems]="totalCount">
|
|
||||||
<clr-dg-page-size [clrPageSizeOptions]="[15, 25, 50]">{{
|
|
||||||
'PAGINATION.PAGE_SIZE' | translate
|
|
||||||
}}</clr-dg-page-size>
|
|
||||||
<span *ngIf="totalCount">
|
|
||||||
{{ pagination.firstItem + 1 }} -
|
|
||||||
{{ pagination.lastItem + 1 }}
|
|
||||||
{{ 'HELM_CHART.OF' | translate }}
|
|
||||||
</span>
|
|
||||||
{{ totalCount }} {{ 'HELM_CHART.ITEMS' | translate }}
|
|
||||||
</clr-dg-pagination>
|
|
||||||
</clr-dg-footer>
|
|
||||||
</clr-datagrid>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="isCardView" class="row card-container version-position">
|
|
||||||
<div *ngFor="let item of charts" class="chart-card">
|
|
||||||
<a
|
|
||||||
let
|
|
||||||
i="index;"
|
|
||||||
class="card clickable"
|
|
||||||
(click)="onChartClick(item)">
|
|
||||||
<div class="card-header">
|
|
||||||
<div class="card-icon">
|
|
||||||
<img
|
|
||||||
class="size-60"
|
|
||||||
[src]="item.icon ? item.icon : chartDefaultIcon"
|
|
||||||
(error)="getDefaultIcon(item)" />
|
|
||||||
</div>
|
|
||||||
<div class="card-title">{{ item.name }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<div class="row flex-items-xs-between">
|
|
||||||
<div>
|
|
||||||
<span class="version-text">{{
|
|
||||||
item.total_versions
|
|
||||||
}}</span>
|
|
||||||
<label
|
|
||||||
class="card-label"
|
|
||||||
*ngIf="item.total_versions !== 1"
|
|
||||||
>{{ 'HELM_CHART.CHARTVERSIONS' | translate }}
|
|
||||||
</label>
|
|
||||||
<label
|
|
||||||
class="card-label"
|
|
||||||
*ngIf="item.total_versions === 1"
|
|
||||||
>{{ 'HELM_CHART.VERSION' | translate }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span
|
|
||||||
class="label"
|
|
||||||
[class.label-danger]="item.deprecated"
|
|
||||||
[class.label-success]="!item.deprecated"
|
|
||||||
>{{ getStatusString(item) | translate }}</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="loading" class="center-x">
|
|
||||||
<span class="vertical-helper"></span>
|
|
||||||
<span class="spinner"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<confirmation-dialog
|
|
||||||
#confirmationDialog
|
|
||||||
(confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
|
||||||
<clr-modal
|
|
||||||
[(clrModalOpen)]="isUploadModalOpen"
|
|
||||||
[clrModalStaticBackdrop]="true"
|
|
||||||
[clrModalClosable]="false">
|
|
||||||
<h3 class="modal-title">
|
|
||||||
{{ 'HELM_CHART.UPLOAD_TITLE' | translate | titlecase }}
|
|
||||||
</h3>
|
|
||||||
<div class="modal-body">
|
|
||||||
<form
|
|
||||||
#chartUploadForm="ngForm"
|
|
||||||
clrForm
|
|
||||||
enctype="multipart/form-data">
|
|
||||||
<div class="clr-form-control">
|
|
||||||
<label
|
|
||||||
class="filename-label clr-control-label clr-col-md-3">
|
|
||||||
{{ 'HELM_CHART.CHART_FILE' | translate }}</label
|
|
||||||
>
|
|
||||||
<div class="clr-input-wrapper">
|
|
||||||
<input
|
|
||||||
class="filename-input clr-input"
|
|
||||||
type="text"
|
|
||||||
placeholder="{{
|
|
||||||
this.chartFile?.name || 'BUTTON.NO_FILE'
|
|
||||||
| translate
|
|
||||||
}}"
|
|
||||||
disabled />
|
|
||||||
<label
|
|
||||||
for="chart"
|
|
||||||
class="btn btn-secondary file-browser-btn"
|
|
||||||
>{{ 'BUTTON.BROWSE' | translate }}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
class="file-input"
|
|
||||||
type="file"
|
|
||||||
id="chart"
|
|
||||||
name="chart"
|
|
||||||
ngModel
|
|
||||||
(change)="onChartFileChangeEvent($event)" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clr-form-control mb-10">
|
|
||||||
<label
|
|
||||||
class="filename-label clr-control-label clr-col-md-3">
|
|
||||||
{{ 'HELM_CHART.CHART_PROV' | translate }}
|
|
||||||
</label>
|
|
||||||
<div class="clr-input-wrapper">
|
|
||||||
<input
|
|
||||||
class="filename-input clr-input"
|
|
||||||
type="text"
|
|
||||||
placeholder="{{
|
|
||||||
this.provFile?.name || 'BUTTON.NO_FILE'
|
|
||||||
| translate
|
|
||||||
}}"
|
|
||||||
disabled />
|
|
||||||
<label
|
|
||||||
for="prov"
|
|
||||||
class="btn btn-secondary file-browser-btn"
|
|
||||||
>{{ 'BUTTON.BROWSE' | translate }}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
class="file-input"
|
|
||||||
type="file"
|
|
||||||
id="prov"
|
|
||||||
name="prov"
|
|
||||||
ngModel
|
|
||||||
(change)="onProvFileChangeEvent($event)" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button
|
|
||||||
class="btn btn-secondary"
|
|
||||||
[disabled]="isUploading"
|
|
||||||
(click)="cancelUpload()">
|
|
||||||
<span>{{ 'BUTTON.CANCEL' | translate }}</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
class="btn btn-primary"
|
|
||||||
id="upload-chart"
|
|
||||||
[disabled]="isUploading"
|
|
||||||
(click)="upload()">
|
|
||||||
<span>{{ 'HELM_CHART.UPLOAD' | translate }}</span>
|
|
||||||
<span *ngIf="isUploading" class="spinner spinner-inline">
|
|
||||||
Loading...
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</clr-modal>
|
|
||||||
</div>
|
|
|
@ -1,148 +0,0 @@
|
||||||
@import "../../../../../shared/mixin";
|
|
||||||
|
|
||||||
$size24:24px;
|
|
||||||
$size60:60px;
|
|
||||||
|
|
||||||
@mixin flex-center {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-tool {
|
|
||||||
position: relative;
|
|
||||||
margin-top: 5px;
|
|
||||||
|
|
||||||
.toolbar {
|
|
||||||
overflow: hidden;
|
|
||||||
/* stylelint-disable */
|
|
||||||
.rightPos {
|
|
||||||
@include grid-right-top-pos;
|
|
||||||
|
|
||||||
margin-top: 20px;
|
|
||||||
|
|
||||||
.filter-divider {
|
|
||||||
display: inline-block;
|
|
||||||
height: 16px;
|
|
||||||
width: 1px;
|
|
||||||
padding-top: 12px;
|
|
||||||
padding-bottom: 12px;
|
|
||||||
position: relative;
|
|
||||||
top: 9px;
|
|
||||||
margin-right: 6px;
|
|
||||||
margin-left: 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-container {
|
|
||||||
margin-top: 40px;
|
|
||||||
|
|
||||||
.chart-card {
|
|
||||||
width: 200px;
|
|
||||||
margin: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-header {
|
|
||||||
.card-icon {
|
|
||||||
@include flex-center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-title {
|
|
||||||
@include text-overflow;
|
|
||||||
|
|
||||||
text-align:center;
|
|
||||||
margin:15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-footer {
|
|
||||||
background-color:#d7d7d7;
|
|
||||||
|
|
||||||
.version-text {
|
|
||||||
font-size:1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-label {
|
|
||||||
width: 60px;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical-helper {
|
|
||||||
display: inline-block;
|
|
||||||
height: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.size-24 {
|
|
||||||
width:$size24;
|
|
||||||
height:$size24;
|
|
||||||
}
|
|
||||||
|
|
||||||
.size-60 {
|
|
||||||
height:$size60;
|
|
||||||
max-width:100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.margin-right-12 {
|
|
||||||
margin-right:12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-input {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filename-span {
|
|
||||||
@include text-overflow;
|
|
||||||
|
|
||||||
display: inline-block;
|
|
||||||
width: 50%;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
clr-modal {
|
|
||||||
.filename-label {
|
|
||||||
padding-top: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filename-input {
|
|
||||||
margin-top: 12px;
|
|
||||||
width: 68%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-browser-btn {
|
|
||||||
margin-left: 15px;
|
|
||||||
max-width: 34%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
clr-icon {
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mb-10 {
|
|
||||||
margin-bottom:10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-center {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.center-x {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
position: absolute;
|
|
||||||
top: 2.5rem;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.version-position {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
|
||||||
import { HelmChartComponent } from './helm-chart.component';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
||||||
import { ClarityModule } from '@clr/angular';
|
|
||||||
import { FormsModule } from '@angular/forms';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { HelmChartService } from '../../helm-chart-detail/helm-chart.service';
|
|
||||||
import { ErrorHandler } from '../../../../../shared/units/error-handler';
|
|
||||||
import {
|
|
||||||
SystemInfoService,
|
|
||||||
UserPermissionService,
|
|
||||||
} from '../../../../../shared/services';
|
|
||||||
import { OperationService } from '../../../../../shared/components/operation/operation.service';
|
|
||||||
|
|
||||||
describe('HelmChartComponent', () => {
|
|
||||||
let component: HelmChartComponent;
|
|
||||||
let fixture: ComponentFixture<HelmChartComponent>;
|
|
||||||
const mockErrorHandler = null;
|
|
||||||
const mockSystemInfoService = {
|
|
||||||
getSystemInfo: () => {
|
|
||||||
return of({
|
|
||||||
with_notary: false,
|
|
||||||
with_admiral: false,
|
|
||||||
admiral_endpoint: '',
|
|
||||||
auth_mode: 'oidc_auth',
|
|
||||||
registry_url: 'nightly-oidc.harbor.io',
|
|
||||||
external_url: 'https://nightly-oidc.harbor.io',
|
|
||||||
project_creation_restriction: 'everyone',
|
|
||||||
self_registration: false,
|
|
||||||
has_ca_root: false,
|
|
||||||
harbor_version: 'dev',
|
|
||||||
registry_storage_provider_name: 'filesystem',
|
|
||||||
read_only: false,
|
|
||||||
with_chartmuseum: true,
|
|
||||||
notification_enable: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const mockHelmChartService = {
|
|
||||||
getChartVersions() {
|
|
||||||
return of([
|
|
||||||
{
|
|
||||||
name: 'string',
|
|
||||||
home: 'string',
|
|
||||||
sources: [],
|
|
||||||
version: 'string',
|
|
||||||
description: 'string',
|
|
||||||
keywords: [],
|
|
||||||
maintainers: [],
|
|
||||||
engine: 'string',
|
|
||||||
icon: 'string',
|
|
||||||
appVersion: 'string',
|
|
||||||
apiVersion: 'string',
|
|
||||||
urls: [],
|
|
||||||
created: 'string',
|
|
||||||
digest: 'string',
|
|
||||||
labels: [],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
getHelmCharts() {
|
|
||||||
return of([]);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const mockUserPermissionService = {
|
|
||||||
getPermission() {
|
|
||||||
return of(true);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const mockOperationService = {
|
|
||||||
publishInfo: () => {
|
|
||||||
return of([]);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
imports: [ClarityModule, TranslateModule.forRoot(), FormsModule],
|
|
||||||
declarations: [HelmChartComponent],
|
|
||||||
providers: [
|
|
||||||
TranslateService,
|
|
||||||
{ provide: ErrorHandler, useValue: mockErrorHandler },
|
|
||||||
{ provide: SystemInfoService, useValue: mockSystemInfoService },
|
|
||||||
{ provide: HelmChartService, useValue: mockHelmChartService },
|
|
||||||
{
|
|
||||||
provide: UserPermissionService,
|
|
||||||
useValue: mockUserPermissionService,
|
|
||||||
},
|
|
||||||
{ provide: OperationService, useValue: mockOperationService },
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(HelmChartComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,392 +0,0 @@
|
||||||
import {
|
|
||||||
Component,
|
|
||||||
EventEmitter,
|
|
||||||
Input,
|
|
||||||
OnInit,
|
|
||||||
Output,
|
|
||||||
ViewChild,
|
|
||||||
} from '@angular/core';
|
|
||||||
import { NgForm } from '@angular/forms';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
import { forkJoin, Observable, throwError as observableThrowError } from 'rxjs';
|
|
||||||
import { catchError, finalize, map } from 'rxjs/operators';
|
|
||||||
import { HelmChartItem } from '../../helm-chart-detail/helm-chart.interface.service';
|
|
||||||
import { HelmChartService } from '../../helm-chart-detail/helm-chart.service';
|
|
||||||
import {
|
|
||||||
State,
|
|
||||||
SystemInfo,
|
|
||||||
SystemInfoService,
|
|
||||||
UserPermissionService,
|
|
||||||
USERSTATICPERMISSION,
|
|
||||||
} from '../../../../../shared/services';
|
|
||||||
import {
|
|
||||||
downloadFile,
|
|
||||||
getPageSizeFromLocalStorage,
|
|
||||||
PageSizeMapKeys,
|
|
||||||
setPageSizeToLocalStorage,
|
|
||||||
} from '../../../../../shared/units/utils';
|
|
||||||
import { ErrorHandler } from '../../../../../shared/units/error-handler';
|
|
||||||
import { OperationService } from '../../../../../shared/components/operation/operation.service';
|
|
||||||
import {
|
|
||||||
operateChanges,
|
|
||||||
OperateInfo,
|
|
||||||
OperationState,
|
|
||||||
} from '../../../../../shared/components/operation/operate';
|
|
||||||
import {
|
|
||||||
ConfirmationButtons,
|
|
||||||
ConfirmationState,
|
|
||||||
ConfirmationTargets,
|
|
||||||
DefaultHelmIcon,
|
|
||||||
Roles,
|
|
||||||
} from '../../../../../shared/entities/shared.const';
|
|
||||||
import { errorHandler } from '../../../../../shared/units/shared.utils';
|
|
||||||
import { ConfirmationDialogComponent } from '../../../../../shared/components/confirmation-dialog';
|
|
||||||
import { ConfirmationMessage } from '../../../../global-confirmation-dialog/confirmation-message';
|
|
||||||
import { ConfirmationAcknowledgement } from '../../../../global-confirmation-dialog/confirmation-state-message';
|
|
||||||
import { ClrDatagridStateInterface } from '@clr/angular';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hbr-helm-chart',
|
|
||||||
templateUrl: './helm-chart.component.html',
|
|
||||||
styleUrls: ['./helm-chart.component.scss'],
|
|
||||||
})
|
|
||||||
export class HelmChartComponent implements OnInit {
|
|
||||||
signedCon: { [key: string]: any | string[] } = {};
|
|
||||||
@Input() projectId: number;
|
|
||||||
@Input() projectName = 'unknown';
|
|
||||||
@Input() urlPrefix: string;
|
|
||||||
@Input() hasSignedIn: boolean;
|
|
||||||
@Input() projectRoleID = Roles.OTHER;
|
|
||||||
@Output() chartClickEvt = new EventEmitter<any>();
|
|
||||||
@Output() chartDownloadEve = new EventEmitter<string>();
|
|
||||||
@Input() chartDefaultIcon: string = DefaultHelmIcon;
|
|
||||||
|
|
||||||
lastFilteredChartName: string;
|
|
||||||
charts: HelmChartItem[] = [];
|
|
||||||
chartsCopy: HelmChartItem[] = [];
|
|
||||||
systemInfo: SystemInfo;
|
|
||||||
selectedRows: HelmChartItem[] = [];
|
|
||||||
loading = true;
|
|
||||||
|
|
||||||
// For Upload
|
|
||||||
isUploading = false;
|
|
||||||
isUploadModalOpen = false;
|
|
||||||
provFile: File;
|
|
||||||
chartFile: File;
|
|
||||||
|
|
||||||
// For View swtich
|
|
||||||
isCardView: boolean;
|
|
||||||
cardHover = false;
|
|
||||||
listHover = false;
|
|
||||||
|
|
||||||
pageSize: number = getPageSizeFromLocalStorage(
|
|
||||||
PageSizeMapKeys.HELM_CHART_COMPONENT
|
|
||||||
);
|
|
||||||
currentPage = 1;
|
|
||||||
totalCount = 0;
|
|
||||||
currentState: State;
|
|
||||||
|
|
||||||
@ViewChild('chartUploadForm') uploadForm: NgForm;
|
|
||||||
|
|
||||||
@ViewChild('confirmationDialog')
|
|
||||||
confirmationDialog: ConfirmationDialogComponent;
|
|
||||||
hasUploadHelmChartsPermission: boolean;
|
|
||||||
hasDownloadHelmChartsPermission: boolean;
|
|
||||||
hasDeleteHelmChartsPermission: boolean;
|
|
||||||
constructor(
|
|
||||||
private errorHandlerEntity: ErrorHandler,
|
|
||||||
private translateService: TranslateService,
|
|
||||||
private systemInfoService: SystemInfoService,
|
|
||||||
private helmChartService: HelmChartService,
|
|
||||||
private userPermissionService: UserPermissionService,
|
|
||||||
private operationService: OperationService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public get registryUrl(): string {
|
|
||||||
return this.systemInfo ? this.systemInfo.registry_url : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
// Get system info for tag views
|
|
||||||
this.systemInfoService.getSystemInfo().subscribe(
|
|
||||||
systemInfo => (this.systemInfo = systemInfo),
|
|
||||||
error => this.errorHandlerEntity.error(error)
|
|
||||||
);
|
|
||||||
this.lastFilteredChartName = '';
|
|
||||||
this.refresh();
|
|
||||||
this.getHelmPermissionRule(this.projectId);
|
|
||||||
}
|
|
||||||
getHelmPermissionRule(projectId: number): void {
|
|
||||||
let hasUploadHelmChartsPermission =
|
|
||||||
this.userPermissionService.getPermission(
|
|
||||||
projectId,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART.KEY,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART.VALUE.UPLOAD
|
|
||||||
);
|
|
||||||
let hasDownloadHelmChartsPermission =
|
|
||||||
this.userPermissionService.getPermission(
|
|
||||||
projectId,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART.KEY,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART.VALUE.DOWNLOAD
|
|
||||||
);
|
|
||||||
let hasDeleteHelmChartsPermission =
|
|
||||||
this.userPermissionService.getPermission(
|
|
||||||
projectId,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART.KEY,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART.VALUE.DELETE
|
|
||||||
);
|
|
||||||
forkJoin(
|
|
||||||
hasUploadHelmChartsPermission,
|
|
||||||
hasDownloadHelmChartsPermission,
|
|
||||||
hasDeleteHelmChartsPermission
|
|
||||||
).subscribe(
|
|
||||||
permissions => {
|
|
||||||
this.hasUploadHelmChartsPermission = permissions[0] as boolean;
|
|
||||||
this.hasDownloadHelmChartsPermission =
|
|
||||||
permissions[1] as boolean;
|
|
||||||
this.hasDeleteHelmChartsPermission = permissions[2] as boolean;
|
|
||||||
},
|
|
||||||
error => this.errorHandlerEntity.error(error)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
updateFilterValue(value: string) {
|
|
||||||
this.lastFilteredChartName = value;
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh() {
|
|
||||||
this.loading = true;
|
|
||||||
this.selectedRows = [];
|
|
||||||
this.helmChartService
|
|
||||||
.getHelmCharts(this.projectName)
|
|
||||||
.pipe(
|
|
||||||
finalize(() => {
|
|
||||||
this.loading = false;
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(
|
|
||||||
charts => {
|
|
||||||
this.charts = charts.filter(x =>
|
|
||||||
x.name.includes(this.lastFilteredChartName)
|
|
||||||
);
|
|
||||||
this.chartsCopy = charts.map(x => Object.assign({}, x));
|
|
||||||
this.totalCount = charts.length;
|
|
||||||
},
|
|
||||||
err => {
|
|
||||||
this.errorHandlerEntity.error(err);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
onChartClick(item: HelmChartItem) {
|
|
||||||
this.chartClickEvt.emit(item.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
resetUploadForm() {
|
|
||||||
this.chartFile = null;
|
|
||||||
this.provFile = null;
|
|
||||||
this.uploadForm.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
onChartUpload() {
|
|
||||||
this.resetUploadForm();
|
|
||||||
this.isUploadModalOpen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelUpload() {
|
|
||||||
this.resetUploadForm();
|
|
||||||
this.isUploadModalOpen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
upload() {
|
|
||||||
if (!this.chartFile && !this.provFile) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.isUploading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.isUploading = true;
|
|
||||||
this.helmChartService
|
|
||||||
.uploadChart(this.projectName, this.chartFile, this.provFile)
|
|
||||||
.pipe(
|
|
||||||
finalize(() => {
|
|
||||||
this.isUploading = false;
|
|
||||||
this.isUploadModalOpen = false;
|
|
||||||
this.refresh();
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(
|
|
||||||
() => {
|
|
||||||
this.translateService
|
|
||||||
.get('HELM_CHART.FILE_UPLOADED')
|
|
||||||
.subscribe(res => this.errorHandlerEntity.info(res));
|
|
||||||
},
|
|
||||||
err => this.errorHandlerEntity.error(err)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
onChartFileChangeEvent(event) {
|
|
||||||
if (event.target.files && event.target.files.length > 0) {
|
|
||||||
this.chartFile = event.target.files[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onProvFileChangeEvent(event) {
|
|
||||||
if (event.target.files && event.target.files.length > 0) {
|
|
||||||
this.provFile = event.target.files[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteChart(chartName: string): Observable<any> {
|
|
||||||
let operateMsg = new OperateInfo();
|
|
||||||
operateMsg.name = 'OPERATION.DELETE_CHART';
|
|
||||||
operateMsg.data.id = chartName;
|
|
||||||
operateMsg.state = OperationState.progressing;
|
|
||||||
operateMsg.data.name = chartName;
|
|
||||||
this.operationService.publishInfo(operateMsg);
|
|
||||||
|
|
||||||
return this.helmChartService
|
|
||||||
.deleteHelmChart(this.projectName, chartName)
|
|
||||||
.pipe(
|
|
||||||
map(() => operateChanges(operateMsg, OperationState.success)),
|
|
||||||
catchError(error => {
|
|
||||||
const message = errorHandler(error);
|
|
||||||
this.translateService
|
|
||||||
.get(message)
|
|
||||||
.subscribe(res =>
|
|
||||||
operateChanges(
|
|
||||||
operateMsg,
|
|
||||||
OperationState.failure,
|
|
||||||
res
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return observableThrowError(error);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteCharts(charts: HelmChartItem[]) {
|
|
||||||
if (charts && charts.length < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let chartsDelete$ = charts.map(chart => this.deleteChart(chart.name));
|
|
||||||
forkJoin(chartsDelete$)
|
|
||||||
.pipe(
|
|
||||||
finalize(() => {
|
|
||||||
this.refresh();
|
|
||||||
this.selectedRows = [];
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(
|
|
||||||
() => {},
|
|
||||||
error => {
|
|
||||||
this.errorHandlerEntity.error(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadLatestVersion(evt?: Event, item?: HelmChartItem) {
|
|
||||||
if (evt) {
|
|
||||||
evt.stopPropagation();
|
|
||||||
}
|
|
||||||
let selectedChart: HelmChartItem;
|
|
||||||
|
|
||||||
if (item) {
|
|
||||||
selectedChart = item;
|
|
||||||
} else {
|
|
||||||
// return if selected version less then 1
|
|
||||||
if (this.selectedRows.length < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
selectedChart = this.selectedRows[0];
|
|
||||||
}
|
|
||||||
if (!selectedChart) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let filename = `charts/${selectedChart.name}-${selectedChart.latest_version}.tgz`;
|
|
||||||
this.helmChartService
|
|
||||||
.downloadChart(this.projectName, filename)
|
|
||||||
.subscribe(
|
|
||||||
res => {
|
|
||||||
downloadFile(res);
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
this.errorHandlerEntity.error(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
openChartDeleteModal() {
|
|
||||||
let chartNames = this.selectedRows.map(chart => chart.name).join(',');
|
|
||||||
let message = new ConfirmationMessage(
|
|
||||||
'HELM_CHART.DELETE_CHART_VERSION_TITLE',
|
|
||||||
'HELM_CHART.DELETE_CHART_VERSION',
|
|
||||||
chartNames,
|
|
||||||
this.selectedRows,
|
|
||||||
ConfirmationTargets.HELM_CHART,
|
|
||||||
ConfirmationButtons.DELETE_CANCEL
|
|
||||||
);
|
|
||||||
this.confirmationDialog.open(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
confirmDeletion(message: ConfirmationAcknowledgement) {
|
|
||||||
if (
|
|
||||||
message &&
|
|
||||||
message.source === ConfirmationTargets.HELM_CHART &&
|
|
||||||
message.state === ConfirmationState.CONFIRMED
|
|
||||||
) {
|
|
||||||
let charts = message.data;
|
|
||||||
this.deleteCharts(charts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
showCard(cardView: boolean) {
|
|
||||||
if (this.isCardView === cardView) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.isCardView = cardView;
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseEnter(itemName: string) {
|
|
||||||
if (itemName === 'card') {
|
|
||||||
this.cardHover = true;
|
|
||||||
} else {
|
|
||||||
this.listHover = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseLeave(itemName: string) {
|
|
||||||
if (itemName === 'card') {
|
|
||||||
this.cardHover = false;
|
|
||||||
} else {
|
|
||||||
this.listHover = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isHovering(itemName: string) {
|
|
||||||
if (itemName === 'card') {
|
|
||||||
return this.cardHover;
|
|
||||||
} else {
|
|
||||||
return this.listHover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultIcon(chart: HelmChartItem) {
|
|
||||||
chart.icon = this.chartDefaultIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
getStatusString(chart: HelmChartItem) {
|
|
||||||
if (chart.deprecated) {
|
|
||||||
return 'HELM_CHART.DEPRECATED';
|
|
||||||
} else {
|
|
||||||
return 'HELM_CHART.ACTIVE';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clrLoad(state: ClrDatagridStateInterface) {
|
|
||||||
if (state?.page?.size) {
|
|
||||||
setPageSizeToLocalStorage(
|
|
||||||
PageSizeMapKeys.HELM_CHART_COMPONENT,
|
|
||||||
state.page.size
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
<hbr-helm-chart
|
|
||||||
[projectId]="projectId"
|
|
||||||
[projectName]="projectName"
|
|
||||||
[urlPrefix]="urlPrefix"
|
|
||||||
[hasSignedIn]="hasSignedIn"
|
|
||||||
[projectRoleID]="project_member_role_id"
|
|
||||||
(chartClickEvt)="onChartClick($event)">
|
|
||||||
</hbr-helm-chart>
|
|
|
@ -1,53 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
|
||||||
import { SessionService } from '../../../../shared/services/session.service';
|
|
||||||
import { ListChartsComponent } from './list-charts.component';
|
|
||||||
import { SharedTestingModule } from '../../../../shared/shared.module';
|
|
||||||
|
|
||||||
describe('ListChartsComponent', () => {
|
|
||||||
let component: ListChartsComponent;
|
|
||||||
let fixture: ComponentFixture<ListChartsComponent>;
|
|
||||||
let fakeSessionService = {
|
|
||||||
getCurrentUser: function () {
|
|
||||||
return 'admin';
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [ListChartsComponent],
|
|
||||||
imports: [SharedTestingModule],
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
providers: [
|
|
||||||
{
|
|
||||||
provide: ActivatedRoute,
|
|
||||||
useValue: {
|
|
||||||
snapshot: {
|
|
||||||
parent: {
|
|
||||||
parent: {
|
|
||||||
params: {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
data: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ provide: Router, useValue: null },
|
|
||||||
{ provide: SessionService, useValue: fakeSessionService },
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ListChartsComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,44 +0,0 @@
|
||||||
import { Project } from '../../project';
|
|
||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
|
||||||
|
|
||||||
import { SessionService } from '../../../../shared/services/session.service';
|
|
||||||
import { SessionUser } from '../../../../shared/entities/session-user';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'project-list-charts',
|
|
||||||
templateUrl: './list-charts.component.html',
|
|
||||||
styleUrls: ['./list-charts.component.scss'],
|
|
||||||
})
|
|
||||||
export class ListChartsComponent implements OnInit {
|
|
||||||
projectId: number;
|
|
||||||
|
|
||||||
projectName: string;
|
|
||||||
urlPrefix: string;
|
|
||||||
hasSignedIn: boolean;
|
|
||||||
project_member_role_id: number;
|
|
||||||
currentUser: SessionUser;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private route: ActivatedRoute,
|
|
||||||
private router: Router,
|
|
||||||
private session: SessionService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
// Get projectId from router-guard params snapshot.
|
|
||||||
this.projectId = +this.route.snapshot.parent.parent.params['id'];
|
|
||||||
// Get current user from registered resolver.
|
|
||||||
this.currentUser = this.session.getCurrentUser();
|
|
||||||
let resolverData = this.route.snapshot.parent.parent.data;
|
|
||||||
if (resolverData) {
|
|
||||||
let project = <Project>resolverData['projectResolver'];
|
|
||||||
this.projectName = project.name;
|
|
||||||
this.project_member_role_id = project.current_user_role_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onChartClick(chartName: string) {
|
|
||||||
this.router.navigateByUrl(`${this.router.url}/${chartName}/versions`);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -64,7 +64,6 @@ export class ProjectDetailComponent
|
||||||
roleName: string;
|
roleName: string;
|
||||||
projectId: number;
|
projectId: number;
|
||||||
hasProjectReadPermission: boolean;
|
hasProjectReadPermission: boolean;
|
||||||
hasHelmChartsListPermission: boolean;
|
|
||||||
hasRepositoryListPermission: boolean;
|
hasRepositoryListPermission: boolean;
|
||||||
hasMemberListPermission: boolean;
|
hasMemberListPermission: boolean;
|
||||||
hasLabelListPermission: boolean;
|
hasLabelListPermission: boolean;
|
||||||
|
@ -91,13 +90,6 @@ export class ProjectDetailComponent
|
||||||
showTabName: 'PROJECT_DETAIL.REPOSITORIES',
|
showTabName: 'PROJECT_DETAIL.REPOSITORIES',
|
||||||
permissions: () => this.hasRepositoryListPermission,
|
permissions: () => this.hasRepositoryListPermission,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
linkName: 'helm-charts',
|
|
||||||
tabLinkInOverflow: false,
|
|
||||||
showTabName: 'PROJECT_DETAIL.HELMCHART',
|
|
||||||
permissions: () =>
|
|
||||||
this.withHelmChart && this.hasHelmChartsListPermission,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
linkName: 'members',
|
linkName: 'members',
|
||||||
tabLinkInOverflow: false,
|
tabLinkInOverflow: false,
|
||||||
|
@ -109,9 +101,7 @@ export class ProjectDetailComponent
|
||||||
tabLinkInOverflow: false,
|
tabLinkInOverflow: false,
|
||||||
showTabName: 'PROJECT_DETAIL.LABELS',
|
showTabName: 'PROJECT_DETAIL.LABELS',
|
||||||
permissions: () =>
|
permissions: () =>
|
||||||
this.hasLabelListPermission &&
|
this.hasLabelListPermission && this.hasLabelCreatePermission,
|
||||||
this.hasLabelCreatePermission &&
|
|
||||||
!this.withAdmiral,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
linkName: 'scanner',
|
linkName: 'scanner',
|
||||||
|
@ -272,13 +262,6 @@ export class ProjectDetailComponent
|
||||||
USERSTATICPERMISSION.REPOSITORY.VALUE.LIST
|
USERSTATICPERMISSION.REPOSITORY.VALUE.LIST
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
permissionsList.push(
|
|
||||||
this.userPermissionService.getPermission(
|
|
||||||
projectId,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART.KEY,
|
|
||||||
USERSTATICPERMISSION.HELM_CHART.VALUE.LIST
|
|
||||||
)
|
|
||||||
);
|
|
||||||
permissionsList.push(
|
permissionsList.push(
|
||||||
this.userPermissionService.getPermission(
|
this.userPermissionService.getPermission(
|
||||||
projectId,
|
projectId,
|
||||||
|
@ -345,7 +328,6 @@ export class ProjectDetailComponent
|
||||||
this.hasMemberListPermission,
|
this.hasMemberListPermission,
|
||||||
this.hasLabelListPermission,
|
this.hasLabelListPermission,
|
||||||
this.hasRepositoryListPermission,
|
this.hasRepositoryListPermission,
|
||||||
this.hasHelmChartsListPermission,
|
|
||||||
this.hasRobotListPermission,
|
this.hasRobotListPermission,
|
||||||
this.hasLabelCreatePermission,
|
this.hasLabelCreatePermission,
|
||||||
this.hasTagRetentionPermission,
|
this.hasTagRetentionPermission,
|
||||||
|
@ -383,14 +365,6 @@ export class ProjectDetailComponent
|
||||||
return this.sessionService.getCurrentUser() != null;
|
return this.sessionService.getCurrentUser() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get withAdmiral(): boolean {
|
|
||||||
return this.appConfigService.getConfig().with_admiral;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get withHelmChart(): boolean {
|
|
||||||
return this.appConfigService.getConfig().with_chartmuseum;
|
|
||||||
}
|
|
||||||
|
|
||||||
backToProject(): void {
|
backToProject(): void {
|
||||||
if (window.sessionStorage) {
|
if (window.sessionStorage) {
|
||||||
window.sessionStorage.setItem('fromDetails', 'true');
|
window.sessionStorage.setItem('fromDetails', 'true');
|
||||||
|
|
|
@ -51,20 +51,6 @@ const routes: Routes = [
|
||||||
m => m.RepositoryModule
|
m => m.RepositoryModule
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'helm-charts',
|
|
||||||
canActivate: [MemberPermissionGuard],
|
|
||||||
data: {
|
|
||||||
permissionParam: {
|
|
||||||
resource: USERSTATICPERMISSION.HELM_CHART.KEY,
|
|
||||||
action: USERSTATICPERMISSION.HELM_CHART.VALUE.LIST,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
loadChildren: () =>
|
|
||||||
import(
|
|
||||||
'./helm-chart/helm-chart-list/helm-chart-list.module'
|
|
||||||
).then(m => m.HelmChartListModule),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'members',
|
path: 'members',
|
||||||
canActivate: [MemberPermissionGuard],
|
canActivate: [MemberPermissionGuard],
|
||||||
|
|
|
@ -23,7 +23,6 @@ export class Project {
|
||||||
update_time: Date;
|
update_time: Date;
|
||||||
current_user_role_id: number;
|
current_user_role_id: number;
|
||||||
repo_count: number;
|
repo_count: number;
|
||||||
chart_count: number;
|
|
||||||
has_project_admin_role: boolean;
|
has_project_admin_role: boolean;
|
||||||
is_member: boolean;
|
is_member: boolean;
|
||||||
role_name: string;
|
role_name: string;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { HelmChartMaintainer } from '../../../helm-chart/helm-chart-detail/helm-chart.interface.service';
|
|
||||||
|
|
||||||
export class ArtifactBuildHistory {
|
export class ArtifactBuildHistory {
|
||||||
created: Date;
|
created: Date;
|
||||||
created_by: string;
|
created_by: string;
|
||||||
|
@ -9,22 +7,6 @@ export interface ArtifactDependency {
|
||||||
version: string;
|
version: string;
|
||||||
repository: string;
|
repository: string;
|
||||||
}
|
}
|
||||||
export interface ArtifactSummary {
|
|
||||||
name: string;
|
|
||||||
home: string;
|
|
||||||
sources: string[];
|
|
||||||
version: string;
|
|
||||||
description: string;
|
|
||||||
keywords: string[];
|
|
||||||
maintainers: HelmChartMaintainer[];
|
|
||||||
engine: string;
|
|
||||||
icon: string;
|
|
||||||
appVersion: string;
|
|
||||||
urls: string[];
|
|
||||||
created?: string;
|
|
||||||
digest: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Addition {
|
export interface Addition {
|
||||||
type: string;
|
type: string;
|
||||||
data?: object;
|
data?: object;
|
||||||
|
|
|
@ -170,61 +170,6 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
class="card clickable"
|
|
||||||
*ngIf="hasReadChartPermission && withHelmChart">
|
|
||||||
<div class="card-header">
|
|
||||||
<div>{{ 'PROJECT_DETAIL.HELMCHART' | translate }}</div>
|
|
||||||
<div class="clr-row number">
|
|
||||||
{{
|
|
||||||
summaryInformation?.chart_count
|
|
||||||
? summaryInformation?.chart_count
|
|
||||||
: 0
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
<div class="clr-row">
|
|
||||||
<div class="clr-col-4 column">
|
|
||||||
{{ 'HELM_CHART.NAME' | translate }}
|
|
||||||
</div>
|
|
||||||
<div class="clr-col-2 column">
|
|
||||||
{{ 'HELM_CHART.STATUS' | translate }}
|
|
||||||
</div>
|
|
||||||
<div class="clr-col-2 column">
|
|
||||||
{{ 'HELM_CHART.CHARTVERSIONS' | translate }}
|
|
||||||
</div>
|
|
||||||
<div class="clr-col-4 column">
|
|
||||||
{{ 'HELM_CHART.CREATED' | translate }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-block">
|
|
||||||
<div class="clr-row" *ngFor="let chart of charts">
|
|
||||||
<div class="clr-col-4 ellipsis chart-name">
|
|
||||||
<img
|
|
||||||
class="size-24 mr-5px"
|
|
||||||
[src]="chart.icon ? chart.icon : chartDefaultIcon"
|
|
||||||
(error)="getDefaultIcon(chart)" />
|
|
||||||
<a
|
|
||||||
href="javascript:void(0)"
|
|
||||||
(click)="onChartClick(chart.name)"
|
|
||||||
>{{ chart.name }}</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="clr-col-2">
|
|
||||||
{{ getStatusString(chart) | translate }}
|
|
||||||
</div>
|
|
||||||
<div class="clr-col-2">{{ chart.total_versions }}</div>
|
|
||||||
<div class="clr-col-4 ellipsis">
|
|
||||||
{{ chart.created | harborDatetime: 'short' }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<button class="btn btn-link" (click)="goToCharts()">
|
|
||||||
{{ 'SUMMARY.SEE_ALL' | translate }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card clickable" *ngIf="showProjectMemberInfo">
|
<div class="card clickable" *ngIf="showProjectMemberInfo">
|
||||||
<div class="card-header no-underline">
|
<div class="card-header no-underline">
|
||||||
<div>{{ 'PROJECT_DETAIL.USERS' | translate }}</div>
|
<div>{{ 'PROJECT_DETAIL.USERS' | translate }}</div>
|
||||||
|
|
|
@ -140,7 +140,6 @@ describe('SummaryComponent', () => {
|
||||||
it('should show two cards', async () => {
|
it('should show two cards', async () => {
|
||||||
component.summaryInformation = mockedSummaryInformation;
|
component.summaryInformation = mockedSummaryInformation;
|
||||||
component.isCardView = true;
|
component.isCardView = true;
|
||||||
component.hasReadChartPermission = true;
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
const cards = fixture.nativeElement.querySelectorAll('.card');
|
const cards = fixture.nativeElement.querySelectorAll('.card');
|
||||||
|
|
|
@ -9,7 +9,6 @@ import {
|
||||||
} from '../../../shared/services';
|
} from '../../../shared/services';
|
||||||
import { ErrorHandler } from '../../../shared/units/error-handler';
|
import { ErrorHandler } from '../../../shared/units/error-handler';
|
||||||
import {
|
import {
|
||||||
DefaultHelmIcon,
|
|
||||||
FALSE_STR,
|
FALSE_STR,
|
||||||
PROJECT_SUMMARY_CARD_VIEW_LOCALSTORAGE_KEY,
|
PROJECT_SUMMARY_CARD_VIEW_LOCALSTORAGE_KEY,
|
||||||
TRUE_STR,
|
TRUE_STR,
|
||||||
|
@ -17,8 +16,6 @@ import {
|
||||||
import { RepositoryService } from '../../../../../ng-swagger-gen/services/repository.service';
|
import { RepositoryService } from '../../../../../ng-swagger-gen/services/repository.service';
|
||||||
import { Project } from '../../../../../ng-swagger-gen/models/project';
|
import { Project } from '../../../../../ng-swagger-gen/models/project';
|
||||||
import { Repository } from '../../../../../ng-swagger-gen/models/repository';
|
import { Repository } from '../../../../../ng-swagger-gen/models/repository';
|
||||||
import { HelmChartItem } from '../helm-chart/helm-chart-detail/helm-chart.interface.service';
|
|
||||||
import { HelmChartService } from '../helm-chart/helm-chart-detail/helm-chart.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'summary',
|
selector: 'summary',
|
||||||
|
@ -28,7 +25,6 @@ import { HelmChartService } from '../helm-chart/helm-chart-detail/helm-chart.ser
|
||||||
export class SummaryComponent implements OnInit {
|
export class SummaryComponent implements OnInit {
|
||||||
showProjectMemberInfo: boolean = false;
|
showProjectMemberInfo: boolean = false;
|
||||||
hasReadRepoPermission: boolean = false;
|
hasReadRepoPermission: boolean = false;
|
||||||
hasReadChartPermission: boolean = false;
|
|
||||||
projectId: number;
|
projectId: number;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
summaryInformation: any;
|
summaryInformation: any;
|
||||||
|
@ -37,8 +33,6 @@ export class SummaryComponent implements OnInit {
|
||||||
cardHover: boolean = false;
|
cardHover: boolean = false;
|
||||||
listHover: boolean = false;
|
listHover: boolean = false;
|
||||||
repos: Repository[] = [];
|
repos: Repository[] = [];
|
||||||
charts: HelmChartItem[] = [];
|
|
||||||
chartDefaultIcon: string = DefaultHelmIcon;
|
|
||||||
constructor(
|
constructor(
|
||||||
private projectService: ProjectService,
|
private projectService: ProjectService,
|
||||||
private userPermissionService: UserPermissionService,
|
private userPermissionService: UserPermissionService,
|
||||||
|
@ -46,8 +40,7 @@ export class SummaryComponent implements OnInit {
|
||||||
private appConfigService: AppConfigService,
|
private appConfigService: AppConfigService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private repoService: RepositoryService,
|
private repoService: RepositoryService,
|
||||||
private router: Router,
|
private router: Router
|
||||||
private helmChartService: HelmChartService
|
|
||||||
) {
|
) {
|
||||||
if (localStorage) {
|
if (localStorage) {
|
||||||
if (
|
if (
|
||||||
|
@ -83,17 +76,12 @@ export class SummaryComponent implements OnInit {
|
||||||
resource: USERSTATICPERMISSION.REPOSITORY.KEY,
|
resource: USERSTATICPERMISSION.REPOSITORY.KEY,
|
||||||
action: USERSTATICPERMISSION.REPOSITORY.VALUE.LIST,
|
action: USERSTATICPERMISSION.REPOSITORY.VALUE.LIST,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
resource: USERSTATICPERMISSION.HELM_CHART.KEY,
|
|
||||||
action: USERSTATICPERMISSION.HELM_CHART.VALUE.LIST,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
this.userPermissionService
|
this.userPermissionService
|
||||||
.hasProjectPermissions(this.projectId, permissions)
|
.hasProjectPermissions(this.projectId, permissions)
|
||||||
.subscribe((results: Array<boolean>) => {
|
.subscribe((results: Array<boolean>) => {
|
||||||
this.showProjectMemberInfo = results[0];
|
this.showProjectMemberInfo = results[0];
|
||||||
this.hasReadRepoPermission = results[1];
|
this.hasReadRepoPermission = results[1];
|
||||||
this.hasReadChartPermission = results[2];
|
|
||||||
});
|
});
|
||||||
this.projectService.getProjectSummary(this.projectId).subscribe(
|
this.projectService.getProjectSummary(this.projectId).subscribe(
|
||||||
res => {
|
res => {
|
||||||
|
@ -107,10 +95,6 @@ export class SummaryComponent implements OnInit {
|
||||||
this.getDataForCardView();
|
this.getDataForCardView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public get withHelmChart(): boolean {
|
|
||||||
return this.appConfigService.getConfig().with_chartmuseum;
|
|
||||||
}
|
|
||||||
|
|
||||||
showCard(cardView: boolean) {
|
showCard(cardView: boolean) {
|
||||||
if (this.isCardView === cardView) {
|
if (this.isCardView === cardView) {
|
||||||
return;
|
return;
|
||||||
|
@ -159,7 +143,6 @@ export class SummaryComponent implements OnInit {
|
||||||
}
|
}
|
||||||
getDataForCardView() {
|
getDataForCardView() {
|
||||||
this.getTop4Repos();
|
this.getTop4Repos();
|
||||||
this.getTop4Charts();
|
|
||||||
}
|
}
|
||||||
getTop4Repos() {
|
getTop4Repos() {
|
||||||
if (this.hasReadRepoPermission) {
|
if (this.hasReadRepoPermission) {
|
||||||
|
@ -174,17 +157,6 @@ export class SummaryComponent implements OnInit {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getTop4Charts() {
|
|
||||||
if (this.hasReadChartPermission) {
|
|
||||||
this.helmChartService
|
|
||||||
.getHelmCharts(this.projectName)
|
|
||||||
.subscribe(res => {
|
|
||||||
if (res && res.length) {
|
|
||||||
this.charts = res.slice(0, 4);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goIntoRepo(repoEvt: Repository): void {
|
goIntoRepo(repoEvt: Repository): void {
|
||||||
const linkUrl = [
|
const linkUrl = [
|
||||||
'harbor',
|
'harbor',
|
||||||
|
@ -199,31 +171,6 @@ export class SummaryComponent implements OnInit {
|
||||||
const linkUrl = ['harbor', 'projects', this.projectId, 'repositories'];
|
const linkUrl = ['harbor', 'projects', this.projectId, 'repositories'];
|
||||||
this.router.navigate(linkUrl);
|
this.router.navigate(linkUrl);
|
||||||
}
|
}
|
||||||
getDefaultIcon(chart: HelmChartItem) {
|
|
||||||
chart.icon = this.chartDefaultIcon;
|
|
||||||
}
|
|
||||||
getStatusString(chart: HelmChartItem) {
|
|
||||||
if (chart.deprecated) {
|
|
||||||
return 'HELM_CHART.DEPRECATED';
|
|
||||||
} else {
|
|
||||||
return 'HELM_CHART.ACTIVE';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onChartClick(chartName: string) {
|
|
||||||
const linkUrl = [
|
|
||||||
'harbor',
|
|
||||||
'projects',
|
|
||||||
this.projectId,
|
|
||||||
'helm-charts',
|
|
||||||
chartName,
|
|
||||||
'versions',
|
|
||||||
];
|
|
||||||
this.router.navigate(linkUrl);
|
|
||||||
}
|
|
||||||
goToCharts() {
|
|
||||||
const linkUrl = ['harbor', 'projects', this.projectId, 'helm-charts'];
|
|
||||||
this.router.navigate(linkUrl);
|
|
||||||
}
|
|
||||||
goToMembers() {
|
goToMembers() {
|
||||||
const linkUrl = ['harbor', 'projects', this.projectId, 'members'];
|
const linkUrl = ['harbor', 'projects', this.projectId, 'members'];
|
||||||
this.router.navigate(linkUrl);
|
this.router.navigate(linkUrl);
|
||||||
|
|
|
@ -22,7 +22,6 @@ export enum RouteConfigId {
|
||||||
const ShouldNotReuseRouteRegExps: RegExp[] = [
|
const ShouldNotReuseRouteRegExps: RegExp[] = [
|
||||||
/\/harbor\/projects\/(\d+)\/repositories$/,
|
/\/harbor\/projects\/(\d+)\/repositories$/,
|
||||||
/\/harbor\/projects\/(\d+)\/repositories\/(\S+)\/artifacts-tab$/,
|
/\/harbor\/projects\/(\d+)\/repositories\/(\S+)\/artifacts-tab$/,
|
||||||
/\/harbor\/projects\/(\d+)\/helm-charts\/(\S+)\/versions\/(\S+)/,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
function testRoute(url: string) {
|
function testRoute(url: string) {
|
||||||
|
|
|
@ -47,7 +47,6 @@ describe('AppConfigService', () => {
|
||||||
expect(req.request.method).toBe('GET');
|
expect(req.request.method).toBe('GET');
|
||||||
req.flush(systeminfo);
|
req.flush(systeminfo);
|
||||||
expect(service.getConfig()).toEqual(systeminfo);
|
expect(service.getConfig()).toEqual(systeminfo);
|
||||||
expect(service.isIntegrationMode()).toBeFalsy();
|
|
||||||
expect(service.isLdapMode()).toBeFalsy();
|
expect(service.isLdapMode()).toBeFalsy();
|
||||||
expect(service.isHttpAuthMode()).toBeFalsy();
|
expect(service.isHttpAuthMode()).toBeFalsy();
|
||||||
expect(service.isOidcMode()).toBeFalsy();
|
expect(service.isOidcMode()).toBeFalsy();
|
||||||
|
|
|
@ -62,14 +62,6 @@ export class AppConfigService {
|
||||||
return this.configurations;
|
return this.configurations;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isIntegrationMode(): boolean {
|
|
||||||
return (
|
|
||||||
this.configurations &&
|
|
||||||
this.configurations.with_admiral &&
|
|
||||||
this.configurations.admiral_endpoint.trim() !== ''
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public isLdapMode(): boolean {
|
public isLdapMode(): boolean {
|
||||||
return (
|
return (
|
||||||
this.configurations &&
|
this.configurations &&
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { ClairDBStatus } from '../shared/services';
|
||||||
|
|
||||||
export class AppConfig {
|
export class AppConfig {
|
||||||
with_notary: boolean;
|
with_notary: boolean;
|
||||||
with_admiral: boolean;
|
|
||||||
with_trivy: boolean;
|
with_trivy: boolean;
|
||||||
admiral_endpoint: string;
|
admiral_endpoint: string;
|
||||||
auth_mode: string;
|
auth_mode: string;
|
||||||
|
@ -29,13 +28,11 @@ export class AppConfig {
|
||||||
next_scan_all: number;
|
next_scan_all: number;
|
||||||
registry_storage_provider_name: string;
|
registry_storage_provider_name: string;
|
||||||
read_only: boolean;
|
read_only: boolean;
|
||||||
with_chartmuseum: boolean;
|
|
||||||
show_popular_repo: boolean;
|
show_popular_repo: boolean;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// Set default value
|
// Set default value
|
||||||
this.with_notary = false;
|
this.with_notary = false;
|
||||||
this.with_admiral = false;
|
|
||||||
this.with_trivy = false;
|
this.with_trivy = false;
|
||||||
this.admiral_endpoint = '';
|
this.admiral_endpoint = '';
|
||||||
this.auth_mode = 'db_auth';
|
this.auth_mode = 'db_auth';
|
||||||
|
@ -51,7 +48,6 @@ export class AppConfig {
|
||||||
this.next_scan_all = 0;
|
this.next_scan_all = 0;
|
||||||
this.registry_storage_provider_name = '';
|
this.registry_storage_provider_name = '';
|
||||||
this.read_only = false;
|
this.read_only = false;
|
||||||
this.with_chartmuseum = false;
|
|
||||||
this.show_popular_repo = false;
|
this.show_popular_repo = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,10 +84,6 @@ export class GlobalSearchComponent implements OnInit, OnDestroy {
|
||||||
this.closeSub = this.searchTrigger.searchClearChan$.subscribe(clear => {
|
this.closeSub = this.searchTrigger.searchClearChan$.subscribe(clear => {
|
||||||
this.searchTerm = '';
|
this.searchTerm = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.appConfigService.isIntegrationMode()) {
|
|
||||||
this.placeholderText = 'GLOBAL_SEARCH.PLACEHOLDER_VIC';
|
|
||||||
}
|
|
||||||
// init _searchTerm from queryParams
|
// init _searchTerm from queryParams
|
||||||
this._searchTerm = this.activatedRoute.snapshot.queryParams[SEARCH_KEY];
|
this._searchTerm = this.activatedRoute.snapshot.queryParams[SEARCH_KEY];
|
||||||
if (this._searchTerm) {
|
if (this._searchTerm) {
|
||||||
|
|
|
@ -20,10 +20,5 @@
|
||||||
<list-repository-ro
|
<list-repository-ro
|
||||||
[repositories]="searchResults.repository"></list-repository-ro>
|
[repositories]="searchResults.repository"></list-repository-ro>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="withHelmChart" id="chart-results">
|
|
||||||
<h2>{{ 'HELM_CHART.HELMCHARTS' | translate }}</h2>
|
|
||||||
<list-chart-version-ro
|
|
||||||
[charts]="searchResults.chart"></list-chart-version-ro>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -50,8 +50,7 @@ export class SearchResultComponent implements OnInit, OnDestroy {
|
||||||
constructor(
|
constructor(
|
||||||
private search: GlobalSearchService,
|
private search: GlobalSearchService,
|
||||||
private msgHandler: MessageHandlerService,
|
private msgHandler: MessageHandlerService,
|
||||||
private searchTrigger: SearchTriggerService,
|
private searchTrigger: SearchTriggerService
|
||||||
private appConfigService: AppConfigService
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
@ -61,9 +60,6 @@ export class SearchResultComponent implements OnInit, OnDestroy {
|
||||||
if (term === '') {
|
if (term === '') {
|
||||||
this.searchResults.project = [];
|
this.searchResults.project = [];
|
||||||
this.searchResults.repository = [];
|
this.searchResults.repository = [];
|
||||||
if (this.withHelmChart) {
|
|
||||||
this.searchResults.chart = [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return !!(term && term.trim());
|
return !!(term && term.trim());
|
||||||
}),
|
}),
|
||||||
|
@ -116,11 +112,6 @@ export class SearchResultComponent implements OnInit, OnDestroy {
|
||||||
src.repository.forEach(repo =>
|
src.repository.forEach(repo =>
|
||||||
res.repository.push(Object.assign({}, repo))
|
res.repository.push(Object.assign({}, repo))
|
||||||
);
|
);
|
||||||
if (this.withHelmChart) {
|
|
||||||
src.chart.forEach(chart =>
|
|
||||||
res.chart.push(JSON.parse(JSON.stringify(chart)))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,9 +148,6 @@ export class SearchResultComponent implements OnInit, OnDestroy {
|
||||||
if (!term || term.trim() === '') {
|
if (!term || term.trim() === '') {
|
||||||
this.searchResults.project = [];
|
this.searchResults.project = [];
|
||||||
this.searchResults.repository = [];
|
this.searchResults.repository = [];
|
||||||
if (this.withHelmChart) {
|
|
||||||
this.searchResults.chart = [];
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Do nothing if search is ongoing
|
// Do nothing if search is ongoing
|
||||||
|
@ -188,7 +176,4 @@ export class SearchResultComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
get withHelmChart(): boolean {
|
|
||||||
return this.appConfigService.getConfig().with_chartmuseum;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,17 +12,14 @@
|
||||||
// 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 { Project } from '../../../base/project/project';
|
import { Project } from '../../../base/project/project';
|
||||||
import { HelmChartSearchResultItem } from '../../../base/project/helm-chart/helm-chart-detail/helm-chart.interface.service';
|
|
||||||
import { Repository } from '../../../../../ng-swagger-gen/models/repository';
|
import { Repository } from '../../../../../ng-swagger-gen/models/repository';
|
||||||
|
|
||||||
export class SearchResults {
|
export class SearchResults {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.project = [];
|
this.project = [];
|
||||||
this.repository = [];
|
this.repository = [];
|
||||||
this.chart = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
project: Project[];
|
project: Project[];
|
||||||
repository: Repository[];
|
repository: Repository[];
|
||||||
chart: HelmChartSearchResultItem[];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
<clr-datagrid>
|
|
||||||
<clr-dg-column>{{ 'HELM_CHART.NAME' | translate }}</clr-dg-column>
|
|
||||||
<clr-dg-column>{{ 'HELM_CHART.VERSION' | translate }}</clr-dg-column>
|
|
||||||
<clr-dg-column>{{ 'HELM_CHART.STATUS' | translate }}</clr-dg-column>
|
|
||||||
<clr-dg-column>{{ 'HELM_CHART.MAINTAINERS' | translate }}</clr-dg-column>
|
|
||||||
<clr-dg-column>{{ 'HELM_CHART.CREATED' | translate }}</clr-dg-column>
|
|
||||||
<clr-dg-placeholder>{{
|
|
||||||
'HELM_CHART.NO_VERSION_PLACEHOLDER' | translate
|
|
||||||
}}</clr-dg-placeholder>
|
|
||||||
<clr-dg-row *clrDgItems="let chart of charts" [clrDgItem]="chart">
|
|
||||||
<clr-dg-cell>
|
|
||||||
<a
|
|
||||||
href="javascript:void(0)"
|
|
||||||
(click)="gotoChartVersion(chart.Chart)"
|
|
||||||
>{{ chart.Name }}</a
|
|
||||||
>
|
|
||||||
</clr-dg-cell>
|
|
||||||
<clr-dg-cell>{{ chart.Chart.version }}</clr-dg-cell>
|
|
||||||
<clr-dg-cell>{{
|
|
||||||
getStatusString(chart.Chart) | translate
|
|
||||||
}}</clr-dg-cell>
|
|
||||||
<clr-dg-cell>{{
|
|
||||||
getMaintainerString(chart.Chart.maintainers)
|
|
||||||
| translate: getMaintainerTranslateInfo(chart.Chart.maintainers)
|
|
||||||
}}</clr-dg-cell>
|
|
||||||
<clr-dg-cell>{{ chart.Chart.created | harborDatetime }}</clr-dg-cell>
|
|
||||||
</clr-dg-row>
|
|
||||||
<clr-dg-footer>
|
|
||||||
<clr-dg-pagination
|
|
||||||
#pagination
|
|
||||||
[clrDgPageSize]="5"
|
|
||||||
[clrDgTotalItems]="charts?.length">
|
|
||||||
<span *ngIf="charts?.length">
|
|
||||||
{{ pagination.firstItem + 1 }} - {{ pagination.lastItem + 1 }}
|
|
||||||
{{ 'HELM_CHART.OF' | translate }}
|
|
||||||
</span>
|
|
||||||
{{ charts?.length }} {{ 'HELM_CHART.ITEMS' | translate }}
|
|
||||||
</clr-dg-pagination>
|
|
||||||
</clr-dg-footer>
|
|
||||||
</clr-datagrid>
|
|
|
@ -1,46 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { ListChartVersionRoComponent } from './list-chart-version-ro.component';
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { SearchTriggerService } from '../global-search/search-trigger.service';
|
|
||||||
import { ProjectService } from '../../services';
|
|
||||||
import { SharedTestingModule } from '../../shared.module';
|
|
||||||
|
|
||||||
describe('ListChartVersionRoComponent', () => {
|
|
||||||
let component: ListChartVersionRoComponent;
|
|
||||||
let fixture: ComponentFixture<ListChartVersionRoComponent>;
|
|
||||||
const mockSearchTriggerService = {
|
|
||||||
closeSearch: () => {},
|
|
||||||
};
|
|
||||||
const mockProjectService = {
|
|
||||||
listProjects: () => {
|
|
||||||
return of({
|
|
||||||
body: [],
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
imports: [SharedTestingModule],
|
|
||||||
declarations: [ListChartVersionRoComponent],
|
|
||||||
providers: [
|
|
||||||
{ provide: ProjectService, useValue: mockProjectService },
|
|
||||||
{
|
|
||||||
provide: SearchTriggerService,
|
|
||||||
useValue: mockSearchTriggerService,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ListChartVersionRoComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,75 +0,0 @@
|
||||||
import { Router } from '@angular/router';
|
|
||||||
import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
|
|
||||||
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 { ProjectService } from '../../services';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'list-chart-version-ro',
|
|
||||||
templateUrl: './list-chart-version-ro.component.html',
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
})
|
|
||||||
export class ListChartVersionRoComponent {
|
|
||||||
@Input() charts: HelmChartSearchResultItem[];
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private searchTrigger: SearchTriggerService,
|
|
||||||
private projectService: ProjectService,
|
|
||||||
private router: Router
|
|
||||||
) {}
|
|
||||||
|
|
||||||
getStatusString(chart: HelmChartVersion) {
|
|
||||||
if (chart.deprecated) {
|
|
||||||
return 'HELM_CHART.DEPRECATED';
|
|
||||||
} else {
|
|
||||||
return 'HELM_CHART.ACTIVE';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getMaintainerString(maintainers: HelmChartMaintainer[]) {
|
|
||||||
if (!maintainers || maintainers.length < 1) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
let maintainer_string = maintainers[0].name;
|
|
||||||
if (maintainers.length > 1) {
|
|
||||||
maintainer_string = 'HELM_CHART.OTHER_MAINTAINERS';
|
|
||||||
}
|
|
||||||
return maintainer_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
getMaintainerTranslateInfo(maintainers: HelmChartMaintainer[]) {
|
|
||||||
if (!maintainers || maintainers.length < 1) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
let name = maintainers[0].name;
|
|
||||||
let number = maintainers.length;
|
|
||||||
return { name: name, number: number };
|
|
||||||
}
|
|
||||||
|
|
||||||
gotoChartVersion(chartVersion: HelmChartVersion) {
|
|
||||||
this.searchTrigger.closeSearch(true);
|
|
||||||
let [projectName, chartName] = chartVersion.name.split('/');
|
|
||||||
this.projectService.listProjects(projectName).subscribe(res => {
|
|
||||||
let projects = res.body || [];
|
|
||||||
if (projects || projects.length >= 1) {
|
|
||||||
let linkUrl = [
|
|
||||||
'harbor',
|
|
||||||
'projects',
|
|
||||||
projects[0].project_id,
|
|
||||||
'helm-charts',
|
|
||||||
chartName,
|
|
||||||
'versions',
|
|
||||||
chartVersion.version,
|
|
||||||
];
|
|
||||||
this.router.navigate(linkUrl);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -15,24 +15,10 @@
|
||||||
}}</span>
|
}}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-nav">
|
|
||||||
<a href="{{ admiralLink }}" class="nav-link" *ngIf="isIntegrationMode"
|
|
||||||
><span class="nav-text">{{ 'APP_TITLE.MGMT' | translate }}</span></a
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="javascript:void(0)"
|
|
||||||
(click)="registryAction()"
|
|
||||||
routerLink="/harbor"
|
|
||||||
class="active nav-link"
|
|
||||||
*ngIf="isIntegrationMode"
|
|
||||||
><span class="nav-text">{{ 'APP_TITLE.REG' | translate }}</span></a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<global-search></global-search>
|
<global-search></global-search>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<clr-dropdown
|
<clr-dropdown class="dropdown-lang dropdown bottom-left">
|
||||||
class="dropdown-lang dropdown bottom-left"
|
|
||||||
*ngIf="!isIntegrationMode">
|
|
||||||
<button class="nav-icon nav-icon-width" clrDropdownToggle>
|
<button class="nav-icon nav-icon-width" clrDropdownToggle>
|
||||||
<clr-icon shape="world" class="icon-left"></clr-icon>
|
<clr-icon shape="world" class="icon-left"></clr-icon>
|
||||||
<span class="currentLocale">{{ currentLang }}</span>
|
<span class="currentLocale">{{ currentLang }}</span>
|
||||||
|
@ -49,9 +35,7 @@
|
||||||
>
|
>
|
||||||
</clr-dropdown-menu>
|
</clr-dropdown-menu>
|
||||||
</clr-dropdown>
|
</clr-dropdown>
|
||||||
<clr-dropdown
|
<clr-dropdown class="dropdown-locale dropdown bottom-left">
|
||||||
class="dropdown-locale dropdown bottom-left"
|
|
||||||
*ngIf="!isIntegrationMode">
|
|
||||||
<button class="nav-icon nav-icon-width" clrDropdownToggle>
|
<button class="nav-icon nav-icon-width" clrDropdownToggle>
|
||||||
<clr-icon shape="date" class="icon-left"></clr-icon>
|
<clr-icon shape="date" class="icon-left"></clr-icon>
|
||||||
<span class="currentLocale">{{
|
<span class="currentLocale">{{
|
||||||
|
|
|
@ -9,9 +9,6 @@ import { MessageHandlerService } from '../../services/message-handler.service';
|
||||||
import { SearchTriggerService } from '../global-search/search-trigger.service';
|
import { SearchTriggerService } from '../global-search/search-trigger.service';
|
||||||
import { SkinableConfig } from '../../../services/skinable-config.service';
|
import { SkinableConfig } from '../../../services/skinable-config.service';
|
||||||
import { SharedTestingModule } from '../../shared.module';
|
import { SharedTestingModule } from '../../shared.module';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
import { DeFaultLang } from '../../entities/shared.const';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
|
|
||||||
describe('NavigatorComponent', () => {
|
describe('NavigatorComponent', () => {
|
||||||
let component: TestComponentWrapperComponent;
|
let component: TestComponentWrapperComponent;
|
||||||
|
|
|
@ -84,10 +84,6 @@ export class NavigatorComponent implements OnInit {
|
||||||
this.translateClarityComponents();
|
this.translateClarityComponents();
|
||||||
}
|
}
|
||||||
this.selectedDatetimeRendering = getDatetimeRendering();
|
this.selectedDatetimeRendering = getDatetimeRendering();
|
||||||
if (this.appConfigService.isIntegrationMode()) {
|
|
||||||
this.appTitle = 'APP_TITLE.VIC';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.appConfigService.getConfig().read_only) {
|
if (this.appConfigService.getConfig().read_only) {
|
||||||
this.msgHandler.handleReadOnly();
|
this.msgHandler.handleReadOnly();
|
||||||
}
|
}
|
||||||
|
@ -126,7 +122,10 @@ export class NavigatorComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public get currentLang(): string {
|
public get currentLang(): string {
|
||||||
return LANGUAGES[this.selectedLang][0] as string;
|
if (this.selectedLang) {
|
||||||
|
return LANGUAGES[this.selectedLang][0] as string;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get currentDatetimeRendering(): string {
|
public get currentDatetimeRendering(): string {
|
||||||
|
@ -136,11 +135,6 @@ export class NavigatorComponent implements OnInit {
|
||||||
public get admiralLink(): string {
|
public get admiralLink(): string {
|
||||||
return this.appConfigService.getAdmiralEndpoint(window.location.href);
|
return this.appConfigService.getAdmiralEndpoint(window.location.href);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get isIntegrationMode(): boolean {
|
|
||||||
return this.appConfigService.isIntegrationMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public get canDownloadCert(): boolean {
|
public get canDownloadCert(): boolean {
|
||||||
return (
|
return (
|
||||||
this.session.getCurrentUser() &&
|
this.session.getCurrentUser() &&
|
||||||
|
|
|
@ -48,8 +48,6 @@ export const enum ConfirmationTargets {
|
||||||
CONFIG,
|
CONFIG,
|
||||||
CONFIG_ROUTE,
|
CONFIG_ROUTE,
|
||||||
CONFIG_TAB,
|
CONFIG_TAB,
|
||||||
HELM_CHART,
|
|
||||||
HELM_CHART_VERSION,
|
|
||||||
STOP_EXECUTIONS,
|
STOP_EXECUTIONS,
|
||||||
SCANNER,
|
SCANNER,
|
||||||
REPLICATION,
|
REPLICATION,
|
||||||
|
|
|
@ -38,26 +38,11 @@ export class ModeGuard implements CanActivate, CanActivateChild {
|
||||||
): Observable<boolean> | boolean {
|
): Observable<boolean> | boolean {
|
||||||
// Show the right sign-in page for different modes
|
// Show the right sign-in page for different modes
|
||||||
return new Observable(observer => {
|
return new Observable(observer => {
|
||||||
if (this.appConfigService.isIntegrationMode()) {
|
if (state.url.startsWith(CommonRoutes.EMBEDDED_SIGN_IN)) {
|
||||||
if (state.url.startsWith(CommonRoutes.SIGN_IN)) {
|
this.router.navigate([CommonRoutes.SIGN_IN], route.queryParams);
|
||||||
this.router.navigate(
|
observer.next(false);
|
||||||
[CommonRoutes.EMBEDDED_SIGN_IN],
|
|
||||||
route.queryParams
|
|
||||||
);
|
|
||||||
observer.next(false);
|
|
||||||
} else {
|
|
||||||
observer.next(true);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (state.url.startsWith(CommonRoutes.EMBEDDED_SIGN_IN)) {
|
observer.next(true);
|
||||||
this.router.navigate(
|
|
||||||
[CommonRoutes.SIGN_IN],
|
|
||||||
route.queryParams
|
|
||||||
);
|
|
||||||
observer.next(false);
|
|
||||||
} else {
|
|
||||||
observer.next(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,31 +112,6 @@ export const USERSTATICPERMISSION = {
|
||||||
DELETE: 'delete',
|
DELETE: 'delete',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
HELM_CHART: {
|
|
||||||
KEY: 'helm-chart',
|
|
||||||
VALUE: {
|
|
||||||
UPLOAD: 'create',
|
|
||||||
DOWNLOAD: 'read',
|
|
||||||
DELETE: 'delete',
|
|
||||||
LIST: 'list',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
HELM_CHART_VERSION: {
|
|
||||||
KEY: 'helm-chart-version',
|
|
||||||
VALUE: {
|
|
||||||
DELETE: 'delete',
|
|
||||||
LIST: 'list',
|
|
||||||
CREATE: 'create',
|
|
||||||
READ: 'read',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
HELM_CHART_VERSION_LABEL: {
|
|
||||||
KEY: 'helm-chart-version-label',
|
|
||||||
VALUE: {
|
|
||||||
CREATE: 'create',
|
|
||||||
DELETE: 'delete',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ROBOT: {
|
ROBOT: {
|
||||||
KEY: 'robot',
|
KEY: 'robot',
|
||||||
VALUE: {
|
VALUE: {
|
||||||
|
|
|
@ -62,17 +62,12 @@ import { LabelComponent } from './components/label/label.component';
|
||||||
import { LabelSignPostComponent } from './components/label/label-signpost/label-signpost.component';
|
import { LabelSignPostComponent } from './components/label/label-signpost/label-signpost.component';
|
||||||
import { LabelPieceComponent } from './components/label/label-piece/label-piece.component';
|
import { LabelPieceComponent } from './components/label/label-piece/label-piece.component';
|
||||||
import { CreateEditLabelComponent } from './components/label/create-edit-label/create-edit-label.component';
|
import { CreateEditLabelComponent } from './components/label/create-edit-label/create-edit-label.component';
|
||||||
import { ListChartVersionRoComponent } from './components/list-chart-version-ro/list-chart-version-ro.component';
|
|
||||||
import { DatePickerComponent } from './components/datetime-picker/datetime-picker.component';
|
import { DatePickerComponent } from './components/datetime-picker/datetime-picker.component';
|
||||||
import {
|
import {
|
||||||
EndpointDefaultService,
|
EndpointDefaultService,
|
||||||
EndpointService,
|
EndpointService,
|
||||||
} from './services/endpoint.service';
|
} from './services/endpoint.service';
|
||||||
import { ImageNameInputComponent } from './components/image-name-input/image-name-input.component';
|
import { ImageNameInputComponent } from './components/image-name-input/image-name-input.component';
|
||||||
import {
|
|
||||||
HelmChartDefaultService,
|
|
||||||
HelmChartService,
|
|
||||||
} from '../base/project/helm-chart/helm-chart-detail/helm-chart.service';
|
|
||||||
import { MessageHandlerService } from './services/message-handler.service';
|
import { MessageHandlerService } from './services/message-handler.service';
|
||||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -142,7 +137,6 @@ ClarityIcons.add({
|
||||||
LabelPieceComponent,
|
LabelPieceComponent,
|
||||||
CreateEditLabelComponent,
|
CreateEditLabelComponent,
|
||||||
CronScheduleComponent,
|
CronScheduleComponent,
|
||||||
ListChartVersionRoComponent,
|
|
||||||
DatePickerComponent,
|
DatePickerComponent,
|
||||||
ImageNameInputComponent,
|
ImageNameInputComponent,
|
||||||
HarborDatetimePipe,
|
HarborDatetimePipe,
|
||||||
|
@ -182,7 +176,6 @@ ClarityIcons.add({
|
||||||
LabelPieceComponent,
|
LabelPieceComponent,
|
||||||
CreateEditLabelComponent,
|
CreateEditLabelComponent,
|
||||||
CronScheduleComponent,
|
CronScheduleComponent,
|
||||||
ListChartVersionRoComponent,
|
|
||||||
DatePickerComponent,
|
DatePickerComponent,
|
||||||
ImageNameInputComponent,
|
ImageNameInputComponent,
|
||||||
HarborDatetimePipe,
|
HarborDatetimePipe,
|
||||||
|
@ -198,7 +191,6 @@ ClarityIcons.add({
|
||||||
provide: ScanningResultService,
|
provide: ScanningResultService,
|
||||||
useClass: ScanningResultDefaultService,
|
useClass: ScanningResultDefaultService,
|
||||||
},
|
},
|
||||||
{ provide: HelmChartService, useClass: HelmChartDefaultService },
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class SharedModule {}
|
export class SharedModule {}
|
||||||
|
|
|
@ -957,8 +957,6 @@ export enum PageSizeMapKeys {
|
||||||
ARTIFACT_LIST_TAB_COMPONENT = 'ArtifactListTabComponent',
|
ARTIFACT_LIST_TAB_COMPONENT = 'ArtifactListTabComponent',
|
||||||
ARTIFACT_TAGS_COMPONENT = 'ArtifactTagComponent',
|
ARTIFACT_TAGS_COMPONENT = 'ArtifactTagComponent',
|
||||||
ARTIFACT_VUL_COMPONENT = 'ArtifactVulnerabilitiesComponent',
|
ARTIFACT_VUL_COMPONENT = 'ArtifactVulnerabilitiesComponent',
|
||||||
HELM_CHART_COMPONENT = 'HelmChartComponent',
|
|
||||||
CHART_VERSION_COMPONENT = 'ChartVersionComponent',
|
|
||||||
MEMBER_COMPONENT = 'MemberComponent',
|
MEMBER_COMPONENT = 'MemberComponent',
|
||||||
LABEL_COMPONENT = 'LabelComponent',
|
LABEL_COMPONENT = 'LabelComponent',
|
||||||
P2P_POLICY_COMPONENT = 'P2pPolicyComponent',
|
P2P_POLICY_COMPONENT = 'P2pPolicyComponent',
|
||||||
|
|
|
@ -651,7 +651,6 @@
|
||||||
"FLATTEN_LEVEL_TIP_1": "'Reduzierung um 1 Ebene'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
"FLATTEN_LEVEL_TIP_1": "'Reduzierung um 1 Ebene'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_2": "'Reduzierung um 2 Ebenen': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
"FLATTEN_LEVEL_TIP_2": "'Reduzierung um 2 Ebenen': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_3": "'Reduzierung um 3 Ebenen': 'a/b/c/d/img' -> 'ns/d/img'",
|
"FLATTEN_LEVEL_TIP_3": "'Reduzierung um 3 Ebenen': 'a/b/c/d/img' -> 'ns/d/img'",
|
||||||
"NOTE": "Hinweis: Charts im Chartmuseum unterstützen lediglich eine Struktur mit zwei Komponenten im Pfad: 'a/chart'",
|
|
||||||
"BANDWIDTH": "Bandbreite",
|
"BANDWIDTH": "Bandbreite",
|
||||||
"BANDWIDTH_ERROR_TIP": "Bitte -1 oder einen Integer-Wert größer als 0 eingeben",
|
"BANDWIDTH_ERROR_TIP": "Bitte -1 oder einen Integer-Wert größer als 0 eingeben",
|
||||||
"BANDWIDTH_TOOLTIP": "Legt die maximale Netzwerkbandbreite für jede Ausführung fest. Bitte auf die Anzahl der parallelen Ausführungen achten. Für umbegrenzte Bandbreite, bitte -1 eingeben",
|
"BANDWIDTH_TOOLTIP": "Legt die maximale Netzwerkbandbreite für jede Ausführung fest. Bitte auf die Anzahl der parallelen Ausführungen achten. Für umbegrenzte Bandbreite, bitte -1 eingeben",
|
||||||
|
@ -763,68 +762,9 @@
|
||||||
"MARKDOWN": "Markdown wird unterstützt",
|
"MARKDOWN": "Markdown wird unterstützt",
|
||||||
"LAST_MODIFIED": "Geändert am"
|
"LAST_MODIFIED": "Geändert am"
|
||||||
},
|
},
|
||||||
"HELM_CHART": {
|
|
||||||
"HELMCHARTS": "Charts",
|
|
||||||
"CHARTVERSIONS": "Versionen",
|
|
||||||
"UPLOAD_TITLE": "Chart Dateien hochladen",
|
|
||||||
"CHART_FILE": "Chart Datei",
|
|
||||||
"CHART_PROV": "Prov Datei",
|
|
||||||
"DOWNLOAD": "Download",
|
|
||||||
"SUMMARY": "Zusammenfassung",
|
|
||||||
"DEPENDENCIES": "Dependencies",
|
|
||||||
"VALUES": "Values",
|
|
||||||
"OVERVIEW": "Übersicht",
|
|
||||||
"HOME": "Home",
|
|
||||||
"SRC_REPO": "Quell Repository",
|
|
||||||
"CREATED": "Erstellt am",
|
|
||||||
"MAINTAINERS": "Maintainers",
|
|
||||||
"OTHER_MAINTAINERS": "{{ name }} und {{ number }} andere",
|
|
||||||
"PULLS": "Pull Anzahl",
|
|
||||||
"VERSION": "Version",
|
|
||||||
"APP_VERSION": "Application Version",
|
|
||||||
"INSTALL": "Installieren",
|
|
||||||
"INSTALL_CHART": "Chart installieren",
|
|
||||||
"NAME": "Name",
|
|
||||||
"REPO": "Repository",
|
|
||||||
"FILTER_FOR_CHARTS": "Filter Charts",
|
|
||||||
"DELETE": "Löschen",
|
|
||||||
"OF": "von",
|
|
||||||
"VERSIONS": "Versionen",
|
|
||||||
"IMAGES": "Images",
|
|
||||||
"ENGINE": "Engine",
|
|
||||||
"ACTION": "Aktion",
|
|
||||||
"UPLOAD": "Hochladen",
|
|
||||||
"DELETE_CHART_VERSION_TITLE": "Lösche Chart Version",
|
|
||||||
"DELETE_CHART_VERSION": "Soll die Version {{param}} gelöscht werden?",
|
|
||||||
"IMPORT": "Importieren",
|
|
||||||
"EXPORT": "Exportieren",
|
|
||||||
"ADD_REPO": "Repo hinzufügen",
|
|
||||||
"SHOW_KV": "Key/Value-Paare",
|
|
||||||
"SHOW_YAML": "YAML Datei",
|
|
||||||
"PLACEHOLDER": "Es konnte kein Chart gefunden werden!",
|
|
||||||
"NO_VERSION_PLACEHOLDER": "Es konnten keine Versionen gefunden werden!",
|
|
||||||
"FILE_UPLOADED": "Datei erfolgreich hochgeladen",
|
|
||||||
"SIGN": "Signieren",
|
|
||||||
"SIGNED": "signiert",
|
|
||||||
"UNSIGNED": "nicht signiert",
|
|
||||||
"ITEMS": "Einträge",
|
|
||||||
"NO_README": "Kein Readme für dieses Chart verfügbar.",
|
|
||||||
"SECURITY": "Sicherheit",
|
|
||||||
"ACTIVE": "Aktiv",
|
|
||||||
"DEPRECATED": "Veraltet",
|
|
||||||
"VERIFY_CHART": "Verifiziere Chart",
|
|
||||||
"COMMAND": "Befehle",
|
|
||||||
"PROV_FILE": "Prov Datei",
|
|
||||||
"READY": "Bereit",
|
|
||||||
"NOT_READY": "Nicht bereit",
|
|
||||||
"LABELS": "Label",
|
|
||||||
"ADD_LABEL_TO_CHART_VERSION": "Label zu dieser Chart-Version hinzufügen",
|
|
||||||
"STATUS": "Status"
|
|
||||||
},
|
|
||||||
"SUMMARY": {
|
"SUMMARY": {
|
||||||
"QUOTAS": "Beschränkungen",
|
"QUOTAS": "Beschränkungen",
|
||||||
"PROJECT_REPOSITORY": "Repositories",
|
"PROJECT_REPOSITORY": "Repositories",
|
||||||
"PROJECT_HELM_CHART": "Helm Chart",
|
|
||||||
"PROJECT_MEMBER": "Mitglieder",
|
"PROJECT_MEMBER": "Mitglieder",
|
||||||
"PROJECT_QUOTAS": "Beschränkungen",
|
"PROJECT_QUOTAS": "Beschränkungen",
|
||||||
"ARTIFACT_COUNT": "Anzahl an Artefakten",
|
"ARTIFACT_COUNT": "Anzahl an Artefakten",
|
||||||
|
@ -852,6 +792,7 @@
|
||||||
"SUB_TITLE_SUFIX": "logs"
|
"SUB_TITLE_SUFIX": "logs"
|
||||||
},
|
},
|
||||||
"CONFIG": {
|
"CONFIG": {
|
||||||
|
"SECURITY": "Security",
|
||||||
"HISTORY": "Archiv",
|
"HISTORY": "Archiv",
|
||||||
"TITLE": "Konfiguration",
|
"TITLE": "Konfiguration",
|
||||||
"AUTH": "Authentifizierung",
|
"AUTH": "Authentifizierung",
|
||||||
|
@ -1636,8 +1577,6 @@
|
||||||
"READ": "Lesen",
|
"READ": "Lesen",
|
||||||
"CREATE": "Erzeugen",
|
"CREATE": "Erzeugen",
|
||||||
"ARTIFACT": "Artefakt",
|
"ARTIFACT": "Artefakt",
|
||||||
"HELM": "Helm Chart",
|
|
||||||
"HELM_VERSION": "Helm Chart Version",
|
|
||||||
"ADD_ROBOT": "Robot-Zugang hinzufügen",
|
"ADD_ROBOT": "Robot-Zugang hinzufügen",
|
||||||
"UPDATE_ROBOT": "Robot-Zugang aktualisieren",
|
"UPDATE_ROBOT": "Robot-Zugang aktualisieren",
|
||||||
"UPDATE_ROBOT_SUCCESSFULLY": "Robot-Zugang aktualisieren erfolgreich",
|
"UPDATE_ROBOT_SUCCESSFULLY": "Robot-Zugang aktualisieren erfolgreich",
|
||||||
|
@ -1707,7 +1646,6 @@
|
||||||
"STOP": "Stoppen",
|
"STOP": "Stoppen",
|
||||||
"LIST": "Auflisten",
|
"LIST": "Auflisten",
|
||||||
"REPOSITORY": "Repository",
|
"REPOSITORY": "Repository",
|
||||||
"HELM_LABEL": "Helm Chart Label",
|
|
||||||
"EXPIRES_IN": "Läuft ab in",
|
"EXPIRES_IN": "Läuft ab in",
|
||||||
"EXPIRED": "Abgelaufen"
|
"EXPIRED": "Abgelaufen"
|
||||||
},
|
},
|
||||||
|
|
|
@ -651,7 +651,6 @@
|
||||||
"FLATTEN_LEVEL_TIP_1": "'Flatten 1 Level'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
"FLATTEN_LEVEL_TIP_1": "'Flatten 1 Level'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_2": "'Flatten 2 Levels': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
"FLATTEN_LEVEL_TIP_2": "'Flatten 2 Levels': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_3": "'Flatten 3 Levels': 'a/b/c/d/img' -> 'ns/d/img'",
|
"FLATTEN_LEVEL_TIP_3": "'Flatten 3 Levels': 'a/b/c/d/img' -> 'ns/d/img'",
|
||||||
"NOTE": "Notes: The Chartmuseum Charts only support the repository structure with 2 path components: 'a/chart'",
|
|
||||||
"BANDWIDTH": "Bandwidth",
|
"BANDWIDTH": "Bandwidth",
|
||||||
"BANDWIDTH_ERROR_TIP": "Please enter -1 or an integer greater than 0",
|
"BANDWIDTH_ERROR_TIP": "Please enter -1 or an integer greater than 0",
|
||||||
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
||||||
|
@ -763,68 +762,9 @@
|
||||||
"MARKDOWN": "Styling with Markdown is supported",
|
"MARKDOWN": "Styling with Markdown is supported",
|
||||||
"LAST_MODIFIED": "Last Modified Time"
|
"LAST_MODIFIED": "Last Modified Time"
|
||||||
},
|
},
|
||||||
"HELM_CHART": {
|
|
||||||
"HELMCHARTS": "Charts",
|
|
||||||
"CHARTVERSIONS": "Versions",
|
|
||||||
"UPLOAD_TITLE": "Upload chart files",
|
|
||||||
"CHART_FILE": "Chart File",
|
|
||||||
"CHART_PROV": "Prov File",
|
|
||||||
"DOWNLOAD": "Download",
|
|
||||||
"SUMMARY": "Summary",
|
|
||||||
"DEPENDENCIES": "Dependencies",
|
|
||||||
"VALUES": "Values",
|
|
||||||
"OVERVIEW": "Overview",
|
|
||||||
"HOME": "Home",
|
|
||||||
"SRC_REPO": "Source Repository",
|
|
||||||
"CREATED": "Created Time",
|
|
||||||
"MAINTAINERS": "Maintainers",
|
|
||||||
"OTHER_MAINTAINERS": "{{ name }} and {{ number }} others",
|
|
||||||
"PULLS": "Pull Count",
|
|
||||||
"VERSION": "Version",
|
|
||||||
"APP_VERSION": "Application Version",
|
|
||||||
"INSTALL": "Install",
|
|
||||||
"INSTALL_CHART": "Install Chart",
|
|
||||||
"NAME": "Name",
|
|
||||||
"REPO": "Repository",
|
|
||||||
"FILTER_FOR_CHARTS": "Filter for charts",
|
|
||||||
"DELETE": "Delete",
|
|
||||||
"OF": "of",
|
|
||||||
"VERSIONS": "versions",
|
|
||||||
"IMAGES": "Images",
|
|
||||||
"ENGINE": "Engine",
|
|
||||||
"ACTION": "Action",
|
|
||||||
"UPLOAD": "Upload",
|
|
||||||
"DELETE_CHART_VERSION_TITLE": "Delete Chart Versions",
|
|
||||||
"DELETE_CHART_VERSION": "Do you want to delete version {{param}}?",
|
|
||||||
"IMPORT": "Import",
|
|
||||||
"EXPORT": "Export",
|
|
||||||
"ADD_REPO": "Add Repo",
|
|
||||||
"SHOW_KV": "Key Value Pairs",
|
|
||||||
"SHOW_YAML": "YAML File",
|
|
||||||
"PLACEHOLDER": "We couldn't find any charts!",
|
|
||||||
"NO_VERSION_PLACEHOLDER": "We couldn't find any versions!",
|
|
||||||
"FILE_UPLOADED": "File upload successfully",
|
|
||||||
"SIGN": "Sign",
|
|
||||||
"SIGNED": "Signed",
|
|
||||||
"UNSIGNED": "Unsigned",
|
|
||||||
"ITEMS": "items",
|
|
||||||
"NO_README": "No readme file provided by this chart.",
|
|
||||||
"SECURITY": "Security",
|
|
||||||
"ACTIVE": "Active",
|
|
||||||
"DEPRECATED": "Deprecated",
|
|
||||||
"VERIFY_CHART": "Verify Chart",
|
|
||||||
"COMMAND": "Commands",
|
|
||||||
"PROV_FILE": "Prov File",
|
|
||||||
"READY": "Ready",
|
|
||||||
"NOT_READY": "Not Ready",
|
|
||||||
"LABELS": "Labels",
|
|
||||||
"ADD_LABEL_TO_CHART_VERSION": "Add labels to this chart version",
|
|
||||||
"STATUS": "Status"
|
|
||||||
},
|
|
||||||
"SUMMARY": {
|
"SUMMARY": {
|
||||||
"QUOTAS": "quotas",
|
"QUOTAS": "quotas",
|
||||||
"PROJECT_REPOSITORY": "Repositories",
|
"PROJECT_REPOSITORY": "Repositories",
|
||||||
"PROJECT_HELM_CHART": "Helm Chart",
|
|
||||||
"PROJECT_MEMBER": "Members",
|
"PROJECT_MEMBER": "Members",
|
||||||
"PROJECT_QUOTAS": "Quotas",
|
"PROJECT_QUOTAS": "Quotas",
|
||||||
"ARTIFACT_COUNT": "Artifact count",
|
"ARTIFACT_COUNT": "Artifact count",
|
||||||
|
@ -852,6 +792,7 @@
|
||||||
"SUB_TITLE_SUFIX": "logs"
|
"SUB_TITLE_SUFIX": "logs"
|
||||||
},
|
},
|
||||||
"CONFIG": {
|
"CONFIG": {
|
||||||
|
"SECURITY": "Security",
|
||||||
"HISTORY": "History",
|
"HISTORY": "History",
|
||||||
"TITLE": "Configuration",
|
"TITLE": "Configuration",
|
||||||
"AUTH": "Authentication",
|
"AUTH": "Authentication",
|
||||||
|
@ -1636,8 +1577,6 @@
|
||||||
"READ": "Read",
|
"READ": "Read",
|
||||||
"CREATE": "Create",
|
"CREATE": "Create",
|
||||||
"ARTIFACT": "Artifact",
|
"ARTIFACT": "Artifact",
|
||||||
"HELM": "Helm Chart",
|
|
||||||
"HELM_VERSION": "Helm Chart Version",
|
|
||||||
"ADD_ROBOT": "Add Robot",
|
"ADD_ROBOT": "Add Robot",
|
||||||
"UPDATE_ROBOT": "Update Robot",
|
"UPDATE_ROBOT": "Update Robot",
|
||||||
"UPDATE_ROBOT_SUCCESSFULLY": "Updated robot successfully",
|
"UPDATE_ROBOT_SUCCESSFULLY": "Updated robot successfully",
|
||||||
|
@ -1707,7 +1646,6 @@
|
||||||
"STOP": "Stop",
|
"STOP": "Stop",
|
||||||
"LIST": "List",
|
"LIST": "List",
|
||||||
"REPOSITORY": "Repository",
|
"REPOSITORY": "Repository",
|
||||||
"HELM_LABEL": "Helm Chart label",
|
|
||||||
"EXPIRES_IN": "Expires in",
|
"EXPIRES_IN": "Expires in",
|
||||||
"EXPIRED": "Expired"
|
"EXPIRED": "Expired"
|
||||||
},
|
},
|
||||||
|
|
|
@ -653,7 +653,6 @@
|
||||||
"FLATTEN_LEVEL_TIP_1": "'Flatten 1 Level'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
"FLATTEN_LEVEL_TIP_1": "'Flatten 1 Level'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_2": "'Flatten 2 Levels': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
"FLATTEN_LEVEL_TIP_2": "'Flatten 2 Levels': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_3": "'Flatten 3 Levels': 'a/b/c/d/img' -> 'ns/d/img'",
|
"FLATTEN_LEVEL_TIP_3": "'Flatten 3 Levels': 'a/b/c/d/img' -> 'ns/d/img'",
|
||||||
"NOTE": "Notes: The Chartmuseum Charts only support the repository structure with 2 path components: 'a/chart'",
|
|
||||||
"BANDWIDTH": "Bandwidth",
|
"BANDWIDTH": "Bandwidth",
|
||||||
"BANDWIDTH_ERROR_TIP": "Please enter -1 or an integer greater than 0",
|
"BANDWIDTH_ERROR_TIP": "Please enter -1 or an integer greater than 0",
|
||||||
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
||||||
|
@ -765,68 +764,9 @@
|
||||||
"MARKDOWN": "Styling with Markdown is supported",
|
"MARKDOWN": "Styling with Markdown is supported",
|
||||||
"LAST_MODIFIED": "Last Modified Time"
|
"LAST_MODIFIED": "Last Modified Time"
|
||||||
},
|
},
|
||||||
"HELM_CHART": {
|
|
||||||
"HELMCHARTS": "Charts",
|
|
||||||
"CHARTVERSIONS": "Versions",
|
|
||||||
"UPLOAD_TITLE": "Upload chart files",
|
|
||||||
"CHART_FILE": "Chart File",
|
|
||||||
"CHART_PROV": "Prov File",
|
|
||||||
"DOWNLOAD": "Download",
|
|
||||||
"SUMMARY": "Summary",
|
|
||||||
"DEPENDENCIES": "Dependencies",
|
|
||||||
"VALUES": "Values",
|
|
||||||
"OVERVIEW": "Overview",
|
|
||||||
"HOME": "Home",
|
|
||||||
"SRC_REPO": "Source Repository",
|
|
||||||
"CREATED": "Created Time",
|
|
||||||
"MAINTAINERS": "Maintainers",
|
|
||||||
"OTHER_MAINTAINERS": "{{ name }} and {{ number }} others",
|
|
||||||
"PULLS": "Pull Count",
|
|
||||||
"VERSION": "Version",
|
|
||||||
"APP_VERSION": "Application Version",
|
|
||||||
"INSTALL": "Install",
|
|
||||||
"INSTALL_CHART": "Install Chart",
|
|
||||||
"NAME": "Name",
|
|
||||||
"REPO": "Repository",
|
|
||||||
"FILTER_FOR_CHARTS": "Filter for charts",
|
|
||||||
"DELETE": "Delete",
|
|
||||||
"OF": "of",
|
|
||||||
"VERSIONS": "versions",
|
|
||||||
"IMAGES": "Images",
|
|
||||||
"ENGINE": "Engine",
|
|
||||||
"ACTION": "Action",
|
|
||||||
"UPLOAD": "Upload",
|
|
||||||
"DELETE_CHART_VERSION_TITLE": "Delete Chart Versions",
|
|
||||||
"DELETE_CHART_VERSION": "Do you want to delete version {{param}}?",
|
|
||||||
"IMPORT": "Import",
|
|
||||||
"EXPORT": "Export",
|
|
||||||
"ADD_REPO": "Add Repo",
|
|
||||||
"SHOW_KV": "Key Value Pairs",
|
|
||||||
"SHOW_YAML": "YAML File",
|
|
||||||
"PLACEHOLDER": "We couldn't find any charts!",
|
|
||||||
"NO_VERSION_PLACEHOLDER": "We couldn't find any versions!",
|
|
||||||
"FILE_UPLOADED": "File upload successfully",
|
|
||||||
"SIGN": "Sign",
|
|
||||||
"SIGNED": "Signed",
|
|
||||||
"UNSIGNED": "Unsigned",
|
|
||||||
"ITEMS": "items",
|
|
||||||
"NO_README": "No readme file provided by this chart.",
|
|
||||||
"SECURITY": "Security",
|
|
||||||
"ACTIVE": "Active",
|
|
||||||
"DEPRECATED": "Deprecated",
|
|
||||||
"VERIFY_CHART": "Verify Chart",
|
|
||||||
"COMMAND": "Commands",
|
|
||||||
"PROV_FILE": "Prov File",
|
|
||||||
"READY": "Ready",
|
|
||||||
"NOT_READY": "Not Ready",
|
|
||||||
"LABELS": "Labels",
|
|
||||||
"ADD_LABEL_TO_CHART_VERSION": "Add labels to this chart version",
|
|
||||||
"STATUS": "Status"
|
|
||||||
},
|
|
||||||
"SUMMARY": {
|
"SUMMARY": {
|
||||||
"QUOTAS": "quotas",
|
"QUOTAS": "quotas",
|
||||||
"PROJECT_REPOSITORY": "Repositories",
|
"PROJECT_REPOSITORY": "Repositories",
|
||||||
"PROJECT_HELM_CHART": "Helm Chart",
|
|
||||||
"PROJECT_MEMBER": "Members",
|
"PROJECT_MEMBER": "Members",
|
||||||
"PROJECT_QUOTAS": "Quotas",
|
"PROJECT_QUOTAS": "Quotas",
|
||||||
"ARTIFACT_COUNT": "Artifact count",
|
"ARTIFACT_COUNT": "Artifact count",
|
||||||
|
@ -854,6 +794,7 @@
|
||||||
"SUB_TITLE_SUFIX": "logs"
|
"SUB_TITLE_SUFIX": "logs"
|
||||||
},
|
},
|
||||||
"CONFIG": {
|
"CONFIG": {
|
||||||
|
"SECURITY": "Security",
|
||||||
"HISTORY": "History",
|
"HISTORY": "History",
|
||||||
"TITLE": "Configuración",
|
"TITLE": "Configuración",
|
||||||
"AUTH": "Autentificación",
|
"AUTH": "Autentificación",
|
||||||
|
@ -1635,8 +1576,6 @@
|
||||||
"READ": "Read",
|
"READ": "Read",
|
||||||
"CREATE": "Create",
|
"CREATE": "Create",
|
||||||
"ARTIFACT": "Artifact",
|
"ARTIFACT": "Artifact",
|
||||||
"HELM": "Helm Chart",
|
|
||||||
"HELM_VERSION": "Helm Chart Version",
|
|
||||||
"ADD_ROBOT": "Add Robot",
|
"ADD_ROBOT": "Add Robot",
|
||||||
"UPDATE_ROBOT": "Update Robot",
|
"UPDATE_ROBOT": "Update Robot",
|
||||||
"UPDATE_ROBOT_SUCCESSFULLY": "Updated robot successfully",
|
"UPDATE_ROBOT_SUCCESSFULLY": "Updated robot successfully",
|
||||||
|
@ -1706,7 +1645,6 @@
|
||||||
"STOP": "Stop",
|
"STOP": "Stop",
|
||||||
"LIST": "List",
|
"LIST": "List",
|
||||||
"REPOSITORY": "Repository",
|
"REPOSITORY": "Repository",
|
||||||
"HELM_LABEL": "Helm Chart label",
|
|
||||||
"EXPIRES_IN": "Expires in",
|
"EXPIRES_IN": "Expires in",
|
||||||
"EXPIRED": "Expired"
|
"EXPIRED": "Expired"
|
||||||
},
|
},
|
||||||
|
|
|
@ -641,7 +641,6 @@
|
||||||
"FLATTEN_LEVEL_TIP_1": "'Aplanissement sur 1 niveau'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
"FLATTEN_LEVEL_TIP_1": "'Aplanissement sur 1 niveau'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_2": "'Aplanissement sur 2 niveaux': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
"FLATTEN_LEVEL_TIP_2": "'Aplanissement sur 2 niveaux': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_3": "'Aplanissement sur 3 niveaux': 'a/b/c/d/img' -> 'ns/d/img'",
|
"FLATTEN_LEVEL_TIP_3": "'Aplanissement sur 3 niveaux': 'a/b/c/d/img' -> 'ns/d/img'",
|
||||||
"NOTE": "Notes: Les graphiques Chartmuseum ne prennent en charge que la structure du référentiel avec 2 composants de chemin : `a/chart` ",
|
|
||||||
"BANDWIDTH": "Bande passante",
|
"BANDWIDTH": "Bande passante",
|
||||||
"BANDWIDTH_ERROR_TIP": "Veuillez saisir -1 ou un nombre entier supérieur à 0",
|
"BANDWIDTH_ERROR_TIP": "Veuillez saisir -1 ou un nombre entier supérieur à 0",
|
||||||
"BANDWIDTH_TOOLTIP": "Définissez la bande passante réseau maximale pour chaque exécution. Veuillez faire attention au nombre d'exécutions simultanées. Pour une bande passante illimitée, veuillez entrer -1",
|
"BANDWIDTH_TOOLTIP": "Définissez la bande passante réseau maximale pour chaque exécution. Veuillez faire attention au nombre d'exécutions simultanées. Pour une bande passante illimitée, veuillez entrer -1",
|
||||||
|
@ -750,67 +749,9 @@
|
||||||
"MARKDOWN": "La syntaxe Markdown est supportée",
|
"MARKDOWN": "La syntaxe Markdown est supportée",
|
||||||
"LAST_MODIFIED": "Dernière modification"
|
"LAST_MODIFIED": "Dernière modification"
|
||||||
},
|
},
|
||||||
"HELM_CHART": {
|
|
||||||
"HELMCHARTS": "Charts",
|
|
||||||
"CHARTVERSIONS": "Versions",
|
|
||||||
"UPLOAD_TITLE": "Téléverser des charts",
|
|
||||||
"CHART_FILE": "Fichier de Chart",
|
|
||||||
"CHART_PROV": "Prov File",
|
|
||||||
"DOWNLOAD": "Télécharger",
|
|
||||||
"SUMMARY": "Résumé",
|
|
||||||
"DEPENDENCIES": "Dépendances",
|
|
||||||
"VALUES": "Valeurs",
|
|
||||||
"OVERVIEW": "Aperçu",
|
|
||||||
"HOME": "Accueil",
|
|
||||||
"SRC_REPO": "Dépôt source",
|
|
||||||
"CREATED": "Date/Heure de création",
|
|
||||||
"MAINTAINERS": "Mainteneurs",
|
|
||||||
"OTHER_MAINTAINERS": "{{ name }} et {{ number }} autres",
|
|
||||||
"PULLS": "Nombre de Pull",
|
|
||||||
"VERSION": "Version",
|
|
||||||
"APP_VERSION": "Version de l'Application",
|
|
||||||
"INSTALL": "Installer",
|
|
||||||
"INSTALL_CHART": "Installer le Chart",
|
|
||||||
"NAME": "Nom",
|
|
||||||
"REPO": "Dépôt",
|
|
||||||
"FILTER_FOR_CHARTS": "Filtrer les charts",
|
|
||||||
"DELETE": "Supprimer",
|
|
||||||
"OF": "sur",
|
|
||||||
"VERSIONS": "versions",
|
|
||||||
"IMAGES": "Images",
|
|
||||||
"ENGINE": "Moteur",
|
|
||||||
"ACTION": "Action",
|
|
||||||
"UPLOAD": "Téléverser",
|
|
||||||
"DELETE_CHART_VERSION_TITLE": "Supprimer des versions de Chart",
|
|
||||||
"DELETE_CHART_VERSION": "Voulez-vous supprimer la version {{param}}?",
|
|
||||||
"IMPORT": "Importer",
|
|
||||||
"EXPORT": "Exporter",
|
|
||||||
"ADD_REPO": "Ajouter Repo",
|
|
||||||
"SHOW_KV": "Paires Clé/Valeur",
|
|
||||||
"SHOW_YAML": "Fichier YAML",
|
|
||||||
"PLACEHOLDER": "Nous n'avons trouvé aucun chart !",
|
|
||||||
"NO_VERSION_PLACEHOLDER": "Nous n'avons trouvé aucune version !",
|
|
||||||
"FILE_UPLOADED": "Fichier envoyé avec succès",
|
|
||||||
"SIGN": "Signer",
|
|
||||||
"SIGNED": "Signé",
|
|
||||||
"UNSIGNED": "Non signé",
|
|
||||||
"ITEMS": "items",
|
|
||||||
"SECURITY": "Sécurité",
|
|
||||||
"ACTIVE": "Actif",
|
|
||||||
"DEPRECATED": "Obsolète",
|
|
||||||
"VERIFY_CHART": "Verifier le Chart",
|
|
||||||
"COMMAND": "Commandes",
|
|
||||||
"PROV_FILE": "Prov File",
|
|
||||||
"READY": "Prêt",
|
|
||||||
"NOT_READY": "Non prêt",
|
|
||||||
"LABELS": "Labels",
|
|
||||||
"ADD_LABEL_TO_CHART_VERSION": "Ajouter des labels à cette version de chart",
|
|
||||||
"STATUS": "Statut"
|
|
||||||
},
|
|
||||||
"SUMMARY": {
|
"SUMMARY": {
|
||||||
"QUOTAS": "Quotas",
|
"QUOTAS": "Quotas",
|
||||||
"PROJECT_REPOSITORY": "Dépôts",
|
"PROJECT_REPOSITORY": "Dépôts",
|
||||||
"PROJECT_HELM_CHART": "Chart Helm",
|
|
||||||
"PROJECT_MEMBER": "Membres",
|
"PROJECT_MEMBER": "Membres",
|
||||||
"PROJECT_QUOTAS": "Quotas",
|
"PROJECT_QUOTAS": "Quotas",
|
||||||
"ARTIFACT_COUNT": "Nombre d'Artefact",
|
"ARTIFACT_COUNT": "Nombre d'Artefact",
|
||||||
|
@ -838,6 +779,7 @@
|
||||||
"SUB_TITLE_SUFIX": "logs"
|
"SUB_TITLE_SUFIX": "logs"
|
||||||
},
|
},
|
||||||
"CONFIG": {
|
"CONFIG": {
|
||||||
|
"SECURITY": "Security",
|
||||||
"HISTORY": "Historique",
|
"HISTORY": "Historique",
|
||||||
"TITLE": "Configuration",
|
"TITLE": "Configuration",
|
||||||
"AUTH": "Identification",
|
"AUTH": "Identification",
|
||||||
|
@ -1606,8 +1548,6 @@
|
||||||
"READ": "Lecture",
|
"READ": "Lecture",
|
||||||
"CREATE": "Création",
|
"CREATE": "Création",
|
||||||
"ARTIFACT": "Artefact",
|
"ARTIFACT": "Artefact",
|
||||||
"HELM": "Chart Helm",
|
|
||||||
"HELM_VERSION": "Version du Chart Helm",
|
|
||||||
"ADD_ROBOT": "Ajouter un Robot",
|
"ADD_ROBOT": "Ajouter un Robot",
|
||||||
"UPDATE_ROBOT": "Mettre à jour le Robot",
|
"UPDATE_ROBOT": "Mettre à jour le Robot",
|
||||||
"UPDATE_ROBOT_SUCCESSFULLY": "Robot mis à jour avec succès",
|
"UPDATE_ROBOT_SUCCESSFULLY": "Robot mis à jour avec succès",
|
||||||
|
@ -1676,7 +1616,6 @@
|
||||||
"PUSH_PERMISSION_TOOLTIP": "L'autorisation 'push' ne peut pas fonctionner seule, elle doit fonctionner avec l'autorisation 'pull'", "STOP": "Stop",
|
"PUSH_PERMISSION_TOOLTIP": "L'autorisation 'push' ne peut pas fonctionner seule, elle doit fonctionner avec l'autorisation 'pull'", "STOP": "Stop",
|
||||||
"LIST": "Liste",
|
"LIST": "Liste",
|
||||||
"REPOSITORY": "Dépôt",
|
"REPOSITORY": "Dépôt",
|
||||||
"HELM_LABEL": "Label du Chart Helm",
|
|
||||||
"EXPIRES_IN": "Expire dans",
|
"EXPIRES_IN": "Expire dans",
|
||||||
"EXPIRED": "Expiré"
|
"EXPIRED": "Expiré"
|
||||||
},
|
},
|
||||||
|
|
|
@ -651,7 +651,6 @@
|
||||||
"FLATTEN_LEVEL_TIP_1": "'Nivelar 1 posição' (padrão): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
"FLATTEN_LEVEL_TIP_1": "'Nivelar 1 posição' (padrão): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_2": "'Nivelar 2 posições': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
"FLATTEN_LEVEL_TIP_2": "'Nivelar 2 posições': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_3": "'Nivelar 3 posições': 'a/b/c/d/img' -> 'ns/d/img'",
|
"FLATTEN_LEVEL_TIP_3": "'Nivelar 3 posições': 'a/b/c/d/img' -> 'ns/d/img'",
|
||||||
"NOTE": "Nota: Chartmuseum suporta helm charts apenas com 2 níveis: 'a/chart'",
|
|
||||||
"BANDWIDTH": "Banda",
|
"BANDWIDTH": "Banda",
|
||||||
"BANDWIDTH_ERROR_TIP": "Informe um número inteiro maior que 0 (zero) ou -1",
|
"BANDWIDTH_ERROR_TIP": "Informe um número inteiro maior que 0 (zero) ou -1",
|
||||||
"BANDWIDTH_TOOLTIP": "Informe o limite de banda para cada execução. Tome cuidado e observe a relação com o número de execuções simultâneas. Para remover qualquer limite, informe -1",
|
"BANDWIDTH_TOOLTIP": "Informe o limite de banda para cada execução. Tome cuidado e observe a relação com o número de execuções simultâneas. Para remover qualquer limite, informe -1",
|
||||||
|
@ -762,66 +761,9 @@
|
||||||
"MARKDOWN": "Estilização com Markdown suportada",
|
"MARKDOWN": "Estilização com Markdown suportada",
|
||||||
"LAST_MODIFIED": "Data da última alteração"
|
"LAST_MODIFIED": "Data da última alteração"
|
||||||
},
|
},
|
||||||
"HELM_CHART": {
|
|
||||||
"HELMCHARTS": "Charts",
|
|
||||||
"CHARTVERSIONS": "Versões",
|
|
||||||
"UPLOAD_TITLE": "Enviar arquivos de chart",
|
|
||||||
"CHART_FILE": "Arquivo Chart",
|
|
||||||
"CHART_PROV": "Arquivo Prov",
|
|
||||||
"DOWNLOAD": "Baixar",
|
|
||||||
"SUMMARY": "Resumo",
|
|
||||||
"DEPENDENCIES": "Dependências",
|
|
||||||
"VALUES": "Valores",
|
|
||||||
"OVERVIEW": "Visão Geral",
|
|
||||||
"HOME": "Painel Principal",
|
|
||||||
"SRC_REPO": "Repositório de origem",
|
|
||||||
"CREATED": "Data de criação",
|
|
||||||
"MAINTAINERS": "Mantenedor",
|
|
||||||
"PULLS": "Contagem de Pulls",
|
|
||||||
"VERSION": "Versão",
|
|
||||||
"APP_VERSION": "Versão da Aplicação",
|
|
||||||
"INSTALL": "Instalar",
|
|
||||||
"INSTALL_CHART": "Instalar Chart",
|
|
||||||
"NAME": "Nome",
|
|
||||||
"REPO": "Repositório",
|
|
||||||
"FILTER_FOR_CHARTS": "Filtrar por charts",
|
|
||||||
"DELETE": "Remover",
|
|
||||||
"OF": "de",
|
|
||||||
"VERSIONS": "versões",
|
|
||||||
"IMAGES": "Imagens",
|
|
||||||
"ENGINE": "Engine",
|
|
||||||
"ACTION": "Ação",
|
|
||||||
"UPLOAD": "Enviar",
|
|
||||||
"DELETE_CHART_VERSION_TITLE": "Remover versões de Chart",
|
|
||||||
"DELETE_CHART_VERSION": "Você quer remover a versão {{param}}?",
|
|
||||||
"IMPORT": "Importar",
|
|
||||||
"EXPORT": "Exportar",
|
|
||||||
"ADD_REPO": "Adicionar Repositório",
|
|
||||||
"SHOW_KV": "Pares chave-valor",
|
|
||||||
"SHOW_YAML": "Arquivo YAML",
|
|
||||||
"PLACEHOLDER": "Não foi possível encontrar nenhum charts!",
|
|
||||||
"NO_VERSION_PLACEHOLDER": "Não foi possível encontrar nenhuma versão!",
|
|
||||||
"FILE_UPLOADED": "Envio de arquivo realizado com sucesso",
|
|
||||||
"SIGN": "Assinar",
|
|
||||||
"SIGNED": "Assinado",
|
|
||||||
"UNSIGNED": "Não assinado",
|
|
||||||
"ITEMS": "itens",
|
|
||||||
"NO_README": "Nenhum arquivo de README fornecido por esse chart.",
|
|
||||||
"SECURITY": "Segurança",
|
|
||||||
"ACTIVE": "Ativo",
|
|
||||||
"DEPRECATED": "Obsoleto",
|
|
||||||
"VERIFY_CHART": "Verificar Chart",
|
|
||||||
"COMMAND": "Comandos",
|
|
||||||
"PROV_FILE": "Arquivo Prov",
|
|
||||||
"READY": "Pronto",
|
|
||||||
"NOT_READY": "Não Pronto",
|
|
||||||
"ADD_LABEL_TO_CHART_VERSION": "Adicionar marcadores",
|
|
||||||
"STATUS": "Situação"
|
|
||||||
},
|
|
||||||
"SUMMARY": {
|
"SUMMARY": {
|
||||||
"QUOTAS": "cotas",
|
"QUOTAS": "cotas",
|
||||||
"PROJECT_REPOSITORY": "Repositórios",
|
"PROJECT_REPOSITORY": "Repositórios",
|
||||||
"PROJECT_HELM_CHART": "Helm Chart",
|
|
||||||
"PROJECT_MEMBER": "Membros",
|
"PROJECT_MEMBER": "Membros",
|
||||||
"PROJECT_QUOTAS": "Cotas",
|
"PROJECT_QUOTAS": "Cotas",
|
||||||
"ARTIFACT_COUNT": "Contagem de artefatos",
|
"ARTIFACT_COUNT": "Contagem de artefatos",
|
||||||
|
@ -849,6 +791,7 @@
|
||||||
"SUB_TITLE_SUFIX": "logs"
|
"SUB_TITLE_SUFIX": "logs"
|
||||||
},
|
},
|
||||||
"CONFIG": {
|
"CONFIG": {
|
||||||
|
"SECURITY": "Security",
|
||||||
"HISTORY": "Histórico",
|
"HISTORY": "Histórico",
|
||||||
"TITLE": "Configuração",
|
"TITLE": "Configuração",
|
||||||
"AUTH": "Autenticação",
|
"AUTH": "Autenticação",
|
||||||
|
@ -1632,8 +1575,6 @@
|
||||||
"READ": "Ler",
|
"READ": "Ler",
|
||||||
"CREATE": "Criar",
|
"CREATE": "Criar",
|
||||||
"ARTIFACT": "Artefato",
|
"ARTIFACT": "Artefato",
|
||||||
"HELM": "Helm Chart",
|
|
||||||
"HELM_VERSION": "Versão do Helm Chart",
|
|
||||||
"ADD_ROBOT": "Adicionar conta",
|
"ADD_ROBOT": "Adicionar conta",
|
||||||
"UPDATE_ROBOT": "Atualizar conta",
|
"UPDATE_ROBOT": "Atualizar conta",
|
||||||
"UPDATE_ROBOT_SUCCESSFULLY": "Conta atualizada com sucesso",
|
"UPDATE_ROBOT_SUCCESSFULLY": "Conta atualizada com sucesso",
|
||||||
|
@ -1703,7 +1644,6 @@
|
||||||
"STOP": "Parar",
|
"STOP": "Parar",
|
||||||
"LIST": "Listar",
|
"LIST": "Listar",
|
||||||
"REPOSITORY": "Repositório",
|
"REPOSITORY": "Repositório",
|
||||||
"HELM_LABEL": "Marcador do Helm Chart",
|
|
||||||
"EXPIRES_IN": "Expires in",
|
"EXPIRES_IN": "Expires in",
|
||||||
"EXPIRED": "Expired"
|
"EXPIRED": "Expired"
|
||||||
},
|
},
|
||||||
|
|
|
@ -651,7 +651,6 @@
|
||||||
"FLATTEN_LEVEL_TIP_1": "'Flatten 1 Level'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
"FLATTEN_LEVEL_TIP_1": "'Flatten 1 Level'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_2": "'Flatten 2 Levels': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
"FLATTEN_LEVEL_TIP_2": "'Flatten 2 Levels': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_3": "'Flatten 3 Levels': 'a/b/c/d/img' -> 'ns/d/img'",
|
"FLATTEN_LEVEL_TIP_3": "'Flatten 3 Levels': 'a/b/c/d/img' -> 'ns/d/img'",
|
||||||
"NOTE": "Notes: The Chartmuseum Charts only support the repository structure with 2 path components: 'a/chart'",
|
|
||||||
"BANDWIDTH": "Bandwidth",
|
"BANDWIDTH": "Bandwidth",
|
||||||
"BANDWIDTH_ERROR_TIP": "Please enter -1 or an integer greater than 0",
|
"BANDWIDTH_ERROR_TIP": "Please enter -1 or an integer greater than 0",
|
||||||
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
||||||
|
@ -763,68 +762,9 @@
|
||||||
"MARKDOWN": "Markdown ile stil desteklenir",
|
"MARKDOWN": "Markdown ile stil desteklenir",
|
||||||
"LAST_MODIFIED": "Last Modified Time"
|
"LAST_MODIFIED": "Last Modified Time"
|
||||||
},
|
},
|
||||||
"HELM_CHART": {
|
|
||||||
"HELMCHARTS": "Tablolar",
|
|
||||||
"CHARTVERSIONS": "Versiyonlar",
|
|
||||||
"UPLOAD_TITLE": "Tabloları dosyalarını yükle",
|
|
||||||
"CHART_FILE": "Tablo Dosyası",
|
|
||||||
"CHART_PROV": "Prov Dosyası",
|
|
||||||
"DOWNLOAD": "Yükle",
|
|
||||||
"SUMMARY": "Özet",
|
|
||||||
"DEPENDENCIES": "Bağımlılıklar",
|
|
||||||
"VALUES": "Değerler",
|
|
||||||
"OVERVIEW": "Genel bakış",
|
|
||||||
"HOME": "Ev",
|
|
||||||
"SRC_REPO": "Kaynak Deposu",
|
|
||||||
"CREATED": "Yaratılış Zamanı",
|
|
||||||
"MAINTAINERS": "Sürdürenler",
|
|
||||||
"OTHER_MAINTAINERS": "{{ name }} ve {{ number }} diğerleri",
|
|
||||||
"PULLS": "İndirme Sayısı",
|
|
||||||
"VERSION": "Versiyon",
|
|
||||||
"APP_VERSION": "Uygulama Versiyonu",
|
|
||||||
"INSTALL": "Yükle",
|
|
||||||
"INSTALL_CHART": "Tablo Yükle",
|
|
||||||
"NAME": "İsim",
|
|
||||||
"REPO": "Depo",
|
|
||||||
"FILTER_FOR_CHARTS": "Tabloları filtrele",
|
|
||||||
"DELETE": "Sil",
|
|
||||||
"OF": "of",
|
|
||||||
"VERSIONS": "versiyonlar",
|
|
||||||
"IMAGES": "İmajlar",
|
|
||||||
"ENGINE": "Motor",
|
|
||||||
"ACTION": "Aksiyon",
|
|
||||||
"UPLOAD": "Yükle",
|
|
||||||
"DELETE_CHART_VERSION_TITLE": "Tablo versiyonlarını sil",
|
|
||||||
"DELETE_CHART_VERSION": "Sürümü silmek istiyor musunuz {{param}}?",
|
|
||||||
"IMPORT": "İçe Aktar",
|
|
||||||
"EXPORT": "Dışa Aktar",
|
|
||||||
"ADD_REPO": "Depo Ekle",
|
|
||||||
"SHOW_KV": "Anahtar Değer Çiftleri",
|
|
||||||
"SHOW_YAML": "YAML Dosyası",
|
|
||||||
"PLACEHOLDER": "Hiçbir tablo bulamadık!",
|
|
||||||
"NO_VERSION_PLACEHOLDER": "Herhangi bir sürüm bulamadık!",
|
|
||||||
"FILE_UPLOADED": "Dosya başarıyla yüklendi",
|
|
||||||
"SIGN": "İmza",
|
|
||||||
"SIGNED": "İmzalandı",
|
|
||||||
"UNSIGNED": "İmzalanmadı",
|
|
||||||
"ITEMS": "öğeler",
|
|
||||||
"NO_README": "Bu tablo tarafından sağlanan beni oku dosyası yok.",
|
|
||||||
"SECURITY": "Güvenlik",
|
|
||||||
"ACTIVE": "Aktif",
|
|
||||||
"DEPRECATED": "Kullanımdan kaldırılan",
|
|
||||||
"VERIFY_CHART": "Tabloyu doğrula",
|
|
||||||
"COMMAND": "Komutlar",
|
|
||||||
"PROV_FILE": "Prov Dosyası",
|
|
||||||
"READY": "Hazır",
|
|
||||||
"NOT_READY": "Hazır Değil",
|
|
||||||
"LABELS": "Etiketler",
|
|
||||||
"ADD_LABEL_TO_CHART_VERSION": "Bu tablo sürümüne etiketler ekle",
|
|
||||||
"STATUS": "Durum"
|
|
||||||
},
|
|
||||||
"SUMMARY": {
|
"SUMMARY": {
|
||||||
"QUOTAS": "kotalar",
|
"QUOTAS": "kotalar",
|
||||||
"PROJECT_REPOSITORY": "Proje depoları",
|
"PROJECT_REPOSITORY": "Proje depoları",
|
||||||
"PROJECT_HELM_CHART": "Proje Helm Tablosu",
|
|
||||||
"PROJECT_MEMBER": "Proje Üyeleri",
|
"PROJECT_MEMBER": "Proje Üyeleri",
|
||||||
"PROJECT_QUOTAS": "Proje kotaları",
|
"PROJECT_QUOTAS": "Proje kotaları",
|
||||||
"ARTIFACT_COUNT": "Buluntu adeti",
|
"ARTIFACT_COUNT": "Buluntu adeti",
|
||||||
|
@ -852,6 +792,7 @@
|
||||||
"SUB_TITLE_SUFIX": "kayıtlar"
|
"SUB_TITLE_SUFIX": "kayıtlar"
|
||||||
},
|
},
|
||||||
"CONFIG": {
|
"CONFIG": {
|
||||||
|
"SECURITY": "Security",
|
||||||
"HISTORY": "Geçmiş",
|
"HISTORY": "Geçmiş",
|
||||||
"TITLE": "Ayarlar",
|
"TITLE": "Ayarlar",
|
||||||
"AUTH": "Doğrulama",
|
"AUTH": "Doğrulama",
|
||||||
|
@ -1636,8 +1577,6 @@
|
||||||
"READ": "Read",
|
"READ": "Read",
|
||||||
"CREATE": "Create",
|
"CREATE": "Create",
|
||||||
"ARTIFACT": "Artifact",
|
"ARTIFACT": "Artifact",
|
||||||
"HELM": "Helm Chart",
|
|
||||||
"HELM_VERSION": "Helm Chart Version",
|
|
||||||
"ADD_ROBOT": "Add Robot",
|
"ADD_ROBOT": "Add Robot",
|
||||||
"UPDATE_ROBOT": "Update Robot",
|
"UPDATE_ROBOT": "Update Robot",
|
||||||
"UPDATE_ROBOT_SUCCESSFULLY": "Updated robot successfully",
|
"UPDATE_ROBOT_SUCCESSFULLY": "Updated robot successfully",
|
||||||
|
@ -1707,7 +1646,6 @@
|
||||||
"STOP": "Stop",
|
"STOP": "Stop",
|
||||||
"LIST": "List",
|
"LIST": "List",
|
||||||
"REPOSITORY": "Repository",
|
"REPOSITORY": "Repository",
|
||||||
"HELM_LABEL": "Helm Chart label",
|
|
||||||
"EXPIRES_IN": "Expires in",
|
"EXPIRES_IN": "Expires in",
|
||||||
"EXPIRED": "Expired"
|
"EXPIRED": "Expired"
|
||||||
},
|
},
|
||||||
|
|
|
@ -653,7 +653,6 @@
|
||||||
"FLATTEN_LEVEL_TIP_1": "'替换1级'(默认项): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
"FLATTEN_LEVEL_TIP_1": "'替换1级'(默认项): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_2": "'替换2级': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
"FLATTEN_LEVEL_TIP_2": "'替换2级': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_3": "'替换3级': 'a/b/c/d/img' -> 'ns/d/img'",
|
"FLATTEN_LEVEL_TIP_3": "'替换3级': 'a/b/c/d/img' -> 'ns/d/img'",
|
||||||
"NOTE": "注意: Chartmuseum Charts 仅支持2层的仓库结构:如 'a/chart'",
|
|
||||||
"BANDWIDTH": "带宽",
|
"BANDWIDTH": "带宽",
|
||||||
"BANDWIDTH_ERROR_TIP": "请输入-1或者大于0的整数",
|
"BANDWIDTH_ERROR_TIP": "请输入-1或者大于0的整数",
|
||||||
"BANDWIDTH_TOOLTIP": "设置执行该条同步规则时的最大网络带宽。实际总带宽需要考虑并发执行的情况。如无需限制,请输入-1",
|
"BANDWIDTH_TOOLTIP": "设置执行该条同步规则时的最大网络带宽。实际总带宽需要考虑并发执行的情况。如无需限制,请输入-1",
|
||||||
|
@ -765,68 +764,9 @@
|
||||||
"MARKDOWN": "支持使用Markdown进行样式设置",
|
"MARKDOWN": "支持使用Markdown进行样式设置",
|
||||||
"LAST_MODIFIED": "最新变更时间"
|
"LAST_MODIFIED": "最新变更时间"
|
||||||
},
|
},
|
||||||
"HELM_CHART": {
|
|
||||||
"HELMCHARTS": "Charts",
|
|
||||||
"CHARTVERSIONS": "版本",
|
|
||||||
"UPLOAD_TITLE": "上传chart文件",
|
|
||||||
"CHART_FILE": "Chart 文件",
|
|
||||||
"CHART_PROV": "Prov 文件",
|
|
||||||
"DOWNLOAD": "下载",
|
|
||||||
"SUMMARY": "概要",
|
|
||||||
"DEPENDENCIES": "依赖",
|
|
||||||
"VALUES": "取值",
|
|
||||||
"OVERVIEW": "总览",
|
|
||||||
"HOME": "首页",
|
|
||||||
"SRC_REPO": "源仓库",
|
|
||||||
"CREATED": "创建时间",
|
|
||||||
"MAINTAINERS": "维护者",
|
|
||||||
"OTHER_MAINTAINERS": "{{ name }} 与其他 {{ number }} 位",
|
|
||||||
"PULLS": "拉取数",
|
|
||||||
"VERSION": "版本",
|
|
||||||
"INSTALL": "安装",
|
|
||||||
"INSTALL_CHART": "安装Chart",
|
|
||||||
"NAME": "名称",
|
|
||||||
"REPO": "仓库",
|
|
||||||
"FILTER_FOR_CHARTS": "过滤Chart",
|
|
||||||
"DELETE": "删除",
|
|
||||||
"OF": "共计",
|
|
||||||
"VERSIONS": "版本",
|
|
||||||
"APP_VERSION": "应用版本",
|
|
||||||
"IMAGES": "镜像",
|
|
||||||
"ENGINE": "引擎",
|
|
||||||
"ACTION": "动作",
|
|
||||||
"UPLOAD": "上传",
|
|
||||||
"DELETE_CHART_VERSION_TITLE": "删除Chart版本",
|
|
||||||
"DELETE_CHART_VERSION": "您要删除chart版本 {{param}} 吗?",
|
|
||||||
"IMPORT": "导入",
|
|
||||||
"EXPORT": "导出",
|
|
||||||
"ADD_REPO": "添加仓库",
|
|
||||||
"SHOW_KV": "展示健值对",
|
|
||||||
"SHOW_YAML": "展示YAML文件",
|
|
||||||
"PLACEHOLDER": "找不到任何的chart!",
|
|
||||||
"NO_VERSION_PLACEHOLDER": "找不到任何的chart版本!",
|
|
||||||
"FILE_UPLOADED": "文件上传成功",
|
|
||||||
"SIGN": "签名",
|
|
||||||
"SIGNED": "已签名",
|
|
||||||
"UNSIGNED": "未签名",
|
|
||||||
"ITEMS": "条记录",
|
|
||||||
"NO_README": "此Chart未提供README文件",
|
|
||||||
"SECURITY": "安全",
|
|
||||||
"ACTIVE": "正常",
|
|
||||||
"DEPRECATED": "废弃",
|
|
||||||
"VERIFY_CHART": "验证Chart",
|
|
||||||
"COMMAND": "命令",
|
|
||||||
"PROV_FILE": "Prov 文件",
|
|
||||||
"READY": "就绪",
|
|
||||||
"NOT_READY": "未就绪",
|
|
||||||
"LABELS": "标签",
|
|
||||||
"ADD_LABEL_TO_CHART_VERSION": "添加标签到此 Chart Version",
|
|
||||||
"STATUS": "状态"
|
|
||||||
},
|
|
||||||
"SUMMARY": {
|
"SUMMARY": {
|
||||||
"QUOTAS": "容量",
|
"QUOTAS": "容量",
|
||||||
"PROJECT_REPOSITORY": "镜像仓库",
|
"PROJECT_REPOSITORY": "镜像仓库",
|
||||||
"PROJECT_HELM_CHART": "Helm Chart",
|
|
||||||
"PROJECT_MEMBER": "成员",
|
"PROJECT_MEMBER": "成员",
|
||||||
"PROJECT_QUOTAS": "容量",
|
"PROJECT_QUOTAS": "容量",
|
||||||
"ARTIFACT_COUNT": "Artifact 数量",
|
"ARTIFACT_COUNT": "Artifact 数量",
|
||||||
|
@ -854,6 +794,7 @@
|
||||||
"SUB_TITLE_SUFIX": "条日志"
|
"SUB_TITLE_SUFIX": "条日志"
|
||||||
},
|
},
|
||||||
"CONFIG": {
|
"CONFIG": {
|
||||||
|
"SECURITY": "安全",
|
||||||
"HISTORY": "历史记录",
|
"HISTORY": "历史记录",
|
||||||
"TITLE": "配置",
|
"TITLE": "配置",
|
||||||
"AUTH": "认证模式",
|
"AUTH": "认证模式",
|
||||||
|
@ -1635,8 +1576,6 @@
|
||||||
"READ": "读取",
|
"READ": "读取",
|
||||||
"CREATE": "创建",
|
"CREATE": "创建",
|
||||||
"ARTIFACT": "Artifact",
|
"ARTIFACT": "Artifact",
|
||||||
"HELM": "Helm Chart",
|
|
||||||
"HELM_VERSION": "Helm Chart Version",
|
|
||||||
"ADD_ROBOT": "添加机器人",
|
"ADD_ROBOT": "添加机器人",
|
||||||
"UPDATE_ROBOT": "更新机器人",
|
"UPDATE_ROBOT": "更新机器人",
|
||||||
"UPDATE_ROBOT_SUCCESSFULLY": "更新机器人成功",
|
"UPDATE_ROBOT_SUCCESSFULLY": "更新机器人成功",
|
||||||
|
@ -1706,7 +1645,6 @@
|
||||||
"STOP": "停止",
|
"STOP": "停止",
|
||||||
"LIST": "查询",
|
"LIST": "查询",
|
||||||
"REPOSITORY": "仓库",
|
"REPOSITORY": "仓库",
|
||||||
"HELM_LABEL": "Helm Chart 标签",
|
|
||||||
"EXPIRES_IN": "有效期剩余",
|
"EXPIRES_IN": "有效期剩余",
|
||||||
"EXPIRED": "已过期"
|
"EXPIRED": "已过期"
|
||||||
},
|
},
|
||||||
|
|
|
@ -648,7 +648,6 @@
|
||||||
"FLATTEN_LEVEL_TIP_1": "'Flatten 1 Level'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
"FLATTEN_LEVEL_TIP_1": "'Flatten 1 Level'(Default): 'a/b/c/d/img' -> 'ns/b/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_2": "'Flatten 2 Levels': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
"FLATTEN_LEVEL_TIP_2": "'Flatten 2 Levels': 'a/b/c/d/img' -> 'ns/c/d/img'",
|
||||||
"FLATTEN_LEVEL_TIP_3": "'Flatten 3 Levels': 'a/b/c/d/img' -> 'ns/d/img'",
|
"FLATTEN_LEVEL_TIP_3": "'Flatten 3 Levels': 'a/b/c/d/img' -> 'ns/d/img'",
|
||||||
"NOTE": "Notes: The Chartmuseum Charts only support the repository structure with 2 path components: 'a/chart'",
|
|
||||||
"BANDWIDTH": "Bandwidth",
|
"BANDWIDTH": "Bandwidth",
|
||||||
"BANDWIDTH_ERROR_TIP": "Please enter -1 or an integer greater than 0",
|
"BANDWIDTH_ERROR_TIP": "Please enter -1 or an integer greater than 0",
|
||||||
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
||||||
|
@ -761,68 +760,9 @@
|
||||||
"MARKDOWN": "支持使用Markdown進行樣式設置",
|
"MARKDOWN": "支持使用Markdown進行樣式設置",
|
||||||
"LAST_MODIFIED": "Last Modified Time"
|
"LAST_MODIFIED": "Last Modified Time"
|
||||||
},
|
},
|
||||||
"HELM_CHART":{
|
|
||||||
"HELMCHARTS":"圖表",
|
|
||||||
"CHARTVERSIONS": "版本",
|
|
||||||
"UPLOAD_TITLE": "上傳chart文件",
|
|
||||||
"CHART_FILE": "Chart 文件",
|
|
||||||
"CHART_PROV": "Prov 文件",
|
|
||||||
"DOWNLOAD": "下載",
|
|
||||||
"SUMMARY": "概要",
|
|
||||||
"DEPENDENCIES": "依賴",
|
|
||||||
"VALUES": "取值",
|
|
||||||
"OVERVIEW": "總覽",
|
|
||||||
"HOME": "首頁",
|
|
||||||
"SRC_REPO":"源倉庫",
|
|
||||||
"CREATED": "創建時間",
|
|
||||||
"MAINTAINERS": "維護者",
|
|
||||||
"OTHER_MAINTAINERS": "{{ name }} 與其他{{ number }} 位",
|
|
||||||
"PULLS": "拉取數",
|
|
||||||
"VERSION": "版本",
|
|
||||||
"INSTALL": "安裝",
|
|
||||||
"INSTALL_CHART": "安裝Chart",
|
|
||||||
"NAME": "名稱",
|
|
||||||
"REPO": "倉庫",
|
|
||||||
"FILTER_FOR_CHARTS": "過濾Chart",
|
|
||||||
"DELETE": "刪除",
|
|
||||||
"OF": "共計",
|
|
||||||
"VERSIONS": "版本",
|
|
||||||
"APP_VERSION": "應用版本",
|
|
||||||
"IMAGES": "鏡像",
|
|
||||||
"ENGINE": "引擎",
|
|
||||||
"ACTION": "動作",
|
|
||||||
"UPLOAD": "上傳",
|
|
||||||
"DELETE_CHART_VERSION_TITLE": "刪除Chart版本",
|
|
||||||
"DELETE_CHART_VERSION": "您要刪除chart版本{{param}} 嗎?",
|
|
||||||
"IMPORT": "導入",
|
|
||||||
"EXPORT": "導出",
|
|
||||||
"ADD_REPO": "添加倉庫",
|
|
||||||
"SHOW_KV": "展示健值對",
|
|
||||||
"SHOW_YAML": "展示YAML文件",
|
|
||||||
"PLACEHOLDER": "找不到任何的chart!",
|
|
||||||
"NO_VERSION_PLACEHOLDER": "找不到任何的chart版本!",
|
|
||||||
"FILE_UPLOADED": "文件上傳成功",
|
|
||||||
"SIGN": "簽名",
|
|
||||||
"SIGNED": "已簽名",
|
|
||||||
"UNSIGNED": "未簽名",
|
|
||||||
"ITEMS": "條記錄",
|
|
||||||
"NO_README": "此Chart未提供README文件",
|
|
||||||
"SECURITY": "安全",
|
|
||||||
"ACTIVE": "正常",
|
|
||||||
"DEPRECATED": "廢棄",
|
|
||||||
"VERIFY_CHART": "驗證Chart",
|
|
||||||
"COMMAND":"命令",
|
|
||||||
"PROV_FILE": "Prov 文件",
|
|
||||||
"READY":"就緒",
|
|
||||||
"NOT_READY": "未就緒",
|
|
||||||
"LABELS": "標籤",
|
|
||||||
"ADD_LABEL_TO_CHART_VERSION": "添加標籤到此Chart Version",
|
|
||||||
"STATUS": "狀態"
|
|
||||||
},
|
|
||||||
"SUMMARY":{
|
"SUMMARY":{
|
||||||
"QUOTAS": "容量",
|
"QUOTAS": "容量",
|
||||||
"PROJECT_REPOSITORY": "鏡像倉庫",
|
"PROJECT_REPOSITORY": "鏡像倉庫",
|
||||||
"PROJECT_HELM_CHART":"Helm Chart",
|
|
||||||
"PROJECT_MEMBER": "成員",
|
"PROJECT_MEMBER": "成員",
|
||||||
"PROJECT_QUOTAS": "容量",
|
"PROJECT_QUOTAS": "容量",
|
||||||
"ARTIFACT_COUNT":"工件數量",
|
"ARTIFACT_COUNT":"工件數量",
|
||||||
|
@ -850,6 +790,7 @@
|
||||||
"SUB_TITLE_SUFIX": "條日誌"
|
"SUB_TITLE_SUFIX": "條日誌"
|
||||||
},
|
},
|
||||||
"CONFIG":{
|
"CONFIG":{
|
||||||
|
"SECURITY": "Security",
|
||||||
"TITLE": "配置",
|
"TITLE": "配置",
|
||||||
"AUTH": "認證模式",
|
"AUTH": "認證模式",
|
||||||
"REPLICATION": "複製",
|
"REPLICATION": "複製",
|
||||||
|
@ -1627,8 +1568,6 @@
|
||||||
"READ": "Read",
|
"READ": "Read",
|
||||||
"CREATE": "Create",
|
"CREATE": "Create",
|
||||||
"ARTIFACT": "Artifact",
|
"ARTIFACT": "Artifact",
|
||||||
"HELM": "Helm Chart",
|
|
||||||
"HELM_VERSION": "Helm Chart Version",
|
|
||||||
"ADD_ROBOT": "Add Robot",
|
"ADD_ROBOT": "Add Robot",
|
||||||
"UPDATE_ROBOT": "Update Robot",
|
"UPDATE_ROBOT": "Update Robot",
|
||||||
"UPDATE_ROBOT_SUCCESSFULLY": "Updated robot successfully",
|
"UPDATE_ROBOT_SUCCESSFULLY": "Updated robot successfully",
|
||||||
|
@ -1698,7 +1637,6 @@
|
||||||
"STOP": "Stop",
|
"STOP": "Stop",
|
||||||
"LIST": "List",
|
"LIST": "List",
|
||||||
"REPOSITORY": "Repository",
|
"REPOSITORY": "Repository",
|
||||||
"HELM_LABEL": "Helm Chart label",
|
|
||||||
"EXPIRES_IN": "Expires in",
|
"EXPIRES_IN": "Expires in",
|
||||||
"EXPIRED": "Expired"
|
"EXPIRED": "Expired"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user