-
-
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
CRM-21849: Inline Relationship Type Edit #11853
CRM-21849: Inline Relationship Type Edit #11853
Conversation
(CiviCRM Review Template WORD-1.1)
I ran this locally to see what I could break. I found the following issues:
|
7a710f2
to
8494007
Compare
@seanmadsen thanks very much for the comprehensive QA
Good catch. This seems to be related to the type casting I did. Unfortunately I found that unlike what the doc block says
I couldn't reproduce this: In my GIF you might point out that I didn't edit the "A" side of the relationship. This is because (for me anyway) there seems to be a bug where editing the "A" side also replaces the value on the "B" side. I have created an issue for this.
Another good spot. I had a look at this and found that whether the options are refreshed or not depends on if the event returns data. In this commit I added some arbitrary data which will cause the options to be refreshed. As I mentioned in the commit message it is sort of a hack to get the desired functionality, but it could be useful data for reacting to the event. One thing to note is that if you choose a disabled relationship type the option will be unselected. Even after enabling the relationship type in the popup it'll be unselected. This is because the rebuilding of the options just goes by the existing selected option, it doesn't do anything like fetching which option should be selected from the database. Basically if the option isn't selected already it doesn't know which one to select after. |
Nice. Looking good, @mickadoo. I havn't re-tested, but I wanted to comment on the one you weren't able to reproduce... The steps I'm taking involve clicking on the "Edit" link, at the far right of the relationship type, which opens a separate form. Can you try that? |
@colemanw there is great review here by @seanmadsen but I think you also need to comment on the approach. Having 'contact_id' as a field for getoptions spec feels a bit odd having skimmed it - but I have not looked closely enough to have formed an opinion about it & the buildOptions structure is your brain child :-) |
@seanmadsen Ah, I didn't realize that. I tried to reproduce and actually I managed to first, but I noticed when I cleared the browser cache the problem went away. It might be an issue where the JS files are being cached, but the HTML content is showing the gear icon @eileenmcnaughton @colemanw A code review would be very helpful. I felt like I was going off the standard path here when I needed to make changes to how the spec functions are working, plus for other |
Ah, caching! I see! Yes, I see what you mean. Ok... I have reviewed this again after Michael's follow-up changes and can verify that he has addressed all my Here's where we're at now then:
We still need someone to review those parts of the checklist that I skipped. |
@colemanw if you're a bit busy maybe you can suggest someone else for a review? |
Just as an aside I'm aware of another PR that is stalled really on needing core (& in particular Coleman to review). It's kind of similar in that there is a non-trivial amount of review effort. In that context I had a conversation about whether it would be possible to buy a 2 hour block of ct review time to get it prioritised over all the unfunded work (with no guarantee of merge in that time but at least definitely getting that time). It seems the blocker to such arrangements is often the 'sales process' - ie. the discussions around it take more time than is actually funded. |
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.
I just tried r-run and ran into a bug. To reproduce:
- Click the "relationships" tab for a contact.
- Click "Add relationship"
- Click the wrench and add a new relationship type.
- Observe the "Contact(s)" field is still frozen an there is a js error in the console:
The problem is that there is a static list of relationship type metadata in the DOM which will not contain any data for the new relationship type. FWIW the variable is named relationshipData
and is generated by CRM_Contact_Form_Relationship::getRelationshipTypeMetadata
.
The solution is probably to add a new ajax callback path to fetch that info, and respond to the triggered event crmOptionsEdited
to refetch it.
This property will be a string, but it is being compared to $contactID which should be an int.
This is used when some extra parameters are required when refreshing option lists after inline editing, i.e. relationship types are limited to the current contact type
Allows to modify spec even if generic getoptions function is used
Based on the docblock I expected contact ID to be an int, but this is not always the case.
The logic on whether to refresh the available options in CRM.popup depends on whether the crmPopupFormSuccess returned data. The data provided here is arbitrary but could be useful in the future for anyone reacting to the event
5ede39b
to
5093350
Compare
The formatting of relationship data is a FE related task and can be done in Javascript. This also allows reloading the data if some options change after editing relationship types.
5093350
to
601cc89
Compare
relationshipData = {}, | ||
contactTypes = {}; | ||
|
||
$('body').on('crmOptionsEdited', 'a.crm-option-edit-link', refreshRelationshipData); |
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.
Create a init
function, it would help to organise the code, also place other initialisation code inside.
(function init () {
$('body').on('crmOptionsEdited', 'a.crm-option-edit-link', refreshRelationshipData);
refreshRelationshipData().done(...)
$relationshipTypeSelect.change(function() {
})()
* Fetch contact types and reset relationship data | ||
*/ | ||
function refreshRelationshipData() { | ||
var defer = $.Deferred(); |
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.
No need to create defer
object, the following will do the same thing
relationshipData = {};
return getContactTypes()
.then(function() {
return getRelationshipData();
});
});
* Fetches the relationship data using latest relationship types | ||
*/ | ||
function getRelationshipData() { | ||
var subtype, |
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.
These variables are used only inside $.each, so we can define them inside only. Overall this is how it should look like
function getRelationshipData() {
var defer = $.Deferred();
if (!$.isEmptyObject(relationshipData)) {
defer.resolve(relationshipData);
}
CRM.api3("RelationshipType", "get")
.done(function (data) {
$.each(data.values, function (key, relType) {
// Please add a comment mentioning what is ["a", "b"]
$.each(["a", "b"], function (index, suffix) {
var subtype = relType["contact_subtype_" + suffix];
var type = subtype || relType["contact_type_" + suffix];
var label = getContactTypeLabel(type) || "Contact";
var placeholder = "- select " + label.toLowerCase() + " -";
relType["placeholder_" + suffix] = placeholder;
});
relationshipData[relType["id"]] = relType;
});
defer.resolve(relationshipData);
});
return defer.promise();
}
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.
nice, I like the early return!
@@ -299,9 +299,6 @@ public function buildQuickForm() { | |||
// Select list | |||
$relationshipList = CRM_Contact_BAO_Relationship::getContactRelationshipType($this->_contactId, $this->_rtype, $this->_relationshipId); | |||
|
|||
// Metadata needed on clientside | |||
$this->assign('relationshipData', self::getRelationshipTypeMetadata($relationshipList)); |
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.
If the function getRelationshipTypeMetadata
is no longer used then it can be removed. I agree this can all be done from the frontend.
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.
It would be nice to clean it up to avoid having code that does the same thing in JS and PHP, but it's still used in one other place. My JS skills are very limited, but if you think it's best that we remove this function and provide some common service to fetch this data then I can give that a shot.
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.
Sorry, didn't realize it was used elsewhere. I don't think that's a priority.
} | ||
|
||
return defer.promise(); | ||
} |
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.
I would recommend not loading contact types via ajax because the two back-to-back ajax calls will be unnecessarily slow. I suggest pre-loading contactType data into the dom (via $form->assign()
) to avoid the lag.
defer.resolve(relationshipData); | ||
} | ||
|
||
CRM.api3("RelationshipType", "get") |
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.
Need to set limit:0
to avoid the api3 default limit of 25.
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.
My bad, we added an API wrapper to remove this by default in CiviHR and I'm too used to dealing with that
One test is failing, but seems to be the same on all PRs right now |
Ok I think this is good to merge. I've completed the review started by Sean and it's now passing on all levels. |
Included in CiviCRM 5.3.0 Core PR: civicrm#11853
Included in CiviCRM 5.2.0 Core PR: civicrm#11853
Please see https://lab.civicrm.org/dev/core/issues/268 |
@mickadoo FYI the function |
This gitlab has been logged https://lab.civicrm.org/dev/core/issues/895 - which suggests a regression that possibly sorta comes from this PR - but with other factors |
…e whole is_form thing halted my work because the keys are munged id + direction which is totally screwy. Probably would be best to ditch that as its only used for civicrm#11853
This adds basic pseudoconstant support for the field using name_a_b and label_a_b (it does not support other properties like name_b_a) For legacy purposes it preserves the work done in civicrm#11853 to return a list like [1_a_b => Child of, 1_b_a => Parent of] if the "is_form" flag is set. This was very nonstandard but is used to support in-place editing of the relationship type list on the relationship form.
This adds basic pseudoconstant support for the field using name_a_b and label_a_b (it does not support other properties like name_b_a) For legacy purposes it preserves the work done in civicrm#11853 to return a list like [1_a_b => Child of, 1_b_a => Parent of] if the "is_form" flag is set. This was very nonstandard but is used to support in-place editing of the relationship type list on the relationship form.
This adds basic pseudoconstant support for the field using name_a_b and label_a_b (it does not support other properties like name_b_a) For legacy purposes it preserves the work done in civicrm#11853 to return a list like [1_a_b => Child of, 1_b_a => Parent of] if the "is_form" flag is set. This was very nonstandard but is used to support in-place editing of the relationship type list on the relationship form.
This adds basic pseudoconstant support for the field using name_a_b and label_a_b (it does not support other properties like name_b_a) For legacy purposes it preserves the work done in civicrm#11853 to return a list like [1_a_b => Child of, 1_b_a => Parent of] if the "is_form" flag is set. This was very nonstandard but is used to support in-place editing of the relationship type list on the relationship form.
Overview
To make it easier to edit relationship types this PR adds an icon to show a popup for inline editing of relationship types.
Before
It was not possible to edit relationship types inline. You had to go to the
civicrm/admin/reltype
screenCalls to
getoptions
for Relationship with field 'relationship_type_id` would result in:After
The relationship type dropdown has an icon to allow inline editing.
The Relationship
getoptions
endpoint supportsrelationship_type_id
Technical Details
getoptions
were ignored if the concrete spec function was not implemented. I wanted to modify the spec, but I didn't want to override the genericgetoptions
function. I modified the generic function to support custom spec functions.getoptions
call done from crm.optionEdit.js so I introducedoption_context
to the elements. If it exists it will be set as a property of the element (along with the other metadata, such asdata-api-entity
anddata-api-field
, and it will be passed along to thegetoptions
call.relationshipData
was previously populated in the backend usingCRM_Contact_BAO_Relationship::getContactRelationshipType
but this means that it stays static. To allow dynamically recreatingrelationshipData
(after editing etc.) the generation was switched to the frontend