mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-30 06:03:45 +01:00
UI enhancement for replication namespace (#14818)
Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
a6d92ca807
commit
eec3619df1
@ -0,0 +1,15 @@
|
|||||||
|
export enum Flatten_Level {
|
||||||
|
NO_FLATTING = 0,
|
||||||
|
FLATTEN_LEVEl_1 = 1,
|
||||||
|
FLATTEN_LEVEl_2 = 2,
|
||||||
|
FLATTEN_LEVEl_3 = 3,
|
||||||
|
FLATTEN_ALL = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Flatten_I18n_MAP = {
|
||||||
|
[Flatten_Level.NO_FLATTING]: 'REPLICATION.NO_FLATTING',
|
||||||
|
[Flatten_Level.FLATTEN_LEVEl_1]: 'REPLICATION.FLATTEN_LEVEL_1',
|
||||||
|
[Flatten_Level.FLATTEN_LEVEl_2]: 'REPLICATION.FLATTEN_LEVEL_2',
|
||||||
|
[Flatten_Level.FLATTEN_LEVEl_3]: 'REPLICATION.FLATTEN_LEVEL_3',
|
||||||
|
[Flatten_Level.FLATTEN_ALL]: 'REPLICATION.FLATTEN_ALL',
|
||||||
|
};
|
@ -151,19 +151,48 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--destination namespaces -->
|
<!--destination namespaces -->
|
||||||
<clr-input-container>
|
<div class="clr-form-control">
|
||||||
<label>{{'REPLICATION.DEST_NAMESPACE' | translate}}
|
<label for="dest_namespace" class="clr-control-label">{{'REPLICATION.DESTINATION' | translate}}</label>
|
||||||
<clr-tooltip>
|
<div class="clr-control-container" [class.clr-error]="ruleForm.controls.dest_namespace.touched && ruleForm.controls.dest_namespace.invalid">
|
||||||
|
<div class="clr-input-wrapper">
|
||||||
|
<label class="sub-label">{{'REPLICATION.NAMESPACE' | translate}}:</label>
|
||||||
|
<input autocomplete="off" class="clr-input" formControlName="dest_namespace" type="text" id="dest_namespace" pattern="^[a-z0-9]+(?:[/._-][a-z0-9]+)*$"
|
||||||
|
maxlength="255">
|
||||||
|
<clr-tooltip class="des-tooltip">
|
||||||
<clr-icon clrTooltipTrigger shape="info-circle" size="24"></clr-icon>
|
<clr-icon clrTooltipTrigger shape="info-circle" size="24"></clr-icon>
|
||||||
<clr-tooltip-content clrPosition="top-left" clrSize="md" *clrIfOpen>
|
<clr-tooltip-content clrPosition="top-left" clrSize="md" *clrIfOpen>
|
||||||
<span>{{'TOOLTIP.DESTINATION_NAMESPACE' | translate}}</span>
|
<span>{{'TOOLTIP.DESTINATION_NAMESPACE' | translate}}</span>
|
||||||
</clr-tooltip-content>
|
</clr-tooltip-content>
|
||||||
</clr-tooltip>
|
</clr-tooltip>
|
||||||
</label>
|
</div>
|
||||||
<input clrInput formControlName="dest_namespace" type="text" id="dest_namespace" pattern="^[a-z0-9]+(?:[/._-][a-z0-9]+)*$"
|
<clr-control-error class="margin-left-90px" *ngIf="ruleForm.controls.dest_namespace.touched && ruleForm.controls.dest_namespace.invalid">
|
||||||
class="inputWidth" maxlength="255">
|
{{'REPLICATION.DESTINATION_NAME_TOOLTIP' | translate}}
|
||||||
<clr-control-error *ngIf='ruleForm.controls.dest_namespace.touched && ruleForm.controls.dest_namespace.invalid'>{{'REPLICATION.DESTINATION_NAME_TOOLTIP' | translate}}</clr-control-error>
|
</clr-control-error>
|
||||||
</clr-input-container>
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--destination namespaces -->
|
||||||
|
<div class="clr-form-control">
|
||||||
|
<label for="dest_namespace_replace_count" class="clr-control-label"></label>
|
||||||
|
<div class="clr-control-container" [class.clr-error]="ruleForm.controls.dest_namespace_replace_count.touched && ruleForm.controls.dest_namespace_replace_count.invalid">
|
||||||
|
<div class="input-width flex">
|
||||||
|
<div class="clr-select-wrapper">
|
||||||
|
<label class="sub-label">{{'REPLICATION.REPO_FLATTENING' | translate}}:</label>
|
||||||
|
<select id="dest_namespace_replace_count" formControlName="dest_namespace_replace_count" class="clr-select count-type">
|
||||||
|
<option *ngFor="let item of flattenLevelMap | keyvalue"
|
||||||
|
[value]="item.key">{{item.value | translate}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="clr-input-wrapper">
|
||||||
|
<clr-tooltip class="des-tooltip">
|
||||||
|
<clr-icon clrTooltipTrigger shape="info-circle" size="24"></clr-icon>
|
||||||
|
<clr-tooltip-content clrPosition="top-left" clrSize="md" *clrIfOpen>
|
||||||
|
{{'REPLICATION.FLATTEN_LEVEL_TIP' | translate}}
|
||||||
|
</clr-tooltip-content>
|
||||||
|
</clr-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!--Trigger-->
|
<!--Trigger-->
|
||||||
<div class="clr-form-control">
|
<div class="clr-form-control">
|
||||||
<label class="clr-control-label required">{{'REPLICATION.TRIGGER_MODE' | translate}}</label>
|
<label class="clr-control-label required">{{'REPLICATION.TRIGGER_MODE' | translate}}</label>
|
||||||
@ -216,13 +245,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="loading-center">
|
|
||||||
<span class="spinner spinner-inline" [hidden]="inProgress === false"></span>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" id="ruleBtnCancel" class="btn btn-outline" [disabled]="this.inProgress" (click)="onCancel()">{{ 'BUTTON.CANCEL' | translate }}</button>
|
<button type="button" id="ruleBtnCancel" class="btn btn-outline" [disabled]="inProgress" (click)="onCancel()">{{ 'BUTTON.CANCEL' | translate }}</button>
|
||||||
<button type="submit" id="ruleBtnOk" class="btn btn-primary" (click)="onSubmit()" [disabled]="!isValid || !hasFormChange()">{{ 'BUTTON.SAVE' | translate }}</button>
|
<button type="submit" id="ruleBtnOk" class="btn btn-primary" [clrLoading]="inProgress" (click)="onSubmit()" [disabled]="!isValid || !hasFormChange()">{{ 'BUTTON.SAVE' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
</clr-modal>
|
</clr-modal>
|
||||||
|
@ -286,3 +286,21 @@ clr-modal {
|
|||||||
.flex {
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
.sub-label {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.clr-control-label {
|
||||||
|
width: 8.6rem;
|
||||||
|
}
|
||||||
|
.count {
|
||||||
|
width: 34px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.des-tooltip {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.count-type {
|
||||||
|
width: 158px;
|
||||||
|
}
|
||||||
|
@ -267,7 +267,7 @@ describe("CreateEditRuleComponent (inline template)", () => {
|
|||||||
|
|
||||||
it("Should open modal to edit replication rule", fakeAsync( () => {
|
it("Should open modal to edit replication rule", fakeAsync( () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
comp.openCreateEditRule(mockRule.id);
|
comp.openCreateEditRule(mockRule);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
tick(5000);
|
tick(5000);
|
||||||
const ruleNameInput: HTMLInputElement = fixture.nativeElement.querySelector("#ruleName");
|
const ruleNameInput: HTMLInputElement = fixture.nativeElement.querySelector("#ruleName");
|
||||||
|
@ -33,9 +33,13 @@ import { cronRegex } from "../../../../../shared/units/utils";
|
|||||||
import { FilterType } from "../../../../../shared/entities/shared.const";
|
import { FilterType } from "../../../../../shared/entities/shared.const";
|
||||||
import { RegistryService } from "../../../../../../../ng-swagger-gen/services/registry.service";
|
import { RegistryService } from "../../../../../../../ng-swagger-gen/services/registry.service";
|
||||||
import { Registry } from "../../../../../../../ng-swagger-gen/models/registry";
|
import { Registry } from "../../../../../../../ng-swagger-gen/models/registry";
|
||||||
|
import { Label } from "../../../../../../../ng-swagger-gen/models/label";
|
||||||
|
import { LabelService } from "../../../../../../../ng-swagger-gen/services/label.service";
|
||||||
|
import { Flatten_I18n_MAP, Flatten_Level } from "../../replication";
|
||||||
|
|
||||||
const PREFIX: string = '0 ';
|
const PREFIX: string = '0 ';
|
||||||
const PAGE_SIZE: number = 100;
|
const PAGE_SIZE: number = 100;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "hbr-create-edit-rule",
|
selector: "hbr-create-edit-rule",
|
||||||
templateUrl: "./create-edit-rule.component.html",
|
templateUrl: "./create-edit-rule.component.html",
|
||||||
@ -77,12 +81,14 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
@Output() reload = new EventEmitter<boolean>();
|
@Output() reload = new EventEmitter<boolean>();
|
||||||
|
|
||||||
@ViewChild(InlineAlertComponent, {static: true}) inlineAlert: InlineAlertComponent;
|
@ViewChild(InlineAlertComponent, {static: true}) inlineAlert: InlineAlertComponent;
|
||||||
|
flattenLevelMap = Flatten_I18n_MAP;
|
||||||
constructor(
|
constructor(
|
||||||
private fb: FormBuilder,
|
private fb: FormBuilder,
|
||||||
private repService: ReplicationService,
|
private repService: ReplicationService,
|
||||||
private endpointService: RegistryService,
|
private endpointService: RegistryService,
|
||||||
private errorHandler: ErrorHandler,
|
private errorHandler: ErrorHandler,
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
|
private labelService: LabelService,
|
||||||
) {
|
) {
|
||||||
this.createForm();
|
this.createForm();
|
||||||
}
|
}
|
||||||
@ -95,8 +101,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
this.supportedFilters = adapter.supported_resource_filters;
|
this.supportedFilters = adapter.supported_resource_filters;
|
||||||
this.supportedFilters.forEach(element => {
|
this.supportedFilters.forEach(element => {
|
||||||
this.filters.push(this.initFilter(element.type));
|
this.filters.push(this.initFilter(element.type));
|
||||||
// get supportedFilterLabels labels from supportedFilters
|
|
||||||
this.getLabelListFromAdapter(element);
|
|
||||||
});
|
});
|
||||||
this.supportedTriggers = adapter.supported_triggers;
|
this.supportedTriggers = adapter.supported_triggers;
|
||||||
this.ruleForm.get("trigger").get("type").setValue(this.supportedTriggers[0]);
|
this.ruleForm.get("trigger").get("type").setValue(this.supportedTriggers[0]);
|
||||||
@ -142,6 +146,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.getAllLabels();
|
||||||
this.getAllRegistries();
|
this.getAllRegistries();
|
||||||
this.nameChecker
|
this.nameChecker
|
||||||
.pipe(debounceTime(300))
|
.pipe(debounceTime(300))
|
||||||
@ -227,6 +232,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
src_registry: new FormControl(),
|
src_registry: new FormControl(),
|
||||||
dest_registry: new FormControl(),
|
dest_registry: new FormControl(),
|
||||||
dest_namespace: "",
|
dest_namespace: "",
|
||||||
|
dest_namespace_replace_count: -1,
|
||||||
trigger: this.fb.group({
|
trigger: this.fb.group({
|
||||||
type: '',
|
type: '',
|
||||||
trigger_settings: this.fb.group({
|
trigger_settings: this.fb.group({
|
||||||
@ -261,7 +267,8 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
},
|
},
|
||||||
deletion: false,
|
deletion: false,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
override: true
|
override: true,
|
||||||
|
dest_namespace_replace_count: Flatten_Level.FLATTEN_LEVEl_1
|
||||||
});
|
});
|
||||||
this.isPushMode = true;
|
this.isPushMode = true;
|
||||||
}
|
}
|
||||||
@ -276,6 +283,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
name: rule.name,
|
name: rule.name,
|
||||||
description: rule.description,
|
description: rule.description,
|
||||||
dest_namespace: rule.dest_namespace,
|
dest_namespace: rule.dest_namespace,
|
||||||
|
dest_namespace_replace_count: rule.dest_namespace_replace_count,
|
||||||
src_registry: rule.src_registry,
|
src_registry: rule.src_registry,
|
||||||
dest_registry: rule.dest_registry,
|
dest_registry: rule.dest_registry,
|
||||||
trigger: rule.trigger,
|
trigger: rule.trigger,
|
||||||
@ -284,7 +292,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
override: rule.override
|
override: rule.override
|
||||||
});
|
});
|
||||||
let filtersArray = this.getFilterArray(rule);
|
let filtersArray = this.getFilterArray(rule);
|
||||||
|
|
||||||
this.noSelectedEndpoint = false;
|
this.noSelectedEndpoint = false;
|
||||||
this.setFilter(filtersArray);
|
this.setFilter(filtersArray);
|
||||||
this.copyUpdateForm = clone(this.ruleForm.value);
|
this.copyUpdateForm = clone(this.ruleForm.value);
|
||||||
@ -359,6 +366,8 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
// add new Replication rule
|
// add new Replication rule
|
||||||
this.inProgress = true;
|
this.inProgress = true;
|
||||||
let copyRuleForm: ReplicationRule = this.ruleForm.value;
|
let copyRuleForm: ReplicationRule = this.ruleForm.value;
|
||||||
|
copyRuleForm.dest_namespace_replace_count = copyRuleForm.dest_namespace_replace_count
|
||||||
|
? parseInt(copyRuleForm.dest_namespace_replace_count.toString(), 10) : 0;
|
||||||
if (this.isPushMode) {
|
if (this.isPushMode) {
|
||||||
copyRuleForm.src_registry = null;
|
copyRuleForm.src_registry = null;
|
||||||
} else {
|
} else {
|
||||||
@ -404,26 +413,38 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
openCreateEditRule(ruleId?: number | string): void {
|
openCreateEditRule(rule?: ReplicationRule): void {
|
||||||
this.formReset();
|
this.formReset();
|
||||||
this.copyUpdateForm = clone(this.ruleForm.value);
|
this.copyUpdateForm = clone(this.ruleForm.value);
|
||||||
this.inlineAlert.close();
|
this.inlineAlert.close();
|
||||||
this.noSelectedEndpoint = true;
|
this.noSelectedEndpoint = true;
|
||||||
this.isRuleNameValid = true;
|
this.isRuleNameValid = true;
|
||||||
this.supportedFilterLabels = [];
|
|
||||||
|
|
||||||
|
|
||||||
this.policyId = -1;
|
this.policyId = -1;
|
||||||
this.createEditRuleOpened = true;
|
this.createEditRuleOpened = true;
|
||||||
this.noEndpointInfo = "";
|
this.noEndpointInfo = "";
|
||||||
if (this.targetList.length === 0) {
|
if (this.targetList.length === 0) {
|
||||||
this.noEndpointInfo = "REPLICATION.NO_ENDPOINT_INFO";
|
this.noEndpointInfo = "REPLICATION.NO_ENDPOINT_INFO";
|
||||||
}
|
}
|
||||||
if (ruleId) {
|
if (rule) {
|
||||||
|
if (this.supportedFilterLabels && this.supportedFilterLabels.length) {
|
||||||
|
this.supportedFilterLabels.forEach((label, index) => {
|
||||||
|
if (rule.filters && rule.filters.length) {
|
||||||
|
rule.filters.forEach(f => {
|
||||||
|
if (f.type === FilterType.LABEL && f.value && f.value.length) {
|
||||||
|
f.value.forEach(name => {
|
||||||
|
if (label.name === name) {
|
||||||
|
this.supportedFilterLabels[index].select = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
this.onGoing = true;
|
this.onGoing = true;
|
||||||
this.policyId = +ruleId;
|
this.policyId = +rule.id;
|
||||||
this.headerTitle = "REPLICATION.EDIT_POLICY_TITLE";
|
this.headerTitle = "REPLICATION.EDIT_POLICY_TITLE";
|
||||||
this.repService.getReplicationRule(ruleId)
|
this.repService.getReplicationRule(rule.id)
|
||||||
.subscribe((ruleInfo) => {
|
.subscribe((ruleInfo) => {
|
||||||
let srcRegistryId = ruleInfo.src_registry.id;
|
let srcRegistryId = ruleInfo.src_registry.id;
|
||||||
this.repService.getRegistryInfo(srcRegistryId)
|
this.repService.getRegistryInfo(srcRegistryId)
|
||||||
@ -458,58 +479,11 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
this.setFilter([]);
|
this.setFilter([]);
|
||||||
this.supportedFilters.forEach(element => {
|
this.supportedFilters.forEach(element => {
|
||||||
this.filters.push(this.initFilter(element.type));
|
this.filters.push(this.initFilter(element.type));
|
||||||
// get supportedFilterLabels labels from supportedFilters
|
|
||||||
this.getLabelListFromAdapter(element);
|
|
||||||
// only when edit replication rule
|
|
||||||
if (ruleInfo && ruleInfo.filters && this.supportedFilterLabels.length ) {
|
|
||||||
this.getLabelListFromRuleInfo(ruleInfo);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.supportedTriggers = adapter.supported_triggers;
|
this.supportedTriggers = adapter.supported_triggers;
|
||||||
this.ruleForm.get("trigger").get("type").setValue(this.supportedTriggers[0]);
|
this.ruleForm.get("trigger").get("type").setValue(this.supportedTriggers[0]);
|
||||||
}
|
}
|
||||||
getLabelListFromAdapter(supportedFilter) {
|
|
||||||
if (supportedFilter.type === FilterType.LABEL && supportedFilter.values) {
|
|
||||||
this.supportedFilterLabels = [];
|
|
||||||
supportedFilter.values.forEach( value => {
|
|
||||||
this.supportedFilterLabels.push({
|
|
||||||
name: value,
|
|
||||||
color: '#FFFFFF',
|
|
||||||
select: false,
|
|
||||||
scope: 'g'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getLabelListFromRuleInfo(ruleInfo) {
|
|
||||||
let labelValueObj = ruleInfo.filters.find((currentValue) => {
|
|
||||||
return currentValue.type === FilterType.LABEL;
|
|
||||||
});
|
|
||||||
if (labelValueObj) {
|
|
||||||
for (const labelValue of labelValueObj.value) {
|
|
||||||
let flagLabel = this.supportedFilterLabels.every((currentValue) => {
|
|
||||||
return currentValue.name !== labelValue;
|
|
||||||
});
|
|
||||||
if (flagLabel) {
|
|
||||||
this.supportedFilterLabels = [
|
|
||||||
{
|
|
||||||
name: labelValue,
|
|
||||||
color: '#FFFFFF',
|
|
||||||
select: true,
|
|
||||||
scope: 'g'
|
|
||||||
}, ...this.supportedFilterLabels];
|
|
||||||
}
|
|
||||||
//
|
|
||||||
for (const labelObj of this.supportedFilterLabels) {
|
|
||||||
if (labelObj.name === labelValue) {
|
|
||||||
labelObj.select = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(): void {
|
close(): void {
|
||||||
this.createEditRuleOpened = false;
|
this.createEditRuleOpened = false;
|
||||||
}
|
}
|
||||||
@ -612,4 +586,56 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
getAllLabels(): void {
|
||||||
|
// 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) {
|
||||||
|
arr.forEach(data => {
|
||||||
|
this.supportedFilterLabels.push({
|
||||||
|
name: data.name,
|
||||||
|
color: data.color ? data.color : '#FFFFFF',
|
||||||
|
select: false,
|
||||||
|
scope: 'g'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} 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);
|
||||||
|
});
|
||||||
|
arr.forEach(data => {
|
||||||
|
this.supportedFilterLabels.push({
|
||||||
|
name: data.name,
|
||||||
|
color: data.color ? data.color : '#FFFFFF',
|
||||||
|
select: false,
|
||||||
|
scope: 'g'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
<clr-dg-column class="col-width">{{'REPLICATION.SRC_REGISTRY' | translate}}</clr-dg-column>
|
<clr-dg-column class="col-width">{{'REPLICATION.SRC_REGISTRY' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column class="col-width">{{'REPLICATION.REPLICATION_MODE' | translate}}</clr-dg-column>
|
<clr-dg-column class="col-width">{{'REPLICATION.REPLICATION_MODE' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column class="min-width">{{'REPLICATION.DESTINATION_NAMESPACE' | translate}}</clr-dg-column>
|
<clr-dg-column class="min-width">{{'REPLICATION.DESTINATION_NAMESPACE' | translate}}</clr-dg-column>
|
||||||
|
<clr-dg-column>{{'REPLICATION.DES_REPO_FLATTENING' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'trigger'">{{'REPLICATION.REPLICATION_TRIGGER' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'trigger'">{{'REPLICATION.REPLICATION_TRIGGER' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'description'">{{'REPLICATION.DESCRIPTION' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'description'">{{'REPLICATION.DESCRIPTION' | translate}}</clr-dg-column>
|
||||||
<clr-dg-placeholder>{{'REPLICATION.PLACEHOLDER' | translate }}</clr-dg-placeholder>
|
<clr-dg-placeholder>{{'REPLICATION.PLACEHOLDER' | translate }}</clr-dg-placeholder>
|
||||||
@ -79,6 +80,7 @@
|
|||||||
<clr-dg-cell class="min-width">
|
<clr-dg-cell class="min-width">
|
||||||
{{p.dest_registry ? p.dest_registry.name : ''}} : {{p.dest_namespace? p.dest_namespace: '-'}}
|
{{p.dest_registry ? p.dest_registry.name : ''}} : {{p.dest_namespace? p.dest_namespace: '-'}}
|
||||||
</clr-dg-cell>
|
</clr-dg-cell>
|
||||||
|
<clr-dg-cell>{{(getFlattenLevelString(p.dest_namespace_replace_count)) | translate}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{p.trigger ? p.trigger.type : ''}}</clr-dg-cell>
|
<clr-dg-cell>{{p.trigger ? p.trigger.type : ''}}</clr-dg-cell>
|
||||||
<clr-dg-cell>
|
<clr-dg-cell>
|
||||||
{{p.description ? trancatedDescription(p.description) : '-'}}
|
{{p.description ? trancatedDescription(p.description) : '-'}}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
vertical-align: text-bottom;
|
vertical-align: text-bottom;
|
||||||
}
|
}
|
||||||
.min-width {
|
.min-width {
|
||||||
width: 224px;
|
width: 236px;
|
||||||
}
|
}
|
||||||
.col-width {
|
.col-width {
|
||||||
width: 140px;
|
width: 140px;
|
||||||
|
@ -40,6 +40,7 @@ import { errorHandler } from "../../../../../shared/units/shared.utils";
|
|||||||
import { ConfirmationAcknowledgement } from "../../../../global-confirmation-dialog/confirmation-state-message";
|
import { ConfirmationAcknowledgement } from "../../../../global-confirmation-dialog/confirmation-state-message";
|
||||||
import { ConfirmationMessage } from "../../../../global-confirmation-dialog/confirmation-message";
|
import { ConfirmationMessage } from "../../../../global-confirmation-dialog/confirmation-message";
|
||||||
import { HELM_HUB } from "../../../../../shared/services/endpoint.service";
|
import { HELM_HUB } from "../../../../../shared/services/endpoint.service";
|
||||||
|
import { Flatten_I18n_MAP } from "../../replication";
|
||||||
@Component({
|
@Component({
|
||||||
selector: "hbr-list-replication-rule",
|
selector: "hbr-list-replication-rule",
|
||||||
templateUrl: "./list-replication-rule.component.html",
|
templateUrl: "./list-replication-rule.component.html",
|
||||||
@ -261,4 +262,10 @@ export class ListReplicationRuleComponent {
|
|||||||
isHelmHub(srcRegistry: any): boolean {
|
isHelmHub(srcRegistry: any): boolean {
|
||||||
return srcRegistry && srcRegistry.type === HELM_HUB;
|
return srcRegistry && srcRegistry.type === HELM_HUB;
|
||||||
}
|
}
|
||||||
|
getFlattenLevelString(level: number) {
|
||||||
|
if (level !== null && Flatten_I18n_MAP[level]) {
|
||||||
|
return Flatten_I18n_MAP[level];
|
||||||
|
}
|
||||||
|
return level;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ export class ReplicationComponent implements OnInit, OnDestroy {
|
|||||||
// edit replication rule
|
// edit replication rule
|
||||||
openEditRule(rule: ReplicationRule) {
|
openEditRule(rule: ReplicationRule) {
|
||||||
if (rule) {
|
if (rule) {
|
||||||
this.createEditPolicyComponent.openCreateEditRule(rule.id);
|
this.createEditPolicyComponent.openCreateEditRule(rule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@ export interface ReplicationRule extends Base {
|
|||||||
dest_registry?: any;
|
dest_registry?: any;
|
||||||
src_namespaces: string[];
|
src_namespaces: string[];
|
||||||
dest_namespace?: string;
|
dest_namespace?: string;
|
||||||
|
dest_namespace_replace_count?: number;
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
override: boolean;
|
override: boolean;
|
||||||
}
|
}
|
||||||
|
@ -628,7 +628,16 @@
|
|||||||
"ENABLE_SUCCESS": "Aktivieren der Regel erfolgreich",
|
"ENABLE_SUCCESS": "Aktivieren der Regel erfolgreich",
|
||||||
"ENABLE_FAILED": "Aktivieren der Regel fehlgeschlagen",
|
"ENABLE_FAILED": "Aktivieren der Regel fehlgeschlagen",
|
||||||
"DISABLE_SUCCESS": "Deaktivieren der Regel erfolgreich",
|
"DISABLE_SUCCESS": "Deaktivieren der Regel erfolgreich",
|
||||||
"DISABLE_FAILED": "Deaktivieren der Regel fehlgeschlagen"
|
"DISABLE_FAILED": "Deaktivieren der Regel fehlgeschlagen",
|
||||||
|
"DES_REPO_FLATTENING": "Destination Repository Flattening",
|
||||||
|
"NAMESPACE": "Namespace",
|
||||||
|
"REPO_FLATTENING": "Flattening",
|
||||||
|
"NO_FLATTING": "No Flatting",
|
||||||
|
"FLATTEN_LEVEL_1": "Flatten 1 Level",
|
||||||
|
"FLATTEN_LEVEL_2": "Flatten 2 Levels",
|
||||||
|
"FLATTEN_LEVEL_3": "Flatten 3 Levels",
|
||||||
|
"FLATTEN_ALL": "Flatten All Levels",
|
||||||
|
"FLATTEN_LEVEL_TIP": "Reduce the nested repository structure when copying images. Default 'Flatten 1 Level' will replace the left most repository component with the destination namespace a/b/c/img -> ns/b/c/img. 'Flatten all Levels' is the legacy option used prior v2.3 resulting in a/b/c/img -> ns/img."
|
||||||
},
|
},
|
||||||
"DESTINATION": {
|
"DESTINATION": {
|
||||||
"NEW_ENDPOINT": "Neuer Endpunkt",
|
"NEW_ENDPOINT": "Neuer Endpunkt",
|
||||||
|
@ -545,7 +545,7 @@
|
|||||||
"DISABLE": "Disable",
|
"DISABLE": "Disable",
|
||||||
"REPLICATION_MODE": "Replication Mode",
|
"REPLICATION_MODE": "Replication Mode",
|
||||||
"SRC_REGISTRY": "Source registry",
|
"SRC_REGISTRY": "Source registry",
|
||||||
"DESTINATION_NAMESPACE": "Destination registry:Namespace",
|
"DESTINATION_NAMESPACE": "Destination Registry:Namespace",
|
||||||
"DESTINATION_NAME_IS_REQUIRED": "Endpoint name is required.",
|
"DESTINATION_NAME_IS_REQUIRED": "Endpoint name is required.",
|
||||||
"NEW_DESTINATION": "New Endpoint",
|
"NEW_DESTINATION": "New Endpoint",
|
||||||
"DESTINATION_URL": "Endpoint URL",
|
"DESTINATION_URL": "Endpoint URL",
|
||||||
@ -628,7 +628,16 @@
|
|||||||
"ENABLE_SUCCESS": "Enabled rule successfully",
|
"ENABLE_SUCCESS": "Enabled rule successfully",
|
||||||
"ENABLE_FAILED": "Enabling rule failed",
|
"ENABLE_FAILED": "Enabling rule failed",
|
||||||
"DISABLE_SUCCESS": "Disabled rule successfully",
|
"DISABLE_SUCCESS": "Disabled rule successfully",
|
||||||
"DISABLE_FAILED": "Disabling rule failed"
|
"DISABLE_FAILED": "Disabling rule failed",
|
||||||
|
"DES_REPO_FLATTENING": "Destination Repository Flattening",
|
||||||
|
"NAMESPACE": "Namespace",
|
||||||
|
"REPO_FLATTENING": "Flattening",
|
||||||
|
"NO_FLATTING": "No Flatting",
|
||||||
|
"FLATTEN_LEVEL_1": "Flatten 1 Level",
|
||||||
|
"FLATTEN_LEVEL_2": "Flatten 2 Levels",
|
||||||
|
"FLATTEN_LEVEL_3": "Flatten 3 Levels",
|
||||||
|
"FLATTEN_ALL": "Flatten All Levels",
|
||||||
|
"FLATTEN_LEVEL_TIP": "Reduce the nested repository structure when copying images. Default 'Flatten 1 Level' will replace the left most repository component with the destination namespace a/b/c/img -> ns/b/c/img. 'Flatten all Levels' is the legacy option used prior v2.3 resulting in a/b/c/img -> ns/img."
|
||||||
},
|
},
|
||||||
"DESTINATION": {
|
"DESTINATION": {
|
||||||
"NEW_ENDPOINT": "New Endpoint",
|
"NEW_ENDPOINT": "New Endpoint",
|
||||||
|
@ -629,7 +629,16 @@
|
|||||||
"ENABLE_SUCCESS": "Enabled rule successfully",
|
"ENABLE_SUCCESS": "Enabled rule successfully",
|
||||||
"ENABLE_FAILED": "Enabling rule failed",
|
"ENABLE_FAILED": "Enabling rule failed",
|
||||||
"DISABLE_SUCCESS": "Disabled rule successfully",
|
"DISABLE_SUCCESS": "Disabled rule successfully",
|
||||||
"DISABLE_FAILED": "Disabling rule failed"
|
"DISABLE_FAILED": "Disabling rule failed",
|
||||||
|
"DES_REPO_FLATTENING": "Destination Repository Flattening",
|
||||||
|
"NAMESPACE": "Namespace",
|
||||||
|
"REPO_FLATTENING": "Flattening",
|
||||||
|
"NO_FLATTING": "No Flatting",
|
||||||
|
"FLATTEN_LEVEL_1": "Flatten 1 Level",
|
||||||
|
"FLATTEN_LEVEL_2": "Flatten 2 Levels",
|
||||||
|
"FLATTEN_LEVEL_3": "Flatten 3 Levels",
|
||||||
|
"FLATTEN_ALL": "Flatten All Levels",
|
||||||
|
"FLATTEN_LEVEL_TIP": "Reduce the nested repository structure when copying images. Default 'Flatten 1 Level' will replace the left most repository component with the destination namespace a/b/c/img -> ns/b/c/img. 'Flatten all Levels' is the legacy option used prior v2.3 resulting in a/b/c/img -> ns/img."
|
||||||
},
|
},
|
||||||
"DESTINATION": {
|
"DESTINATION": {
|
||||||
"NEW_ENDPOINT": "Nuevo Endpoint",
|
"NEW_ENDPOINT": "Nuevo Endpoint",
|
||||||
|
@ -618,7 +618,16 @@
|
|||||||
"ENABLE_SUCCESS": "Enabled rule successfully",
|
"ENABLE_SUCCESS": "Enabled rule successfully",
|
||||||
"ENABLE_FAILED": "Enabling rule failed",
|
"ENABLE_FAILED": "Enabling rule failed",
|
||||||
"DISABLE_SUCCESS": "Disabled rule successfully",
|
"DISABLE_SUCCESS": "Disabled rule successfully",
|
||||||
"DISABLE_FAILED": "Disabling rule failed"
|
"DISABLE_FAILED": "Disabling rule failed",
|
||||||
|
"DES_REPO_FLATTENING": "Destination Repository Flattening",
|
||||||
|
"NAMESPACE": "Namespace",
|
||||||
|
"REPO_FLATTENING": "Flattening",
|
||||||
|
"NO_FLATTING": "No Flatting",
|
||||||
|
"FLATTEN_LEVEL_1": "Flatten 1 Level",
|
||||||
|
"FLATTEN_LEVEL_2": "Flatten 2 Levels",
|
||||||
|
"FLATTEN_LEVEL_3": "Flatten 3 Levels",
|
||||||
|
"FLATTEN_ALL": "Flatten All Levels",
|
||||||
|
"FLATTEN_LEVEL_TIP": "Reduce the nested repository structure when copying images. Default 'Flatten 1 Level' will replace the left most repository component with the destination namespace a/b/c/img -> ns/b/c/img. 'Flatten all Levels' is the legacy option used prior v2.3 resulting in a/b/c/img -> ns/img."
|
||||||
},
|
},
|
||||||
"DESTINATION": {
|
"DESTINATION": {
|
||||||
"NEW_ENDPOINT": "Nouveau Point Final",
|
"NEW_ENDPOINT": "Nouveau Point Final",
|
||||||
|
@ -628,7 +628,16 @@
|
|||||||
"ENABLE_SUCCESS": "Enabled rule successfully",
|
"ENABLE_SUCCESS": "Enabled rule successfully",
|
||||||
"ENABLE_FAILED": "Enabling rule failed",
|
"ENABLE_FAILED": "Enabling rule failed",
|
||||||
"DISABLE_SUCCESS": "Disabled rule successfully",
|
"DISABLE_SUCCESS": "Disabled rule successfully",
|
||||||
"DISABLE_FAILED": "Disabling rule failed"
|
"DISABLE_FAILED": "Disabling rule failed",
|
||||||
|
"DES_REPO_FLATTENING": "Destination Repository Flattening",
|
||||||
|
"NAMESPACE": "Namespace",
|
||||||
|
"REPO_FLATTENING": "Flattening",
|
||||||
|
"NO_FLATTING": "No Flatting",
|
||||||
|
"FLATTEN_LEVEL_1": "Flatten 1 Level",
|
||||||
|
"FLATTEN_LEVEL_2": "Flatten 2 Levels",
|
||||||
|
"FLATTEN_LEVEL_3": "Flatten 3 Levels",
|
||||||
|
"FLATTEN_ALL": "Flatten All Levels",
|
||||||
|
"FLATTEN_LEVEL_TIP": "Reduce the nested repository structure when copying images. Default 'Flatten 1 Level' will replace the left most repository component with the destination namespace a/b/c/img -> ns/b/c/img. 'Flatten all Levels' is the legacy option used prior v2.3 resulting in a/b/c/img -> ns/img."
|
||||||
},
|
},
|
||||||
"DESTINATION": {
|
"DESTINATION": {
|
||||||
"NEW_ENDPOINT": "Novo Endpoint",
|
"NEW_ENDPOINT": "Novo Endpoint",
|
||||||
|
@ -628,7 +628,16 @@
|
|||||||
"ENABLE_SUCCESS": "Enabled rule successfully",
|
"ENABLE_SUCCESS": "Enabled rule successfully",
|
||||||
"ENABLE_FAILED": "Enabling rule failed",
|
"ENABLE_FAILED": "Enabling rule failed",
|
||||||
"DISABLE_SUCCESS": "Disabled rule successfully",
|
"DISABLE_SUCCESS": "Disabled rule successfully",
|
||||||
"DISABLE_FAILED": "Disabling rule failed"
|
"DISABLE_FAILED": "Disabling rule failed",
|
||||||
|
"DES_REPO_FLATTENING": "Destination Repository Flattening",
|
||||||
|
"NAMESPACE": "Namespace",
|
||||||
|
"REPO_FLATTENING": "Flattening",
|
||||||
|
"NO_FLATTING": "No Flatting",
|
||||||
|
"FLATTEN_LEVEL_1": "Flatten 1 Level",
|
||||||
|
"FLATTEN_LEVEL_2": "Flatten 2 Levels",
|
||||||
|
"FLATTEN_LEVEL_3": "Flatten 3 Levels",
|
||||||
|
"FLATTEN_ALL": "Flatten All Levels",
|
||||||
|
"FLATTEN_LEVEL_TIP": "Reduce the nested repository structure when copying images. Default 'Flatten 1 Level' will replace the left most repository component with the destination namespace a/b/c/img -> ns/b/c/img. 'Flatten all Levels' is the legacy option used prior v2.3 resulting in a/b/c/img -> ns/img."
|
||||||
},
|
},
|
||||||
"DESTINATION": {
|
"DESTINATION": {
|
||||||
"NEW_ENDPOINT": "Yeni Uç Nokta",
|
"NEW_ENDPOINT": "Yeni Uç Nokta",
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
"RESOURCE_FILTER": "过滤资源的类型。",
|
"RESOURCE_FILTER": "过滤资源的类型。",
|
||||||
"PUSH_BASED": "把资源由本地Harbor推送到远端仓库。",
|
"PUSH_BASED": "把资源由本地Harbor推送到远端仓库。",
|
||||||
"PULL_BASED": "把资源由远端仓库拉取到本地Harbor。",
|
"PULL_BASED": "把资源由远端仓库拉取到本地Harbor。",
|
||||||
"DESTINATION_NAMESPACE": "指定目的端名称空间。如果不填,资源会被放到和源相同的名称空间下。",
|
"DESTINATION_NAMESPACE": "指定目标名称空间。如果不填,资源会被放到和源相同的名称空间下。",
|
||||||
"OVERRIDE": "如果存在具有相同名称的资源,请指定是否覆盖目标上的资源。",
|
"OVERRIDE": "如果存在具有相同名称的资源,请指定是否覆盖目标上的资源。",
|
||||||
"EMAIL": "请使用正确的邮箱地址,比如name@example.com。",
|
"EMAIL": "请使用正确的邮箱地址,比如name@example.com。",
|
||||||
"USER_NAME": "不能包含特殊字符且长度不能超过255。",
|
"USER_NAME": "不能包含特殊字符且长度不能超过255。",
|
||||||
@ -546,7 +546,7 @@
|
|||||||
"DISABLE": "停用",
|
"DISABLE": "停用",
|
||||||
"REPLICATION_MODE": "复制模式",
|
"REPLICATION_MODE": "复制模式",
|
||||||
"SRC_REGISTRY": "源仓库",
|
"SRC_REGISTRY": "源仓库",
|
||||||
"DESTINATION_NAMESPACE": "目标仓库:命名空间",
|
"DESTINATION_NAMESPACE": "目标仓库:名称空间",
|
||||||
"DESTINATION_NAME_IS_REQUIRED": "目标名称为必填项。",
|
"DESTINATION_NAME_IS_REQUIRED": "目标名称为必填项。",
|
||||||
"NEW_DESTINATION": "创建目标",
|
"NEW_DESTINATION": "创建目标",
|
||||||
"DESTINATION_URL": "目标URL",
|
"DESTINATION_URL": "目标URL",
|
||||||
@ -573,6 +573,7 @@
|
|||||||
"ADVANCED": "高级检索",
|
"ADVANCED": "高级检索",
|
||||||
"STATUS": "状态",
|
"STATUS": "状态",
|
||||||
"OPERATION": "操作",
|
"OPERATION": "操作",
|
||||||
|
"REPLICATION_TRIGGER": "触发器",
|
||||||
"CREATION_TIME": "创建时间",
|
"CREATION_TIME": "创建时间",
|
||||||
"UPDATE_TIME": "更新时间",
|
"UPDATE_TIME": "更新时间",
|
||||||
"END_TIME": "结束时间",
|
"END_TIME": "结束时间",
|
||||||
@ -610,15 +611,15 @@
|
|||||||
"DELETE_ENABLED": "默认启用该规则",
|
"DELETE_ENABLED": "默认启用该规则",
|
||||||
"NEW": "新增",
|
"NEW": "新增",
|
||||||
"NAME_TOOLTIP": "项目名称由小写字符、数字和._-组成且至少2个字符并以字符或者数字开头。",
|
"NAME_TOOLTIP": "项目名称由小写字符、数字和._-组成且至少2个字符并以字符或者数字开头。",
|
||||||
"DESTINATION_NAME_TOOLTIP": "目标名称由小写字符、数字和._-/组成且至少2个字符并以字符或者数字开头。",
|
"DESTINATION_NAME_TOOLTIP": "名称空间由小写字符、数字和._-/组成且至少2个字符并以字符或者数字开头。",
|
||||||
"ACKNOWLEDGE": "确认",
|
"ACKNOWLEDGE": "确认",
|
||||||
"RULE_DISABLED": "这个规则因为过滤选项中的标签被删除已经不能用了,更新过滤项以便重新启用规则。",
|
"RULE_DISABLED": "这个规则因为过滤选项中的标签被删除已经不能用了,更新过滤项以便重新启用规则。",
|
||||||
"REPLI_MODE": "复制模式",
|
"REPLI_MODE": "复制模式",
|
||||||
"SOURCE_REGISTRY": "源Registry",
|
"SOURCE_REGISTRY": "源仓库",
|
||||||
"SOURCE_NAMESPACES": "源Namespace",
|
"SOURCE_NAMESPACES": "源名称空间",
|
||||||
"DEST_REGISTRY": "目的Registry",
|
"DEST_REGISTRY": "目标仓库",
|
||||||
"DEST_NAMESPACE": "目的Namespace",
|
"DEST_NAMESPACE": "目标名称空间",
|
||||||
"NAMESPACE_TOOLTIP": "Namespace名称由小写字符、数字和._-组成且至少2个字符并以字符或者数字开头。",
|
"NAMESPACE_TOOLTIP": "名称空间名称由小写字符、数字和._-组成且至少2个字符并以字符或者数字开头。",
|
||||||
"TAG": "Tag",
|
"TAG": "Tag",
|
||||||
"LABEL": "标签",
|
"LABEL": "标签",
|
||||||
"RESOURCE": "资源",
|
"RESOURCE": "资源",
|
||||||
@ -629,7 +630,16 @@
|
|||||||
"ENABLE_SUCCESS": "启用规则成功",
|
"ENABLE_SUCCESS": "启用规则成功",
|
||||||
"ENABLE_FAILED": "启用规则失败",
|
"ENABLE_FAILED": "启用规则失败",
|
||||||
"DISABLE_SUCCESS": "禁用规则成功",
|
"DISABLE_SUCCESS": "禁用规则成功",
|
||||||
"DISABLE_FAILED": "禁用规则失败"
|
"DISABLE_FAILED": "禁用规则失败",
|
||||||
|
"DES_REPO_FLATTENING": "目标仓库扁平化",
|
||||||
|
"NAMESPACE": "名称空间",
|
||||||
|
"REPO_FLATTENING": "仓库扁平化",
|
||||||
|
"NO_FLATTING": "无替换",
|
||||||
|
"FLATTEN_LEVEL_1": "替换1级",
|
||||||
|
"FLATTEN_LEVEL_2": "替换2级",
|
||||||
|
"FLATTEN_LEVEL_3": "替换3级",
|
||||||
|
"FLATTEN_ALL": "替换所有级",
|
||||||
|
"FLATTEN_LEVEL_TIP": "此项用以在复制镜像时减少仓库的层级结构。默认值'替换1级'表示将用目标名称空间替换仓库的最左侧一级,例如:a/b/c/img -> namespace/b/c/img,其他替换层级以此类推。'替换所有级'是v2.3之前版本所使用的行为,它表示 a/b/c/img -> namespace/img。"
|
||||||
},
|
},
|
||||||
"DESTINATION": {
|
"DESTINATION": {
|
||||||
"NEW_ENDPOINT": "新建目标",
|
"NEW_ENDPOINT": "新建目标",
|
||||||
|
@ -625,7 +625,16 @@
|
|||||||
"ENABLE_SUCCESS": "Enabled rule successfully",
|
"ENABLE_SUCCESS": "Enabled rule successfully",
|
||||||
"ENABLE_FAILED": "Enabling rule failed",
|
"ENABLE_FAILED": "Enabling rule failed",
|
||||||
"DISABLE_SUCCESS": "Disabled rule successfully",
|
"DISABLE_SUCCESS": "Disabled rule successfully",
|
||||||
"DISABLE_FAILED": "Disabling rule failed"
|
"DISABLE_FAILED": "Disabling rule failed",
|
||||||
|
"DES_REPO_FLATTENING": "Destination Repository Flattening",
|
||||||
|
"NAMESPACE": "Namespace",
|
||||||
|
"REPO_FLATTENING": "Flattening",
|
||||||
|
"NO_FLATTING": "No Flatting",
|
||||||
|
"FLATTEN_LEVEL_1": "Flatten 1 Level",
|
||||||
|
"FLATTEN_LEVEL_2": "Flatten 2 Levels",
|
||||||
|
"FLATTEN_LEVEL_3": "Flatten 3 Levels",
|
||||||
|
"FLATTEN_ALL": "Flatten All Levels",
|
||||||
|
"FLATTEN_LEVEL_TIP": "Reduce the nested repository structure when copying images. Default 'Flatten 1 Level' will replace the left most repository component with the destination namespace a/b/c/img -> ns/b/c/img. 'Flatten all Levels' is the legacy option used prior v2.3 resulting in a/b/c/img -> ns/img."
|
||||||
},
|
},
|
||||||
"DESTINATION":{
|
"DESTINATION":{
|
||||||
"NEW_ENDPOINT": "新建目標",
|
"NEW_ENDPOINT": "新建目標",
|
||||||
|
Loading…
Reference in New Issue
Block a user