Skip to content

Commit 61f2383

Browse files
authored
Merge pull request DSpace#1976 from 4Science/main_1950_DURACOM-101
Common Extendend Regex format for submission-forms
2 parents fa2dc72 + 8f91e14 commit 61f2383

2 files changed

Lines changed: 77 additions & 4 deletions

File tree

src/app/shared/form/builder/parsers/field-parser.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
import {Inject, InjectionToken} from '@angular/core';
1+
import { Inject, InjectionToken } from '@angular/core';
22

33
import uniqueId from 'lodash/uniqueId';
4-
import {DynamicFormControlLayout, DynamicFormControlRelation, MATCH_VISIBLE, OR_OPERATOR} from '@ng-dynamic-forms/core';
4+
import {
5+
DynamicFormControlLayout,
6+
DynamicFormControlRelation,
7+
MATCH_VISIBLE,
8+
OR_OPERATOR
9+
} from '@ng-dynamic-forms/core';
510

611
import { hasValue, isNotEmpty, isNotNull, isNotUndefined } from '../../../empty.util';
712
import { FormFieldModel } from '../models/form-field.model';
@@ -22,6 +27,12 @@ export const SUBMISSION_ID: InjectionToken<string> = new InjectionToken<string>(
2227
export const CONFIG_DATA: InjectionToken<FormFieldModel> = new InjectionToken<FormFieldModel>('configData');
2328
export const INIT_FORM_VALUES: InjectionToken<any> = new InjectionToken<any>('initFormValues');
2429
export const PARSER_OPTIONS: InjectionToken<ParserOptions> = new InjectionToken<ParserOptions>('parserOptions');
30+
/**
31+
* This pattern checks that a regex field uses the common ECMAScript format: `/{pattern}/{flags}`, in which the flags
32+
* are part of the regex, or a simpler one with only pattern `/{pattern}/` or `{pattern}`.
33+
* The regex itself is encapsulated inside a `RegExp` object, that will validate the pattern syntax.
34+
*/
35+
export const REGEX_FIELD_VALIDATOR = new RegExp('(\\/?)(.+)\\1([gimsuy]*)', 'i');
2536

2637
export abstract class FieldParser {
2738

@@ -43,7 +54,7 @@ export abstract class FieldParser {
4354
public abstract modelFactory(fieldValue?: FormFieldMetadataValueObject, label?: boolean): any;
4455

4556
public parse() {
46-
if (((this.getInitValueCount() > 1 && !this.configData.repeatable) || (this.configData.repeatable))
57+
if (((this.getInitValueCount() > 1 && !this.configData.repeatable) || (this.configData.repeatable))
4758
&& (this.configData.input.type !== ParserType.List)
4859
&& (this.configData.input.type !== ParserType.Tag)
4960
) {
@@ -315,6 +326,7 @@ export abstract class FieldParser {
315326
* fields in type bind, made up of a 'match' outcome (make this field visible), an 'operator'
316327
* (OR) and a 'when' condition (the bindValues array).
317328
* @param configuredTypeBindValues array of types from the submission definition (CONFIG_DATA)
329+
* @param typeField
318330
* @private
319331
* @return DynamicFormControlRelation[] array with one relation in it, for type bind matching to show a field
320332
*/
@@ -343,8 +355,21 @@ export abstract class FieldParser {
343355
return hasValue(this.configData.input.regex);
344356
}
345357

358+
/**
359+
* Adds pattern validation to `controlModel`, it uses the encapsulated `configData` to test the regex,
360+
* contained in the input config, against the common `ECMAScript` standard validator {@link REGEX_FIELD_VALIDATOR},
361+
* and creates an equivalent `RegExp` object that will be used during form-validation against the user-input.
362+
* @param controlModel
363+
* @protected
364+
*/
346365
protected addPatternValidator(controlModel) {
347-
const regex = new RegExp(this.configData.input.regex);
366+
const validatorMatcher = this.configData.input.regex.match(REGEX_FIELD_VALIDATOR);
367+
let regex;
368+
if (validatorMatcher != null && validatorMatcher.length > 3) {
369+
regex = new RegExp(validatorMatcher[2], validatorMatcher[3]);
370+
} else {
371+
regex = new RegExp(this.configData.input.regex);
372+
}
348373
controlModel.validators = Object.assign({}, controlModel.validators, { pattern: regex });
349374
controlModel.errorMessages = Object.assign(
350375
{},

src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { DynamicQualdropModel } from '../ds-dynamic-form-ui/models/ds-dynamic-qu
44
import { DynamicOneboxModel } from '../ds-dynamic-form-ui/models/onebox/dynamic-onebox.model';
55
import { DsDynamicInputModel } from '../ds-dynamic-form-ui/models/ds-dynamic-input.model';
66
import { ParserOptions } from './parser-options';
7+
import { FieldParser } from './field-parser';
78

89
describe('OneboxFieldParser test suite', () => {
910
let field1: FormFieldModel;
@@ -101,4 +102,51 @@ describe('OneboxFieldParser test suite', () => {
101102
expect(fieldModel instanceof DynamicOneboxModel).toBe(true);
102103
});
103104

105+
describe('should handle a DynamicOneboxModel with regex', () => {
106+
let regexField: FormFieldModel;
107+
let parser: FieldParser;
108+
let fieldModel: any;
109+
110+
beforeEach(() => {
111+
regexField = {
112+
input: { type: 'onebox', regex: '/[a-z]+/mi' },
113+
label: 'Title',
114+
mandatory: 'false',
115+
repeatable: false,
116+
hints: 'Enter the name of the events, if any.',
117+
selectableMetadata: [
118+
{
119+
metadata: 'title',
120+
controlledVocabulary: 'EVENTAuthority',
121+
closed: false
122+
}
123+
],
124+
languageCodes: []
125+
} as FormFieldModel;
126+
127+
parser = new OneboxFieldParser(submissionId, regexField, initFormValues, parserOptions);
128+
fieldModel = parser.parse();
129+
});
130+
131+
it('should have initialized pattern validator', () => {
132+
expect(fieldModel instanceof DynamicOneboxModel).toBe(true);
133+
expect(fieldModel.validators).not.toBeNull();
134+
expect(fieldModel.validators.pattern).not.toBeNull();
135+
});
136+
137+
it('should mark valid not case sensitive basic characters regex in multiline', () => {
138+
let pattern = fieldModel.validators.pattern as RegExp;
139+
expect(pattern.test('HELLO')).toBe(true);
140+
expect(pattern.test('hello')).toBe(true);
141+
expect(pattern.test('hello\nhello\nhello')).toBe(true);
142+
expect(pattern.test('HeLlO')).toBe(true);
143+
});
144+
145+
it('should be invalid for non-basic alphabet characters', () => {
146+
let pattern = fieldModel.validators.pattern as RegExp;
147+
expect(pattern.test('12345')).toBe(false);
148+
expect(pattern.test('àèìòùáéíóú')).toBe(false);
149+
});
150+
});
151+
104152
});

0 commit comments

Comments
 (0)