mirror of
https://github.com/goharbor/harbor
synced 2024-09-20 08:35:37 +00:00
Modify cron regex for UI (#14254)
Signed-off-by: sshijun <sshijun@vmware.com>
This commit is contained in:
parent
202342cf0c
commit
74b6bfe731
7
src/portal/package-lock.json
generated
7
src/portal/package-lock.json
generated
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "harbor",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -5391,6 +5391,11 @@
|
|||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"cron-validator": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/cron-validator/-/cron-validator-1.2.1.tgz",
|
||||
"integrity": "sha512-RqdpGSokGFICPc8qAkT38aXqZLLanXghQTK2q7a2x2FabSwDd2ARrazd5ElEWAXzToUcMG4cZIwDH+5RM0q1mA=="
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
"@webcomponents/webcomponentsjs": "^2.0.0",
|
||||
"buffer": "^5.2.1",
|
||||
"core-js": "^2.5.4",
|
||||
"cron-validator": "^1.2.1",
|
||||
"intl": "^1.2.5",
|
||||
"jasmine-core": "^3.3.0",
|
||||
"mutationobserver-shim": "^0.3.2",
|
||||
|
|
|
@ -176,15 +176,16 @@
|
|||
</select>
|
||||
</div>
|
||||
<div formGroupName="trigger_settings" class="clr-form-control">
|
||||
<div [hidden]="isNotSchedule()">
|
||||
<label class="required">Cron String</label>
|
||||
<label for="targetCron" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-sm tooltip-top-right"
|
||||
[class.invalid]="!isNotSchedule() && cronTouched && !cronInputValid(ruleForm.value.trigger?.trigger_settings?.cron || '')">
|
||||
<input (input)="inputInvalid($event)" type="text" name=targetCron id="targetCron" required class="form-control cron-input clr-input" formControlName="cron">
|
||||
<span class="tooltip-content">
|
||||
<div class="flex" [hidden]="isNotSchedule()">
|
||||
<label for="targetCron" class="required">Cron String</label>
|
||||
<div class="clr-control-container" [class.clr-error]="cronInputShouldShowError()">
|
||||
<div class="clr-input-wrapper">
|
||||
<input autocomplete="off" (input)="inputInvalid($event)" type="text" name=targetCron id="targetCron" required class="form-control cron-input clr-input" formControlName="cron">
|
||||
</div>
|
||||
<clr-control-error *ngIf="cronInputShouldShowError()">
|
||||
{{'TOOLTIP.CRON_REQUIRED' | translate }}
|
||||
</span>
|
||||
</label>
|
||||
</clr-control-error>
|
||||
</div>
|
||||
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-lg tooltip-top-left top-7 cron-tooltip">
|
||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||
<div class="tooltip-content table-box">
|
||||
|
|
|
@ -283,4 +283,6 @@ clr-modal {
|
|||
.select-width {
|
||||
min-width:11rem;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||
!this.isRuleNameValid ||
|
||||
(!this.isPushMode && !sourceRegistry ||
|
||||
this.isPushMode && !destRegistry)
|
||||
|| !(!this.isNotSchedule() && cron && this.cronInputValid(this.ruleForm.value.trigger.trigger_settings.cron || '')
|
||||
|| !(!this.isNotSchedule() && cron && cronRegex(this.ruleForm.value.trigger.trigger_settings.cron || '')
|
||||
|| this.isNotSchedule()));
|
||||
}
|
||||
|
||||
|
@ -545,19 +545,13 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
return filtersArray;
|
||||
}
|
||||
cronInputValid(cronValue): boolean {
|
||||
return cronRegex(cronValue);
|
||||
}
|
||||
get cronTouched(): boolean {
|
||||
let triggerControl = this.ruleForm.controls.trigger as FormGroup;
|
||||
if (!triggerControl) {
|
||||
return false;
|
||||
}
|
||||
let trigger_settingsControls = triggerControl.controls.trigger_settings as FormGroup;
|
||||
if (!trigger_settingsControls) {
|
||||
return false;
|
||||
}
|
||||
return trigger_settingsControls.controls.cron.touched || trigger_settingsControls.controls.cron.dirty;
|
||||
cronInputShouldShowError(): boolean {
|
||||
return this.ruleForm && this.ruleForm.get('trigger')
|
||||
&& this.ruleForm.get('trigger').get('trigger_settings')
|
||||
&& this.ruleForm.get('trigger').get('trigger_settings').get('cron')
|
||||
&& (this.ruleForm.get('trigger').get('trigger_settings').get('cron').touched
|
||||
|| this.ruleForm.get('trigger').get('trigger_settings').get('cron').dirty)
|
||||
&& !cronRegex(this.ruleForm.get('trigger').get('trigger_settings').get('cron').value);
|
||||
}
|
||||
stickLabel(value, index) {
|
||||
value.select = !value.select;
|
||||
|
@ -582,6 +576,10 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
|||
if (!e.target.value || (e.target.value && e.target.value.indexOf(PREFIX)) !== 0) {
|
||||
e.target.value = PREFIX;
|
||||
}
|
||||
e.target.value = e.target.value.replace(/\s+/g, ' ');
|
||||
if (e.target.value && e.target.value.split(/\s+/g).length > 6) {
|
||||
e.target.value = e.target.value.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<div class="height-1rem clr-input-wrapper">
|
||||
<label for="targetCron" aria-haspopup="true" role="tooltip" [class.clr-error]="dateInvalid"
|
||||
class="tooltip tooltip-validation tooltip-md tooltip-top-left cron-label">
|
||||
<input type="text" (blur)="blurInvalid()" (input)="inputInvalid($event)" name="targetCron" id="targetCron"
|
||||
<input autocomplete="off" type="text" (blur)="blurInvalid()" (input)="inputInvalid($event)" name="targetCron" id="targetCron"
|
||||
#cronStringInput="ngModel" required class="clr-input form-control ml-1" [(ngModel)]="cronString">
|
||||
<clr-tooltip>
|
||||
<clr-icon clrTooltipTrigger shape="info-circle" size="24"></clr-icon>
|
||||
|
|
|
@ -3,8 +3,9 @@ import { HttpHeaders } from '@angular/common/http';
|
|||
import { RequestQueryParams } from '../services';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { Comparator, State, HttpOptionInterface, HttpOptionTextInterface, QuotaUnitInterface } from '../services';
|
||||
import { QuotaUnits, StorageMultipleConstant, LimitCount } from '../entities/shared.const';
|
||||
import { QuotaUnits, StorageMultipleConstant } from '../entities/shared.const';
|
||||
import { AbstractControl } from "@angular/forms";
|
||||
import { isValidCron } from 'cron-validator';
|
||||
/**
|
||||
* Api levels
|
||||
*/
|
||||
|
@ -463,17 +464,16 @@ export function getChanges(original: any, afterChange: any): { [key: string]: an
|
|||
return changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* validate cron expressions
|
||||
* @param testValue
|
||||
*/
|
||||
export function cronRegex(testValue: any): boolean {
|
||||
const regSecond = "^((([0-9])*|(\\*))(\\-|\\,|\\/)?([0-9])*)*\\s+";
|
||||
const regMinute = "((([0-9])*|(\\*))(\\-|\\,|\\/)?([0-9])*)*\\s+";
|
||||
const regHour = "((([0-9])*|(\\*))(\\-|\\,|\\/)?([0-9])*)*\\s+";
|
||||
const regDay = "((([0-9])*|(\\*|\\?))(\\-|\\,|\\/)?([0-9])*)*\\s+";
|
||||
const regMonth = "((([0-9a-zA-Z])*|(\\*))(\\-|\\,|\\/)?([0-9a-zA-Z])*)*\\s+";
|
||||
const regWeek = "(((([0-9a-zA-Z])*|(\\*|\\?))(\\-|\\,|\\/)?([0-9a-zA-Z])*))*(|\\s)+";
|
||||
const regYear = "((([0-9])*|(\\*|\\?))(\\-|\\,|\\/)?([0-9])*)$";
|
||||
const regEx = regSecond + regMinute + regHour + regDay + regMonth + regWeek + regYear;
|
||||
let reg = new RegExp(regEx, "i");
|
||||
return reg.test(testValue.trim());
|
||||
// must have 6 fields
|
||||
if (testValue && testValue.trim().split(/\s+/g).length < 6) {
|
||||
return false;
|
||||
}
|
||||
return isValidCron(testValue, {seconds: true, alias: true, allowBlankDay: true});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue
Block a user