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

Custom Asset Field Reordering #17873

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

Conversation

cconard96
Copy link
Contributor

  • I have read the CONTRIBUTING document.
  • I have performed a self-review of my code.
  • I have added tests that prove my fix is effective or that my feature works.
  • This change requires a documentation update.

Taking over from #16975
Currently focusing on reordering default fields until the custom fields PR is merged, and then the Fields tab UI will be adjusted and support for the custom fields added.

@cconard96 cconard96 force-pushed the feature/custom_asset_field_order branch 2 times, most recently from 2cb5785 to 024575a Compare September 25, 2024 10:11
@orthagh
Copy link
Contributor

orthagh commented Sep 26, 2024

Now #17462 has been merged, here are a few notes on that feature as it's the continuation;

Technically

  • fields attributes (mandatory, full width, etc) should be expanded to native fields
  • so we may store these informations in fields_display
  • I suggest so to remove these attributes from glpi_assets_customfields

Regarding UX/UI

  • we may have an edit icon for editing field attributes
  • native and custom fields should be set/displayed in the same grid (mainly to let people reorder them)
  • I STRONGLY suggest using modals in the current UI (for addition and edition). People may add a lot of custom fields and the need to scroll breaks the usage.
  • We shouldn't have a "Save" button globally. Maybe it's just a display bug, if not, all actions should auto-save.
  • "fake inputs" on the grid should display the default value if any
  • The addition process (and primary button) should be common for native and custom fields, maybe a toggle at the top lets you choose the proper form.

That's all for the moment, I may have other minor suggestions later (after seeing a first iteration)

@cconard96 cconard96 self-assigned this Sep 26, 2024
@cconard96 cconard96 force-pushed the feature/custom_asset_field_order branch from 9b8edd1 to 40ba2a6 Compare September 30, 2024 18:10
@cconard96 cconard96 force-pushed the feature/custom_asset_field_order branch from 3c9f33d to 42e5059 Compare October 8, 2024 12:10
@cconard96
Copy link
Contributor Author

cconard96 commented Oct 8, 2024

A checklist based on previous review comment:

  • Allow changing field options for core fields. Since core fields aren't really defined well, the options will be stored in the fields_display column for core fields. For custom fields, it is easier to keep storing the options the way they already are.
  • Edit icon to change field options, change custom field properties, and delete custom fields
  • All field previews reflect the correct type (string, number, dropdown) regardless of if they are core or custom.
  • Ability to delete custom field definitions in new UI
  • Reflect full width option in UI
  • Reflect mandatory option in UI. Need to manually add the mandatory indicator to the preview when needed.
  • Reflect readonly option in UI. Since all previews are disabled, need some other way to indicate a readonly field.
  • Show default value in UI
  • Process to add fields to the order preview is the same for core and custom fields

Also had to redo the field display as flexbox instead of grid for sorting to work properly when fields could be regular or full width.

@cconard96
Copy link
Contributor Author

Tests need updated, but I think this is ready for a review of the initial implementation.

Copy link
Contributor

@AdrienClairembault AdrienClairembault left a comment

Choose a reason for hiding this comment

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

Could you also add some tests ?

New logic should be validated as much as possible on PHPunit side, with a few cypress tests for the things that can also be done on the UI.

Comment on lines +48 to +49
http_response_code(404);
exit();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
http_response_code(404);
exit();
throw new NotFoundHttpException();

'results' => $field_results,
'count' => count($all_fields)
], JSON_THROW_ON_ERROR);
exit();
Copy link
Contributor

Choose a reason for hiding this comment

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

We have removed all exit calls, see #18042.

Suggested change
exit();

Comment on lines +103 to +104
}
http_response_code(400);
Copy link
Contributor

Choose a reason for hiding this comment

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

If we remove the exit statement, this need to be in an else.

Suggested change
}
http_response_code(400);
} else {
throw new BadRequestHttpException();
}

Comment on lines +37 to +38
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

throw new NotFoundHttpException();
}
$asset_definition->showFieldOptionsForCoreField($_GET['key']);
exit();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
exit();

}
$custom_field->fields['field_options']['disabled'] = true;
echo $custom_field->getFieldType()->getFormInput('', null);
exit();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
exit();

Copy link
Contributor

Choose a reason for hiding this comment

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

Symfony controllers have been available for a while now, IMO we shouldn't create any new legacy front files.

