{% block form_fields %}
- {% if item.isField('name') %}
- {{ fields.autoNameField(
- 'name',
- item,
- (item_type == 'Contact' ? __('Surname') : __('Name')),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('firstname') %}
- {{ fields.autoNameField(
- 'firstname',
- item,
- __('First name'),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('template_name') and withtemplate == 1 and no_header %}
- {{ fields.autoNameField(
- 'template_name',
- item,
- __('Template name'),
- 0,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('is_active') %}
- {% if withtemplate >= 1 %}
- {{ fields.hiddenField('is_active', item.fields['is_active'], __('Is active'), {
- 'add_field_html': __('No')
- }) }}
- {% else %}
- {% endif %}
- {% endif %}
-
- {% if item.isField('states_id') and item is usingtrait('Glpi\\Features\\State') %}
- {{ fields.dropdownField(
- 'State',
- 'states_id',
- item.fields['states_id'],
- __('Status'),
- field_options|merge({
- 'entity': item.fields['entities_id'],
- 'condition': item.getStateVisibilityCriteria()
- })
- ) }}
- {% endif %}
-
- {% set fk = item.getForeignKeyField() %}
- {% if item.isField(fk) and item_type != 'Software' %}
- {{ fields.dropdownField(
- item_type,
- fk,
- item.fields[fk],
- __('As child of'),
- field_options|merge({
- 'entity': item.fields['entities_id'],
- })
- ) }}
- {% endif %}
-
- {% if item_type != 'SoftwareLicense' and item.isField('is_helpdesk_visible') %}
- {# TODO Drop unused 'is_helpdesk_visible' field in SoftwareLicense schema? #}
- {{ fields.checkboxField(
- 'is_helpdesk_visible',
- item.fields['is_helpdesk_visible'],
- __('Associable to a ticket'),
- field_options
- ) }}
- {% endif %}
-
-
- {% set conditions_met = 0 %}
- {% set dc_breadcrumbs %}
- {% if item is usingtrait('Glpi\\Features\\DCBreadcrumb') %}
- {{ call(item.getType() ~ '::renderDcBreadcrumb', [
- item.getID
- ])|raw }}
- {% endif %}
- {% endset %}
- {% if dc_breadcrumbs|trim|length > 0 %}
- {{ fields.htmlField(
- '',
- dc_breadcrumbs,
- __('Data center position'),
- ) }}
- {% set conditions_met = conditions_met + 1 %}
- {% endif %}
-
- {% if cluster is not null %}
- {{ fields.htmlField(
- '',
- cluster.getLink(),
- _n('Cluster', 'Clusters', 1),
- ) }}
- {% set conditions_met = conditions_met + 1 %}
- {% endif %}
- {% if conditions_met == 1 %}
- {{ fields.nullField() }}
- {% endif %}
-
- {% if item.isField('locations_id') %}
- {{ fields.dropdownField(
- 'Location',
- 'locations_id',
- item.fields['locations_id'],
- 'Location'|itemtype_name,
- field_options|merge({
- 'entity': item.fields['entities_id'],
- })
- ) }}
- {% endif %}
-
- {% if item_type == 'Unmanaged' and item.isField('item_type') %}
- {{ fields.dropdownArrayField(
- 'item_type',
- item.fields['itemtype'],
- _n('Type', 'Types', 1),
- [
- 'Computer', 'NetworkEquipment', 'Printer', 'Peripheral', 'Phone'
- ],
- field_options
- ) }}
- {% endif %}
-
- {% if item_type == 'DefaultFilter' and item.isField('itemtype') %}
- {% set field_options = field_options|merge({'types': config('globalsearch_types')}) %}
- {{ fields.dropdownItemTypes(
- 'itemtype',
- item.fields['itemtype'],
- __('Itemtype'),
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('date_domaincreation') %}
- {{ fields.datetimeField('date_domaincreation', item.fields['date_domaincreation'], __('Registration date')) }}
- {% endif %}
-
- {% set type_itemtype = item.getTypeClass() %}
- {% set type_fk = item.getTypeForeignKeyField() %}
- {% if item.isField(type_fk) %}
- {{ fields.dropdownField(
- type_itemtype,
- type_fk,
- item.fields[type_fk],
- type_itemtype|itemtype_name,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('usertitles_id') %}
- {{ fields.dropdownField(
- 'UserTitle',
- 'usertitles_id',
- item.fields['usertitles_id'],
- 'UserTitle'|itemtype_name,
- field_options|merge({
- 'entity': item.fields['entities_id'],
- })
- ) }}
- {% endif %}
-
- {% if item.isField('registration_number') %}
- {{ fields.autoNameField(
- 'registration_number',
- item,
- (item_type starts with 'User' ? _x('user', 'Administrative number') : _x('infocom', 'Administrative number')),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('phone') %}
- {{ fields.autoNameField(
- 'phone',
- item,
- 'Phone'|itemtype_name,
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('phone2') %}
- {{ fields.autoNameField(
- 'phone2',
- item,
- __('Phone 2'),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('phonenumber') %}
- {{ fields.autoNameField(
- 'phonenumber',
- item,
- 'Phone'|itemtype_name,
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('mobile') %}
- {{ fields.autoNameField(
- 'mobile',
- item,
- __('Mobile phone'),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('fax') %}
- {{ fields.autoNameField(
- 'fax',
- item,
- __('Fax'),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('website') %}
- {{ fields.autoNameField(
- 'website',
- item,
- __('Website'),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('email') %}
- {{ fields.autoNameField(
- 'email',
- item,
- _n('Email', 'Emails', 1),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('address') %}
- {{ fields.textareaField('address', item.fields['address'], __('Address')) }}
- {% endif %}
-
- {% if item.isField('postalcode') %}
- {{ fields.autoNameField(
- 'postalcode',
- item,
- __('Postal code'),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('town') %}
- {{ fields.autoNameField(
- 'town',
- item,
- __('City'),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {# Post code field named differently for Suppliers. Placed after town to maintain field order from 9.5)#}
- {% if item.isField('postcode') %}
- {{ fields.autoNameField(
- 'postcode',
- item,
- __('Postal code'),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item_type == 'Supplier' or item_type == 'Contact' %}
- {{ fields.autoNameField(
- 'state',
- item,
- _x('location', 'State'),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('country') %}
- {{ fields.autoNameField(
- 'country',
- item,
- __('Country'),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('date_expiration') %}
- {% if item_type == 'Certificate' %}
- {{ fields.dateField('date_expiration', item.fields['date_expiration'], __('Expiration date'), {
- 'helper': __('Empty for infinite'),
- 'checkIsExpired': false,
- 'expiration_class' : params.expiration_class
- }|merge(field_options)) }}
- {% elseif item_type == 'ItemAntivirus' %}
- {{ fields.dateField('date_expiration', item.fields['date_expiration'], __('Expiration date'), {
- 'helper': __('Empty for infinite'),
- 'checkIsExpired': true,
- }|merge(field_options)) }}
- {% else %}
- {{ fields.datetimeField('date_expiration', item.fields['date_expiration'], __('Expiration date'), {
- 'helper': __('Empty for infinite'),
- 'checkIsExpired': true
- }|merge(field_options)) }}
- {% endif %}
- {% endif %}
-
- {% if item.isField('ref') %}
- {{ fields.textField(
- 'ref',
- item.fields['ref'],
- __('Reference'),
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('users_id_tech') %}
- {{ fields.dropdownField(
- 'User',
- 'users_id_tech',
- item.fields['users_id_tech'],
- __('Technician in charge'),
- field_options|merge({
- 'entity': item.fields['entities_id'],
- 'right': 'own_ticket',
- })
- ) }}
- {% endif %}
-
- {% if item.isField('manufacturers_id') %}
- {{ fields.dropdownField(
- 'Manufacturer',
- 'manufacturers_id',
- item.fields['manufacturers_id'],
- (item_type starts with 'Software' ? __('Publisher') : 'Manufacturer'|itemtype_name),
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('groups_id_tech') or item is usingtrait('Glpi\\Features\\AssignableItem') %}
- {{ fields.dropdownField(
- 'Group',
- 'groups_id_tech',
- item.fields['groups_id_tech'],
- __('Group in charge'),
- field_options|merge({
- 'entity': item.fields['entities_id'],
- 'condition': {'is_assign': 1},
- 'multiple': item is usingtrait('Glpi\\Features\\AssignableItem') ? true : false
- })
- ) }}
- {% endif %}
-
- {% set model_itemtype = item.getModelClass() %}
- {% set model_fk = item.getModelForeignKeyField() %}
- {% if item.isField(model_fk) %}
- {{ fields.dropdownField(
- model_itemtype,
- model_fk,
- item.fields[model_fk],
- _n('Model', 'Models', 1),
- field_options
- ) }}
- {% endif %}
-
- {% if item_type != 'SoftwareLicense' and item.isField('contact_num') %}
- {# TODO Drop unused 'contact_num' field in Software License schema? #}
- {{ fields.textField(
- 'contact_num',
- item.fields['contact_num'],
- __('Alternate username number'),
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('serial') %}
- {{ fields.textField(
- 'serial',
- item.fields['serial'],
- __('Serial number'),
- field_options
- ) }}
- {% endif %}
-
- {% if item_type != 'SoftwareLicense' and item.isField('contact') %}
- {# TODO Drop unused 'contact' field in Software License schema? #}
- {{ fields.textField(
- 'contact',
- item.fields['contact'],
- __('Alternate username'),
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('otherserial') %}
- {{ fields.autoNameField(
- 'otherserial',
- item,
- __('Inventory number'),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('sysdescr') %}
- {{ fields.textareaField('sysdescr', item.fields['sysdescr'], __('Sysdescr')) }}
- {% endif %}
-
- {% if item.isField('snmpcredentials_id') %}
- {{ fields.dropdownField(
- 'SNMPCredential',
- 'snmpcredentials_id',
- item.fields['snmpcredentials_id'],
- 'SNMPCredential'|itemtype_name,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('users_id') %}
- {{ fields.dropdownField(
- 'User',
- 'users_id',
- item.fields['users_id'],
- 'User'|itemtype_name,
- field_options|merge({
- 'entity': item.fields['entities_id'],
- 'right': 'all',
- })
- ) }}
- {% endif %}
-
- {% if item.isField('is_global') %}
- {% set management_restrict = 0 %}
- {% if item_type == 'Monitor' %}
- {% set management_restrict = config('monitors_management_restrict') %}
- {% elseif item_type == 'Peripheral' %}
- {% set management_restrict = config('peripherals_management_restrict') %}
- {% elseif item_type == 'Phone' %}
- {% set management_restrict = config('phones_management_restrict') %}
- {% elseif item_type == 'Printer' %}
- {% set management_restrict = config('printers_management_restrict') %}
- {% else %}
- {% set management_restrict = 0 %}
- {% endif %}
- {% set dd_globalswitch %}
- {% do call('Dropdown::showGlobalSwitch', [item.fields['id'], {
- 'withtemplate': withtemplate,
- 'value': item.fields['is_global'],
- 'management_restrict': management_restrict,
- 'target': target,
- 'width': '100%',
- }]) %}
- {% endset %}
- {{ fields.htmlField(
- 'is_global',
- dd_globalswitch,
- __('Management type'),
- ) }}
- {% endif %}
-
- {% if item.isField('size') %}
- {{ fields.numberField(
- 'size',
- item.fields['size'],
- __('Size'),
- field_options|merge({
- 'min': 0,
- 'step': 0.01
- }),
- ) }}
- {% endif %}
-
- {% if item.isField('networks_id') %}
- {{ fields.dropdownField(
- 'Network',
- 'networks_id',
- item.fields['networks_id'],
- _n('Network', 'Networks', 1),
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('groups_id') or item is usingtrait('Glpi\\Features\\AssignableItem') %}
- {{ fields.dropdownField(
- 'Group',
- 'groups_id',
- item.fields['groups_id'],
- 'Group'|itemtype_name,
- field_options|merge({
- 'entity': item.fields['entities_id'],
- 'condition': {'is_itemgroup': 1},
- 'multiple': item is usingtrait('Glpi\\Features\\AssignableItem') ? true : false
- })
- ) }}
- {% endif %}
-
- {% if item.isField('uuid') %}
- {{ fields.textField(
- 'uuid',
- item.fields['uuid'],
- __('UUID'),
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('version') %}
- {{ fields.autoNameField(
- 'version',
- item,
- _n('Version', 'Versions', 1),
- withtemplate,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('comment') %}
- {{ fields.textareaField(
- 'comment',
- item.fields['comment'],
- _n('Comment', 'Comments', get_plural_number()),
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('ram') %}
- {{ fields.numberField(
- 'ram',
- item.fields['ram'],
- __('%1$s (%2$s)')|format(_n('Memory', 'Memories', 1), __('Mio')),
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('alarm_threshold') %}
- {% set dd_alarm_treshold %}
- {% do call('Dropdown::showNumber', ['alarm_threshold', {
- 'value': item.fields['alarm_threshold'],
- 'rand': rand,
- 'width': '100%',
- 'min': 0,
- 'max': 100,
- 'step': 1,
- 'toadd': {'-1': __('Never')}
- }|merge(params)]) %}
- {% endset %}
- {% set last_alert_html %}
-
- {% do call('Alert::displayLastAlert', [item_type, item.fields['id']]) %}
-
- {% endset %}
- {{ fields.htmlField(
- 'alarm_threshold',
- dd_alarm_treshold,
- __('Alert threshold'),
- field_options|merge({
- add_field_html: last_alert_html
- })
- ) }}
- {% endif %}
-
- {% if item.isField('brand') %}
- {{ fields.textField(
- 'brand',
- item.fields['brand'],
- __('Brand'),
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('begin_date') %}
- {{ fields.dateField(
- 'begin_date',
- item.fields['begin_date'],
- __('Start date'),
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('autoupdatesystems_id') %}
- {{ fields.dropdownField(
- 'AutoUpdateSystem',
- 'autoupdatesystems_id',
- item.fields['autoupdatesystems_id'],
- 'AutoUpdateSystem'|itemtype_name,
- field_options
- ) }}
- {% endif %}
-
- {% if item.isField('pictures') %}
- {{ fields.fileField('pictures', null, _n('Picture', 'Pictures', get_plural_number()), {
- 'onlyimages': true,
- 'multiple': true,
- }) }}
- {% endif %}
-
- {% if item.isField('is_active') %}
- {{ fields.dropdownYesNo(
- 'is_active',
- item.fields['is_active'],
- __('Active'),
- field_options
- ) }}
- {% endif %}
-
- {# display last_boot data only if item is dynamic and have field #}
- {% if item.isField('last_boot') and item.isField('is_dynamic') and item.fields['is_dynamic'] %}
- {{ fields.htmlField('last_boot', item.fields['last_boot']|formatted_datetime(true), __('Last boot date')) }}
- {% endif %}
+ {% for field in field_order %}
+ {% set specific_field_options = field_options|merge(additional_field_options[field]|default({})) %}
+
+ {% if field is same as 'name' %}
+ {{ fields.autoNameField('name', item, (item_type == 'Contact' ? __('Surname') : __('Name')), withtemplate, specific_field_options) }}
+ {% elseif field is same as 'firstname' %}
+ {{ fields.autoNameField('firstname', item, __('First name'), withtemplate, specific_field_options) }}
+ {% elseif field is same as 'template_name' and withtemplate == 1 and no_header %}
+ {{ fields.autoNameField('template_name', item, __('Template name'), 0, specific_field_options) }}
+ {% elseif item.isField('is_active') and field is same as '_template_is_active' and withtemplate >= 1 %}
+ {{ fields.hiddenField('is_active', item.fields['is_active'], __('Is active'), {
+ 'add_field_html': __('No')
+ }) }}
+ {% elseif field is same as 'states_id' and item is usingtrait('Glpi\\Features\\State') %}
+ {{ fields.dropdownField(
+ 'State',
+ 'states_id',
+ item.fields['states_id'],
+ __('Status'),
+ specific_field_options|merge({
+ 'entity': item.fields['entities_id'],
+ 'condition': item.getStateVisibilityCriteria()
+ })
+ ) }}
+ {% elseif field is same as item.getForeignKeyField() and item_type != 'Software' %}
+ {{ fields.dropdownField(
+ item_type,
+ field,
+ item.fields[field],
+ __('As child of'),
+ specific_field_options|merge({
+ 'entity': item.fields['entities_id'],
+ })
+ ) }}
+ {% elseif field is same as 'is_helpdesk_visible' and item_type != 'SoftwareLicense' %}
+ {# TODO Drop unused 'is_helpdesk_visible' field in SoftwareLicense schema? #}
+ {{ fields.checkboxField(
+ 'is_helpdesk_visible',
+ item.fields['is_helpdesk_visible'],
+ __('Associable to a ticket'),
+ specific_field_options
+ ) }}
+ {% elseif field is same as '_dc_breadcrumbs' %}
+ {% set conditions_met = 0 %}
+ {% set dc_breadcrumbs %}
+ {% if item is usingtrait('Glpi\\Features\\DCBreadcrumb') %}
+ {{ call(item.getType() ~ '::renderDcBreadcrumb', [
+ item.getID
+ ])|raw }}
+ {% endif %}
+ {% endset %}
+ {% if dc_breadcrumbs|trim|length > 0 %}
+ {{ fields.htmlField(
+ '',
+ dc_breadcrumbs,
+ __('Data center position'),
+ ) }}
+ {% set conditions_met = conditions_met + 1 %}
+ {% endif %}
+
+ {% if cluster is not null %}
+ {{ fields.htmlField(
+ '',
+ cluster.getLink(),
+ _n('Cluster', 'Clusters', 1),
+ ) }}
+ {% set conditions_met = conditions_met + 1 %}
+ {% endif %}
+ {% if conditions_met == 1 %}
+ {{ fields.nullField() }}
+ {% endif %}
+ {% elseif field is same as 'locations_id' %}
+ {{ fields.dropdownField(
+ 'Location',
+ 'locations_id',
+ item.fields['locations_id'],
+ 'Location'|itemtype_name,
+ specific_field_options|merge({
+ 'entity': item.fields['entities_id'],
+ })
+ ) }}
+ {% elseif field is same as 'item_type' and item_type == 'Unmanaged' %}
+ {{ fields.dropdownArrayField(
+ 'item_type',
+ item.fields['itemtype'],
+ _n('Type', 'Types', 1),
+ [
+ 'Computer', 'NetworkEquipment', 'Printer', 'Peripheral', 'Phone'
+ ],
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'itemtype' and item_type == 'DefaultFilter' %}
+ {{ fields.dropdownItemTypes(
+ 'itemtype',
+ item.fields['itemtype'],
+ __('Itemtype'),
+ specific_field_options|merge({'types': config('globalsearch_types')})
+ ) }}
+ {% elseif field is same as 'date_domaincreation' %}
+ {{ fields.datetimeField('date_domaincreation', item.fields['date_domaincreation'], __('Registration date')) }}
+ {% elseif field is same as item.getTypeForeignKeyField() %}
+ {% set type_itemtype = item.getTypeClass() %}
+ {{ fields.dropdownField(
+ type_itemtype,
+ field,
+ item.fields[field],
+ type_itemtype|itemtype_name,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'usertitles_id' %}
+ {{ fields.dropdownField(
+ 'UserTitle',
+ 'usertitles_id',
+ item.fields['usertitles_id'],
+ 'UserTitle'|itemtype_name,
+ specific_field_options|merge({
+ 'entity': item.fields['entities_id'],
+ })
+ ) }}
+ {% elseif field is same as 'registration_number' %}
+ {{ fields.autoNameField(
+ 'registration_number',
+ item,
+ (item_type starts with 'User' ? _x('user', 'Administrative number') : _x('infocom', 'Administrative number')),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'phone' %}
+ {{ fields.autoNameField(
+ 'phone',
+ item,
+ 'Phone'|itemtype_name,
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'phone2' %}
+ {{ fields.autoNameField(
+ 'phone2',
+ item,
+ __('Phone 2'),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'phonenumber' %}
+ {{ fields.autoNameField(
+ 'phonenumber',
+ item,
+ 'Phone'|itemtype_name,
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'mobile' %}
+ {{ fields.autoNameField(
+ 'mobile',
+ item,
+ __('Mobile phone'),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'fax' %}
+ {{ fields.autoNameField(
+ 'fax',
+ item,
+ __('Fax'),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'website' %}
+ {{ fields.autoNameField(
+ 'website',
+ item,
+ __('Website'),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'email' %}
+ {{ fields.autoNameField(
+ 'email',
+ item,
+ _n('Email', 'Emails', 1),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'address' %}
+ {{ fields.textareaField('address', item.fields['address'], __('Address')) }}
+ {% elseif field is same as 'postalcode' %}
+ {{ fields.autoNameField(
+ 'postalcode',
+ item,
+ __('Postal code'),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'town' %}
+ {{ fields.autoNameField(
+ 'town',
+ item,
+ __('City'),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'postcode' %}
+ {{ fields.autoNameField(
+ 'postcode',
+ item,
+ __('Postal code'),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'state' and (item_type == 'Supplier' or item_type == 'Contact') %}
+ {{ fields.autoNameField(
+ 'state',
+ item,
+ _x('location', 'State'),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'country' %}
+ {{ fields.autoNameField(
+ 'country',
+ item,
+ __('Country'),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'date_expiration' %}
+ {% if item_type == 'Certificate' %}
+ {{ fields.dateField('date_expiration', item.fields['date_expiration'], __('Expiration date'), {
+ 'helper': __('Empty for infinite'),
+ 'checkIsExpired': false,
+ 'expiration_class' : params.expiration_class
+ }|merge(specific_field_options)) }}
+ {% elseif item_type == 'ItemAntivirus' %}
+ {{ fields.dateField('date_expiration', item.fields['date_expiration'], __('Expiration date'), {
+ 'helper': __('Empty for infinite'),
+ 'checkIsExpired': true,
+ }|merge(specific_field_options)) }}
+ {% else %}
+ {{ fields.datetimeField('date_expiration', item.fields['date_expiration'], __('Expiration date'), {
+ 'helper': __('Empty for infinite'),
+ 'checkIsExpired': true
+ }|merge(specific_field_options)) }}
+ {% endif %}
+ {% elseif field is same as 'ref' %}
+ {{ fields.textField(
+ 'ref',
+ item.fields['ref'],
+ __('Reference'),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'users_id_tech' %}
+ {{ fields.dropdownField(
+ 'User',
+ 'users_id_tech',
+ item.fields['users_id_tech'],
+ __('Technician in charge'),
+ specific_field_options|merge({
+ 'entity': item.fields['entities_id'],
+ 'right': 'own_ticket',
+ })
+ ) }}
+ {% elseif field is same as 'manufacturers_id' %}
+ {{ fields.dropdownField(
+ 'Manufacturer',
+ 'manufacturers_id',
+ item.fields['manufacturers_id'],
+ (item_type starts with 'Software' ? __('Publisher') : 'Manufacturer'|itemtype_name),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'groups_id_tech' %}
+ {# TODO previous code had "or" condition for AssignableItem trait for this field. Still needed? #}
+ {{ fields.dropdownField(
+ 'Group',
+ 'groups_id_tech',
+ item.fields['groups_id_tech'],
+ __('Group in charge'),
+ specific_field_options|merge({
+ 'entity': item.fields['entities_id'],
+ 'condition': {'is_assign': 1},
+ 'multiple': item is usingtrait('Glpi\\Features\\AssignableItem') ? true : false
+ })
+ ) }}
+ {% elseif field is same as item.getModelForeignKeyField() %}
+ {% set model_itemtype = item.getModelClass() %}
+ {{ fields.dropdownField(
+ model_itemtype,
+ field,
+ item.fields[field],
+ _n('Model', 'Models', 1),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'contact_num' and item_type != 'SoftwareLicense' %}
+ {# TODO Drop unused 'contact_num' field in Software License schema? #}
+ {{ fields.textField(
+ 'contact_num',
+ item.fields['contact_num'],
+ __('Alternate username number'),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'serial' %}
+ {{ fields.textField(
+ 'serial',
+ item.fields['serial'],
+ __('Serial number'),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'contact' and item_type != 'SoftwareLicense' %}
+ {# TODO Drop unused 'contact' field in Software License schema? #}
+ {{ fields.textField(
+ 'contact',
+ item.fields['contact'],
+ __('Alternate username'),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'otherserial' %}
+ {{ fields.autoNameField(
+ 'otherserial',
+ item,
+ __('Inventory number'),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'sysdescr' %}
+ {{ fields.textareaField('sysdescr', item.fields['sysdescr'], __('Sysdescr')) }}
+ {% elseif field is same as 'snmpcredentials_id' %}
+ {{ fields.dropdownField(
+ 'SNMPCredential',
+ 'snmpcredentials_id',
+ item.fields['snmpcredentials_id'],
+ 'SNMPCredential'|itemtype_name,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'users_id' %}
+ {{ fields.dropdownField(
+ 'User',
+ 'users_id',
+ item.fields['users_id'],
+ 'User'|itemtype_name,
+ specific_field_options|merge({
+ 'entity': item.fields['entities_id'],
+ 'right': 'all',
+ })
+ ) }}
+ {% elseif field is same as 'is_global' %}
+ {% set management_restrict = 0 %}
+ {% if item_type == 'Monitor' %}
+ {% set management_restrict = config('monitors_management_restrict') %}
+ {% elseif item_type == 'Peripheral' %}
+ {% set management_restrict = config('peripherals_management_restrict') %}
+ {% elseif item_type == 'Phone' %}
+ {% set management_restrict = config('phones_management_restrict') %}
+ {% elseif item_type == 'Printer' %}
+ {% set management_restrict = config('printers_management_restrict') %}
+ {% else %}
+ {% set management_restrict = 0 %}
+ {% endif %}
+ {% set dd_globalswitch %}
+ {% do call('Dropdown::showGlobalSwitch', [item.fields['id'], {
+ 'withtemplate': withtemplate,
+ 'value': item.fields['is_global'],
+ 'management_restrict': management_restrict,
+ 'target': target,
+ 'width': '100%',
+ }]) %}
+ {% endset %}
+ {{ fields.htmlField(
+ 'is_global',
+ dd_globalswitch,
+ __('Management type'),
+ ) }}
+ {% elseif field is same as 'size' %}
+ {{ fields.numberField(
+ 'size',
+ item.fields['size'],
+ __('Size'),
+ specific_field_options|merge({
+ 'min': 0,
+ 'step': 0.01
+ }),
+ ) }}
+ {% elseif field is same as 'networks_id' %}
+ {{ fields.dropdownField(
+ 'Network',
+ 'networks_id',
+ item.fields['networks_id'],
+ _n('Network', 'Networks', 1),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'groups_id' %}
+ {# TODO previous code had "or" condition for AssignableItem trait for this field. Still needed? #}
+ {{ fields.dropdownField(
+ 'Group',
+ 'groups_id',
+ item.fields['groups_id'],
+ 'Group'|itemtype_name,
+ specific_field_options|merge({
+ 'entity': item.fields['entities_id'],
+ 'condition': {'is_itemgroup': 1},
+ 'multiple': item is usingtrait('Glpi\\Features\\AssignableItem') ? true : false
+ })
+ ) }}
+ {% elseif field is same as 'uuid' %}
+ {{ fields.textField(
+ 'uuid',
+ item.fields['uuid'],
+ __('UUID'),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'version' %}
+ {{ fields.autoNameField(
+ 'version',
+ item,
+ _n('Version', 'Versions', 1),
+ withtemplate,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'comment' %}
+ {{ fields.textareaField(
+ 'comment',
+ item.fields['comment'],
+ _n('Comment', 'Comments', get_plural_number()),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'ram' %}
+ {{ fields.numberField(
+ 'ram',
+ item.fields['ram'],
+ __('%1$s (%2$s)')|format(_n('Memory', 'Memories', 1), __('Mio')),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'alarm_threshold' %}
+ {% set dd_alarm_treshold %}
+ {% do call('Dropdown::showNumber', ['alarm_threshold', {
+ 'value': item.fields['alarm_threshold'],
+ 'rand': rand,
+ 'width': '100%',
+ 'min': 0,
+ 'max': 100,
+ 'step': 1,
+ 'toadd': {'-1': __('Never')}
+ }|merge(params)]) %}
+ {% endset %}
+ {% set last_alert_html %}
+
+ {% do call('Alert::displayLastAlert', [item_type, item.fields['id']]) %}
+
+ {% endset %}
+ {{ fields.htmlField(
+ 'alarm_threshold',
+ dd_alarm_treshold,
+ __('Alert threshold'),
+ specific_field_options|merge({
+ add_field_html: last_alert_html
+ })
+ ) }}
+ {% elseif field is same as 'brand' %}
+ {{ fields.textField(
+ 'brand',
+ item.fields['brand'],
+ __('Brand'),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'begin_date' %}
+ {{ fields.dateField(
+ 'begin_date',
+ item.fields['begin_date'],
+ __('Start date'),
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'autoupdatesystems_id' %}
+ {{ fields.dropdownField(
+ 'AutoUpdateSystem',
+ 'autoupdatesystems_id',
+ item.fields['autoupdatesystems_id'],
+ 'AutoUpdateSystem'|itemtype_name,
+ specific_field_options
+ ) }}
+ {% elseif field is same as 'pictures' %}
+ {{ fields.fileField('pictures', null, _n('Picture', 'Pictures', get_plural_number()), {
+ 'onlyimages': true,
+ 'multiple': true,
+ }) }}
+ {% elseif field is same as 'is_active' %}
+ {{ fields.dropdownYesNo('is_active', item.fields['is_active'], __('Active'), specific_field_options) }}
+ {% elseif field is same as 'last_boot' and item.isField('is_dynamic') and item.fields['is_dynamic'] %}
+ {# display last_boot data only if item is dynamic and have field #}
+ {{ fields.htmlField('last_boot', item.fields['last_boot']|formatted_datetime(true), __('Last boot date')) }}
+ {% elseif field in custom_fields|keys %}
+ {{ custom_fields[field].getFieldType().getFormInput(field, item.fields[field])|raw }}
+ {% endif %}
+ {% endfor %}
{% if item_type in config("asset_types") %}
{% set barcode %}
diff --git a/templates/pages/admin/assetdefinition/fields_display.html.twig b/templates/pages/admin/assetdefinition/fields_display.html.twig
new file mode 100644
index 000000000000..3a87f1b03a8c
--- /dev/null
+++ b/templates/pages/admin/assetdefinition/fields_display.html.twig
@@ -0,0 +1,96 @@
+{#
+ # ---------------------------------------------------------------------
+ #
+ # GLPI - Gestionnaire Libre de Parc Informatique
+ #
+ # http://glpi-project.org
+ #
+ # @copyright 2015-2024 Teclib' and contributors.
+ # @licence https://www.gnu.org/licenses/gpl-3.0.html
+ #
+ # ---------------------------------------------------------------------
+ #
+ # LICENSE
+ #
+ # This file is part of GLPI.
+ #
+ # This program is free software: you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation, either version 3 of the License, or
+ # (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with this program. If not, see
.
+ #
+ # ---------------------------------------------------------------------
+ #}
+
+{% extends "generic_show_form.html.twig" %}
+{% import 'components/form/fields_macros.html.twig' as fields %}
+
+{% set all_fields = all_fields ?? {} %}
+
+{% set params = {} %}
+{# do not display delete button #}
+{% set params = params|merge({'candel': false}) %}
+{# do not display footer with dates #}
+{% set params = params|merge({'formfooter': false}) %}
+{% set rand = rand|default(random()) %}
+
+{% block form_fields %}
+
+
+
+
+
+{% endblock %}
diff --git a/templates/pages/assets/asset.html.twig b/templates/pages/assets/asset.html.twig
index 8eff694eb637..cd6b536ed836 100644
--- a/templates/pages/assets/asset.html.twig
+++ b/templates/pages/assets/asset.html.twig
@@ -43,9 +43,4 @@
_get['Glpi\\Asset\\AssetDefinition'|itemtype_foreign_key]|default(0),
) }}
{% endif %}
-
- {% for custom_field_definition in custom_field_definitions %}
- {% set field_name = 'custom_' ~ custom_field_definition.fields['name'] %}
- {{ custom_field_definition.getFieldType().getFormInput(field_name, item.fields[field_name])|raw }}
- {% endfor %}
{% endblock %}
diff --git a/tests/DbTestCase.php b/tests/DbTestCase.php
index 041191586a77..aeb169ddf016 100644
--- a/tests/DbTestCase.php
+++ b/tests/DbTestCase.php
@@ -347,8 +347,9 @@ protected function initAssetDefinition(
'is_active' => true,
'capacities' => $capacities,
'profiles' => $profiles,
+ 'fields_display' => [],
],
- skip_fields: ['capacities', 'profiles'] // JSON encoded fields cannot be automatically checked
+ skip_fields: ['capacities', 'profiles', 'fields_display'] // JSON encoded fields cannot be automatically checked
);
$this->array($this->callPrivateMethod($definition, 'getDecodedCapacitiesField'))->isEqualTo($capacities);
$this->array($this->callPrivateMethod($definition, 'getDecodedProfilesField'))->isEqualTo($profiles);
diff --git a/tests/cypress/e2e/Asset/custom_fields.cy.js b/tests/cypress/e2e/Asset/custom_fields.cy.js
index 37604f8d2792..1d54aeafe621 100644
--- a/tests/cypress/e2e/Asset/custom_fields.cy.js
+++ b/tests/cypress/e2e/Asset/custom_fields.cy.js
@@ -36,11 +36,54 @@ describe("Custom Assets - Custom Fields", () => {
cy.login();
});
- it('Custom field creation and display', () => {
- // This can be split into multiple tests when the new API supports custom assets and custom fields
- cy.visit('/front/asset/assetdefinition.form.php');
+ function parseRequest(interception) {
+ let formDataObject = {};
+
+ if (interception.request.headers['content-type'].startsWith('multipart/form-data')) {
+ // Parse the multipart form data to an object
+ const boundary = interception.request.headers['content-type'].split('boundary=')[1];
+ const parts = interception.request.body.split(`--${boundary}`).map((part) => part.trim()).filter((part) => part !== '');
+ for (const part of parts) {
+ if (part.trim() === '--') {
+ continue;
+ }
+ const [, name, value] = part.match(/name="([^"]*)"\s*([\s\S]*)\s*/);
+ if (name.endsWith('[]')) {
+ const arrayName = name.slice(0, -2);
+ if (!formDataObject[arrayName]) {
+ formDataObject[arrayName] = [];
+ }
+ formDataObject[arrayName].push(value.trim());
+ } else {
+ formDataObject[name] = value.trim();
+ }
+ }
+ } else if (interception.request.headers['content-type'].startsWith('application/x-www-form-urlencoded')) {
+ // Parse the urlencoded form data to an object
+ const urlSearchParams = new URLSearchParams(interception.request.body);
+ for (const [name, value] of urlSearchParams) {
+ if (name.endsWith('[]')) {
+ const arrayName = name.slice(0, -2);
+ if (!formDataObject[arrayName]) {
+ formDataObject[arrayName] = [];
+ }
+ formDataObject[arrayName].push(value);
+ } else {
+ formDataObject[name] = value;
+ }
+ }
+ }
+ return formDataObject;
+ }
+
+ const getAssetName = () => {
const asset_name_chars = 'abcdefghijklmnopqrstuvwxyz';
- const asset_name = `customasset${Array.from({ length: 10 }, () => asset_name_chars.charAt(Math.floor(Math.random() * asset_name_chars.length))).join('')}`;
+ return `customasset${Array.from({ length: 10 }, () => asset_name_chars.charAt(Math.floor(Math.random() * asset_name_chars.length))).join('')}`;
+ };
+
+ it('Reordering fields', () => {
+ cy.visit('/front/asset/assetdefinition.form.php');
+ const asset_name = getAssetName();
cy.findByLabelText(/System name/i).type(asset_name);
cy.findByLabelText("Active").select('1', { force: true });
cy.findByRole('button', {name: "Add"}).click();
@@ -48,264 +91,164 @@ describe("Custom Assets - Custom Fields", () => {
cy.get('div.toast-container .toast-body a').click();
cy.url().should('include', '/front/asset/assetdefinition.form.php?id=');
- cy.findByRole('tab', {name: 'Custom fields'}).click();
-
- cy.findByRole('button', {name: 'Add a new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
- cy.findByRole('button', {name: 'Add a new field'}).click();
- cy.findByLabelText('Label').type('Test String');
- cy.findByLabelText('Type').select('String', { force: true });
-
- // Verify readonly and mandatory options don't affect the default value field
- cy.findByLabelText('Readonly').check();
- cy.findByLabelText('Mandatory').check();
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.findByLabelText('Default value', {selector: 'input:not([readonly]):not([disabled]):not([required])'}).should('exist');
- cy.findByLabelText('Readonly').uncheck();
- cy.findByLabelText('Mandatory').uncheck();
-
- cy.findByRole('button', {name: 'Add'}).click();
- });
- cy.findByRole('button', {name: 'Add a new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
- cy.findByRole('button', {name: 'Add a new field'}).click();
- cy.findByLabelText('Label').type('Test Text');
- cy.findByLabelText('Type').select('Text', { force: true });
-
- // Verify readonly and mandatory options don't affect the default value field
- cy.findByLabelText('Readonly').check();
- cy.findByLabelText('Mandatory').check();
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.findByLabelText('Default value', {selector: 'input:not([readonly]):not([disabled]):not([required])'}).should('exist');
- cy.findByLabelText('Readonly').uncheck();
- cy.findByLabelText('Mandatory').uncheck();
-
- cy.findByRole('button', {name: 'Add'}).click();
- });
- cy.findByRole('button', {name: 'Add a new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
- cy.findByRole('button', {name: 'Add a new field'}).click();
- cy.findByLabelText('Label').type('Test Number');
- cy.findByLabelText('Type').select('Number', { force: true });
-
- cy.findByLabelText('Minimum').type('{selectall}{del}10');
- cy.findByLabelText('Maximum').type('{selectall}{del}20');
- cy.findByLabelText('Step').type('{selectall}{del}2');
-
- // Verify readonly and mandatory options don't affect the default value field
- cy.findByLabelText('Readonly').check();
- cy.findByLabelText('Mandatory').check();
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.findByLabelText('Default value', {selector: 'input:not([readonly]):not([disabled]):not([required])'}).should('exist');
- cy.findByLabelText('Readonly').uncheck();
- cy.findByLabelText('Mandatory').uncheck();
-
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.findByLabelText('Default value').type('{selectall}{del}12');
-
- cy.findByRole('button', {name: 'Add'}).click();
- });
- cy.findByRole('button', {name: 'Add a new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
- cy.findByRole('button', {name: 'Add a new field'}).click();
- cy.findByLabelText('Label').type('Test Date');
- cy.findByLabelText('Type').select('Date', { force: true });
-
- // Verify readonly and mandatory options don't affect the default value field
- cy.findByLabelText('Readonly').check();
- cy.findByLabelText('Mandatory').check();
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.get('input[name="default_value"]:not([readonly]):not([disabled]):not([required])').should('exist');
- cy.findByLabelText('Readonly').uncheck();
- cy.findByLabelText('Mandatory').uncheck();
-
- cy.findByRole('button', {name: 'Add'}).click();
- });
- cy.findByRole('button', {name: 'Add a new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
- cy.findByRole('button', {name: 'Add a new field'}).click();
- cy.findByLabelText('Label').type('Test Datetime');
- cy.findByLabelText('Type').select('Date and time', { force: true });
-
- // Verify readonly and mandatory options don't affect the default value field
- cy.findByLabelText('Readonly').check();
- cy.findByLabelText('Mandatory').check();
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.get('input[name="default_value"]:not([readonly]):not([disabled]):not([required])').should('exist');
- cy.findByLabelText('Readonly').uncheck();
- cy.findByLabelText('Mandatory').uncheck();
-
- cy.findByRole('button', {name: 'Add'}).click();
- });
- cy.findByRole('button', {name: 'Add a new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
- cy.findByRole('button', {name: 'Add a new field'}).click();
- cy.findByLabelText('Label').type('Test Dropdown');
- cy.findByLabelText('Type').select('Dropdown', { force: true });
- cy.findByLabelText('Item type').select('Monitor', { force: true });
-
- // Verify readonly and mandatory options don't affect the default value field
- cy.findByLabelText('Readonly').check();
- cy.findByLabelText('Mandatory').check();
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.findByLabelText('Default value', {selector: 'select:not([readonly]):not([disabled]):not([required])'}).should('exist');
- cy.findByLabelText('Readonly').uncheck();
- cy.findByLabelText('Mandatory').uncheck();
-
- // Test the default value input respects the "Multiple values" option
- cy.findByLabelText('Multiple values').check();
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.findByLabelText('Default value').should('have.attr', 'multiple');
- cy.findByLabelText('Multiple values').uncheck();
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.findByLabelText('Default value').should('not.have.attr', 'multiple');
-
- cy.findByRole('button', {name: 'Add'}).click();
- });
- cy.findByRole('button', {name: 'Add a new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
- cy.findByRole('button', {name: 'Add a new field'}).click();
- cy.findByLabelText('Label').type('Test MultiDropdown');
- cy.findByLabelText('Type').select('Dropdown', { force: true });
- cy.findByLabelText('Item type').select('Monitor', { force: true });
- cy.findByLabelText('Multiple values').check();
-
- // Verify readonly and mandatory options don't affect the default value field
- cy.findByLabelText('Readonly').check();
- cy.findByLabelText('Mandatory').check();
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.findByLabelText('Default value', {selector: 'select:not([readonly]):not([disabled]):not([required])'}).should('exist');
- cy.findByLabelText('Readonly').uncheck();
- cy.findByLabelText('Mandatory').uncheck();
-
- cy.findByRole('button', {name: 'Add'}).click();
- });
- cy.findByRole('button', {name: 'Add a new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
- cy.findByRole('button', {name: 'Add a new field'}).click();
- cy.findByLabelText('Label').type('Test URL');
- cy.findByLabelText('Type').select('URL', { force: true });
-
- // Verify readonly and mandatory options don't affect the default value field
- cy.findByLabelText('Readonly').check();
- cy.findByLabelText('Mandatory').check();
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.findByLabelText('Default value', {selector: 'input:not([readonly]):not([disabled]):not([required])'}).should('exist');
- cy.findByLabelText('Readonly').uncheck();
- cy.findByLabelText('Mandatory').uncheck();
-
- cy.findByRole('button', {name: 'Add'}).click();
- });
- cy.findByRole('button', {name: 'Add a new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
- cy.findByRole('button', {name: 'Add a new field'}).click();
- cy.findByLabelText('Label').type('Test YesNo');
- cy.findByLabelText('Type').select('Yes/No', { force: true });
-
- // Verify readonly and mandatory options don't affect the default value field
- cy.findByLabelText('Readonly').check();
- cy.findByLabelText('Mandatory').check();
- cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
- cy.findByLabelText('Default value', {selector: 'select:not([readonly]):not([disabled]):not([required])'}).should('exist');
- cy.findByLabelText('Readonly').uncheck();
- cy.findByLabelText('Mandatory').uncheck();
-
- cy.findByRole('button', {name: 'Add'}).click();
- });
-
- //Check the Item type column in the custom fields list is correct for dropdowns
- cy.findByRole('cell', {name: 'Test Dropdown'}).should('exist').siblings().contains('Monitor').should('exist');
- cy.findByRole('cell', {name: 'Test MultiDropdown'}).should('exist').siblings().contains('Monitor').should('exist');
-
cy.findByRole('tab', {name: 'Profiles'}).click();
cy.get('input[type="checkbox"][id^="cb_checkall_table"]').check({ force: true });
cy.findByRole('button', {name: 'Save'}).click();
- cy.visit(`/front/asset/asset.form.php?class=${asset_name}&id=-1&withtemplate=2`);
- // Validate the custom fields look OK
- cy.findByLabelText('Test String')
- .should('have.attr', 'type', 'text')
- .should('have.attr', 'maxlength', '255');
- cy.findByLabelText('Test Text').should('be.visible');
- cy.findByLabelText('Test Number')
- .should('have.attr', 'type', 'number')
- .should('have.attr', 'min', '10')
- .should('have.attr', 'max', '20')
- .should('have.attr', 'step', '2');
-
- // FlatPickr input is not reachable by its label.
- cy.get('label').contains('Test Date').next().within(() => {
- cy.get('.flatpickr-input').should('exist');
+ cy.findByRole('tab', {name: /^Fields/}).click();
+ cy.get('#sortable-fields[aria-dropeffect]').within(() => {
+ cy.get('.sortable-field[data-key="name"][draggable="true"]')
+ .as('name_field')
+ .should('be.visible')
+ .invoke('index').should('eq', 0);
+ cy.get('.sortable-field[data-key="states_id"][draggable="true"]')
+ .as('states_id_field')
+ .should('be.visible')
+ .invoke('index').should('eq', 1);
+ cy.get("@name_field").then(($name_field) => {
+ cy.get("@states_id_field").then(($states_id_field) => {
+ $name_field.insertAfter($states_id_field);
+ });
+ });
});
+ cy.findByRole('button', {name: 'Save'}).click();
- // FlatPickr input is not reachable by its label.
- cy.get('label').contains('Test Datetime').next().within(() => {
- cy.get('.flatpickr-input').should('exist');
- });
-
- cy.getDropdownByLabelText('Test Dropdown')
- .should('be.visible')
- .should('have.class', 'select2-selection--single');
- cy.getDropdownByLabelText('Test MultiDropdown')
- .should('be.visible')
- .should('have.class', 'select2-selection--multiple');
-
- cy.findByLabelText('Test URL').should('have.attr', 'type', 'url');
+ cy.get('.sortable-field[data-key="name"][draggable="true"]').invoke('index').should('eq', 1);
+ cy.get('.sortable-field[data-key="states_id"][draggable="true"]').invoke('index').should('eq', 0);
- cy.getDropdownByLabelText('Test YesNo').selectDropdownValue('No');
- cy.getDropdownByLabelText('Test YesNo').selectDropdownValue('Yes');
+ cy.visit(`/front/asset/asset.form.php?class=${asset_name}&id=-1&withtemplate=2`);
+ cy.findByLabelText('Name').closest('.form-field').should('be.visible').invoke('index').should('eq', 1);
+ cy.findByLabelText('Status').closest('.form-field').should('be.visible').invoke('index').should('eq', 0);
});
- it('Custom field update', () => {
+ it('Create custom fields', () => {
+ function createField(label, type, options = new Map()) {
+ cy.findByRole('button', {name: 'Create new field'}).click();
+ cy.findByRole('button', {name: 'Create new field'}).siblings('.modal').should('be.visible').within(() => {
+ cy.findByLabelText('Label').type(label);
+ cy.findByLabelText('Type').select(type, {force: true});
+
+ if (options.has('item_type')) {
+ cy.findByLabelText('Item type').select(options.get('item_type'), {force: true});
+ }
+ if (options.has('min')) {
+ cy.findByLabelText('Minimum').type(`{selectall}{del}${options.get('min')}`);
+ }
+ if (options.has('max')) {
+ cy.findByLabelText('Maximum').type(`{selectall}{del}${options.get('max')}`);
+ }
+ if (options.has('step')) {
+ cy.findByLabelText('Step').type(`{selectall}{del}${options.get('step')}`);
+ }
+ if (options.has('multiple_values')) {
+ cy.findByLabelText('Multiple values').check();
+ }
+ if (options.has('readonly')) {
+ cy.findByLabelText('Readonly').check();
+ }
+ if (options.has('mandatory')) {
+ cy.findByLabelText('Mandatory').check();
+ }
+
+ cy.findByRole('button', {name: 'Add'}).click();
+ });
+ cy.waitForNetworkIdle('/ajax/asset/customfield.php', 100);
+ cy.findByRole('button', {name: 'Create new field'}).siblings('.modal').should('not.be.visible');
+ cy.get(`.sortable-field[data-key="custom_${label.toLowerCase().replace(' ', '_')}"]`).should('be.visible');
+ }
+
cy.visit('/front/asset/assetdefinition.form.php');
- const asset_name_chars = 'abcdefghijklmnopqrstuvwxyz';
- const asset_name = `customasset${Array.from({ length: 10 }, () => asset_name_chars.charAt(Math.floor(Math.random() * asset_name_chars.length))).join('')}`;
+ const asset_name = getAssetName();
cy.findByLabelText(/System name/i).type(asset_name);
cy.findByLabelText("Active").select('1', { force: true });
cy.findByRole('button', {name: "Add"}).click();
-
cy.get('div.toast-container .toast-body a').click();
cy.url().should('include', '/front/asset/assetdefinition.form.php?id=');
- cy.findByRole('tab', {name: 'Custom fields'}).click();
-
- cy.findByRole('button', {name: 'Add a new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
- cy.findByRole('button', {name: 'Add a new field'}).click();
- cy.findByLabelText('Label').type('Test String');
- cy.findByLabelText('Type').select('String', { force: true });
- cy.findByRole('button', {name: 'Add'}).click();
+ cy.findByRole('tab', {name: /^Fields/}).click();
+
+ cy.intercept({
+ pathname: '/ajax/asset/assetdefinition.php',
+ query: {
+ action: 'get_all_fields'
+ },
+ times: 1
+ }, (req) => {
+ req.reply({
+ results: [
+ {text: "Fake field", type: 'Glpi\\Asset\\CustomFieldType\\StringType', id: "fake_field"},
+ {text: "Fake custom field", type: 'Glpi\\Asset\\CustomFieldType\\StringType', id: "custom_fake_field"}
+ ]
+ });
});
- cy.findByRole('cell', {name: 'Test String'}).click();
- cy.findByLabelText('Label').should('have.value', 'Test String');
- cy.findByLabelText('Type').should('not.exist');
- cy.get('span.form-control').contains('String').should('exist');
- cy.findByLabelText('System name').should('have.value', 'test_string');
- cy.findByLabelText('Label').type(' Updated');
- // System name preview should not update because the system name cannot/will not actually change
- cy.findByLabelText('System name').should('have.value', 'test_string');
- cy.findByRole('button', {name: 'Save'}).click();
-
- cy.findByRole('cell', {name: 'Test String Updated'}).click();
- cy.findByLabelText('Label').should('have.value', 'Test String Updated');
- cy.findByLabelText('Type').should('not.exist');
- cy.get('span.form-control').contains('String').should('exist');
- cy.findByLabelText('System name').should('have.value', 'test_string');
+ cy.findByRole('button', {name: 'Create new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
+ cy.findByLabelText('Field').siblings('.select2').find('.select2-selection__arrow').trigger('mousedown', {which: 1});
+
+ cy.root().closest('body').find('.select2-results__option').contains('Fake field').should('be.visible');
+ cy.root().closest('body').find('.select2-results__option').contains('Fake custom field').should('be.visible');
+
+ createField('Test String', 'String');
+ createField('Test Text', 'Text');
+ createField('Test Number', 'Number', new Map([['min', '10'], ['max', '20'], ['step', '2']]));
+ createField('Test Date', 'Date');
+ createField('Test Datetime', 'Date and time');
+ createField('Test Dropdown', 'Dropdown', new Map([['item_type', 'Monitor']]));
+ createField('Test MultiDropdown', 'Dropdown', new Map([['item_type', 'Monitor'], ['multiple_values', true]]));
+ createField('Test URL', 'URL');
+ createField('Test YesNo', 'Yes/No');
+
+ // Intercept form submission to check the form display values sent
+ cy.intercept('POST', '/front/asset/assetdefinition.form.php').as('saveFieldsDisplay');
+ cy.findByRole('button', {name: 'Save'}).click();
+ cy.wait('@saveFieldsDisplay').then((interception) => {
+ const formDataObject = parseRequest(interception);
+ expect(formDataObject['_update_fields_display']).to.be.equal('1');
+ expect(formDataObject['fields_display']).to.include.members([
+ 'custom_test_string', 'custom_test_text', 'custom_test_number', 'custom_test_date', 'custom_test_datetime',
+ 'custom_test_dropdown', 'custom_test_multidropdown', 'custom_test_url', 'custom_test_yesno'
+ ]);
+ });
+ });
});
- it('Custom field delete', () => {
+ it('Edit core fields', () => {
cy.visit('/front/asset/assetdefinition.form.php');
- const asset_name_chars = 'abcdefghijklmnopqrstuvwxyz';
- const asset_name = `customasset${Array.from({ length: 10 }, () => asset_name_chars.charAt(Math.floor(Math.random() * asset_name_chars.length))).join('')}`;
+ const asset_name = getAssetName();
cy.findByLabelText(/System name/i).type(asset_name);
cy.findByLabelText("Active").select('1', { force: true });
cy.findByRole('button', {name: "Add"}).click();
-
cy.get('div.toast-container .toast-body a').click();
cy.url().should('include', '/front/asset/assetdefinition.form.php?id=');
- cy.findByRole('tab', {name: 'Custom fields'}).click();
+ cy.findByRole('tab', {name: /^Fields/}).click();
- cy.findByRole('button', {name: 'Add a new field'}).parents('.tab-pane').should('have.class', 'active').first().within(() => {
- cy.findByRole('button', {name: 'Add a new field'}).click();
- cy.findByLabelText('Label').type('Test String');
- cy.findByLabelText('Type').select('String', { force: true });
- cy.findByRole('button', {name: 'Add'}).click();
+ cy.intercept({
+ pathname: '/ajax/asset/assetdefinition.php',
+ query: { action: 'get_all_fields' },
+ times: 1
+ }, (req) => {
+ req.reply({ results: [] });
});
- cy.findByRole('cell', {name: 'Test String'}).click();
- cy.findByRole('button', {name: 'Delete permanently'}).click();
- cy.findByRole('cell', {name: 'Test String'}).should('not.exist');
+ cy.get('.sortable-field[data-key="name"] .edit-field').click();
+ cy.get('#core_field_options_editor').within(() => {
+ cy.findByLabelText('Full width').should('be.visible').check();
+ cy.findByLabelText('Readonly').should('be.visible').check();
+ cy.findByLabelText('Mandatory').should('be.visible').check();
+ cy.intercept('POST', '/ajax/asset/assetdefinition.php').as('saveFieldOptions');
+ cy.findByRole('button', {name: 'Save'}).click();
+ cy.wait('@saveFieldOptions').then((interception) => {
+ const formDataObject = parseRequest(interception);
+ expect(formDataObject['action']).to.be.equal('get_field_placeholder');
+ cy.location('search').then((search) => {
+ expect(`${formDataObject['assetdefinitions_id']}`).to.be.equal((new URLSearchParams(search)).get('id'));
+ });
+ expect(formDataObject['fields[0][key]']).to.be.equal('name');
+ expect(formDataObject['fields[0][field_options][full_width]']).to.be.equal('1');
+ expect(formDataObject['fields[0][field_options][readonly]']).to.be.equal('1');
+ expect(formDataObject['fields[0][field_options][required]']).to.be.equal('1');
+ });
+ });
});
});
diff --git a/tests/functional/Glpi/Asset/Asset.php b/tests/functional/Glpi/Asset/Asset.php
index f48d19c76d69..574a97f70945 100644
--- a/tests/functional/Glpi/Asset/Asset.php
+++ b/tests/functional/Glpi/Asset/Asset.php
@@ -251,4 +251,22 @@ public function testPostGetFromDB()
$this->string($asset->fields['custom_test_string_two'])->isEqualTo('default2');
$this->array($asset->fields['custom_test_dropdown'])->isEqualTo(['1', '2']);
}
+
+ public function testGetFormFields()
+ {
+ $definition = $this->initAssetDefinition();
+ $asset = $this->createItem($definition->getAssetClassName(), [
+ 'name' => 'test asset',
+ 'entities_id' => $this->getTestRootEntity(true),
+ ]);
+ $this->createItem(\Glpi\Asset\CustomFieldDefinition::class, [
+ 'assets_assetdefinitions_id' => $definition->getID(),
+ 'name' => 'test_string',
+ 'label' => 'Test string',
+ 'type' => StringType::class,
+ 'default_value' => 'default',
+ ]);
+
+ $this->assertTrue(!array_diff(['id', 'name', 'serial', '_template_is_active', 'custom_test_string'], $asset->getFormFields()));
+ }
}
diff --git a/tests/functional/Glpi/Asset/AssetDefinition.php b/tests/functional/Glpi/Asset/AssetDefinition.php
index bfb075800790..fc9e08c90930 100644
--- a/tests/functional/Glpi/Asset/AssetDefinition.php
+++ b/tests/functional/Glpi/Asset/AssetDefinition.php
@@ -254,6 +254,7 @@ protected function addInputProvider(): iterable
'capacities' => '[]',
'profiles' => '[]',
'translations' => '[]',
+ 'fields_display' => '[]',
],
'messages' => [],
];
@@ -295,6 +296,7 @@ protected function addInputProvider(): iterable
'capacities' => '[]',
'profiles' => '[]',
'translations' => '[]',
+ 'fields_display' => '[]',
],
'messages' => [],
];
@@ -308,6 +310,7 @@ protected function addInputProvider(): iterable
'capacities' => '[]',
'profiles' => '[]',
'translations' => '[]',
+ 'fields_display' => '[]',
],
'messages' => [],
];
@@ -335,6 +338,7 @@ protected function addInputProvider(): iterable
'capacities' => '[]',
'profiles' => '[]',
'translations' => '[]',
+ 'fields_display' => '[]',
],
'messages' => [],
];
@@ -361,6 +365,7 @@ protected function addInputProvider(): iterable
'capacities' => '[]',
'profiles' => '[]',
'translations' => '[]',
+ 'fields_display' => '[]',
],
'messages' => [],
];
@@ -385,6 +390,9 @@ protected function addInputProvider(): iterable
// default value for `translations`
$data['output']['translations'] = '[]';
}
+ if (is_array($data['output']) && !array_key_exists('fields_display', $data['output'])) {
+ $data['output']['fields_display'] = '[]';
+ }
yield $data;
}
}