mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-24 17:47:46 +01:00
Fix bug for harbor 1.9.0
1.modify the quota message. 2.fix replication ng bug when no filter. 3.fix summary ui style. 4.fix quota-edit page validation when input a large number Signed-off-by: Yogi_Wang <yawang@vmware.com>
This commit is contained in:
parent
679bab9f80
commit
48cb2da09b
@ -78,4 +78,7 @@
|
|||||||
width: 3.5rem;
|
width: 3.5rem;
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ import { InlineAlertComponent } from '../../../inline-alert/inline-alert.compone
|
|||||||
|
|
||||||
import { QuotaUnits, QuotaUnlimited, QUOTA_DANGER_COEFFICIENT, QUOTA_WARNING_COEFFICIENT } from "../../../shared/shared.const";
|
import { QuotaUnits, QuotaUnlimited, QUOTA_DANGER_COEFFICIENT, QUOTA_WARNING_COEFFICIENT } from "../../../shared/shared.const";
|
||||||
|
|
||||||
import { clone, getSuitableUnit, getByte, GetIntegerAndUnit, validateLimit } from '../../../utils';
|
import { clone, getSuitableUnit, getByte, GetIntegerAndUnit, validateCountLimit, validateLimit } from '../../../utils';
|
||||||
import { EditQuotaQuotaInterface, QuotaHardLimitInterface } from '../../../service';
|
import { EditQuotaQuotaInterface, QuotaHardLimitInterface } from '../../../service';
|
||||||
import { distinctUntilChanged } from 'rxjs/operators';
|
import { distinctUntilChanged } from 'rxjs/operators';
|
||||||
|
|
||||||
@ -103,10 +103,16 @@ export class EditProjectQuotasComponent implements OnInit {
|
|||||||
Validators.pattern('(^-1$)|(^([1-9]+)([0-9]+)*$)'),
|
Validators.pattern('(^-1$)|(^([1-9]+)([0-9]+)*$)'),
|
||||||
validateLimit(this.currentForm.form.controls['storageUnit'])
|
validateLimit(this.currentForm.form.controls['storageUnit'])
|
||||||
]);
|
]);
|
||||||
|
this.currentForm.form.controls['count'].setValidators(
|
||||||
|
[
|
||||||
|
Validators.required,
|
||||||
|
Validators.pattern('(^-1$)|(^([1-9]+)([0-9]+)*$)'),
|
||||||
|
validateCountLimit()
|
||||||
|
]);
|
||||||
this.currentForm.form.valueChanges
|
this.currentForm.form.valueChanges
|
||||||
.pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)))
|
.pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)))
|
||||||
.subscribe((data) => {
|
.subscribe((data) => {
|
||||||
['storage', 'storageUnit'].forEach(fieldName => {
|
['storage', 'storageUnit', 'count'].forEach(fieldName => {
|
||||||
if (this.currentForm.form.get(fieldName) && this.currentForm.form.get(fieldName).value !== null) {
|
if (this.currentForm.form.get(fieldName) && this.currentForm.form.get(fieldName).value !== null) {
|
||||||
this.currentForm.form.get(fieldName).updateValueAndValidity();
|
this.currentForm.form.get(fieldName).updateValueAndValidity();
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||||||
// get supportedFilterLabels labels from supportedFilters
|
// get supportedFilterLabels labels from supportedFilters
|
||||||
this.getLabelListFromAdapter(element);
|
this.getLabelListFromAdapter(element);
|
||||||
// only when edit replication rule
|
// only when edit replication rule
|
||||||
if (ruleInfo && this.supportedFilterLabels.length) {
|
if (ruleInfo && ruleInfo.filters && this.supportedFilterLabels.length ) {
|
||||||
this.getLabelListFromRuleInfo(ruleInfo);
|
this.getLabelListFromRuleInfo(ruleInfo);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -90,6 +90,7 @@ export const QuotaUnits = [
|
|||||||
];
|
];
|
||||||
export const QuotaUnlimited = -1;
|
export const QuotaUnlimited = -1;
|
||||||
export const StorageMultipleConstant = 1024;
|
export const StorageMultipleConstant = 1024;
|
||||||
|
export const LimitCount = 100000000;
|
||||||
export enum QuotaUnit {
|
export enum QuotaUnit {
|
||||||
TB = "TB", GB = "GB", MB = "MB", KB = "KB", BIT = "Byte"
|
TB = "TB", GB = "GB", MB = "MB", KB = "KB", BIT = "Byte"
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,9 @@ import { HttpHeaders } from '@angular/common/http';
|
|||||||
import { RequestQueryParams } from './service/RequestQueryParams';
|
import { RequestQueryParams } from './service/RequestQueryParams';
|
||||||
import { DebugElement } from '@angular/core';
|
import { DebugElement } from '@angular/core';
|
||||||
import { Comparator, State, HttpOptionInterface, HttpOptionTextInterface, QuotaUnitInterface } from './service/interface';
|
import { Comparator, State, HttpOptionInterface, HttpOptionTextInterface, QuotaUnitInterface } from './service/interface';
|
||||||
import { QuotaUnits, StorageMultipleConstant } from './shared/shared.const';
|
import { QuotaUnits, StorageMultipleConstant, LimitCount } from './shared/shared.const';
|
||||||
import { AbstractControl } from "@angular/forms";
|
import { AbstractControl } from "@angular/forms";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the different async channels to the Promise<T> type.
|
* Convert the different async channels to the Promise<T> type.
|
||||||
*
|
*
|
||||||
@ -504,15 +505,30 @@ export const GetIntegerAndUnit = (hardNumber: number, quotaUnitsDeep: QuotaUnitI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export const validateLimit = (unitContrl) => {
|
|
||||||
return (control: AbstractControl) => {
|
export const validateCountLimit = () => {
|
||||||
if (getByte(control.value, unitContrl.value) > StorageMultipleConstant * StorageMultipleConstant
|
return (control: AbstractControl) => {
|
||||||
* StorageMultipleConstant * StorageMultipleConstant * StorageMultipleConstant) {
|
if (control.value > LimitCount) {
|
||||||
return {
|
return {
|
||||||
error: true
|
error: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const validateLimit = unitContrl => {
|
||||||
|
return (control: AbstractControl) => {
|
||||||
|
if (
|
||||||
|
// 1024TB
|
||||||
|
getByte(control.value, unitContrl.value) >
|
||||||
|
Math.pow(StorageMultipleConstant, 5)
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
error: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,11 +35,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" *ngIf="isSystemAdmin">
|
<div class="form-group" *ngIf="isSystemAdmin">
|
||||||
<label for="create_project_count-limit" class="required col-md-3 form-group-label-override">{{'PROJECT.COUNT_QUOTA' | translate}}</label>
|
<label for="create_project_count_limit" class="required col-md-3 form-group-label-override">{{'PROJECT.COUNT_QUOTA' | translate}}</label>
|
||||||
<label for="create_project_count-limit" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-left"
|
<label for="create_project_count_limit" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-left"
|
||||||
[class.invalid]="projectCountLimit.invalid && (projectCountLimit.dirty || projectCountLimit.touched)" >
|
[class.invalid]="projectCountLimit.invalid && (projectCountLimit.dirty || projectCountLimit.touched)" >
|
||||||
<input type="text" id="create_project_count-limit" [(ngModel)]="countLimit"
|
<input type="text" id="create_project_count_limit" [(ngModel)]="countLimit"
|
||||||
name="create_project_count-limit" class="input-width"
|
name="create_project_count_limit" class="input-width"
|
||||||
pattern="(^-1$)|(^([1-9]+)([0-9]+)*$)"
|
pattern="(^-1$)|(^([1-9]+)([0-9]+)*$)"
|
||||||
required
|
required
|
||||||
#projectCountLimit="ngModel"
|
#projectCountLimit="ngModel"
|
||||||
@ -56,18 +56,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" *ngIf="isSystemAdmin">
|
<div class="form-group" *ngIf="isSystemAdmin">
|
||||||
<label for="create_project_storage-limit" class="required col-md-3 form-group-label-override">{{'PROJECT.STORAGE_QUOTA' | translate}}</label>
|
<label for="create_project_storage_limit" class="required col-md-3 form-group-label-override">{{'PROJECT.STORAGE_QUOTA' | translate}}</label>
|
||||||
<label for="create_project_storage-limit" aria-haspopup="true" role="tooltip" class="tooltip-quota-storage tooltip tooltip-validation tooltip-md tooltip-top-left"
|
<label for="create_project_storage_limit" aria-haspopup="true" role="tooltip" class="tooltip-quota-storage tooltip tooltip-validation tooltip-md tooltip-top-left"
|
||||||
[class.invalid]="(projectStorageLimit.invalid && (projectStorageLimit.dirty || projectStorageLimit.touched))||projectStorageLimit.errors" >
|
[class.invalid]="(projectStorageLimit.invalid && (projectStorageLimit.dirty || projectStorageLimit.touched))||projectStorageLimit.errors" >
|
||||||
<input type="text" id="create_project_storage-limit" [(ngModel)]="storageLimit"
|
<input type="text" id="create_project_storage_limit" [(ngModel)]="storageLimit"
|
||||||
name="create_project_storage-limit" size="255" class="input-width"
|
name="create_project_storage_limit" size="255" class="input-width"
|
||||||
#projectStorageLimit="ngModel"
|
#projectStorageLimit="ngModel"
|
||||||
autocomplete="off" >
|
autocomplete="off" >
|
||||||
<span class="tooltip-content">
|
<span class="tooltip-content">
|
||||||
{{ 'PROJECT.STORAGE_QUOTA_TIP' | translate }}
|
{{ 'PROJECT.STORAGE_QUOTA_TIP' | translate }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<select clrSelect id="create_project_storage-limit-unit" name="create_project_storage-limit-unit" [(ngModel)]="storageLimitUnit">
|
<select clrSelect id="create_project_storage_limit_unit" name="create_project_storage_limit_unit" [(ngModel)]="storageLimitUnit">
|
||||||
<ng-template ngFor let-quotaUnit [ngForOf]="quotaUnits" let-i="index">
|
<ng-template ngFor let-quotaUnit [ngForOf]="quotaUnits" let-i="index">
|
||||||
<option *ngIf="i>1"[value]="quotaUnit.UNIT">{{ quotaUnit.UNIT }}</option>
|
<option *ngIf="i>1"[value]="quotaUnit.UNIT">{{ quotaUnit.UNIT }}</option>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -34,7 +34,7 @@ import { InlineAlertComponent } from "../../shared/inline-alert/inline-alert.com
|
|||||||
|
|
||||||
import { Project } from "../project";
|
import { Project } from "../project";
|
||||||
import { ProjectService, QuotaUnits, QuotaHardInterface, QuotaUnlimited, getByte
|
import { ProjectService, QuotaUnits, QuotaHardInterface, QuotaUnlimited, getByte
|
||||||
, GetIntegerAndUnit, clone, StorageMultipleConstant, validateLimit} from "@harbor/ui";
|
, GetIntegerAndUnit, clone, StorageMultipleConstant, validateLimit, validateCountLimit} from "@harbor/ui";
|
||||||
import { errorHandler } from '@angular/platform-browser/src/browser';
|
import { errorHandler } from '@angular/platform-browser/src/browser';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -118,17 +118,23 @@ export class CreateProjectComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
this.storageDefaultLimit = this.storageLimit;
|
this.storageDefaultLimit = this.storageLimit;
|
||||||
this.storageDefaultLimitUnit = this.storageLimitUnit;
|
this.storageDefaultLimitUnit = this.storageLimitUnit;
|
||||||
if (this.isSystemAdmin) {
|
if (this.isSystemAdmin) {
|
||||||
this.currentForm.form.controls['create_project_storage-limit'].setValidators(
|
this.currentForm.form.controls['create_project_storage_limit'].setValidators(
|
||||||
[
|
[
|
||||||
Validators.required,
|
Validators.required,
|
||||||
Validators.pattern('(^-1$)|(^([1-9]+)([0-9]+)*$)'),
|
Validators.pattern('(^-1$)|(^([1-9]+)([0-9]+)*$)'),
|
||||||
validateLimit(this.currentForm.form.controls['create_project_storage-limit-unit'])
|
validateLimit(this.currentForm.form.controls['create_project_storage_limit_unit'])
|
||||||
]);
|
]);
|
||||||
|
this.currentForm.form.controls['create_project_count_limit'].setValidators(
|
||||||
|
[
|
||||||
|
Validators.required,
|
||||||
|
Validators.pattern('(^-1$)|(^([1-9]+)([0-9]+)*$)'),
|
||||||
|
validateCountLimit()
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
this.currentForm.form.valueChanges
|
this.currentForm.form.valueChanges
|
||||||
.pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)))
|
.pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)))
|
||||||
.subscribe((data) => {
|
.subscribe((data) => {
|
||||||
['create_project_storage-limit', 'create_project_storage-limit-unit'].forEach(fieldName => {
|
['create_project_storage_limit', 'create_project_storage_limit_unit', 'create_project_count_limit'].forEach(fieldName => {
|
||||||
if (this.currentForm.form.get(fieldName) && this.currentForm.form.get(fieldName).value !== null) {
|
if (this.currentForm.form.get(fieldName) && this.currentForm.form.get(fieldName).value !== null) {
|
||||||
this.currentForm.form.get(fieldName).updateValueAndValidity();
|
this.currentForm.form.get(fieldName).updateValueAndValidity();
|
||||||
}
|
}
|
||||||
|
@ -36,4 +36,19 @@
|
|||||||
progress {
|
progress {
|
||||||
max-height: 0.48rem;
|
max-height: 0.48rem;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
::ng-deep {
|
||||||
|
.progress {
|
||||||
|
&.warning>progress {
|
||||||
|
color: orange;
|
||||||
|
|
||||||
|
&::-webkit-progress-value {
|
||||||
|
background-color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-moz-progress-bar {
|
||||||
|
background-color: orange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -226,9 +226,9 @@
|
|||||||
"OF": "of",
|
"OF": "of",
|
||||||
"COUNT_QUOTA": "Count quota",
|
"COUNT_QUOTA": "Count quota",
|
||||||
"STORAGE_QUOTA": "Storage quota",
|
"STORAGE_QUOTA": "Storage quota",
|
||||||
"COUNT_QUOTA_TIP": "The upper limit of Count Quota should be integers.",
|
"COUNT_QUOTA_TIP": "Please enter an integer between '1' & '100,000,000', '-1' for unlimited.",
|
||||||
"STORAGE_QUOTA_TIP": "The upper limit of Storage Quota should be integers,and maximum upper limit is 1024TB",
|
"STORAGE_QUOTA_TIP": "The upper limit of Storage Quota only takes integer values, capped at '1024TB'. Enter '-1' for unlimited quota",
|
||||||
"QUOTA_UNLIMIT_TIP": "If you want to unlimited this quota, please input -1."
|
"QUOTA_UNLIMIT_TIP": "For unlimited quota, please enter '-1'."
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "Summary",
|
"SUMMARY": "Summary",
|
||||||
|
@ -227,9 +227,9 @@
|
|||||||
"OF": "of",
|
"OF": "of",
|
||||||
"COUNT_QUOTA": "Count quota",
|
"COUNT_QUOTA": "Count quota",
|
||||||
"STORAGE_QUOTA": "Storage quota",
|
"STORAGE_QUOTA": "Storage quota",
|
||||||
"COUNT_QUOTA_TIP": "The upper limit of Count Quota should be integers.",
|
"COUNT_QUOTA_TIP": "Please enter an integer between '1' & '100,000,000', '-1' for unlimited",
|
||||||
"STORAGE_QUOTA_TIP": "The upper limit of Storage Quota should be integers,and maximum upper limit is 1024TB",
|
"STORAGE_QUOTA_TIP": "The upper limit of Storage Quota only takes integer values, capped at '1024TB'. Enter '-1' for unlimited quota",
|
||||||
"QUOTA_UNLIMIT_TIP": "If you want to unlimited this quota, please input -1."
|
"QUOTA_UNLIMIT_TIP": "For unlimited quota, please enter '-1'."
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "Summary",
|
"SUMMARY": "Summary",
|
||||||
|
@ -220,9 +220,9 @@
|
|||||||
"OF": "de",
|
"OF": "de",
|
||||||
"COUNT_QUOTA": "Count quota",
|
"COUNT_QUOTA": "Count quota",
|
||||||
"STORAGE_QUOTA": "Storage quota",
|
"STORAGE_QUOTA": "Storage quota",
|
||||||
"COUNT_QUOTA_TIP": "The upper limit of Count Quota should be integers.",
|
"COUNT_QUOTA_TIP": "Please enter an integer between '1' & '100,000,000', '-1' for unlimited",
|
||||||
"STORAGE_QUOTA_TIP": "The upper limit of Storage Quota should be integers,and maximum upper limit is 1024TB",
|
"STORAGE_QUOTA_TIP": "The upper limit of Storage Quota only takes integer values, capped at '1024TB'. Enter '-1' for unlimited quota",
|
||||||
"QUOTA_UNLIMIT_TIP": "If you want to unlimited this quota, please input -1."
|
"QUOTA_UNLIMIT_TIP": "For unlimited quota, please enter '-1'."
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "Summary",
|
"SUMMARY": "Summary",
|
||||||
|
@ -224,9 +224,9 @@
|
|||||||
"OF": "de",
|
"OF": "de",
|
||||||
"COUNT_QUOTA": "Count quota",
|
"COUNT_QUOTA": "Count quota",
|
||||||
"STORAGE_QUOTA": "Storage quota",
|
"STORAGE_QUOTA": "Storage quota",
|
||||||
"COUNT_QUOTA_TIP": "The upper limit of Count Quota should be integers.",
|
"COUNT_QUOTA_TIP": "Please enter an integer between '1' & '100,000,000', '-1' for unlimited",
|
||||||
"STORAGE_QUOTA_TIP": "The upper limit of Storage Quota should be integers,and maximum upper limit is 1024TB",
|
"STORAGE_QUOTA_TIP": "The upper limit of Storage Quota only takes integer values, capped at '1024TB'. Enter '-1' for unlimited quota",
|
||||||
"QUOTA_UNLIMIT_TIP": "If you want to unlimited this quota, please input -1."
|
"QUOTA_UNLIMIT_TIP": "For unlimited quota, please enter '-1'."
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "Summary",
|
"SUMMARY": "Summary",
|
||||||
|
@ -225,9 +225,9 @@
|
|||||||
"INLINE_HELP_PUBLIC": "当项目设为公开后,任何人都有此项目下镜像的读权限。命令行用户不需要“docker login”就可以拉取此项目下的镜像。",
|
"INLINE_HELP_PUBLIC": "当项目设为公开后,任何人都有此项目下镜像的读权限。命令行用户不需要“docker login”就可以拉取此项目下的镜像。",
|
||||||
"COUNT_QUOTA": "存储数量",
|
"COUNT_QUOTA": "存储数量",
|
||||||
"STORAGE_QUOTA": "存储容量",
|
"STORAGE_QUOTA": "存储容量",
|
||||||
"COUNT_QUOTA_TIP": "存储数量上限应该是整数.",
|
"COUNT_QUOTA_TIP": "请输入一个'1' ~ '100000000'之间的整数, '-1'表示不设置上限。",
|
||||||
"STORAGE_QUOTA_TIP": "存储容量的上限应该设置成为整数.并且最大值不能超过1024TB",
|
"STORAGE_QUOTA_TIP": "存储配额的上限仅采用整数值,上限为1024TB。输入“-1”作为无限制配额。",
|
||||||
"QUOTA_UNLIMIT_TIP": "如果你想要对存储不设置上限,请输入-1."
|
"QUOTA_UNLIMIT_TIP": "如果你想要对存储不设置上限,请输入-1。"
|
||||||
},
|
},
|
||||||
"PROJECT_DETAIL": {
|
"PROJECT_DETAIL": {
|
||||||
"SUMMARY": "概要",
|
"SUMMARY": "概要",
|
||||||
|
Loading…
Reference in New Issue
Block a user