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

ContactSummary - Replace Membership tab with Searchkit display #28810

Merged
merged 8 commits into from
Jan 12, 2024

Conversation

jitendrapurohit
Copy link
Contributor

@jitendrapurohit jitendrapurohit commented Dec 29, 2023

Overview

ContactSummary - Replace Membership tab with Searchkit display

Before

Outdated code to render membership tab.

After

Uses searchkit display -

image

Comments

Tagging wip, since there are still few differences (issues?) from previous display.

  • Change Billing Details action link should only be visible if related payment processor supports updateSubscriptionBillingInfo
  • Cancel Auto-renewal link should only be displayed if processor supports cancelRecurring
  • Warning display on cancel click.
  • Submit/Renew Credit Card Membership should only be displayed if payment processor exist in the system that supports BackOffice payments
  • Membership Type table should only be displayed if organisation has a mem type. Currently the table to render Membership Type is displayed for all contacts since there is no way to hide the full SK display if there are no rows?

Perhaps, we can add a setting eg Hide SK display if no results?

Copy link

civibot bot commented Dec 29, 2023

🤖 Thank you for contributing to CiviCRM! ❤️ We will need to test and review this PR. 👷

Introduction for new contributors...
  • If this is your first PR, an admin will greenlight automated testing with the command ok to test or add to whitelist.
  • A series of tests will automatically run. You can see the results at the bottom of this page (if there are any problems, it will include a link to see what went wrong).
  • A demo site will be built where anyone can try out a version of CiviCRM that includes your changes.
  • If this process needs to be repeated, an admin will issue the command test this please to rerun tests and build a new demo site.
  • Before this PR can be merged, it needs to be reviewed. Please keep in mind that reviewers are volunteers, and their response time can vary from a few hours to a few weeks depending on their availability and their knowledge of this particular part of CiviCRM.
  • A great way to speed up this process is to "trade reviews" with someone - find an open PR that you feel able to review, and leave a comment like "I'm reviewing this now, could you please review mine?" (include a link to yours). You don't have to wait for a response to get started (and you don't have to stop at one!) the more you review, the faster this process goes for everyone 😄
  • To ensure that you are credited properly in the final release notes, please add yourself to contributor-key.yml
  • For more information about contributing, see CONTRIBUTING.md.
Quick links for reviewers...

➡️ Online demo of this PR 🔗

@civibot civibot bot added the master label Dec 29, 2023
@colemanw
Copy link
Member

This is very good @jitendrapurohit thanks for working on it. Some notes:

  1. The link issues can likely be solved by implementing a LinksProvider once SearchKit - New getLinks API action for advanced link handling #27973 is merged (I'm looking for someone to review that PR).
  2. Yes, the first two tabs I replaced with SearchKit (Notes & Relationships) I fully deleted the old tab code. But I think the rest of the tabs are going to need a transition period since Contributions, Memberships, Events etc. are more complex and more-often customized. So AdminUI - Replace Contact Summary Activities tab #27717 adds the Activities tab to the AdminUI extension and I think it's best to do that here as well.
  3. That PR also includes a commit to allow a tab to be overridden, so you won't need any hooks or anything to do that as long as the name of the Afform matches the naming convention used in that PR it will just work (once that PR is merged... also looking for a reviewer).
  4. Since CiviMember is not enabled for every site, I had been thinking about how to make these tabs conditional & I think the answer is to use permissions. The "access CiviMember" permission will not exit and always return FALSE if the component is disabled, so we can set that as the Afform permission. This requires merging Afform - Allow permission to control visibility on contact summary #28796 (once again looking for review).
  5. To make the Saved Searches conditional, you should add an early return to the top of each .mgd.php file like this:
    if (!CRM_Core_Component::isEnabled('CiviEvent')) {
    return [];
    }

@jitendrapurohit jitendrapurohit force-pushed the sk_membertab branch 4 times, most recently from 9e76629 to 738f27f Compare January 5, 2024 12:55
$action = $params['where'][0][2];
$actionLinkIndex = self::getActionIndex($links, $action);
$links = [$links[$actionLinkIndex]];
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@colemanw Since the requirement here is to add new links to the action menu & not the toolbar, the searchkit expects this to return only 1 value and replaces the path link to 0th key here. To accommodate this, I had to perform this check and return the value accordingly. Is there a more optimal approach to address this requirement?

Copy link
Member

Choose a reason for hiding this comment

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

@jitendrapurohit I think a more optimal approach than this would be to break this into 2 callbacks instead of 1.
Like this:

public static function getSubscribedEvents(): array {
return [
'civi.api4.getLinks' => 'alterContactLinks',
'civi.api.respond' => 'alterContactLinksResult',
];
}

The idea is to split the logic between the two callbacks based on the way they each work:

  • civi.api4.getLinks event gets called first. It's not context-aware, and the results are cached. So in this callback you should unconditionally add all links. This happens before the WHERE clause is applied.
  • civi.api.respond event, happens after the WHERE clause is applied, and it is context-aware, so this is where you do the fine-tuning and remove links that are not applicable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, pretty sure i started with this approach but was seeing weird number of links in the action menu. Will try this out again & let you know how it goes. Thanks.

@jitendrapurohit
Copy link
Contributor Author

To make the Saved Searches conditional, you should add an early return to the top of each .mgd.php file like this:

@colemanw Seems .mgd condition works site-wide and not per contact basis? The membership type searchkit needs to be displayed based on $cid it is loading for.

Does it make sense to add a new setting on the table config eg Hide display if table result is empty to control the display of SK? Something like this patch?

@colemanw
Copy link
Member

colemanw commented Jan 7, 2024

Does it make sense to add a new setting on the table config eg Hide display if table result is empty to control the display of SK? Something like this patch?

@jitendrapurohit I think the simplest solution for now would be to implement hook_civicrm_tabset() in the AdminUI extension. It can conditionally unset the tab based on the contact being viewed.

For that matter, we can also use that hook to conditionally unset the Membership component tabs if CiviMember is disabled (once we move the tab to core it will live in the civi_member extension and so that disabling-with-component will be automatic, so this is a simple stopgap while the tab is in the AdminUI extension).

@jitendrapurohit
Copy link
Contributor Author

@colemanw Have now added 2 afforms

  • afsearchTabMember - For Inidividuals & Household contact types.
  • afformTabMember - For Orgs which includes membership type SK display.

Due to these names, the existing tab of Membership is replaced with the afform tab for both contact types.

I feel this is now ready to review.

@jitendrapurohit jitendrapurohit changed the title WIP - ContactSummary - Replace Membership tab with Searchkit display ContactSummary - Replace Membership tab with Searchkit display Jan 9, 2024
"allow_verification_by_email": false,
"email_confirmation_template_id": null,
"navigation": null,
"modified_date": "2024-01-09 13:48:38"
Copy link
Member

Choose a reason for hiding this comment

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

@jitendrapurohit our new convention is to use .aff.php files instead of .aff.json (the php format allows the use of E::ts() for the title). And "modified date" shouldn't be included.
If you don't want to convert these files by hand, you can use the command civix export Afform afformTabMember (that command will generate the aff.html and .aff.php files plus all the .mgd.php for embedded search displays in the form).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, thanks for the above. Have updated 👍

@colemanw
Copy link
Member

colemanw commented Jan 9, 2024

Ok @jitendrapurohit this looks really good. My one question is that your MembershipLinksProvider seems to be providing a lot of links, which the searchDisplay ought to be able to access, but I'm seeing a lot of hard-coded paths in the search display. Can they be switched over to entity + action instead of path as the keys in the link?

private static function unsetLinks(array &$links, array $actions) {
foreach ($actions as $action) {
$actionLinkIndex = self::getActionIndex($links, $action);
unset($links[$actionLinkIndex]);
Copy link
Member

Choose a reason for hiding this comment

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

Probably need to wrap this unset in a conditional like if (isset($actionLinkIndex)) since getActionIndex() could return null (this could happen because of filtering by the WHERE clause excluding the links so they don't need to be unset.).

Comment on lines 19 to 23
'search_displays' => [
'Contact_Summary_Memberships.Contact_Summary_Memberships_Active',
'Contact_Summary_Memberships.Contact_Summary_Memberships_Inactive',
'Contact_Summary_Membership_Type.Contact_Summary_Membership_Type',
],
Copy link
Member

Choose a reason for hiding this comment

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

This is a calculated field, not stored. Should be removed from this file.

'icon' => 'fa-external-link',
'text' => E::ts('Edit'),
'style' => 'default',
'path' => 'civicrm/admin/member/membershipType/add?action=update&id=[id]&reset=1',
Copy link
Member

Choose a reason for hiding this comment

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

Can this use entity+action instead of path?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Have now added links for MembershipType entity in xml & updated the same here. Thanks.

'condition' => [],
],
[
'path' => 'civicrm/contact/view/membership?action=renew&reset=1&cid=[contact_id]&id=[id]&context=membership&selectedChild=member',
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
'path' => 'civicrm/contact/view/membership?action=renew&reset=1&cid=[contact_id]&id=[id]&context=membership&selectedChild=member',
'path' => '',

Path should be omitted when using entity+action as it will be fetched from getLinks api.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, looks like when MembershipLinksProvider was added with entity+action, the path remained in the mgd file even after the file was refreshed from api4 export? Thanks for spotting. Updated.

'dataType' => 'Integer',
'label' => E::ts('Related'),
'sortable' => TRUE,
'rewrite' => "{crmAPI var='owner_count' entity='Membership' action='getcount' owner_membership_id=[id]}\n{if \$owner_count}\n {\$owner_count} {ts}created{/ts}\n{else}\n {ts}N/A{/ts}\n{/if}",
Copy link
Member

Choose a reason for hiding this comment

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

Can this be done with a join + group_by id?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems we dont yet have a self join on SK?

@colemanw
Copy link
Member

This looks great @jitendrapurohit.
We're still early in the release cycle so let's merge this & it can get tested in the alpha & beta.

@colemanw colemanw merged commit 3f5a060 into civicrm:master Jan 12, 2024
3 checks passed
@jitendrapurohit
Copy link
Contributor Author

Thanks for merging @colemanw. I've just created a followup PR to fix auto renew column display #29012

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

Successfully merging this pull request may close these issues.

2 participants