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

feat(forms): Convert default values when question type change #17073

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

ccailly
Copy link
Contributor

@ccailly ccailly commented May 6, 2024

Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets

Added a mechanism for converting default values when changing question types.

@ccailly ccailly self-assigned this May 6, 2024
@ccailly ccailly added this to the 11.0.0 milestone May 6, 2024
@AdrienClairembault
Copy link
Contributor

I am not sure if this should be done on the server.
IMO, it would be better on the client as we don't really need server input on this and it slow the process.

The onQuestionTypeChange could return a short js script instead.

What do you think @cedric-anne ?

@cedric-anne
Copy link
Member

I am not sure if this should be done on the server. IMO, it would be better on the client as we don't really need server input on this and it slow the process.

The onQuestionTypeChange could return a short js script instead.

What do you think @cedric-anne ?

I am not sure that this kind of logic is even required. Maybe it can automatically be done by using strict input types. For instance:

  • type="email" when an email address is expected;
  • type="number" when an integer/float is expected;
  • type="text" when a small text is expected;
  • textarea when a longer text is expected.

Switching from on type to another will probably natively invalidate/discard the value if it is not compatible.

@ccailly
Copy link
Contributor Author

ccailly commented May 13, 2024

I am not sure that this kind of logic is even required. Maybe it can automatically be done by using strict input types. For instance:

* `type="email"` when an email address is expected;

* `type="number"` when an integer/float is expected;

* `type="text"` when a small text is expected;

* `textarea` when a longer text is expected.

Switching from on type to another will probably natively invalidate/discard the value if it is not compatible.

This logic follows on from @orthagh's request in the PR, which integrates actors #16791 (review). This logic could also be relevant when switching between checkbox and radio questions.

In this PR, a first example has been made with short answers, which seem a little less relevant than actors or selectables.

@cedric-anne
Copy link
Member

cedric-anne commented May 13, 2024

Having a unique PHP endpoint is probably easier to handle. Indeed, I am afraid that some cases may not be handled on JS side only, and would require to create specific ajax endpoints. It is preferable to have a unique ajax endpoint that forwards to a PHP logic normalized by an interface instead of having multiple specific ajax endpoints added later in GLPI or in plugins.

@ccailly ccailly force-pushed the feature/form-keep-data-when-switch-type branch from be937b5 to 1233b7b Compare May 16, 2024 11:47
@AdrienClairembault
Copy link
Contributor

AdrienClairembault commented May 23, 2024

I am still not sold on the backend part.
Right now, every action run directly on the front end without any delay.
Adding a backend call here will cause a delay on one of the most common action.

Each question could define two javascript method:

1) extractValue
Return the computed value of the question.
For a simple text question, it can be the raw text.
For a checkbox question, it can be an array of the available options.
For complex ajax-backed dropdown like the actor question type, it could return null as the value is too complex to be shared with other questions.

2) initializeFromValue
Initialize the new type from the given value (which would be retrieved by extractValue).
For a simple text question, we accept any string values.
For a checkbox question, we accept any array of strings.
For a question too complex to be initialized from something else we don't accept anything.

I think this way it can be handled with 0 backend interference.
The goal is to support a few type changes between similar and compatible types (most importantly, the switch from checkbox <-> dropdown <-> radio as it would be painful for the user to re-type all options), not ALL possibles types changes.

What do you think @cedric-anne ?

@cedric-anne
Copy link
Member

OK to do it on JS side, using JS callbacks defined by the QuestionType PHP classes, and defined by the interface.

A way to do it could be to have a public function getFormEditorJsOptions(): string method, that would return, for instance

return <<<JS
    {
        "extractDefaultValue": function (input_name) { return null; },
        "convertDefaultValue": function (input_name, value) { return value; },
        ...
    }
JS;

and it would be registered on form initialization this way

{% for question_type in question types %}
    glpi_form_editor_controller.registerQuestionTypeOptions('{{ get_class(question_type)|e('js') }}, {{ question_type.getFormEditorJsOptions() }})
{% endfor %}

It is probably the most flexible way to permit to each question type to register some specific behaviours on Js side, but it would require to be as much documented as possible.

@cedric-anne
Copy link
Member

OK to do it on JS side, using JS callbacks defined by the QuestionType PHP classes, and defined by the interface.

A way to do it could be to have a public function getFormEditorJsOptions(): string method, that would return, for instance

return <<<JS
    {
        "extractDefaultValue": function (input_name) { return null; },
        "convertDefaultValue": function (input_name, value) { return value; },
        ...
    }
JS;

and it would be registered on form initialization this way

{% for question_type in question types %}
    glpi_form_editor_controller.registerQuestionTypeOptions('{{ get_class(question_type)|e('js') }}, {{ question_type.getFormEditorJsOptions() }})
{% endfor %}

It is probably the most flexible way to permit to each question type to register some specific behaviours on Js side, but it would require to be as much documented as possible.

For GLPI native question types, the JS options may probably be placed in some dedicated JS files and the PHP code may be something like that (to be tested):

public function getFormEditorJsOptions(): string
{
    return 'await import("/path/to/question/defaults.js");';
}

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