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

Mark datepicker field as valid only if it's value is an instance of Date #392

Merged
merged 5 commits into from
Jul 2, 2019

Conversation

romanblanco
Copy link
Member

@romanblanco romanblanco commented Jun 10, 2019

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1692863
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1692980

Steps to Reproduce from BZ ticket:

  1. create a new service dialog with a datepicker field
  2. add the service dialog to the catalog
  3. in the service catalog select the service dialog and click on order
  4. Clear the date from the field and enter "test" in the datepicker field

@JPrause
Copy link
Member

JPrause commented Jun 13, 2019

@romanblanco can you assign a reviewer. We need this for the 5.10.6 build on Monday, June 17

@romanblanco
Copy link
Member Author

@himdel could you do the review?

@himdel
Copy link
Contributor

himdel commented Jun 13, 2019

Will do :)

@himdel himdel self-requested a review June 13, 2019 14:25
@@ -171,6 +171,11 @@ export default class DialogDataService {
}
}

if (field.type === 'DialogFieldDateControl') {
validation.isValid = (fieldValue instanceof Date);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm worried this will fail for dynamic fields - the server can't send a Date object, so we have to convert, and that's called only from $onInit it seems, not when updating a field

Copy link
Member Author

Choose a reason for hiding this comment

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

I believe that setupField should take care of converting data to Date object, maybe I just need to include DialogFieldDateTimeControl, anyway I need to verify this works.

if (field.type === 'DialogFieldDateTimeControl') {
if (_.isNull(field.values) || _.isUndefined(field.values)) {
field.dateField = field.timeField = new Date();
} else {
field.dateField = field.timeField = new Date(data.values);
}
}

Copy link
Member Author

@romanblanco romanblanco Jun 14, 2019

Choose a reason for hiding this comment

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

looks like the Dialog User doesn't work well if the value is updated from Automate.

I've applied a simple Automate method (thanks @d-m-u):

new_date = Time.utc(2019, 07, 02)
$evm.object['value'] = new_date

I'm not sure if the method is applied correctly, but from what happens I think the problem is in the Dialog User anyway:

  1. I cleared out the field so it's empty -> the Submit button correctly gets disabled
  2. I checked checkbox that should update the dynamic DialogFieldDateControl field
  3. The field is updated with today's date (not utc(2019, 07, 02)) -> the Submit button is still disabled

If I pick the date from calendar manually, the button gets enabled, as expected.

Now I'm using this to log the data to evm.log:

trigger = $evm.root['dialog_trigger']

$evm.log(:info, "======= trigger value #{trigger}")
if trigger == "t"
  new_date = Time.utc(2019, 07, 02)
  $evm.object['value'] = new_date
  $evm.log(:info, "======== new date #{$evm.object['value']}")
else # "f"
  $evm.object['value'] = ''
  $evm.log(:info, "======== clearing up date #{$evm.object['value']}")
end

but can't get the log into evm.log nor automate.log, and in setupField I'm getting only undefined, so I might be using the Automate wrong as well.

Copy link
Member Author

@romanblanco romanblanco Jun 17, 2019

Choose a reason for hiding this comment

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

With f0cb00c I'm getting the values as Date() even after using Automate, only the validation doesn't get run.

I'm not receiving any values into value attribute, so using default_value.

There's a lot of confusion with using values, value or default_value. I'm not sure what exactly is correct, also I think DialogFieldDateTimePicker won't work correctly if it works with value instead of values.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, it is pretty confusing. On the automate side, you want to set the 'value' key like you're doing above:
$evm.object['value'] = something

However, on the ui-components side, for most of the field types, default_value is the value that is getting passed back from the refresh API call that we should be looking at to determine what to show to the user after a refresh happens. We changed it in 7dcb1f7. For sorted items, values is the key we use since it needs to be a list, and default_value is simply the one that is selected from that list.

On the ui-components side, because of the way datetime controls work, there's special logic for the date and time parts because the default_value comes in as a string (cause it's just a JSON response), and then it gets parsed and separated into a dateField and a timeField since the controls are separate.

