Optimization for tag-retention UI

Signed-off-by: Shijun Sun (c) <sshijun@vmware.com>
This commit is contained in:
Shijun Sun (c) 2019-07-30 17:27:40 +08:00 committed by AllForNothing
parent dcc79ca2a4
commit cb6a426c7d
11 changed files with 109 additions and 27 deletions

View File

@ -3,6 +3,8 @@ import { Type } from "@angular/core";
import { CronScheduleComponent } from "./cron-schedule.component"; import { CronScheduleComponent } from "./cron-schedule.component";
import { CronTooltipComponent } from "./cron-tooltip/cron-tooltip.component"; import { CronTooltipComponent } from "./cron-tooltip/cron-tooltip.component";
export * from "./cron-schedule.component";
export * from './cron-tooltip/cron-tooltip.component';
export const CRON_SCHEDULE_DIRECTIVES: Type<any>[] = [ export const CRON_SCHEDULE_DIRECTIVES: Type<any>[] = [
CronScheduleComponent, CronScheduleComponent,
CronTooltipComponent CronTooltipComponent

View File

@ -27,4 +27,5 @@ export * from "./gridview/index";
export * from "./repository-gridview/index"; export * from "./repository-gridview/index";
export * from "./operation/index"; export * from "./operation/index";
export * from "./_animations/index"; export * from "./_animations/index";
export * from "./cron-schedule/index";

View File

@ -32,7 +32,7 @@ export class Retention {
this.trigger = { this.trigger = {
kind: "Schedule", kind: "Schedule",
settings: { settings: {
cron: "@daily", cron: "0 0 0 * * *",
} }
}; };
} }

View File

@ -1,9 +1,9 @@
<div class="clr-row pt-1 fw8"> <div class="clr-row pt-1 fw8">
<div class="clr-col-2"> <div class="clr-col">
<label class="fw9-l">{{'TAG_RETENTION.RETENTION_RULES' | translate}}</label><span <label class="label-left font-size-54">{{'TAG_RETENTION.RETENTION_RULES' | translate}}</label><span
class="badge badge-3 clr-offset-1">{{retention?.rules?.length ? retention?.rules?.length : 0}}</span> class="badge badge-3 ml-5">{{retention?.rules?.length ? retention?.rules?.length : 0}}</span>
<span *ngIf="loadingRule" class="spinner spinner-inline ml-2">Loading...</span>
</div> </div>
</div> </div>
<div class="clr-row pt-1"> <div class="clr-row pt-1">
<div class="clr-col"> <div class="clr-col">
@ -45,14 +45,9 @@
</div> </div>
</li> </li>
</ul> </ul>
<div class="clr-row pt-1"> <div class="v-center clr-row pt-1">
<div class="clr-col-5 color-97"> <div class="clr-col-5 color-97 font-size-54">
<div> {{'TAG_RETENTION.ADD_RULE_HELP_1' | translate}}
<span>{{'TAG_RETENTION.ADD_RULE_HELP_1' | translate}}</span>
</div>
<div>
<span>{{'TAG_RETENTION.ADD_RULE_HELP_2' | translate}}</span>
</div>
</div> </div>
<div class="clr-col"> <div class="clr-col">
<button class="btn btn-link" (click)="openAddRule()">{{'TAG_RETENTION.ADD_RULE' | translate}}</button> <button class="btn btn-link" (click)="openAddRule()">{{'TAG_RETENTION.ADD_RULE' | translate}}</button>
@ -60,8 +55,11 @@
</div> </div>
</div> </div>
</div> </div>
<div class="cron-selection">
<cron-selection #cronScheduleComponent [labelCurrent]="label" [labelEdit]='label' [originCron]='originCron()' (inputvalue)="updateCron($event)"></cron-selection>
</div>
<div class="clr-row pt-1"> <div class="clr-row pt-1">
<div class="clr-col-2 pt-2"><label class="fw9-l">{{'TAG_RETENTION.RETENTION_RUNS' | translate}}</label></div> <div class="clr-col-2 pt-2"><label class="label-left font-size-54">{{'TAG_RETENTION.RETENTION_RUNS' | translate}}</label></div>
<div class="clr-col-10"> <div class="clr-col-10">
<clr-dg-action-bar> <clr-dg-action-bar>
<button [disabled]="!(retention?.rules?.length > 0)" class="btn btn-outline" <button [disabled]="!(retention?.rules?.length > 0)" class="btn btn-outline"
@ -71,7 +69,9 @@
<button [disabled]="!(retention?.rules?.length > 0)" class="btn btn-outline" <button [disabled]="!(retention?.rules?.length > 0)" class="btn btn-outline"
(click)="whatIfRun()">{{'TAG_RETENTION.WHAT_IF_RUN' | translate}}</button> (click)="whatIfRun()">{{'TAG_RETENTION.WHAT_IF_RUN' | translate}}</button>
<button [disabled]="!(selectedItem && (selectedItem.status ==='InProgress' || selectedItem.status ==='Running'))" <button [disabled]="!(selectedItem && (selectedItem.status ==='InProgress' || selectedItem.status ==='Running'))"
class="btn btn-outline" (click)="abortRun()">{{'TAG_RETENTION.ABORT' | translate}}</button> class="btn btn-outline" (click)="abortRun()">
<clr-icon shape="stop"></clr-icon>
<span class="ml-5">{{'TAG_RETENTION.ABORT' | translate}}</span></button>
<button [disabled]="!retentionId" class="btn btn-outline" <button [disabled]="!retentionId" class="btn btn-outline"
(click)="refreshList()"> (click)="refreshList()">
<clr-icon shape="refresh"></clr-icon> <clr-icon shape="refresh"></clr-icon>

View File

@ -11,8 +11,7 @@
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
font-size: 0.6rem; font-size: .541667rem;
font-weight: 500;
} }
.ml-5 { .ml-5 {
@ -44,3 +43,18 @@
opacity: 0; opacity: 0;
z-index: 999; z-index: 999;
} }
.cron-selection {
margin-top: 20px;
display: flex;
align-items: center;
}
.label-left {
color: #000;
}
.v-center {
height: 48px;
line-height: 48px;
}
.font-size-54 {
font-size: .541667rem;
}

View File

@ -19,12 +19,20 @@ import { TagRetentionService } from "./tag-retention.service";
import { Retention, Rule } from "./retention"; import { Retention, Rule } from "./retention";
import { Project } from "../project"; import { Project } from "../project";
import { clone, ErrorHandler } from "@harbor/ui"; import { clone, ErrorHandler } from "@harbor/ui";
import { OriginCron } from "@harbor/ui";
import { CronScheduleComponent } from "@harbor/ui";
const MIN = 60000; const MIN = 60000;
const SEC = 1000; const SEC = 1000;
const MIN_STR = "min"; const MIN_STR = "min";
const SEC_STR = "sec"; const SEC_STR = "sec";
const SCHEDULE_TYPE = {
NONE: "None",
DAILY: "Daily",
WEEKLY: "Weekly",
HOURLY: "Hourly",
CUSTOM: "Custom"
};
@Component({ @Component({
selector: 'tag-retention', selector: 'tag-retention',
templateUrl: './tag-retention.component.html', templateUrl: './tag-retention.component.html',
@ -48,7 +56,6 @@ export class TagRetentionComponent implements OnInit {
} }
}; };
projectId: number; projectId: number;
addRuleOpened: boolean = false;
isRetentionRunOpened: boolean = false; isRetentionRunOpened: boolean = false;
isAbortedOpened: boolean = false; isAbortedOpened: boolean = false;
selectedItem: any; selectedItem: any;
@ -61,15 +68,36 @@ export class TagRetentionComponent implements OnInit {
historyList = []; historyList = [];
loadingExecutions: boolean = false; loadingExecutions: boolean = false;
loadingHistories: boolean = false; loadingHistories: boolean = false;
dryRun: boolean = false; label: string = 'TAG_RETENTION.TRIGGER';
loadingRule: boolean = false;
@ViewChild('cronScheduleComponent')
cronScheduleComponent: CronScheduleComponent;
@ViewChild('addRule') addRuleComponent: AddRuleComponent; @ViewChild('addRule') addRuleComponent: AddRuleComponent;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private tagRetentionService: TagRetentionService, private tagRetentionService: TagRetentionService,
private errorHandler: ErrorHandler, private errorHandler: ErrorHandler,
) { ) {
} }
originCron(): OriginCron {
let originCron: OriginCron = {
type: SCHEDULE_TYPE.DAILY,
cron: "0 0 0 * * *"
};
originCron.cron = this.retention.trigger.settings.cron;
if (originCron.cron === "") {
originCron.type = SCHEDULE_TYPE.NONE;
} else if (originCron.cron === "0 0 * * * *") {
originCron.type = SCHEDULE_TYPE.HOURLY;
} else if (originCron.cron === "0 0 0 * * *") {
originCron.type = SCHEDULE_TYPE.DAILY;
} else if (originCron.cron === "0 0 0 * * 0") {
originCron.type = SCHEDULE_TYPE.WEEKLY;
} else {
originCron.type = SCHEDULE_TYPE.CUSTOM;
}
return originCron;
}
ngOnInit() { ngOnInit() {
this.projectId = +this.route.snapshot.parent.params['id']; this.projectId = +this.route.snapshot.parent.params['id'];
@ -88,7 +116,27 @@ export class TagRetentionComponent implements OnInit {
this.getMetadata(); this.getMetadata();
this.refreshList(); this.refreshList();
} }
updateCron(cron: string) {
let retention: Retention = clone(this.retention);
retention.trigger.settings.cron = cron;
if (!this.retentionId) {
this.tagRetentionService.createRetention(retention).subscribe(
response => {
this.cronScheduleComponent.isEditMode = false;
this.refreshAfterCreatRetention();
}, error => {
this.errorHandler.error(error);
});
} else {
this.tagRetentionService.updateRetention(this.retentionId, retention).subscribe(
response => {
this.cronScheduleComponent.isEditMode = false;
this.retention = retention;
}, error => {
this.errorHandler.error(error);
});
}
}
getMetadata() { getMetadata() {
this.tagRetentionService.getRetentionMetadata().subscribe( this.tagRetentionService.getRetentionMetadata().subscribe(
response => { response => {
@ -103,8 +151,10 @@ export class TagRetentionComponent implements OnInit {
this.tagRetentionService.getRetention(this.retentionId).subscribe( this.tagRetentionService.getRetention(this.retentionId).subscribe(
response => { response => {
this.retention = response; this.retention = response;
this.loadingRule = false;
}, error => { }, error => {
this.errorHandler.error(error); this.errorHandler.error(error);
this.loadingRule = false;
}); });
} }
} }
@ -122,10 +172,13 @@ export class TagRetentionComponent implements OnInit {
let retention: Retention = clone(this.retention); let retention: Retention = clone(this.retention);
retention.rules.splice(index, 1); retention.rules.splice(index, 1);
this.ruleIndex = -1; this.ruleIndex = -1;
this.loadingRule = true;
this.tagRetentionService.updateRetention(this.retentionId, retention).subscribe( this.tagRetentionService.updateRetention(this.retentionId, retention).subscribe(
response => { response => {
this.loadingRule = false;
this.retention = retention; this.retention = retention;
}, error => { }, error => {
this.loadingRule = false;
this.errorHandler.error(error); this.errorHandler.error(error);
}); });
} }
@ -241,11 +294,13 @@ export class TagRetentionComponent implements OnInit {
this.retentionId = response.metadata.retention_id; this.retentionId = response.metadata.retention_id;
this.getRetention(); this.getRetention();
}, error => { }, error => {
this.loadingRule = false;
this.errorHandler.error(error); this.errorHandler.error(error);
}); });
} }
clickAdd(rule) { clickAdd(rule) {
this.loadingRule = true;
if (this.addRuleComponent.isAdd) { if (this.addRuleComponent.isAdd) {
let retention: Retention = clone(this.retention); let retention: Retention = clone(this.retention);
retention.rules.push(rule); retention.rules.push(rule);
@ -255,12 +310,15 @@ export class TagRetentionComponent implements OnInit {
this.refreshAfterCreatRetention(); this.refreshAfterCreatRetention();
}, error => { }, error => {
this.errorHandler.error(error); this.errorHandler.error(error);
this.loadingRule = false;
}); });
} else { } else {
this.tagRetentionService.updateRetention(this.retentionId, retention).subscribe( this.tagRetentionService.updateRetention(this.retentionId, retention).subscribe(
response => { response => {
this.loadingRule = false;
this.retention = retention; this.retention = retention;
}, error => { }, error => {
this.loadingRule = false;
this.errorHandler.error(error); this.errorHandler.error(error);
}); });
} }
@ -270,8 +328,10 @@ export class TagRetentionComponent implements OnInit {
this.tagRetentionService.updateRetention(this.retentionId, retention).subscribe( this.tagRetentionService.updateRetention(this.retentionId, retention).subscribe(
response => { response => {
this.retention = retention; this.retention = retention;
this.loadingRule = false;
}, error => { }, error => {
this.errorHandler.error(error); this.errorHandler.error(error);
this.loadingRule = false;
}); });
} }
} }

