-
-
Notifications
You must be signed in to change notification settings - Fork 824
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
dev/core/#101: Allow further customization of search form in hooks #12078
dev/core/#101: Allow further customization of search form in hooks #12078
Conversation
Reviewing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<td>{$form.tag_search.label} {help id="id-all-tags"}<br />{$form.tag_search.html}</td> | ||
{if $form.tag_search} | ||
<td>{$form.tag_search.label} {help id="id-all-tags"}<br/> | ||
{$form .tag_search.html} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$form
and .tag_search.html
. If you remove this space it fixes the issue.
@michaelmcandrew it's perhaps not possible here but where I have been updating forms to be more changeable by hooks I have been doing it by assigning the fields to use as an array - e.g 4fb5fcf#diff-7f0dd843b42789babf5e6a63cde98198L72 (part of the motivation for an array approach is they can also be re-ordered and others can be asserted - ie the default becomes to add an item in the array with
if there is no special handling for that field |
@eileenmcnaughton, i guess you meant @mickadoo |
Hello @eileenmcnaughton I was investigating the structure of the template and the form controller and even though I agree that looping through each field would be more extensible, I concluded that it would be a bit difficult to implement. These are the issues I found:
Since the solution you propose is not straight forward I suggest implementing this solution for now which works well with the current implementation of the advanced search template. We could then draw a plan to make the advanced search templates more customizable as a whole. |
@reneolivio - my main concern with this 'as is' is that there is a potential that anyone who took advantage of it would later feel burnt if we change it again. Regarding "There's no way to tell the section each field belongs to nor the ones that belong to the basic section." The way we've done it elsewhere (e.g. billing block) is more like
and in the template (not correct code)
(I don't know if that file exists approach actually works - I was just thinking for a complex field it might be cleaner). Regarding the labels - in my experience people don't define the labels in the tpl files because they couldn't put in the correct label when adding the field - they just copied another field done that way at some point in time. It shouldn't be too hard to fix those |
b4904b4
to
25ac93f
Compare
Hello @eileenmcnaughton !! I took a stab at your proposed solution, I'll update things here if you don't mind: After
Technical details
$form->assign('basicSearchFields', [
'sort_name',
'email',
'contact_type',
'group',
'contact_tags',
'tag_search',
'all_tag_types',
'phone_numeric',
'phone_location_type_id',
'phone_phone_type_id',
'privacy_toggle',
'preferred_communication_method',
'contact_source',
'job_title',
'preferred_language',
'contact_id',
'external_identifier',
'uf_user',
]);
$smarty = CRM_Core_Smarty::singleton();
$smarty->register_modifier('template_exists', array(&$smarty, 'template_exists'));
<div class="advanced-search-fields basic-fields form-layout">
{foreach from=$basicSearchFields item=basicSearchField}
{assign var=field value=$form[$basicSearchField]}
{if $field}
{capture assign=fieldTemplatePath}CRM/Contact/Form/Search/Criteria/Fields/{$basicSearchField}.tpl{/capture}
{if $fieldTemplatePath|template_exists}
{include file=$fieldTemplatePath}
{else}
<div class="search-field">
{$field.label}<br />
{$field.html}
</div>
{/if}
{/if}
{/foreach}
</div> Why .advanced-search-fields {
display: grid;
/* defines a column divided by 3 sections, each with -10px wide: */
grid-template-columns: [col] repeat(3, calc(100% / 3 - 10px));
width: 100%;
}
.advanced-search-fields .search-field {
padding: 5px;
}
.advanced-search-fields .search-field__span-2 {
grid-column: col / span 2;
}
.advanced-search-fields .search-field__span-3 {
grid-column: col / span 3;
} There's good support for CSS Grid across all major browsers, except for IE10 and lower. Not sure which version you are supporting.
{capture assign=fieldTemplatePath}CRM/Contact/Form/Search/Criteria/Fields/{$basicSearchField}.tpl{/capture}
{if $fieldTemplatePath|template_exists}
{include file=$fieldTemplatePath}
{else}
<div class="search-field">
{$field.label}<br />
{$field.html}
</div>
{/if} A sample field template would be like this: <div class="search-field">
{$form.contact_tags.label}<br />
{$form.contact_tags.html}
</div>
{if $isTagset}
<div class="search-field search-field__span-2">
{include file="CRM/common/Tagset.tpl"}
</div>
{/if} Please let me know if this approach is acceptable. Also, please guide me on how to test this on another extension. I know that by removing things from the |
Thanks @reneolivo - I'll loop in @colemanw re the css / layout & I'll take a close look at the code - with any luck I can figure out how to unit test it. Also ping @monishdeb @seamuslee001 FYI |
test this please |
CRM/Contact/Form/Search/Criteria.php
Outdated
@@ -35,6 +35,32 @@ class CRM_Contact_Form_Search_Criteria { | |||
* @param CRM_Core_Form $form | |||
*/ | |||
public static function basic(&$form) { | |||
// Allows the template to determine if another template exists: | |||
$smarty = CRM_Core_Smarty::singleton(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This didn't work for me. What did work was
a) adding a new file called modifier.template_exists.php in packages/Smarty/plugins
b) then clearing smarty caches
but it didn't work for me so am using
function smarty_modifier_template_exists($template)
{
$templatePath = __DIR__ . '/../../../templates/' . $template;
return is_file($templatePath);
}
If you want to put up a PR for a new modifer against the packages repo I will merge it
@reneolivo I took a look at this & it seems pretty good. I have a proposal to move from flat field definitions to a fieldSpec - try compucorp@f4e095a
Per my comment above - I had to add a modifier to packages to get the smarty include check working - but I'm leaning towards the field tpl being defined in the array (if needed ) ie.
It feels like a similar lever of complexity to doing the file_exists in smarty & would be overrideable from php which might be nice. Other points
Once you've checked the proposal / comments above we will ping Coleman to check the markup although it seems sane to me |
…nsion. This is an effort at a way to genericise core forms that basically exist to do crud on an entity. We have a number of fairly straight forward forms of this type in core and, in order to allow extensions to use custom fields on a range of entities we should support editing them on these core crud forms. To add custom data support to an entity we need to a) add the custom data to the form using CRM_Custom_Form_CustomData::addToForm($this); b) ensure that the entity is saved using an api call not a BAO call c) add the custom data block to the tpl file - ie {include file="CRM/common/customDataBlock.tpl"} (the above is possible due to previous work to add support & simplify) In this PR the adding of the customData is done in the EntityFormTrait, the api is previously converted and the custom data is included by using a generic tpl to support metadata applied to the form. By using metadata on the form we can also give extension writers a lot more control over what is on the form as they can add to, alter, or remove the metadata in a php hook. This is the crux of this issue civicrm#12078 & it likewise is looking to use a generic field template to add fields based on metadata. A key difference between the 2 prs is that one uses divs & the other a table & that might preclude close sharing of the approach. Note this PR DOES have the impact of adding translate links to 2 localisable relationship type fields that did not currently have them - I think this is a good thing? Example of how to enable custom fields for RelationshipType in an extension. ``` civicrm_api3('OptionValue', 'create', [ 'option_group_id' => 'cg_extend_objects', 'name' => 'civicrm_relationship_type', 'label' => ts('Relationship Type'), 'value' => 'RelationshipType', ]); ```
…nsion. This is an effort at a way to genericise core forms that basically exist to do crud on an entity. We have a number of fairly straight forward forms of this type in core and, in order to allow extensions to use custom fields on a range of entities we should support editing them on these core crud forms. To add custom data support to an entity we need to a) add the custom data to the form using CRM_Custom_Form_CustomData::addToForm($this); b) ensure that the entity is saved using an api call not a BAO call c) add the custom data block to the tpl file - ie {include file="CRM/common/customDataBlock.tpl"} (the above is possible due to previous work to add support & simplify) In this PR the adding of the customData is done in the EntityFormTrait, the api is previously converted and the custom data is included by using a generic tpl to support metadata applied to the form. By using metadata on the form we can also give extension writers a lot more control over what is on the form as they can add to, alter, or remove the metadata in a php hook. This is the crux of this issue civicrm#12078 & it likewise is looking to use a generic field template to add fields based on metadata. A key difference between the 2 prs is that one uses divs & the other a table & that might preclude close sharing of the approach. Note this PR DOES have the impact of adding translate links to 2 localisable relationship type fields that did not currently have them - I think this is a good thing? Example of how to enable custom fields for RelationshipType in an extension. ``` civicrm_api3('OptionValue', 'create', [ 'option_group_id' => 'cg_extend_objects', 'name' => 'civicrm_relationship_type', 'label' => ts('Relationship Type'), 'value' => 'RelationshipType', ]); ```
…nsion. This is an effort at a way to genericise core forms that basically exist to do crud on an entity. We have a number of fairly straight forward forms of this type in core and, in order to allow extensions to use custom fields on a range of entities we should support editing them on these core crud forms. To add custom data support to an entity we need to a) add the custom data to the form using CRM_Custom_Form_CustomData::addToForm($this); b) ensure that the entity is saved using an api call not a BAO call c) add the custom data block to the tpl file - ie {include file="CRM/common/customDataBlock.tpl"} (the above is possible due to previous work to add support & simplify) In this PR the adding of the customData is done in the EntityFormTrait, the api is previously converted and the custom data is included by using a generic tpl to support metadata applied to the form. By using metadata on the form we can also give extension writers a lot more control over what is on the form as they can add to, alter, or remove the metadata in a php hook. This is the crux of this issue civicrm#12078 & it likewise is looking to use a generic field template to add fields based on metadata. A key difference between the 2 prs is that one uses divs & the other a table & that might preclude close sharing of the approach. Note this PR DOES have the impact of adding translate links to 2 localisable relationship type fields that did not currently have them - I think this is a good thing? Example of how to enable custom fields for RelationshipType in an extension. ``` civicrm_api3('OptionValue', 'create', [ 'option_group_id' => 'cg_extend_objects', 'name' => 'civicrm_relationship_type', 'label' => ts('Relationship Type'), 'value' => 'RelationshipType', ]); ```
…nsion. This is an effort at a way to genericise core forms that basically exist to do crud on an entity. We have a number of fairly straight forward forms of this type in core and, in order to allow extensions to use custom fields on a range of entities we should support editing them on these core crud forms. To add custom data support to an entity we need to a) add the custom data to the form using CRM_Custom_Form_CustomData::addToForm($this); b) ensure that the entity is saved using an api call not a BAO call c) add the custom data block to the tpl file - ie {include file="CRM/common/customDataBlock.tpl"} (the above is possible due to previous work to add support & simplify) In this PR the adding of the customData is done in the EntityFormTrait, the api is previously converted and the custom data is included by using a generic tpl to support metadata applied to the form. By using metadata on the form we can also give extension writers a lot more control over what is on the form as they can add to, alter, or remove the metadata in a php hook. This is the crux of this issue civicrm#12078 & it likewise is looking to use a generic field template to add fields based on metadata. A key difference between the 2 prs is that one uses divs & the other a table & that might preclude close sharing of the approach. Note this PR DOES have the impact of adding translate links to 2 localisable relationship type fields that did not currently have them - I think this is a good thing? Example of how to enable custom fields for RelationshipType in an extension. ``` civicrm_api3('OptionValue', 'create', [ 'option_group_id' => 'cg_extend_objects', 'name' => 'civicrm_relationship_type', 'label' => ts('Relationship Type'), 'value' => 'RelationshipType', ]); ```
…nsion. This is an effort at a way to genericise core forms that basically exist to do crud on an entity. We have a number of fairly straight forward forms of this type in core and, in order to allow extensions to use custom fields on a range of entities we should support editing them on these core crud forms. To add custom data support to an entity we need to a) add the custom data to the form using CRM_Custom_Form_CustomData::addToForm($this); b) ensure that the entity is saved using an api call not a BAO call c) add the custom data block to the tpl file - ie {include file="CRM/common/customDataBlock.tpl"} (the above is possible due to previous work to add support & simplify) In this PR the adding of the customData is done in the EntityFormTrait, the api is previously converted and the custom data is included by using a generic tpl to support metadata applied to the form. By using metadata on the form we can also give extension writers a lot more control over what is on the form as they can add to, alter, or remove the metadata in a php hook. This is the crux of this issue civicrm#12078 & it likewise is looking to use a generic field template to add fields based on metadata. A key difference between the 2 prs is that one uses divs & the other a table & that might preclude close sharing of the approach. Note this PR DOES have the impact of adding translate links to 2 localisable relationship type fields that did not currently have them - I think this is a good thing? Example of how to enable custom fields for RelationshipType in an extension. ``` civicrm_api3('OptionValue', 'create', [ 'option_group_id' => 'cg_extend_objects', 'name' => 'civicrm_relationship_type', 'label' => ts('Relationship Type'), 'value' => 'RelationshipType', ]); ```
@Monish from perspective of wanting fields to define labels in html in way good for supporting a11y, do you see any issues here or have suggestions to make? Ideally these changes when rolled out gradually across the code base would eliminate/greatly reduce the special case handling we are seeing is needed on many fields/forms. |
Hello @eileenmcnaughton, I cherry-picked your changes, but had to do some fixes too. Here are some pointers:
$templatePath = __DIR__ . '/../../../../templates/' . $template;
return is_file($templatePath); I don't feel
|
@reneolivo did you read this? https://lab.civicrm.org/dev/core/issues/115 When I worked through #12128 to achieve a similar outcome I would up preferring to define the tpl rather than use the file_exists
seems more flexible for overwriting? |
@eileenmcnaughton I'll have a look at the issue, I didn't get to see it, seems I'll need a bit of time to catch up to the thread. But I rather use convention over configuration: if we manage to make this field extensible it's one less field to configure. I'll catch up to issue's thread and also run some tests and let you know. |
@eileenmcnaughton I have seen the comments on the issue and your other PR as well. I approve of the changes, even the I'll wait until your PR gets approved before starting to change this one in case something changes from the spec so we don't duplicate efforts before everything is settled. Is that ok? |
@reneolivo thanks |
ebb4b2d
to
dbcbae0
Compare
@eileenmcnaughton I have implemented the following changes:
|
Also - either as this or as a follow up I think we should extract a form template - i.e we have this one https://github.com/civicrm/civicrm-core/blob/master/templates/CRM/Core/Form/Field.tpl but it uses not Div so perhaps CRM/Core/Form/FieldDiv.tpl too |
@reneolivo I started an issue to document the fields format over here https://github.com/civicrm/civicrm-dev-docs/issues/534 |
Actually css might be OK - might have been cached |
OK - I have found one issue but I feel like I looked fairly carefully & we are down to the following
|
2a4718f
to
1028e76
Compare
@eileenmcnaughton I worked on your feedback. Here are the changes:
Also, the tag set field is displayed when there is a tag set related to contacts. Since this field was previously displayed by checking if the template has the The field is displayed in a new row as opposed to how it was displayed before, in a 4th column, because the CSS grid was already fixed to 3 columns. It's important to note that CSS grids were chosen over the previous table structure because the former is more flexible when removing a particular field. For example, if one would remove all the cells in a row, the row would still exist, occupying an empty space. |
I think we are there on this. I've had a few looks at it & as of yesterday the items you have now addressed were the only outstanding ones. Let's merge -on-pass |
@reneolivo jenkins failed on (one) style warning |
By implementing the field spec pattern as detailed in dev/core#115 extension developers have more control over what is displayed in this template without needing to resort to overriding it
1028e76
to
a39762f
Compare
bang! |
…nced search Included in CiviCRM 5.3.0 Core PR: civicrm#12078 Gitlab Issue: https://lab.civicrm.org/dev/core/issues/101
…nced search Included in CiviCRM 5.4.0 Core PR: civicrm#12078 Gitlab Issue: https://lab.civicrm.org/dev/core/issues/101
…nced search Included in CiviCRM 5.4.0 Core PR: civicrm#12078 Gitlab Issue: https://lab.civicrm.org/dev/core/issues/101
…nced search Included in CiviCRM 5.4.0 Core PR: civicrm#12078 Gitlab Issue: https://lab.civicrm.org/dev/core/issues/101
Overview
The contact search form uses the template
templates/CRM/Contact/Form/Search/Criteria/Basic.tpl
. In the template there are already some conditionals to hide certain fields, such asHowever only some fields are covered. For an extension developer who wants to hide more fields here it is difficult without causing warnings or breaking the layout.
To make it easier conditionals should be applied to each form element.
Before
Form conditionals were only available for some form elements in the
templates/CRM/Contact/Form/Search/Criteria/Basic.tpl
templateWhat it looked like before:
After
Form conditionals are available for all form elements in the
templates/CRM/Contact/Form/Search/Criteria/Basic.tpl
templateWhat it looked like after (with no fields changed, should be the same as "Before")
What it looked like after with the following fields removed
Notes
I reformatted the code a bit, fixing warnings from the IDE. I also changed some existing conditionals to not output anything if the element wasn't set. As it was before they would still show an empty
td
element leading to gaps in the form like:Without these empty
td
elements the gaps are filled:Gitlab Issue
https://lab.civicrm.org/dev/core/issues/101