Update for date-validators.

This commit is contained in:
kunw 2017-05-17 18:38:19 +08:00
parent 45ef8adca2
commit b26902448d
8 changed files with 146 additions and 86 deletions

View File

@ -179,11 +179,6 @@ export class CreateEditRuleComponent implements OnInit, AfterViewChecked {
openCreateEditRule(editable: boolean, ruleId?: number | string): void {
this.createEditRuleOpened = true;
this.createEditRule = this.initCreateEditRule;
if(!this.createEditRule) {
return;
}
this.editable = editable;
this.isCreateEndpoint = false;
@ -200,6 +195,7 @@ export class CreateEditRuleComponent implements OnInit, AfterViewChecked {
toPromise<ReplicationRule>(this.replicationService
.getReplicationRule(ruleId))
.then(rule=>{
if(rule) {
this.createEditRule.ruleId = ruleId;
this.createEditRule.name = rule.name;
this.createEditRule.description = rule.description;
@ -210,7 +206,7 @@ export class CreateEditRuleComponent implements OnInit, AfterViewChecked {
this.initVal.description = this.createEditRule.description;
this.initVal.enable = this.createEditRule.enable;
}
)
}).catch(err=>this.errorHandler.error(err));
} else {
this.actionType = ActionType.ADD_NEW;
this.translateService.get('REPLICATION.ADD_POLICY').subscribe(res=>this.modalTitle=res);
@ -243,7 +239,7 @@ export class CreateEditRuleComponent implements OnInit, AfterViewChecked {
getRuleByForm(): ReplicationRule {
let rule: ReplicationRule = this.initReplicationRule;
rule.project_id = this.projectId;
rule.id = this.createEditRule.endpointId;
rule.id = this.createEditRule.ruleId;
rule.name = this.createEditRule.name;
rule.description = this.createEditRule.description;
rule.enabled = this.createEditRule.enable ? 1 : 0;

View File

@ -0,0 +1,50 @@
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Directive, OnChanges, Input, SimpleChanges } from '@angular/core';
import { NG_VALIDATORS, Validator, Validators, ValidatorFn, AbstractControl } from '@angular/forms';
@Directive({
selector: '[dateValidator]',
providers: [{provide: NG_VALIDATORS, useExisting: DateValidatorDirective, multi: true}]
})
export class DateValidatorDirective implements Validator, OnChanges {
@Input() dateValidator: string;
private valFn = Validators.nullValidator;
ngOnChanges(changes: SimpleChanges): void {
const change = changes['dateValidator'];
if (change) {
this.valFn = dateValidator();
} else {
this.valFn = Validators.nullValidator;
}
}
validate(control: AbstractControl): {[key: string]: any} {
return this.valFn(control) || Validators.nullValidator;
}
}
export function dateValidator(): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} => {
let controlValue = control.value;
let valid = true;
if(controlValue) {
const regYMD=/^(19|20)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/g;
const regDMY=/^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$/g;
valid = (regYMD.test(controlValue) || regDMY.test(controlValue));
}
return valid ? Validators.nullValidator : {'dateValidator': { value: controlValue }};
};
}

View File

@ -0,0 +1,9 @@
export const DATETIME_PICKER_TEMPLATE: string = `
<clr-icon shape="date"></clr-icon>
<label aria-haspopup="true" role="tooltip" [class.invalid]="dateInvalid" class="tooltip tooltip-validation tooltip-sm">
<input type="date" #searchTime="ngModel" [(ngModel)]="dateInput" name="searchTime" placeholder="dd/mm/yyyy" dateValidator (change)="doSearch()">
<span *ngIf="dateInvalid" class="tooltip-content">
{{'AUDIT_LOG.INVALID_DATE' | translate }}
</span>
</label>
`;

View File

@ -0,0 +1,43 @@
import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
import { NgModel } from '@angular/forms';
import { DATETIME_PICKER_TEMPLATE } from './datetime-picker.component.html';
@Component({
selector: 'hbr-datetime',
template: DATETIME_PICKER_TEMPLATE
})
export class DatePickerComponent {
@Input() dateInput: string;
@Input() oneDayOffset: boolean;
@ViewChild('searchTime')
searchTime: NgModel;
@Output() search = new EventEmitter<string>();
get dateInvalid(): boolean {
return (this.searchTime.errors && this.searchTime.errors.dateValidator && (this.searchTime.dirty || this.searchTime.touched)) || false;
}
convertDate(strDate: string): string {
if(/^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$/.test(strDate)) {
let parts = strDate.split(/[-\/]/);
strDate = parts[2] /*Year*/ + '-' +parts[1] /*Month*/ + '-' + parts[0] /*Date*/;
}
return strDate;
}
doSearch() {
let searchTerm: string = '';
if(this.searchTime.valid && this.dateInput) {
let timestamp: number = new Date(this.convertDate(this.searchTime.value)).getTime() / 1000;
if(this.oneDayOffset) {
timestamp += 3600 * 24;
}
searchTerm = timestamp.toString();
}
this.search.emit(searchTerm);
}
}

View File

@ -0,0 +1,8 @@
import { Type } from '@angular/core';
import { DatePickerComponent } from './datetime-picker.component';
import { DateValidatorDirective } from './date-validator.directive';
export const DATETIME_PICKER_DIRECTIVES: Type<any>[] = [
DatePickerComponent,
DateValidatorDirective
];

View File

@ -18,6 +18,7 @@ import { SERVICE_CONFIG, IServiceConfig } from './service.config';
import { CONFIRMATION_DIALOG_DIRECTIVES } from './confirmation-dialog/index';
import { INLINE_ALERT_DIRECTIVES } from './inline-alert/index';
import { DATETIME_PICKER_DIRECTIVES } from './datetime-picker/index';
import {
AccessLogService,
@ -137,7 +138,8 @@ export function initConfig(translateService: TranslateService, config: IServiceC
REPLICATION_DIRECTIVES,
LIST_REPLICATION_RULE_DIRECTIVES,
LIST_REPLICATION_JOB_DIRECTIVES,
CREATE_EDIT_RULE_DIRECTIVES
CREATE_EDIT_RULE_DIRECTIVES,
DATETIME_PICKER_DIRECTIVES
],
exports: [
LOG_DIRECTIVES,
@ -152,7 +154,8 @@ export function initConfig(translateService: TranslateService, config: IServiceC
REPLICATION_DIRECTIVES,
LIST_REPLICATION_RULE_DIRECTIVES,
LIST_REPLICATION_JOB_DIRECTIVES,
CREATE_EDIT_RULE_DIRECTIVES
CREATE_EDIT_RULE_DIRECTIVES,
DATETIME_PICKER_DIRECTIVES
],
providers: []
})

View File

@ -39,21 +39,9 @@ export const REPLICATION_TEMPLATE: string = `
<option *ngFor="let j of jobStatus" value="{{j.key}}" [selected]="currentJobStatus.key === j.key">{{j.description | translate}}</option>
</select>
</div>
<div class="flex-items-xs-middle">
<clr-icon shape="date"></clr-icon>
<label for="fromDateInput" aria-haspopup="true" role="tooltip" [class.invalid]="fromTimeInvalid" class="tooltip tooltip-validation invalid tooltip-sm">
<input id="fromDateInput" type="date" #fromTime="ngModel" name="from" [(ngModel)]="search.startTime" dateValidator placeholder="dd/mm/yyyy" (change)="doJobSearchByStartTime(fromTime.value)">
<span *ngIf="fromTimeInvalid" class="tooltip-content">
{{'AUDIT_LOG.INVALID_DATE' | translate }}
</span>
</label>
<clr-icon shape="date"></clr-icon>
<label for="toDateInput" aria-haspopup="true" role="tooltip" [class.invalid]="toTimeInvalid" class="tooltip tooltip-validation invalid tooltip-sm">
<input id="toDateInput" type="date" #toTime="ngModel" name="to" [(ngModel)]="search.endTime" dateValidator placeholder="dd/mm/yyyy" (change)="doJobSearchByEndTime(toTime.value)">
<span *ngIf="toTimeInvalid" class="tooltip-content">
{{'AUDIT_LOG.INVALID_DATE' | translate }}
</span>
</label>
<div class="flex-items-xs-middle">
<hbr-datetime [dateInput]="search.startTime" (search)="doJobSearchByStartTime($event)"></hbr-datetime>
<hbr-datetime [dateInput]="search.endTime" [oneDayOffset]="true" (search)="doJobSearchByEndTime($event)"></hbr-datetime>
</div>
</div>
</div>

View File

@ -99,17 +99,6 @@ export class ReplicationComponent implements OnInit {
@ViewChild(CreateEditRuleComponent)
createEditPolicyComponent: CreateEditRuleComponent;
@ViewChild('fromTime') fromTimeInput: NgModel;
@ViewChild('toTime') toTimeInput: NgModel;
get fromTimeInvalid(): boolean {
return (this.fromTimeInput.errors && this.fromTimeInput.errors.dateValidator && (this.fromTimeInput.dirty || this.fromTimeInput.touched)) || false;
}
get toTimeInvalid(): boolean {
return (this.toTimeInput.errors && this.toTimeInput.errors.dateValidator && (this.toTimeInput.dirty || this.toTimeInput.touched)) || false;
}
constructor(
private errorHandler: ErrorHandler,
private replicationService: ReplicationService,
@ -122,11 +111,6 @@ export class ReplicationComponent implements OnInit {
this.currentJobStatus = this.jobStatus[0];
this.currentJobSearchOption = 0;
this.retrievePolicies();
// let isCreate = this.route.snapshot.parent.queryParams['is_create'];
// if (isCreate && <boolean>isCreate) {
// this.openModal();
// }
}
retrievePolicies(): void {
@ -174,34 +158,30 @@ export class ReplicationComponent implements OnInit {
params.set('page_size', this.search.pageSize + '');
toPromise<any>(this.replicationService
.getJobs(this.search.ruleId, params))
.then(
response=>{
this.jobsTotalRecordCount = response.headers.get('x-total-count');
this.jobsTotalPage = Math.ceil(this.jobsTotalRecordCount / this.search.pageSize);
this.changedJobs = response.json();
this.jobs = this.changedJobs;
for(let i = 0; i < this.jobs.length; i++) {
let j = this.jobs[i];
if(j.status == 'retrying' || j.status == 'error') {
this.translateService.get('REPLICATION.FOUND_ERROR_IN_JOBS')
.subscribe(res=>this.errorHandler.error(res));
break;
}
}
},
error=>this.errorHandler.error(error)
);
.getJobs(this.search.ruleId, params))
.then(
response=>{
this.jobsTotalRecordCount = response.headers.get('x-total-count');
this.jobsTotalPage = Math.ceil(this.jobsTotalRecordCount / this.search.pageSize);
this.changedJobs = response.json();
this.jobs = this.changedJobs;
this.jobs.forEach(j=>{
if(j.status === 'retrying' || j.status === 'error') {
this.translateService.get('REPLICATION.FOUND_ERROR_IN_JOBS')
.subscribe(res=>this.errorHandler.error(res));
}
})
}).catch(error=>this.errorHandler.error(error));
}
selectOneRule(rule: ReplicationRule) {
if(rule) {
this.search.ruleId = rule.id || '';
this.search.repoName = '';
this.search.status = '';
this.currentJobSearchOption = 0;
this.currentJobStatus = { 'key': 'all', 'description': 'REPLICATION.ALL' };
this.fetchReplicationJobs();
if (rule) {
this.search.ruleId = rule.id || '';
this.search.repoName = '';
this.search.status = '';
this.currentJobSearchOption = 0;
this.currentJobStatus = { 'key': 'all', 'description': 'REPLICATION.ALL' };
this.fetchReplicationJobs();
}
}
@ -258,30 +238,13 @@ export class ReplicationComponent implements OnInit {
(option === 1) ? this.currentJobSearchOption = 0 : this.currentJobSearchOption = 1;
}
convertDate(strDate: string): string {
if(/^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$/.test(strDate)) {
let parts = strDate.split(/[-\/]/);
strDate = parts[2] /*Year*/ + '-' +parts[1] /*Month*/ + '-' + parts[0] /*Date*/;
}
return strDate;
}
doJobSearchByStartTime(strDate: string) {
this.search.startTimestamp = '';
if(this.fromTimeInput.valid && strDate) {
strDate = this.convertDate(strDate);
this.search.startTimestamp = new Date(strDate).getTime() / 1000 + '';
}
doJobSearchByStartTime(fromTimestamp: string) {
this.search.startTimestamp = fromTimestamp;
this.fetchReplicationJobs();
}
doJobSearchByEndTime(strDate: string) {
this.search.endTimestamp = '';
if(this.toTimeInput.valid && strDate) {
strDate = this.convertDate(strDate);
let oneDayOffset = 3600 * 24;
this.search.endTimestamp = (new Date(strDate).getTime() / 1000 + oneDayOffset) + '';
}
doJobSearchByEndTime(toTimestamp: string) {
this.search.endTimestamp = toTimestamp;
this.fetchReplicationJobs();
}
}