{"action":"created","issue":{"url":"https://api.github.com/repos/civicrm/civihr/issues/1112","repository_url":"https://api.github.com/repos/civicrm/civihr","labels_url":"https://api.github.com/repos/civicrm/civihr/issues/1112/labels{/name}","comments_url":"https://api.github.com/repos/civicrm/civihr/issues/1112/comments","events_url":"https://api.github.com/repos/civicrm/civihr/issues/1112/events","html_url":"https://github.com/civicrm/civihr/pull/1112","id":173136011,"number":1112,"title":"PCHR-1509: Show departments in contact page header","user":{"login":"AkA84","id":6400898,"avatar_url":"https://avatars.githubusercontent.com/u/6400898?v=3","gravatar_id":"","url":"https://api.github.com/users/AkA84","html_url":"https://github.com/AkA84","followers_url":"https://api.github.com/users/AkA84/followers","following_url":"https://api.github.com/users/AkA84/following{/other_user}","gists_url":"https://api.github.com/users/AkA84/gists{/gist_id}","starred_url":"https://api.github.com/users/AkA84/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AkA84/subscriptions","organizations_url":"https://api.github.com/users/AkA84/orgs","repos_url":"https://api.github.com/users/AkA84/repos","events_url":"https://api.github.com/users/AkA84/events{/privacy}","received_events_url":"https://api.github.com/users/AkA84/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2016-08-25T07:51:52Z","updated_at":"2016-09-12T11:32:57Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/civicrm/civihr/pulls/1112","html_url":"https://github.com/civicrm/civihr/pull/1112","diff_url":"https://github.com/civicrm/civihr/pull/1112.diff","patch_url":"https://github.com/civicrm/civihr/pull/1112.patch"},"body":"## Problem\r\nThe department did not appear anymore in the \"enhanced\" contact summary header\r\n\r\n<img width=\"1000\" alt=\"before\" src=\"https://cloud.githubusercontent.com/assets/6400898/17961679/6e9c67c4-6aad-11e6-98e7-2cfe0e3a40ca.png\">\r\n\r\nThis was due to a change in how we store the department in the `civicrm_hrjobroles` table. Initially the department was stored as the `id` of the option value (each department is an option value in the _hrjc_department_ option group), but it was later changed, in [this PR](https://github.com/civicrm/civihr/pull/955) to be stored as the `value` of the option value, by leveraging the [Pseudoconstant](https://wiki.civicrm.org/confluence/display/CRMDOC/Pseudoconstant+(option+list)+Reference) mechanism that CiviCRM offers.\r\n\r\nSo basically we changed how we store the reference to the department, but forgot to also amend how we fetch it, since we were still using the `id` to do that\r\n```php\r\npublic static function getDepartmentsList($contractID)  {\r\n  // ...\r\n  $query = \"SELECT cov.id, cov.label\r\n          FROM civicrm_hrjobroles hrjr\r\n          LEFT JOIN civicrm_option_value cov\r\n          ON hrjr.department = cov.id\r\n          WHERE hrjr.job_contract_id = %1\";\r\n```\r\n\r\nAdditionally  the `getDepartmentsList` method would return the departments of *all* the job roles, including the ones that have expired\r\n\r\n## Solution\r\n<img width=\"1000\" alt=\"after\" src=\"https://cloud.githubusercontent.com/assets/6400898/17961695/851c07fc-6aad-11e6-82fc-fb61c12c44f7.png\">\r\n\r\nBy changing the query in `getDepartmentsList`, the department is now fetched correctly, by using its `value`. Since different option values can have the same value, the query limits the search in the _hrjc_department_ option group\r\n```php\r\n$query = \"SELECT cov.id, cov.label\r\n          FROM civicrm_hrjobroles hrjr\r\n          INNER JOIN civicrm_option_value cov\r\n            ON hrjr.department = cov.value\r\n          INNER JOIN civicrm_option_group cog\r\n            ON cov.option_group_id = cog.id\r\n          WHERE hrjr.job_contract_id = %1\r\n            AND cog.name = 'hrjc_department'\";\r\n```\r\n\r\nAlso now only the departments of the current job roles are returned\r\n\r\n### Technical notes\r\nI've also refactored the `_hrui_updateContactSummaryUI` function by breaking it down in smaller functions\r\n\r\n## Problem\r\nThe \"Departments\" section of the contact page header didn't automatically update when a job role would get added/updated/deleted\r\n\r\n![before](https://cloud.githubusercontent.com/assets/6400898/18020603/94c4f49e-6be2-11e6-934a-2d0d7574384b.gif)\r\n\r\n## Solution\r\nNow on create/update/edit the contact header gets updated on the fly to reflect the correct current list of departments\r\n\r\n![after](https://cloud.githubusercontent.com/assets/6400898/18020618/a719b22e-6be2-11e6-8f9f-902ae933829b.gif)\r\n\r\n### Technical notes\r\n\r\n#### `HrJobRoles.getcurrentdepartments` API endpoint\r\nIn order to update the list of departments on the fly, the angular app needed a way to access the `CRM_Hrjobroles_BAO_HrJobRoles::getCurrentDepartmentsList` method, and for this reason a new api endpoint was added\r\n\r\n#### `DOMEventTrigger` service\r\nInitially this update-contact-header features only happened in the job contracts angular app (whenever a job contract was added/updated/deleted the header would get updated as well), and as a temporary solution all the jQuery DOM modification required for the update were directly in a service\r\n```js\r\n// In `ContractService`\r\nchangeHeaderInfo: function() {\r\n  this.getCurrentContract(settings.contactId).then(function(currentContract){\r\n    if(currentContract)  {\r\n      cj('.crm-summary-contactname-block').removeClass('crm-summary-contactname-block-without-contract');\r\n      // ...\r\n    } else {\r\n      cj('.crm-summary-contactname-block').addClass('crm-summary-contactname-block-without-contract');\r\n      // ...\r\n    }\r\n  })\r\n```\r\nnow that the same thing was required to happen also in the job roles extension, this temporary solution wasn't good anymore\r\n\r\nSo the best (although *still temporary*) solution is to have the `hrui` extension take care of the DOM manipulation (that's what it is for after all), which would be triggered by the two angular apps. Basically you need two angular apps emitting an event that a jQuery script would intercept and act upon\r\n\r\nFor this reason the `DOMEventTrigger` was written, which is a very simple service that triggers a given event (with given custom data attached) to the `document`, which can then be intercepted by any scripts that needs to listen to it. The reason it is a service it's so that in case the implementation can be improved, the angular apps will not be affected as the implementation is hidden within the service:\r\n```js\r\n// In HRJobRolesController\r\nHRJobRolesService.getCurrentDepartments(jobRole.job_contract_id).then(function (departments) {\r\n  DOMEventTrigger('updateContactHeader', {\r\n    roles: { departments: departments }\r\n  });\r\n});\r\n```\r\n```js\r\n// In contact.js in the hrui extension\r\n$(document)\r\n  .on('updateContactHeader', function (e, data) {\r\n    if (typeof data.contract !== 'undefined')  {\r\n      updateContactHeaderContractDetails(data.contract);\r\n    }\r\n\r\n    if (typeof data.roles !== 'undefined')  {\r\n      updateContactHeaderRolesDetails(data.roles);\r\n    }\r\n  });\r\n```\r\nIs is likely that this kind of communication could happen in other areas in CiviHR, given that the our angular apps cover only a portion of the overall application, so having this kind of service (and approach) could be, although not perfect, a good step in the right direction \r\n\r\n"},"comment":{"url":"https://api.github.com/repos/civicrm/civihr/issues/comments/246320806","html_url":"https://github.com/civicrm/civihr/pull/1112#issuecomment-246320806","issue_url":"https://api.github.com/repos/civicrm/civihr/issues/1112","id":246320806,"user":{"login":"deb1990","id":5058867,"avatar_url":"https://avatars.githubusercontent.com/u/5058867?v=3","gravatar_id":"","url":"https://api.github.com/users/deb1990","html_url":"https://github.com/deb1990","followers_url":"https://api.github.com/users/deb1990/followers","following_url":"https://api.github.com/users/deb1990/following{/other_user}","gists_url":"https://api.github.com/users/deb1990/gists{/gist_id}","starred_url":"https://api.github.com/users/deb1990/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/deb1990/subscriptions","organizations_url":"https://api.github.com/users/deb1990/orgs","repos_url":"https://api.github.com/users/deb1990/repos","events_url":"https://api.github.com/users/deb1990/events{/privacy}","received_events_url":"https://api.github.com/users/deb1990/received_events","type":"User","site_admin":false},"created_at":"2016-09-12T11:32:57Z","updated_at":"2016-09-12T11:32:57Z","body":"Approve"}}
{"actor":{"display_login":"deb1990"}}