Comment on lines +53 to +60
foreach ($all_fields as $k => $v) {
$field_info = is_array($v) ? $v : ['text' => $v];
if (!empty($_POST['searchText']) && stripos($field_info['text'], $_POST['searchText']) === false) {
continue;
}
$field_info['id'] = $k;
$field_results[] = $field_info;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

It is usually best to move this kind of code into the method of a class, as it allow to test it easily with phpunit (and it also make the code reusable and able to benefits from things like dependency injection if needed).

(Not required to change it, just a general comment about best practices for next time).

Comment on lines +57 to +80
{% set default_field_order = [
'name', 'firstname', 'template_name', '_template_is_active', 'states_id', item.getForeignKeyField(), 'is_helpdesk_visible',
'_dc_breadcrumbs', 'locations_id', 'item_type', 'itemtype', 'date_domaincreation', item.getTypeForeignKeyField(),
'usertitles_id', 'registration_number', 'phone', 'phone2', 'phonenumber', 'mobile', 'fax', 'website', 'email',
'address', 'postalcode', 'town', 'postcode', 'state', 'country', 'date_expiration', 'ref', 'users_id_tech',
'manufacturers_id', 'groups_id_tech', item.getModelForeignKeyField(), 'contact_num', 'serial', 'contact', 'otherserial',
'sysdescr', 'snmpcredentials_id', 'users_id', 'is_global', 'size', 'networks_id', 'groups_id', 'uuid', 'version',
'comment', 'ram', 'alarm_threshold', 'brand', 'begin_date', 'autoupdatesystems_id', 'pictures', 'is_active', 'last_boot'
] %}
{# Support custom fields for generic assets #}
{% set custom_fields = custom_fields|default({}) %}
{# Set real field older using 'field_order' provided and any fields missing added to the end of the order array #}
{% set field_order = field_order|default(default_field_order) %}
{% set field_order = field_order|merge(array_diff(default_field_order, field_order)) %}
{# Add missing custom fields to end of the order array #}
{% set custom_fields_keys = custom_fields|keys %}
{% set field_order = field_order|merge(array_diff(custom_fields_keys, field_order)) %}
{# Remove fields that don't apply #}
{% set field_order = field_order|filter((f) => f starts with '_' or item.isField(f)) %}

{# Exclude specified fields #}
{% set fields_excluded = fields_excluded|default([]) %}
{% set field_order = field_order|filter((f) => f not in fields_excluded) %}

Copy link
Contributor

Choose a reason for hiding this comment

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

That seems like a lot of computation inside a view.
Maybe it could be computed by a testable method on PHP's side ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There isn't really a lot of logic here and it makes sense to handle it all at this level. At best, this would be replaced by a call to a PHP method, but that doesn't seem strictly needed.

@orthagh
Copy link
Contributor

orthagh commented Oct 14, 2024

A quick functional review for today's checkout on my side:

  • we can't set a default value for classic fields
  • The same for the "disabled" attribute but, for this one, I'm not sure it could be useful
  • The dropdowns in classic fields (models, manufacturers, etc) can be tagged as "multiple values", but it works only for groups_id/groups_id_tech.
  • We lack an indication a custom dropdown has been set as multiple (like done for other attributes as "mandatory", "read-only", etc)
  • There is a strange bug also with this attribute, when I set it on groups_id, save, set on groups_id tech, save, the first fields lose the attribute in the editor. Anyway, I don't think there is a need to have this toggle on classic fields. The group fields will have the behavior, when displaying an asset, no matter what is set up in the editor.
  • Could you explain the top helper phrase "Fields not added below will be appended at the end of the form rather than be hidden". I'm not sure to understand what it does.
  • I'm not satisfied with the current UX for adding classic fields and custom ones, but I don't have any suggestions (yet) I'll think about it.

@cconard96
Copy link
Contributor Author

* we can't set a default value for classic fields

Didn't realize that was required. This PR was originally just to reorder fields in the UI. I didn't see a spec anywhere for anything extra like making core fields mandatory/readonly/full width/etc. Also all this extra stuff is just in the web UI display. Nothing enforces it on the server side so the API doesn't respect it.

* The same for the "disabled" attribute but, for this one, I'm not sure it could be useful

Doubt it is useful

* The dropdowns in classic fields (models, manufacturers, etc) can be tagged as "multiple values", but it works only for groups_id/groups_id_tech.

Not intended to even have this option. Core fields have no structure so I faked it by reusing the custom field stuff.

* We lack an indication a custom dropdown has been set as multiple (like done for other attributes as "mandatory", "read-only", etc)

We kind of do. You just need to know that select2 controls look like a regular text field when they allow multiple options.

* There is a strange bug also with this attribute, when I set it on groups_id, save, set on groups_id tech, save, the first fields lose the attribute in the editor. **Anyway, I don't think there is a need to have this toggle on classic fields**. The group fields will have the behavior, when displaying an asset, no matter what is set up in the editor.

Not supposed to be an option.

* Could you explain the top helper phrase "Fields not added below will be appended at the end of the form rather than be hidden". I'm not sure to understand what it does.

You cannot hide fields using this UI currently. Look at the generic_show_form template and you see how this is all handled. It takes a custom defined order if one is provided and then appends the missing fields based on the default order. So, if we add new core fields that don't exist in the field order config for a custom asset, they will still appear in the form but be at the end of the form.

I did add handling for a fields_excluded twig parameter to exclude fields completely from the UI but it wasn't hooked up to this new UI. I missed that the spec did actually specify this feature.

The original spec was basically just:

  • Can reorder fields in UI
  • Can hide fields
  • Core fields cannot be changed at all

@cconard96 cconard96 force-pushed the feature/custom_asset_field_order branch from 039a6dc to 6c0c6a2 Compare October 14, 2024 15:20
@cconard96 cconard96 force-pushed the feature/custom_asset_field_order branch from 6c0c6a2 to 27d3488 Compare October 14, 2024 15:21
@orthagh
Copy link
Contributor

orthagh commented Oct 21, 2024

When hiding everything except "name", a few fields remain on a custom asset: "UUID" and "update source".
Note, that it's not particularly useful from a functional pov, but you can't remove everything.
It fails with the following error:

[2024-10-21 08:57:30] glpiphplog.CRITICAL:   *** Uncaught Exception TypeError: array_merge(): Argument #1 must be of type array, null given in .../ajax/asset/assetdefinition.php at line 92

@cconard96
Copy link
Contributor Author

When hiding everything except "name", a few fields remain on a custom asset: "UUID" and "update source".

I can't recreate. I also cannot recreate the situation where all fields can be removed. AFAIK it would be impossible from the web UI because all fields_display fields would be removed and therefore nothing is sent to the server. The missing field isn't treated as a deletion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants