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

Afform - Quick add links for Autocomplete fields #27754

Merged
merged 1 commit into from
Nov 1, 2023

Conversation

colemanw
Copy link
Member

@colemanw colemanw commented Oct 8, 2023

Overview

APIv3-based EntityRef fields have quick-add buttons which link to profile forms (e.g. "New Individual"). This implements a similar feature for the newer APIv4-based Autocomplete fields, using Afforms instead of Profiles.

See https://lab.civicrm.org/dev/core/-/issues/4484

Usage

  1. Create a new form in FormBuilder.
  2. Add an Autocomplete field for Contacts (so far this PR only includes "New Individual" and "New Organization" quick-add forms for testing).
  3. Configure the field and choose "New Individual" or "New Organization" (or both) from the "Quick Add" dropdown.
    image
  4. Visit the form and you'll be able to add a new individual on-the-fly.

Technical Details

For lack of anything fancier, the "quick-add" forms are identified by their route: any form with a route starting with "civicrm/quick-add" is automatically available in the dropdown pictured in step 3 (if the entity type matches).

This makes it quite configurable/flexible. You can make as many quick-add forms as you wish, to suit different types of Autocomplete fields.

@civibot
Copy link

civibot bot commented Oct 8, 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 Oct 8, 2023
@highfalutin
Copy link
Contributor

Exciting work, @colemanw! If I read the code correctly, the main thing that's still missing is, within the FormBuilder admin ui, the configuration of "quick-add" for entityref fields.

@highfalutin
Copy link
Contributor

highfalutin commented Oct 9, 2023

I still want to advocate for allowing admins to override the default quick-add form. An example use case:

  • I have an Activity submission form called "Prize Awarded"
  • I have two entity reference fields on the form, for recording the preliminary activities that led up to the prize being awarded: "Nomination" and "Jury Consideration". Both entityrefs are to Activities -- but two different types of activities, each with their own custom fields.
  • I'd like to be able to quick-add a nomination and/or jury consideration while I'm filling out the "Prize Awarded" form. The two quick-add forms would be different from each other.
    • each one sets a different activity type as a "value" (not exposed to the user)
    • each one includes just the custom fields appropriate for its type

I think making this possible wouldn't be too hard. As you code the UI for configuring quick-add on entityref fields, you'd just need to provide options for "default" (which would be civicrm/quick-add/Activity), and also a drop-down menu allowing the admin to select any existing submission form route.

When it comes to rendering the afform, if non-default quick-add forms have been selected, they'd need to be prepended to CRM.config.quickAdd.

@colemanw colemanw changed the title WIP - Quick add Afform - Quick add links for Autocomplete fields Oct 23, 2023
@colemanw
Copy link
Member Author

@highfalutin I had to go chase a couple rabbits down their holes before coming back to this. But now that #27553 and #27659 and #27713 are merged I've rebased & completed work on this PR and it's working pretty well.

I still want to advocate for allowing admins to override the default quick-add form.

Your wish is granted. 🧞 I'll update the description with a step-by-step. Let me know when you get a chance to review.

@colemanw colemanw marked this pull request as ready for review October 23, 2023 19:07
@colemanw
Copy link
Member Author

Retest this please

@colemanw colemanw force-pushed the quickAdd branch 2 times, most recently from 3b4495f to 7a9d50d Compare October 26, 2023 17:11
@brienneK
Copy link
Contributor

When I click on the Quick Add drop down menu, I get 'None found', instead of 'New Individual'
Selection_051

@colemanw
Copy link
Member Author

retest this please

1 similar comment
@colemanw
Copy link
Member Author

retest this please

@colemanw
Copy link
Member Author

Thanks for testing @briennekordis I just rebuilt the demo site for this PR and now it's present:

image

@colemanw
Copy link
Member Author

Wow Jenkins has really been having a bad week.
retest this please

@highfalutin
Copy link
Contributor

Testing this locally, I am able to create an afform (A1), add an Existing Contact field, and select "New Individual" as the quick-add form for that field.

However, when I open the rendered afform A1 and click the "New Individual" button, the modal form that opens is another copy of the same form A1 -- not a New Individual form.

@colemanw
Copy link
Member Author

colemanw commented Nov 1, 2023

Hmm, ok let's get a new online demo going. @civicrm-builder retest this please

})
// Pop-up Afform when clicking quick-add links
.on('click.crmEntity', '.crm-entityref-quick-add a', () => {
let url = $(this).attr('href');
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
let url = $(this).attr('href');
let url = $('#select2-drop .crm-entityref-quick-add a').attr('href');

Copy link
Contributor

Choose a reason for hiding this comment

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

For some reason, in my testing, this was referring to the wrong element. Changing this line fixes the quick-add behavior.

Copy link
Contributor

Choose a reason for hiding this comment

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

... except when multiple quick-add buttons are configured, it only respects the first one. Hmmmm.

Copy link
Member Author

Choose a reason for hiding this comment

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

@highfalutin Aha! I found "some reason" - it's because arrow functions behave differently than regular functions with this binding.
Fixed now, thanks for the hint.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, this works for multiple quick-add buttons:

Suggested change
let url = $(this).attr('href');
let url = $(event.target).attr('href');

@highfalutin
Copy link
Contributor

afforms for testing
[
  {
    "requires": [],
    "title": "Event Registration with Quick Add",
    "description": "",
    "is_public": false,
    "permission": [
      "access CiviCRM"
    ],
    "type": "form",
    "entity_type": null,
    "join_entity": null,
    "placement": [],
    "summary_contact_type": null,
    "summary_weight": null,
    "icon": "fa-list-alt",
    "server_route": "civicrm/reg",
    "permission_operator": "AND",
    "redirect": null,
    "submit_enabled": true,
    "submit_limit": null,
    "create_submission": true,
    "navigation": {
      "parent": null,
      "label": "Event Registration with Quick Add",
      "weight": 0
    },
    "name": "afformEventRegistrationWithQuickAdd",
    "layout": [
      {
        "#tag": "af-form",
        "ctrl": "afform",
        "#children": [
          {
            "#text": "\n  "
          },
          {
            "#tag": "af-entity",
            "data": {
              "status_id": "1",
              "event_id": "1",
              "role_id": [
                "1"
              ]
            },
            "actions": {
              "create": true,
              "update": false
            },
            "type": "Participant",
            "name": "Participant1",
            "label": "Participant 1",
            "security": "RBAC"
          },
          {
            "#text": "\n  "
          },
          {
            "#tag": "fieldset",
            "af-fieldset": "Participant1",
            "class": "af-container",
            "af-title": "Participant 1",
            "#children": [
              {
                "#text": "\n    "
              },
              {
                "#tag": "af-field",
                "name": "contact_id",
                "defn": {
                  "input_attrs": {
                    "quickAdd": "civicrm/quick-add/Individual/with-phone-email"
                  }
                }
              },
              {
                "#text": "\n    "
              },
              {
                "#tag": "button",
                "class": "af-button btn btn-primary",
                "crm-icon": "fa-check",
                "ng-click": "afform.submit()",
                "#children": [
                  {
                    "#text": "Submit"
                  }
                ]
              },
              {
                "#text": "\n  "
              }
            ]
          },
          {
            "#text": "\n"
          }
        ]
      },
      {
        "#text": "\n"
      }
    ]
  },
  {
    "requires": [],
    "title": "New Individual Phone Email",
    "description": "",
    "is_public": false,
    "permission": [
      "access CiviCRM"
    ],
    "type": "form",
    "entity_type": null,
    "join_entity": null,
    "placement": [],
    "summary_contact_type": null,
    "summary_weight": null,
    "icon": "fa-list-alt",
    "server_route": "civicrm/quick-add/Individual/with-phone-email",
    "permission_operator": "AND",
    "redirect": null,
    "submit_enabled": true,
    "submit_limit": null,
    "create_submission": true,
    "navigation": null,
    "name": "afformNewIndividualPhoneEmal",
    "layout": [
      {
        "#tag": "af-form",
        "ctrl": "afform",
        "#children": [
          {
            "#text": "\n  "
          },
          {
            "#tag": "af-entity",
            "data": {
              "contact_type": "Individual",
              "source": "New Individual Phone Email"
            },
            "type": "Contact",
            "name": "Individual1",
            "label": "Individual 1",
            "actions": {
              "create": true,
              "update": true
            },
            "security": "RBAC"
          },
          {
            "#text": "\n  "
          },
          {
            "#tag": "fieldset",
            "af-fieldset": "Individual1",
            "class": "af-container",
            "af-title": "Individual 1",
            "#children": [
              {
                "#text": "\n    "
              },
              {
                "#tag": "af-field",
                "name": "first_name"
              },
              {
                "#text": "\n    "
              },
              {
                "#tag": "af-field",
                "name": "last_name"
              },
              {
                "#text": "\n    "
              },
              {
                "#tag": "div",
                "af-join": "Email",
                "af-repeat": "Add",
                "af-copy": "Copy",
                "min": "1",
                "#children": [
                  {
                    "#text": "\n      "
                  },
                  {
                    "#tag": "afblock-contact-email"
                  },
                  {
                    "#text": "\n    "
                  }
                ]
              },
              {
                "#text": "\n    "
              },
              {
                "#tag": "div",
                "af-join": "Phone",
                "af-repeat": "Add",
                "af-copy": "Copy",
                "min": "1",
                "#children": [
                  {
                    "#text": "\n      "
                  },
                  {
                    "#tag": "afblock-contact-phone"
                  },
                  {
                    "#text": "\n    "
                  }
                ]
              },
              {
                "#text": "\n  "
              }
            ]
          },
          {
            "#text": "\n  "
          },
          {
            "#tag": "button",
            "class": "af-button btn btn-primary",
            "crm-icon": "fa-check",
            "ng-click": "afform.submit()",
            "#children": [
              {
                "#text": "Submit"
              }
            ]
          },
          {
            "#text": "\n"
          }
        ]
      },
      {
        "#text": "\n"
      }
    ]
  }
]

Copy link
Contributor

@highfalutin highfalutin left a comment

Choose a reason for hiding this comment

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

These changes are also needed; otherwise buttons for all afforms under "civicrm/quick-add/X" are shown.

}
let markup = '<div class="crm-entityref-links crm-entityref-quick-add">';
CRM.config.quickAdd.forEach((link) => {
if (quickAddLinks.includes(link.path)) {
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
if (quickAddLinks.includes(link.path)) {
if (_.includes(quickAddLinks, link.path)) {

Copy link
Member Author

Choose a reason for hiding this comment

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

I've been trying to use more vanilla and less lo-dash recently, as that seems to be the direction the whole internet is headed. Did you find a bug here or is it just a style thing?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's a bug.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, I think I found the cause - quickAddLinks is a string but was supposed to be an array. One sec...

Copy link
Contributor

Choose a reason for hiding this comment

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

That's why I made the Line 580 suggestion.

multiple = !!select2Options.multiple;
const $el = $(this).off('.crmEntity');
let staticItems = getStaticOptions(select2Options.static),
quickAddLinks = select2Options.quickAdd,
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
quickAddLinks = select2Options.quickAdd,
quickAddLinks = select2Options.quickAdd ? select2Options.quickAdd.split(',') : [],

@colemanw
Copy link
Member Author

colemanw commented Nov 1, 2023

@highfalutin thanks for patiently testing this. I've fixed the array formatting, the this binding, also added a "New Organization" form and fixed both forms to make "Email" not required. Re-tested locally and pushed.
We're getting close!

@highfalutin
Copy link
Contributor

highfalutin commented Nov 1, 2023

Thanks @colemanw! The last bug we were talking about still needs to be fixed. At js/Common.js line 580, quickAddLinks is still a string, not an array.

The reason I propose _.includes() in line 547 is that Array.prototype.includes is not yet supported in most browsers.

@colemanw
Copy link
Member Author

colemanw commented Nov 1, 2023

@highfalutin quickAddLinks is still a string, not an array.

I think that might just be your existing test forms. If you regenerate those with the updated patch I've fixed the Afform GUI to always set that value as an array.

Array.prototype.includes is not yet supported in most browsers.

I'm not quite sure what you mean... that link shows green for every browser except IE. I think we've pretty much given up on maintaining IE support.

@highfalutin
Copy link
Contributor

Ah, ok, I re-tested and am no longer seeing the bug. My bad re: includes. I was confusing it with another thing that I was looking up at the same time.

@highfalutin
Copy link
Contributor

The last test I did was whether quick-adds could be used within quick-adds. And they can!

IMO this can be merged.

@colemanw
Copy link
Member Author

colemanw commented Nov 1, 2023

Excellent

@colemanw colemanw merged commit 3e20ee7 into civicrm:master Nov 1, 2023
@colemanw colemanw deleted the quickAdd branch November 1, 2023 16:02
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.

3 participants