@romanblanco
Copy link
Member Author

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1702497 (updated in description)

@romanblanco romanblanco changed the title Mark datepicker field as valid only if it's value is an instance of Date [WIP] Mark datepicker field as valid only if it's value is an instance of Date Jun 17, 2019
@miq-bot miq-bot added the wip label Jun 17, 2019
@romanblanco romanblanco force-pushed the bz1692863 branch 2 times, most recently from ec8f8c6 to 306c507 Compare June 20, 2019 13:01
@miq-bot
Copy link
Member

miq-bot commented Jun 20, 2019

Checked commits romanblanco/ui-components@1744f67~...306c507 with ruby 2.3.3, rubocop 0.69.0, haml-lint 0.20.0, and yamllint 1.10.0
0 files checked, 0 offenses detected
Everything looks fine. 👍

@romanblanco
Copy link
Member Author

update:

the validation works now, the only issue is if the value comes from automate, the form does not refresh by itself.

After hovering the form, the 'Submit' button gets updated:

Screencast from 2019-06-24 12-43-45

If the value is updated manually by the user, changesHappened is called. $doCheck is called if the new value comes from Automate. I've tried to use

this.onUpdate({ dialogFieldName: this.field.name, value: fieldValue });

called by changesHappened, expecting the form would get updated, but still no change. I'm still trying to find what's missing.

@romanblanco romanblanco changed the title [WIP] Mark datepicker field as valid only if it's value is an instance of Date Mark datepicker field as valid only if it's value is an instance of Date Jun 24, 2019
@miq-bot miq-bot removed the wip label Jun 24, 2019
@romanblanco
Copy link
Member Author

romanblanco commented Jun 24, 2019

