-
-
Notifications
You must be signed in to change notification settings - Fork 825
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
AdminUI - dynamically generate afform tabs for CustomGroups of style Tab with table #31503
AdminUI - dynamically generate afform tabs for CustomGroups of style Tab with table #31503
Conversation
add dynamic forms for editing and adding custom group data
🤖 Thank you for contributing to CiviCRM! ❤️ We will need to test and review this PR. 👷 Introduction for new contributors...
Quick links for reviewers...
|
Further question... group-level config settings - it's very evident during this that we are trying to interpret settings that were based on a different context, so I'm wondering of the scope to add/alter the config options available on CustomGroup / CustomField to be more suited to this new paradigm? Immediate examples of things I'd consider adding:
You may be thinking: "well you can just customise any of those things in afform" -- but I think there is a case for being able to specify the defaults as part of the CustomGroup / CustomField meta. Would make packaging that sort of stuff up into extensions much easier for one. (You provide managed records for CustomGroup / CustomField and all of the afforms will be derived from this, you don't have to package the CustomGroups and the Afforms, and keep those things in sync, and update your packaged afforms in order to pull through improvements in the default CustomGroup => Afform derivation.) |
f59ff40
to
714cec1
Compare
… 'access all custom data'
714cec1
to
1ef716a
Compare
@ufundo Q: What happens if you set a "Maximum number of multiple records" limit on the custom group? Does the afform respect that? |
Good question. I haven't done anything for that, so I'm guessing:
It's a bit tricky because the Add form won't know about the restriction until you hit submit with a given entity_id; but from a user perspective you don't want to go through the trouble of filling in the form, only to find you can't submit it. Easy option: hide the button to the Add form in the tab? Hard option: some kind of custom angular directive that immediately checks any value added to |
Looks like you can create records exceeding the configured limit using Api4. So it's prob just implemented in the QuickForm atm.
Good enough for now? |
FYI @lcdservices - work so far on making an Afform/Search Kit tab for "Tab with table" CustomGroups You can see it working on the test site here: |
I think the correct option is to implement the Api4 |
That sounds good!
I think the other piece would be making the create form url the canonical url for "Create" - at the moment it's just using a (relatively) hard coded URL. Some hook on |
Hmm - even if we make our form the canonical "create" form - SearchDisplay run is going to have to know what entity_id it needs to create for 🤔 Well lets see |
@ufundo I would say just make the url to this form the canonical link in the api. Don't worry about a hook. |
I've made a checkAccess check which seems to work for stopping Adding the link is less successful: for some reason trying to add that (Other minor point: you get the option for Update form button in SearchKit, but you still have the Update searchaction taks button, so you get two indistguishable options that do different things) |
ext/civicrm_admin_ui/Civi/Api4/Action/CustomGroup/GetSearchKit.php
Outdated
Show resolved
Hide resolved
ext/civicrm_admin_ui/Civi/Api4/Action/CustomGroup/GetSearchKit.php
Outdated
Show resolved
Hide resolved
ext/civicrm_admin_ui/Civi/Api4/Event/Subscriber/CustomGroupEntityLinks.php
Outdated
Show resolved
Hide resolved
03c89b7
to
a40c9f1
Compare
ext/civicrm_admin_ui/Civi/Api4/Action/CustomGroup/GetSearchKit.php
Outdated
Show resolved
Hide resolved
Realised my paths were generating wrong. I don't know why it cause the error it did, but seems fixed now. And the Add button does indeed show/hide interactively correctly 😁 |
So clever how it derives the toolbar token values from the where in the search! And then checks access based on those parameters too... 🤯 |
Thanks, I really wanted to put all the cleverness into SearchKit itself to enable no-code CRUD forms for most entities. |
@ufundo I'm not entirely sure I understand the benefit to wrapping those getter functions into API actions. I'm not opposed, just not quite sure why anybody would ever need to call them as APIs. |
I thought it was an efficient and consistent way to fetch all the required info for each CustomGroup in one go, and then process them sequentially. I didn't realise there was already a cache, so no need to fetch. I still think it's structurally tidy to do it an "entity"-based way. And generally it's nice to use consistent APIs across all the code (I'm going to have to go look up how the |
I was thinking it would involve some kind of check on whether the get params were suitably simple that the api could answer without a DB query. Certainly no explicit or implicit joins or group by. Field formatting and things like that are probably harder to triage. But it feels like all the calls I've written in this PR are fairly clearly answerable based on the cache. |
…tiple for the CustomGroup
a40c9f1
to
ca5a32a
Compare
I gave it a go #31508 and it does seem to work... though it opens another can of worms around case sensitivity. Happy to switch back to the regular cache for now if you'd prefer to avoid that can @colemanw ? The can was useful to open for a minute at least :
|
7df3244
to
14f4870
Compare
Ok I've switched to using |
retest this please |
@colemanw I think this is ready to go? (using the pre-existing caching for now) |
Looks great! Thanks @ufundo |
Overview
Following #31484 - this adds a SearchKit and tab for each CustomGroup where style = Tab with table
Before
Hard-coded Tab with table:
![image](https://private-user-images.githubusercontent.com/6513484/388437631-e9450c89-5c05-471d-93f0-9cf9311a0eee.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk3OTkyOTAsIm5iZiI6MTczOTc5ODk5MCwicGF0aCI6Ii82NTEzNDg0LzM4ODQzNzYzMS1lOTQ1MGM4OS01YzA1LTQ3MWQtOTNmMC05Y2Y5MzExYTBlZWUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTdUMTMyOTUwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NGNjNjJkNDI0NGU1ZDA0MzcyZmNjZmJlZjNmZjQ3ZWZmNTg0MWUxZDFjM2RhZmZiN2VmZGYxMmFkZGJlN2RlZiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.2Fja_ZemtlOsCEKXRK_EDzvSKhec6UDT3ta8VaX6aWg)
Error when adding a record (from @colemanw )
![image](https://private-user-images.githubusercontent.com/6513484/388437865-33222a39-44b1-490e-8ff3-b87345e3ccfe.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk3OTkyOTAsIm5iZiI6MTczOTc5ODk5MCwicGF0aCI6Ii82NTEzNDg0LzM4ODQzNzg2NS0zMzIyMmEzOS00NGIxLTQ5MGUtOGZmMy1iODczNDVlM2NjZmUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTdUMTMyOTUwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9Mjc1YTNiNDUwMDc4YTJjZjMzYTk4YWNhZWIyMzliMDliYzRjZWMyNDdlODA5ODk3ZWExMTFkNTcwNzAzY2NjMSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.pqJfI41U0PeBKjh3G4RGlXKpZhc0Aj_EduySt1Heiq0)
After
Generated afform tab:
![image](https://private-user-images.githubusercontent.com/6513484/388440564-57e8f72b-5337-4063-8ed3-d4bac11fb310.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk3OTkyOTAsIm5iZiI6MTczOTc5ODk5MCwicGF0aCI6Ii82NTEzNDg0LzM4ODQ0MDU2NC01N2U4ZjcyYi01MzM3LTQwNjMtOGVkMy1kNGJhYzExZmIzMTAucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTdUMTMyOTUwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZTgzZmUzZTIzNzJmYzNhYTUzODVkNTUzZWM5YWE0ZmQ2ZTJkMmJiNjk3ZGJmMDQ4MzEyYjIxNGVmNTFkMmUyMiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.waDC19QDoVigz6PAMQYaYfp8QIouvyvJSIHVwijQG3Q)
Additional functionality:
e.g.
add a filter field:
![image](https://private-user-images.githubusercontent.com/6513484/388441339-bb699891-b7ae-466a-8976-c59d2dad9c74.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk3OTkyOTAsIm5iZiI6MTczOTc5ODk5MCwicGF0aCI6Ii82NTEzNDg0LzM4ODQ0MTMzOS1iYjY5OTg5MS1iN2FlLTQ2NmEtODk3Ni1jNTlkMmRhZDljNzQucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTdUMTMyOTUwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NjljYjliYjk3NmUwNWE1ZDJhMjUxNThlOWE4OTI4NDE0MWE5ZWZiY2E1OTkwYWQ5NjQwOWY0NjQ2NDBlNjg2OSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.CI6E9ag9l6KFdpnEsC02bHlE3Y35Yq_bY-CXclOGzx8)
Technical Details
For each multi-value Tab with table custom group, we generate:
Display in table
is setThere's a bit of back-n-forth in terms of the interplay between
afform_core
andcivicrm_admin_ui
:The SearchKit bits are added in
civicrm_admin_ui
only.The code for Afform generation is added to CustomGroup.GetAfforms action, which is implemented in
afform_core
because it includes the Custom Group blocks, which are already provided byafform_core
. But generating the additional forms is gated based on havingcivicrm_admin_ui
enabled. (These forms depend on the search kit bits fromcivicrm_admin_ui
.)(*) - this required small patch to the tabset hook in afform, because it uses a convention for displacing tabs based on matching the afform name to the existing tab ID. But I really wanted the new afforms to use the CustomGroup name, whereas the existing tabs are keyed by the custom group id.
The whole thing lends itself to more generalisability. I've tried to structure in a way that supports some of the next steps below.
Questions
Permissions:
Deprecation:
Next steps