View File

@ -1161,7 +1161,8 @@
"WITHOUT": " without ", "WITHOUT": " without ",
"LOWER_LABELS": " labels", "LOWER_LABELS": " labels",
"WITH_CONDITION": " with", "WITH_CONDITION": " with",
"LOWER_TAGS": " tags" "LOWER_TAGS": " tags",
"TRIGGER": "Schedule"
} }
} }

View File

@ -1159,7 +1159,8 @@
"WITHOUT": " without ", "WITHOUT": " without ",
"LOWER_LABELS": " labels", "LOWER_LABELS": " labels",
"WITH_CONDITION": " with", "WITH_CONDITION": " with",
"LOWER_TAGS": " tags" "LOWER_TAGS": " tags",
"TRIGGER": "Schedule"
} }
} }

View File

@ -1131,7 +1131,8 @@
"WITHOUT": " without ", "WITHOUT": " without ",
"LOWER_LABELS": " labels", "LOWER_LABELS": " labels",
"WITH_CONDITION": " with", "WITH_CONDITION": " with",
"LOWER_TAGS": " tags" "LOWER_TAGS": " tags",
"TRIGGER": "Schedule"
} }
} }

View File

@ -1156,7 +1156,8 @@
"WITHOUT": " without ", "WITHOUT": " without ",
"LOWER_LABELS": " labels", "LOWER_LABELS": " labels",
"WITH_CONDITION": " with", "WITH_CONDITION": " with",
"LOWER_TAGS": " tags" "LOWER_TAGS": " tags",
"TRIGGER": "Schedule"
} }

View File

@ -1157,7 +1157,8 @@
"WITHOUT": "没有", "WITHOUT": "没有",
"LOWER_LABELS": "标签", "LOWER_LABELS": "标签",
"WITH_CONDITION": "基于条件", "WITH_CONDITION": "基于条件",
"LOWER_TAGS": "tags" "LOWER_TAGS": "tags",
"TRIGGER": "定时执行"
} }
} }