It seems that the issue is not introduced by the changes in this PR. Creating a new issue (#396), removing [WIP] label.

if (_.isNull(field.default_value) || _.isUndefined(field.default_value)) {
field.dateField = field.timeField = new Date();
} else {
field.dateField = field.timeField = new Date(data.default_value);
Copy link
Member

Choose a reason for hiding this comment

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

timeField both here and on line 48 I don't think mean anything for a DialogFieldDateControl, only if the type is a DialogFieldDateTimeControl.

@eclarizio
Copy link
Member

If the value is updated manually by the user, changesHappened is called. $doCheck is called if the new value comes from Automate. I've tried to use
this.onUpdate({ dialogFieldName: this.field.name, value: fieldValue });
called by changesHappened, expecting the form would get updated, but still no change. I'm still trying to find what's missing.

Actually, I think it's similar if you have a text box with an automate method that changes the regex validation it doesn't update until you focus/unfocus the field. So, I would agree with that being a separate issue and limiting this PR to simply not allowing something like test to be input into a date field.

@martinpovolny
Copy link
Member

@eclarizio : please, check again.

Copy link
Member

@eclarizio eclarizio left a comment

Choose a reason for hiding this comment

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

@romanblanco One small comment, I think it's still good overall, will approve after a response to my comment.

if (data.default_value) {
defaultValue = data.default_value;
}

if (data.type === 'DialogFieldDateControl' || data.type === 'DialogFieldDateTimeControl') {
defaultValue = data.dateField ? new Date(data.dateField) : new Date();
Copy link
Member

Choose a reason for hiding this comment

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

I think my only concern here is if data.dateField is going to ever be populated for DialogFieldDateTimeControl, because up on line 46, we are only setting field.dateField for DialogFieldDateControl. Is that a problem?

Copy link
Member Author

@romanblanco romanblanco Jun 28, 2019

Choose a reason for hiding this comment

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

because up on line 46, we are only setting field.dateField for DialogFieldDateControl

@eclarizio we're setting the data.dateField and data.timeField for DialogFieldDateTimeControl right above the DialogFieldDateControl, on line L38-L44:

 38     if (field.type === 'DialogFieldDateTimeControl') {
 39       if (_.isNull(field.values) || _.isUndefined(field.values)) {
 40         field.dateField = field.timeField = new Date();
 41       } else {
 42         field.dateField = field.timeField = new Date(data.values);
 43       }
 44     }

update: altough, it's possible that we're not using the data.values here correctly, and should be using data.default_value.

update 2: using default_value for DialogFieldDateTimeControl corrected in #398 (I'll rebase the PR after this one is merged)

Copy link
Contributor

@himdel himdel Jun 28, 2019

Choose a reason for hiding this comment

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

I'm still confused about this change here (moving defaultValue=... under the other if, in setDefaultValue).

Previously, default_value coming from the server would get used.
Now, only data.dateField will ever be used for date/time values.

So...
a) why not data.timeField also?
b) should we really never use default_value from the server when dealing with date&time?

Copy link
Member Author

Choose a reason for hiding this comment

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

why not data.timeField also?

the timeField is only related to DialogFieldDateTimeControl, there's no time field in DialogFieldDateControl

Copy link
Member Author

Choose a reason for hiding this comment

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

should we really never use default_value from the server when dealing with date&time?

we're using the default_value on the line 46 that @eclarizio has mentioned

Copy link
Contributor

@himdel himdel Jul 1, 2019

Choose a reason for hiding this comment

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

OK, so default_value is now read only in setupField and we're using dateField only in setDefaultValue. (LGTM, setDefaultValue is only called by setupField.)

But, that still doesn't explain why timeField gets ignored when in a if (data.type === 'DialogFieldDateControl' || data.type === 'DialogFieldDateTimeControl') condition ;).

Copy link
Member Author

@romanblanco romanblanco Jul 1, 2019

Choose a reason for hiding this comment

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

@himdel you're right. The (data.type === 'DialogFieldDateControl' || data.type === 'DialogFieldDateTimeControl') condition should be split. I'll update the PR.

update:

I believe the timeField does not need to be included in here, as we're only setting a default_value for the field.

Any change of fields is processed in

public dateTimeFieldChanged() {
let dateField = this.dialogField.dateField;
let fullYear = dateField.getFullYear();
let month = dateField.getMonth();
let date = dateField.getDate();
if (this.dialogField.timeField === undefined) {
this.dialogField.timeField = new Date();
}
let hours = this.dialogField.timeField.getHours();
let minutes = this.dialogField.timeField.getMinutes();
let fullDate = new Date(fullYear, month, date, hours, minutes);
this.changesHappened([fullDate]);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

ah, LGTM then, thanks :)

@himdel himdel merged commit ffdd33d into ManageIQ:master Jul 2, 2019
@himdel himdel self-assigned this Jul 2, 2019
@himdel himdel added this to the Sprint 115 Ending Jul 8, 2019 milestone Jul 2, 2019
@romanblanco romanblanco deleted the bz1692863 branch July 2, 2019 11:18
simaishi pushed a commit that referenced this pull request Jul 2, 2019
Mark datepicker field as valid only if it's value is an instance of Date

(cherry picked from commit ffdd33d)

https://bugzilla.redhat.com/show_bug.cgi?id=1702497
https://bugzilla.redhat.com/show_bug.cgi?id=1726388
@simaishi
Copy link

simaishi commented Jul 2, 2019

Hammer backport details:

$ git log -1
commit 0cdc27e97bdfcbda7aa192213bd6fac3f47e1e22
Author: Martin Hradil <[email protected]>
Date:   Tue Jul 2 11:08:05 2019 +0200

    Merge pull request #392 from romanblanco/bz1692863
    
    Mark datepicker field as valid only if it's value is an instance of Date
    
    (cherry picked from commit ffdd33d7ad457b2f6b895c690716b9bfc1b9bc89)
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1702497
    https://bugzilla.redhat.com/show_bug.cgi?id=1726388

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.

7 participants