Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WiP] Textfield to support RegExp validation #459

Merged
merged 6 commits into from
Nov 29, 2022
Merged

Conversation

drehelis
Copy link
Contributor

@drehelis drehelis commented Jun 14, 2021

I was in a need for special form of text field validation done on the frontend. This PR tries to solve this by adding regular-expression validation capabilities.

Couple of caveats -

  • Escaping characters such as \ when editing JSON config manually is required.
  • Can't get the Admin UI properly generate regex object. Hence, WiP :-)
  • Add Tests

Parameter config should look like:

{
  "name": "RegExp textfield",
  "max_length": "12",
  "regex": {
    "pattern": "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$",
    "description": "Email address only"
  }
}

Small demo:

Screen.Recording.2021-06-14.at.15.48.54.mov

Copy link
Owner

@bugy bugy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good to me, just a couple of improvement suggestions

@@ -279,6 +282,8 @@ def validate_value(self, value, *, ignore_required=False):
if is_empty(value):
if self.required and not ignore_required:
return 'is not specified'
if self.regex:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is redundant

if self.regex is not None:
regex_pattern = self.regex.get('pattern', None)
if (not is_empty(regex_pattern)):
regex_matched = bool(re.match(regex_pattern, value))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think bool is not needed here

@@ -73,6 +73,12 @@
title="Excluded files"
@error="handleError('Excluded files', $event)"/>
</div>
<div v-if="selectedType === 'text' || selectedType === undefined" class="row">
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be you could combine it with the max length row?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean, move both regex_pattern & regex_description textfields under the same div with max_length?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep

let regexPattern = new RegExp(regex.pattern);
let matchFound = regexPattern.test(value);
if (!matchFound) {
return regex.description
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since description can be empty, please provide a fallback value

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When/if description is left empty, regex.description is the regex pattern itself. The idea is to provide the end-user with a meaningful error message when it comes to regex validation but if, for some reason, you don't, shouldn't print the regex pattern is enough of a fallback value?

return 'does not match regex pattern: ' + self.regex.get('description', regex_pattern)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The python code you are referencing is a backend validation, a user should never see it. It's just an additional safety net.

if (type === 'text') {
if (regex) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do I get started with tests? How do I run them locally on my dev env?
It would be nice to document this on the Wiki somewhere :-)

@@ -289,6 +294,13 @@ def validate_value(self, value, *, ignore_required=False):
return None

if self.type == 'text':
if self.regex is not None:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a couple of tests?

@@ -74,6 +76,7 @@ def _reload(self):
self.min = config.get('min')
self.max = config.get('max')
self.max_length = config.get('max_length')
self.regex = config.get('regex')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also update the method "get_sorted_config" below

@@ -235,6 +249,8 @@ export default {
this.min = config['min'];
this.max = config['max'];
this.max_length = config['max_length'];
this.regex_pattern = get(config, 'regex.pattern', '');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use camelCase for naming in javascript

@bugy bugy mentioned this pull request Jul 5, 2021
@ashishp0911
Copy link

Hello ,
This doesn't seem to work. I tried the exact pattern mentioned in this thread , but there doesn't seem to be any validation on the Input Field or am I missing something

The parameter section below : -

"parameters": [
{
"name": "Input",
"required": true,
"param": "-i",
"env_var": "INP",
"type": "text",
"regex": {
"pattern": "^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$",
"description": "Input Validation"
}
}

Regards,
Ashish .A. Poojary

@bugy
Copy link
Owner

bugy commented Nov 27, 2022

Hi @ashishp0911, how did you test it? This PR was not merged, i.e. not available in script server builds.

@ashishp0911
Copy link

@bugy My Bad , I spoke too early. I mistook the closed case #466 and thought this feature has been implemented in the latest build.
Any updates on the rollout of this feature ?

# Conflicts:
#	src/model/parameter_config.py
#	src/tests/test_utils.py
#	web-src/src/admin/components/scripts-config/ParameterConfigForm.vue
@bugy
Copy link
Owner

bugy commented Nov 27, 2022

I have to apologize to @drehelis for missing that one. To be honest I was waiting for "review request", but I had to check this ticket on my own. Totally my fault for not tracking the project properly.

I made some minor adjustments, and will wait for build before merging. Probably tomorrow.

@bugy bugy merged commit 081b20f into bugy:master Nov 29, 2022
@bugy bugy added this to the 1.18.0 milestone Nov 29, 2022
@drehelis drehelis deleted the regex_text branch November 29, 2022 19:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants