mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-19 16:55:16 +01:00
Modify tag-retention UI
Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
27245021d3
commit
beed897170
@ -12,9 +12,10 @@ import {
|
||||
clone
|
||||
} from '../utils';
|
||||
import { ErrorHandler } from '../error-handler/index';
|
||||
import { SystemSettingsComponent, VulnerabilityConfigComponent, GcComponent} from './index';
|
||||
import { Configuration } from './config';
|
||||
import { map, catchError } from "rxjs/operators";
|
||||
import { VulnerabilityConfigComponent } from "./vulnerability/vulnerability-config.component";
|
||||
import { GcComponent } from "./gc";
|
||||
import { SystemSettingsComponent } from "./system/system-settings.component";
|
||||
|
||||
@Component({
|
||||
selector: 'hbr-registry-config',
|
||||
|
@ -5,32 +5,7 @@
|
||||
<div class="modal-body no-scrolling">
|
||||
<p class="color-97">{{'TAG_RETENTION.ADD_SUBTITLE' | translate}}</p>
|
||||
<div class="height-72">
|
||||
<div class="clr-row">
|
||||
<div class="clr-col-4">
|
||||
<div class="over-line"></div>
|
||||
<label>{{'TAG_RETENTION.BY_WHAT' | translate}}</label>
|
||||
</div>
|
||||
<div class="clr-col-5">
|
||||
<div class="over-line"></div>
|
||||
<div class="clr-select-wrapper w-100">
|
||||
<select [(ngModel)]="template" class="clr-select w-100">
|
||||
<option *ngFor="let t of metadata?.templates"
|
||||
value="{{t?.rule_template}}">{{getI18nKey(t?.display_text)|translate}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clr-col-3">
|
||||
<div class="over-line">
|
||||
<span *ngIf="template !=='always'">{{getI18nKey(unit)|translate}}</span>
|
||||
</div>
|
||||
<div class="w-100 disabled">
|
||||
<input *ngIf="template !=='always'" [(ngModel)]="num" class="clr-input w-100">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="height-72">
|
||||
<div class="clr-row">
|
||||
<div class="clr-row mt-1">
|
||||
<div class="clr-col-4">
|
||||
<span>{{'TAG_RETENTION.IN_REPOSITORIES' | translate}}</span>
|
||||
</div>
|
||||
@ -55,6 +30,31 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="height-72">
|
||||
<div class="clr-row">
|
||||
<div class="clr-col-4">
|
||||
<div class="over-line"></div>
|
||||
<label>{{'TAG_RETENTION.BY_WHAT' | translate}}</label>
|
||||
</div>
|
||||
<div class="clr-col-5">
|
||||
<div class="over-line"></div>
|
||||
<div class="clr-select-wrapper w-100">
|
||||
<select [(ngModel)]="template" class="clr-select w-100">
|
||||
<option *ngFor="let t of metadata?.templates"
|
||||
value="{{t?.rule_template}}">{{getI18nKey(t?.display_text)|translate}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clr-col-3">
|
||||
<div class="over-line">
|
||||
<span *ngIf="template !=='always' && template !=='none'">{{getI18nKey(unit)|translate}}</span>
|
||||
</div>
|
||||
<div class="w-100 disabled">
|
||||
<input *ngIf="template !=='always'&& template !=='none'" [(ngModel)]="num" class="clr-input w-100">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="height-72">
|
||||
<div class="clr-row">
|
||||
<div class="clr-col-4">
|
||||
|
@ -39,7 +39,7 @@ export class Retention {
|
||||
}
|
||||
|
||||
export class Rule {
|
||||
isDisabled: boolean;
|
||||
disabled: boolean;
|
||||
id: number;
|
||||
priority: number;
|
||||
action: string;
|
||||
@ -51,6 +51,7 @@ export class Rule {
|
||||
};
|
||||
|
||||
constructor() {
|
||||
this.disabled = false;
|
||||
this.action = "retain";
|
||||
this.params = {};
|
||||
this.scope_selectors = {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="clr-row pt-1 fw8">
|
||||
<div class="clr-col">
|
||||
<label class="label-left font-size-54">{{'TAG_RETENTION.RETENTION_RULES' | translate}}</label><span
|
||||
class="badge badge-3 ml-5">{{retention?.rules?.length ? retention?.rules?.length : 0}}</span>
|
||||
class="badge badge-3 ml-5">{{retention?.rules?.length ? retention?.rules?.length : 0}}/15</span>
|
||||
<span *ngIf="loadingRule" class="spinner spinner-inline ml-2">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -10,15 +10,35 @@
|
||||
<ul *ngIf="retention?.rules?.length > 0" class="list-unstyled">
|
||||
<li class="rule" *ngFor="let rule of retention?.rules;let i = index;">
|
||||
<div class="clr-row">
|
||||
<div class="clr-col rule-name">
|
||||
<div class="clr-col-1">
|
||||
<clr-icon *ngIf="!rule?.disabled" class="color-green" shape="success-standard"></clr-icon>
|
||||
<clr-icon *ngIf="rule?.disabled" class="color-red" shape="error-standard"></clr-icon>
|
||||
</div>
|
||||
<div class="clr-col">
|
||||
<span>
|
||||
<clr-icon (click)="openEditor(i)" shape="ellipsis-vertical"
|
||||
class="dropdown-toggle hand"></clr-icon>
|
||||
<div class="dropdown" [ngClass]="{open:ruleIndex===i}">
|
||||
<div class="dropdown-menu">
|
||||
<button *ngIf="!rule?.disabled" type="button" class="dropdown-item"
|
||||
(click)="toggleDisable(i,true)">{{'TAG_RETENTION.DISABLE' | translate}}</button>
|
||||
<button *ngIf="rule?.disabled" type="button" class="dropdown-item"
|
||||
(click)="toggleDisable(i,false)">{{'TAG_RETENTION.ENABLE' | translate}}</button>
|
||||
<button type="button" class="dropdown-item"
|
||||
(click)="editRuleByIndex(i)">{{'TAG_RETENTION.EDIT' | translate}}</button>
|
||||
<button type="button" class="dropdown-item"
|
||||
(click)="deleteRule(i)">{{'TAG_RETENTION.DELETE' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<span class="rule-name">
|
||||
<span>{{'TAG_RETENTION.IN_REPOSITORIES' | translate}}</span>
|
||||
<span>{{getI18nKey(rule?.scope_selectors?.repository[0]?.decoration)|translate}}</span>
|
||||
<span>{{formatPattern(rule?.scope_selectors?.repository[0]?.pattern)}}</span>
|
||||
<span>,</span>
|
||||
<span>{{getI18nKey(rule?.action)|translate}}</span>
|
||||
<span>{{getI18nKey(rule?.template)|translate:{number: rule?.params[rule?.template] } }}</span>
|
||||
<span class="color-97">{{'TAG_RETENTION.WITH_CONDITION' | translate}}</span>
|
||||
<span>{{'TAG_RETENTION.REPO' | translate}}</span>
|
||||
<span>{{getI18nKey(rule?.scope_selectors?.repository[0]?.decoration)|translate}}</span>
|
||||
<span>{{formatPattern(rule?.scope_selectors?.repository[0]?.pattern)}}</span>
|
||||
<span class="color-97 space">{{'TAG_RETENTION.AND' | translate}}</span>
|
||||
<span>{{'TAG_RETENTION.LOWER_TAGS' | translate}}</span>
|
||||
<span>{{getI18nKey(rule?.tag_selectors[0]?.decoration)|translate}}</span>
|
||||
<span>{{formatPattern(rule?.tag_selectors[0]?.pattern)}}</span>
|
||||
@ -30,18 +50,6 @@
|
||||
</ng-container>
|
||||
</span>
|
||||
</div>
|
||||
<div class="clr-col-1">
|
||||
<clr-icon (click)="openEditor(i)" shape="ellipsis-vertical"
|
||||
class="dropdown-toggle hand"></clr-icon>
|
||||
<div class="dropdown" [ngClass]="{open:ruleIndex===i}">
|
||||
<div class="dropdown-menu">
|
||||
<button type="button" class="dropdown-item"
|
||||
(click)="editRuleByIndex(i)">{{'TAG_RETENTION.EDIT' | translate}}</button>
|
||||
<button type="button" class="dropdown-item"
|
||||
(click)="deleteRule(i)">{{'TAG_RETENTION.DELETE' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@ -50,7 +58,7 @@
|
||||
{{'TAG_RETENTION.ADD_RULE_HELP_1' | translate}}
|
||||
</div>
|
||||
<div class="clr-col">
|
||||
<button class="btn btn-link" (click)="openAddRule()">{{'TAG_RETENTION.ADD_RULE' | translate}}</button>
|
||||
<button [disabled]="retention?.rules?.length >= 15" class="btn btn-link" (click)="openAddRule()">{{'TAG_RETENTION.ADD_RULE' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -77,18 +85,15 @@
|
||||
<clr-icon shape="refresh"></clr-icon>
|
||||
</button>
|
||||
</clr-dg-action-bar>
|
||||
<clr-datagrid [clrDgLoading]="loadingExecutions" [(clrDgSingleSelected)]="selectedItem">
|
||||
<clr-datagrid (clrDgRefresh)="clrLoad()" [clrDgLoading]="loadingExecutions" [(clrDgSingleSelected)]="selectedItem">
|
||||
<clr-dg-column>
|
||||
{{'TAG_RETENTION.SERIAL' | translate}}
|
||||
<clr-dg-string-filter [clrDgStringFilter]="serialFilter"></clr-dg-string-filter>
|
||||
</clr-dg-column>
|
||||
<clr-dg-column>
|
||||
{{'TAG_RETENTION.STATUS' | translate}}
|
||||
<clr-dg-string-filter [clrDgStringFilter]="statusFilter"></clr-dg-string-filter>
|
||||
</clr-dg-column>
|
||||
<clr-dg-column>
|
||||
{{'TAG_RETENTION.DRY_RUN' | translate}}
|
||||
<clr-dg-string-filter [clrDgStringFilter]="dryRunFilter"></clr-dg-string-filter>
|
||||
</clr-dg-column>
|
||||
<clr-dg-column>
|
||||
{{'TAG_RETENTION.START_TIME' | translate}}
|
||||
@ -99,7 +104,7 @@
|
||||
<clr-dg-placeholder>
|
||||
{{'TAG_RETENTION.NO_EXECUTION' | translate}}
|
||||
</clr-dg-placeholder>
|
||||
<clr-dg-row *clrDgItems="let execution of executionList;let i = index;" [clrDgItem]="execution">
|
||||
<clr-dg-row *ngFor="let execution of executionList;let i = index;" [clrDgItem]="execution">
|
||||
<clr-dg-cell class="hand" (click)="openDetail(i,execution.id)">
|
||||
<clr-icon shape="angle" [dir]="index===i?'down':'right'"></clr-icon>
|
||||
<span class="ml-1">{{execution.id}}</span>
|
||||
@ -114,6 +119,7 @@
|
||||
<clr-datagrid [clrDgLoading]="loadingHistories" class="w-100">
|
||||
<clr-dg-column>{{'TAG_RETENTION.REPOSITORY' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'TAG_RETENTION.STATUS' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'TAG_RETENTION.RETAINED' | translate}}/{{'TAG_RETENTION.TOTAL' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'TAG_RETENTION.START_TIME' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'TAG_RETENTION.DURATION' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'TAG_RETENTION.LOG' | translate}}</clr-dg-column>
|
||||
@ -123,6 +129,7 @@
|
||||
<clr-dg-row *clrDgItems="let task of historyList" [clrDgItem]="task">
|
||||
<clr-dg-cell>{{task.repository}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{task.status}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{task.retained}}/{{task.total}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{task.start_time|date:'short'}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{task.duration}}</clr-dg-cell>
|
||||
<clr-dg-cell><span (click)="seeLog(task.execution_id,task.id)"
|
||||
@ -141,12 +148,12 @@
|
||||
</clr-dg-row-detail>
|
||||
</clr-dg-row>
|
||||
<clr-dg-footer>
|
||||
<span *ngIf="pagination.totalItems">{{pagination.firstItem + 1}}
|
||||
<span *ngIf="totalCount">{{pagination?.firstItem + 1}}
|
||||
-
|
||||
{{pagination.lastItem + 1 }} {{'ROBOT_ACCOUNT.OF' |
|
||||
{{pagination?.lastItem + 1 }} {{'ROBOT_ACCOUNT.OF' |
|
||||
translate}} </span>
|
||||
{{pagination.totalItems }} {{'ROBOT_ACCOUNT.ITEMS' | translate}}
|
||||
<clr-dg-pagination #pagination [clrDgPageSize]="10"></clr-dg-pagination>
|
||||
<clr-dg-pagination [clrDgTotalItems]="totalCount" #pagination [(clrDgPage)]="currentPage" [clrDgPageSize]="pageSize"></clr-dg-pagination>
|
||||
</clr-dg-footer>
|
||||
</clr-datagrid>
|
||||
</div>
|
||||
|
@ -58,7 +58,7 @@ export class TagRetentionComponent implements OnInit {
|
||||
projectId: number;
|
||||
isRetentionRunOpened: boolean = false;
|
||||
isAbortedOpened: boolean = false;
|
||||
selectedItem: any;
|
||||
selectedItem: any = null;
|
||||
ruleIndex: number = -1;
|
||||
index: number = -1;
|
||||
retentionId: number;
|
||||
@ -66,10 +66,13 @@ export class TagRetentionComponent implements OnInit {
|
||||
editIndex: number;
|
||||
executionList = [];
|
||||
historyList = [];
|
||||
loadingExecutions: boolean = false;
|
||||
loadingHistories: boolean = false;
|
||||
loadingExecutions: boolean = true;
|
||||
loadingHistories: boolean = true;
|
||||
label: string = 'TAG_RETENTION.TRIGGER';
|
||||
loadingRule: boolean = false;
|
||||
currentPage: number = 1;
|
||||
pageSize: number = 10;
|
||||
totalCount: number = 0;
|
||||
@ViewChild('cronScheduleComponent')
|
||||
cronScheduleComponent: CronScheduleComponent;
|
||||
@ViewChild('addRule') addRuleComponent: AddRuleComponent;
|
||||
@ -114,7 +117,6 @@ export class TagRetentionComponent implements OnInit {
|
||||
}
|
||||
this.getRetention();
|
||||
this.getMetadata();
|
||||
this.refreshList();
|
||||
}
|
||||
updateCron(cron: string) {
|
||||
let retention: Retention = clone(this.retention);
|
||||
@ -167,7 +169,20 @@ export class TagRetentionComponent implements OnInit {
|
||||
this.addRuleComponent.isAdd = false;
|
||||
this.ruleIndex = -1;
|
||||
}
|
||||
|
||||
toggleDisable(index, isActionDisable) {
|
||||
let retention: Retention = clone(this.retention);
|
||||
retention.rules[index].disabled = isActionDisable;
|
||||
this.ruleIndex = -1;
|
||||
this.loadingRule = true;
|
||||
this.tagRetentionService.updateRetention(this.retentionId, retention).subscribe(
|
||||
response => {
|
||||
this.loadingRule = false;
|
||||
this.retention = retention;
|
||||
}, error => {
|
||||
this.loadingRule = false;
|
||||
this.errorHandler.error(error);
|
||||
});
|
||||
}
|
||||
deleteRule(index) {
|
||||
let retention: Retention = clone(this.retention);
|
||||
retention.rules.splice(index, 1);
|
||||
@ -210,17 +225,27 @@ export class TagRetentionComponent implements OnInit {
|
||||
|
||||
refreshList() {
|
||||
this.index = -1 ;
|
||||
if (this.retentionId) {
|
||||
this.selectedItem = null;
|
||||
this.loadingExecutions = true;
|
||||
this.tagRetentionService.getRunNowList(this.retentionId).subscribe(
|
||||
res => {
|
||||
if (this.retentionId) {
|
||||
this.tagRetentionService.getRunNowList(this.retentionId, this.currentPage, this.pageSize).subscribe(
|
||||
response => {
|
||||
// Get total count
|
||||
if (response.headers) {
|
||||
let xHeader: string = response.headers.get("x-total-count");
|
||||
if (xHeader) {
|
||||
this.totalCount = parseInt(xHeader, 0);
|
||||
}
|
||||
}
|
||||
this.executionList = response.body as Array<any>;
|
||||
this.loadingExecutions = false;
|
||||
this.executionList = res;
|
||||
TagRetentionComponent.calculateDuration(this.executionList);
|
||||
}, error => {
|
||||
this.loadingExecutions = false;
|
||||
this.errorHandler.error(error);
|
||||
});
|
||||
} else {
|
||||
this.loadingExecutions = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,4 +372,7 @@ export class TagRetentionComponent implements OnInit {
|
||||
getI18nKey(str: string) {
|
||||
return this.tagRetentionService.getI18nKey(str);
|
||||
}
|
||||
clrLoad() {
|
||||
this.refreshList();
|
||||
}
|
||||
}
|
||||
|
@ -12,11 +12,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
import { Injectable } from "@angular/core";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { HttpClient, HttpParams, HttpResponse } from "@angular/common/http";
|
||||
import { Retention, RuleMetadate } from "./retention";
|
||||
import { Observable, throwError as observableThrowError } from "rxjs";
|
||||
import { map, catchError } from "rxjs/operators";
|
||||
import { Project } from "../project";
|
||||
import { buildHttpRequestOptionsWithObserveResponse } from "@harbor/ui";
|
||||
|
||||
@Injectable()
|
||||
export class TagRetentionService {
|
||||
@ -39,6 +40,7 @@ export class TagRetentionService {
|
||||
"withoutLabels": "WITHOUT",
|
||||
"COUNT": "UNIT_COUNT",
|
||||
"DAYS": "UNIT_DAY",
|
||||
"none": "NONE"
|
||||
};
|
||||
|
||||
constructor(
|
||||
@ -96,10 +98,14 @@ export class TagRetentionService {
|
||||
.pipe(catchError(error => observableThrowError(error)));
|
||||
}
|
||||
|
||||
getRunNowList(retentionId) {
|
||||
return this.http.get(`/api/retentions/${retentionId}/executions`)
|
||||
.pipe(map(response => response as Array<any>))
|
||||
.pipe(catchError(error => observableThrowError(error)));
|
||||
getRunNowList(retentionId, page: number, pageSize: number) {
|
||||
let params = new HttpParams();
|
||||
if (page && pageSize) {
|
||||
params = params.set('page', page + '').set('page_size', pageSize + '');
|
||||
}
|
||||
return this.http
|
||||
.get<HttpResponse<Array<any>>>(`/api/retentions/${retentionId}/executions`, buildHttpRequestOptionsWithObserveResponse(params))
|
||||
.pipe(catchError(error => observableThrowError(error)), );
|
||||
}
|
||||
|
||||
getExecutionHistory(retentionId, executionId) {
|
||||
|
@ -1128,11 +1128,11 @@
|
||||
"RULE_TEMPLATE_3": "the most recently pushed # images",
|
||||
"RULE_TEMPLATE_4": "the most recently pulled # images",
|
||||
"RULE_TEMPLATE_5": "always",
|
||||
"ACTION_RETAIN": "Retain",
|
||||
"ACTION_RETAIN": " retain",
|
||||
"UNIT_DAY": "DAYS",
|
||||
"UNIT_COUNT": "COUNT",
|
||||
"NUMBER": "NUMBER",
|
||||
"IN_REPOSITORIES": "Repositories",
|
||||
"IN_REPOSITORIES": "For the repositories",
|
||||
"REP_SEPARATOR": "Enter multiple comma separated repos,repo*,or **",
|
||||
"TAGS": "Tags",
|
||||
"MATCHES_TAGS": "Matches tags",
|
||||
@ -1163,7 +1163,10 @@
|
||||
"LOWER_LABELS": " labels",
|
||||
"WITH_CONDITION": " with",
|
||||
"LOWER_TAGS": " tags",
|
||||
"TRIGGER": "Schedule"
|
||||
"TRIGGER": "Schedule",
|
||||
"RETAINED": "Retained",
|
||||
"TOTAL": "Total",
|
||||
"NONE": "none"
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1126,11 +1126,11 @@
|
||||
"RULE_TEMPLATE_3": "the most recently pushed # images",
|
||||
"RULE_TEMPLATE_4": "the most recently pulled # images",
|
||||
"RULE_TEMPLATE_5": "always",
|
||||
"ACTION_RETAIN": "Retain",
|
||||
"ACTION_RETAIN": " retain",
|
||||
"UNIT_DAY": "DAYS",
|
||||
"UNIT_COUNT": "COUNT",
|
||||
"NUMBER": "NUMBER",
|
||||
"IN_REPOSITORIES": "Repositories",
|
||||
"IN_REPOSITORIES": "For the repositories",
|
||||
"REP_SEPARATOR": "Enter multiple comma separated repos,repo*,or **",
|
||||
"TAGS": "Tags",
|
||||
"MATCHES_TAGS": "Matches tags",
|
||||
@ -1161,7 +1161,10 @@
|
||||
"LOWER_LABELS": " labels",
|
||||
"WITH_CONDITION": " with",
|
||||
"LOWER_TAGS": " tags",
|
||||
"TRIGGER": "Schedule"
|
||||
"TRIGGER": "Schedule",
|
||||
"RETAINED": "Retained",
|
||||
"TOTAL": "Total",
|
||||
"NONE": "none"
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1098,11 +1098,11 @@
|
||||
"RULE_TEMPLATE_3": "the most recently pushed # images",
|
||||
"RULE_TEMPLATE_4": "the most recently pulled # images",
|
||||
"RULE_TEMPLATE_5": "always",
|
||||
"ACTION_RETAIN": "Retain",
|
||||
"ACTION_RETAIN": " retain",
|
||||
"UNIT_DAY": "DAYS",
|
||||
"UNIT_COUNT": "COUNT",
|
||||
"NUMBER": "NUMBER",
|
||||
"IN_REPOSITORIES": "Repositories",
|
||||
"IN_REPOSITORIES": "For the repositories",
|
||||
"REP_SEPARATOR": "Enter multiple comma separated repos,repo*,or **",
|
||||
"TAGS": "Tags",
|
||||
"MATCHES_TAGS": "Matches tags",
|
||||
@ -1133,7 +1133,10 @@
|
||||
"LOWER_LABELS": " labels",
|
||||
"WITH_CONDITION": " with",
|
||||
"LOWER_TAGS": " tags",
|
||||
"TRIGGER": "Schedule"
|
||||
"TRIGGER": "Schedule",
|
||||
"RETAINED": "Retained",
|
||||
"TOTAL": "Total",
|
||||
"NONE": "none"
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1123,11 +1123,11 @@
|
||||
"RULE_TEMPLATE_3": "the most recently pushed # images",
|
||||
"RULE_TEMPLATE_4": "the most recently pulled # images",
|
||||
"RULE_TEMPLATE_5": "always",
|
||||
"ACTION_RETAIN": "Retain",
|
||||
"ACTION_RETAIN": " retain",
|
||||
"UNIT_DAY": "DAYS",
|
||||
"UNIT_COUNT": "COUNT",
|
||||
"NUMBER": "NUMBER",
|
||||
"IN_REPOSITORIES": "Repositories",
|
||||
"IN_REPOSITORIES": "For the repositories",
|
||||
"REP_SEPARATOR": "Enter multiple comma separated repos,repo*,or **",
|
||||
"TAGS": "Tags",
|
||||
"MATCHES_TAGS": "Matches tags",
|
||||
@ -1158,7 +1158,10 @@
|
||||
"LOWER_LABELS": " labels",
|
||||
"WITH_CONDITION": " with",
|
||||
"LOWER_TAGS": " tags",
|
||||
"TRIGGER": "Schedule"
|
||||
"TRIGGER": "Schedule",
|
||||
"RETAINED": "Retained",
|
||||
"TOTAL": "Total",
|
||||
"NONE": "none"
|
||||
}
|
||||
|
||||
|
||||
|
@ -1128,7 +1128,7 @@
|
||||
"UNIT_DAY": "天数",
|
||||
"UNIT_COUNT": "个数",
|
||||
"NUMBER": "数量",
|
||||
"IN_REPOSITORIES": "仓库",
|
||||
"IN_REPOSITORIES": "适用于仓库",
|
||||
"REP_SEPARATOR": "使用逗号分隔repos,repo*和**",
|
||||
"TAGS": "Tags",
|
||||
"MATCHES_TAGS": "匹配tags",
|
||||
@ -1159,7 +1159,10 @@
|
||||
"LOWER_LABELS": "标签",
|
||||
"WITH_CONDITION": "基于条件",
|
||||
"LOWER_TAGS": "tags",
|
||||
"TRIGGER": "定时执行"
|
||||
"TRIGGER": "定时执行",
|
||||
"RETAINED": "保留数",
|
||||
"TOTAL": "总数",
|
||||
"NONE": "空"
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user