Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagexml
titlerelationships/list.gsp (in coreapps module)
<%
    // Nearly every page you write should do this, to get the standard reference application decoration and includes
    ui.decorateWith("appui", "standardEmrPage")
 
    // include angular and angular-uiplugins
    ui.includeJavascript("uicommons", "angular.js")
    ui.includeJavascript("uicommons", "angular-resource.min.js")
    ui.includeJavascript("uicommons", "angular-ui/ui-bootstrap-tpls-0.6.0.min.js")
    ui.includeJavascript("uicommons", "ngDialog/ngDialog.js")
    ui.includeCss("uicommons", "ngDialog/ngDialog.min.css")
 
    // we use the following OpenMRS angular services and directives
    ui.includeJavascript("uicommons", "angular-common.js")
    ui.includeJavascript("uicommons", "services/relationshipService.js")
    ui.includeJavascript("uicommons", "services/relationshipTypeService.js")
    ui.includeJavascript("uicommons", "services/personService.js")
    ui.includeJavascript("uicommons", "directives/select-person.js")
 
    // custom JS and CSS for this page
    ui.includeJavascript("coreapps", "relationships/relationships.js")
    ui.includeCss("coreapps", "relationships/relationshipslist.css")
%>
 
<!-- Configuring breadcrumbs; you'd typically copy-paste this from another page and change the last item in the list -->
<script type="text/javascript">
    var breadcrumbs = [
        { icon: "icon-home", link: '/' + OPENMRS_CONTEXT_PATH + '/index.htm' },
        { label: "${ ui.escapeJs(patient.patient.familyName) }, ${ ui.escapeJs(patient.patient.givenName) }" ,
            link: '${ui.pageLink("coreapps", "clinicianfacing/patient", [patientId: patient.patient.id])}'},
        { label: "${ ui.escapeJs(ui.message("coreapps.task.relationships.label")) }" }
    ]
</script>
 
<!-- Include the standard patient header before we get to the specifics of this page -->
${ ui.includeFragment("coreapps", "patientHeader", [ patient: patient.patient ]) }
 
<!-- Your page should have a title -->
<h2>$<h3>${ ui.message("coreapps.task.relationships.label") }</h2>h3>
<div id="relationships-app" ng-controller="PersonRelationshipsCtrl" 
<!-- ng-init="init('${ patient.patient.uuid }')" is the most convenient way to bootstrap the static js code with dynamic data from this gsp -->
<div id="relationships-app" ng-controller="PersonRelationshipsCtrl" ng-init="init('${ patient.patient.uuid }')">

    <!-- This is how you do an inline angular template -->
    <div<script type="text/ng-show="addDialogModetemplate" class="dialog" id="add-relationship-dialogaddDialogTemplate">
        <div class="dialog-header">
            <%<h3><%= ui.message("coreapps.relationships.add.header", "{{ addDialogOtherLabelngDialogData.otherLabel }}") %>%></h3>
        </div>
        <div class="dialog-content">
            <div>
                <label>
                    <%= ui.message("coreapps.relationships.add.choose", "{{ addDialogOtherLabelngDialogData.otherLabel }}") %>
                </label>
                <select-person ng-model="otherPerson" exclude-person="${ patient.patient.uuid }" />
            </div>
            <div class="add-confirm-spacer">
                <div ng-show="otherPerson" >
                    <h3>${ ui.message("coreapps.relationships.add.confirm") }</h3>
                    <p>{{ addDialogThisLabelngDialogData.thisLabel }}: ${ ui.format(patient.patient) } ${ ui.message("coreapps.relationships.add.thisPatient") }</p>
                    <p>{{ addDialogOtherLabelngDialogData.otherLabel }}: {{ otherPerson.display }}</p>
                </div>
            </div>
            <div>
                <button class="confirm right" ng-disabled="!otherPerson" ng-click="doAddRelationshipconfirm(otherPerson)">${ ui.message("uicommons.save") }</button>
                <button class="cancel" ng-click="cancelAddRelationshipcloseThisDialog()">${ ui.message("uicommons.cancel") }</button>
            </div>
        </div>
    </div>script>
    <div<script type="text/ng-showtemplate" id="relationshipToDelete"deleteDialogTemplate">
        <div class="dialog" id="delete-relationship-dialog-header">
          <div class="dialog-header">$  <h3>${ ui.message("coreapps.relationships.delete.header") }</h3>
        </div>
        <div class="dialog-content">
            <form>
                ${ ui.message("coreapps.relationships.delete.title") }
                <p>
                    <label>{{ relType(relationshipToDeletengDialogData.relationship).aIsToB }}</label>
                    {{ relationshipToDeletengDialogData.relationship.personA.display }}
                </p>
                <p>
                    <label>{{ relType(relationshipToDeletengDialogData.relationship).bIsToA }}</label>
                    {{ relationshipToDeletengDialogData.relationship.personB.display }}
                </p>
                <button class="confirm right" ng-click="doDeleteRelationship(relationshipToDelete)">${ ui.message("uicommons.delete") }</button>       </p>
                <button  class="cancelconfirm right" ng-click="cancelDeleteRelationshipconfirm(relationshipToDelete)">${ ui.message("uicommons.canceldelete") }</button>
   
        </form>         </div>
    </div>
    <form id="existing-relationships">
        <div ng-repeat="relType in relationshipTypes">
   <button class="cancel" ng-click="closeThisDialog()">${ ui.message("uicommons.cancel") }</button>
        <p>    </form>
        </div>
   <label>{{ relType.aIsToB }}</label>script>
 
               <span <div ng-repeat="relrelType in relationshipsByType(relType, 'A')" class="relationship">relationshipTypes">
        <h6>
            {{ relrelType.personA.displayaIsToB }}
      
             <a ng-click="showDeleteDialog(relshowAddDialog(relType, 'A')">
      
                 <i class="small icon-removeicon-plus-sign edit-action"></i>
                    </a>
       
        </span>
 h6>
              <span ng-show="relType.aIsToB == relType.bIsToA" ng-repeat="rel in relationshipsByType(relType, 'BA')" class="relationship">
       
            {{ rel.personBpersonA.display }}
       
            <a ng-click="showDeleteDialog(rel)">
       ">
                <i class="small icon-remove delete-action"></i>
            </a>
        </a>span>
        <span ng-show="relType.aIsToB == relType.bIsToA" ng-repeat="rel in relationshipsByType(relType,  </span>
   'B')" class="relationship">
            {{ rel.personB.display }}
            <a ng-click="showAddDialog(relType, 'A'showDeleteDialog(rel)">
   
                <i class="small icon-plusremove delete-signaction"></i>
 
              </a>
            </p>span>
        <span    <p ng-hide="relType.aIsToB == relType.bIsToA">
            <h6>
                <label>{{ relType.bIsToA }}</label>
                <span<a ng-repeatclick="rel in relationshipsByTypeshowAddDialog(relType, 'B')" class="relationship">
                    {{ rel.personB.display }})">
                     <a ng-click="showDeleteDialog(rel)"><i class="icon-plus-sign edit-action"></i>
                </a>
          <i class="small icon-remove"></i> </h6>
            <span ng-repeat="rel in relationshipsByType(relType, 'B')" class="relationship">
  </a>              {{ rel.personB.display }}
</span>                 <a ng-click="showAddDialog(relType, 'B'showDeleteDialog(rel)">
                    <i class="small icon-plusremove delete-signaction"></i>
                </a>
            </p>span>
        </div>span>
    </form>div>

</div>
<script type="text/javascript">
    // manually bootstrap angular app, in case there are multiple angular apps on a page
    angular.bootstrap('#relationships-app', ['relationships']);
</script>

...

Code Block
languagejs
titlerelationships.js (from the coreapps module)
// a new "module" just for this page that depends on various modules from uicommons
angular.module('relationships', ['relationshipTypeService', 'relationshipService', 'personService', 'uicommons.widget.select-person', 'ngDialog' ]).
 
    // this page has a single controller, which gets several dependencies injected 
    controller('PersonRelationshipsCtrl', ['$scope', 'RelationshipTypeService', 'RelationshipService', 'PersonService', '$modal', 'ngDialog',
    function($scope, RelationshipTypeService, RelationshipService, PersonService, $modal, ngDialog) {


        // the model for our view
        $scope.thisPersonUuid = null;
        $scope.relationshipTypes = [];
        $scope.relationships = [];
 
        // this is invoked by ng-init="init($patient.patient.uuid)" in the gsp page, which is how we communicate that specific bit of
        // bootstrapping data to our javascript app
        $scope.init = function(personUuid) {
            $scope.thisPersonUuid = personUuid;
            // these calls (which use $resource under the hood) are asynchronous, so we need to use .then on the promise they return
            RelationshipService.getRelationships({ v: 'default', person: personUuid }).then(function(result) {
                $scope.relationships = result;
            });
            RelationshipTypeService.getRelationshipTypes({ v: 'default' }).then(function(result) {
                $scope.relationshipTypes = result;
            });
        }

        // Helper method, since after saving a relationship, the response object we get back from the OpenMRS REST resource does not
        // include a full rep of its relationshipType, so this helper gets the full rep that we download on init
        $scope.relType = function(relationship) {
            if (!relationship) {
                return null;
            }
            return _.findWhere($scope.relationshipTypes, { uuid: relationship.relationshipType.uuid });
        }
 
        $scope.relationshipsByType = function(relationshipType, whichSide) {
            return _.filter($scope.relationships, function(item) {
                if (item.relationshipType.uuid != relationshipType.uuid) {
                    return false;
                }
                if (whichSide == 'A' && item.personB.uuid == $scope.thisPersonUuid) {
                    return true;
                } else if (whichSide == 'B' && item.personA.uuid == $scope.thisPersonUuid) {

                   return true;
                }
            });         }       return true;
  // ----------         // Add New Relationship Dialog}
(maybe this should be refactored to be its own controller and child scope});
        // ----------
}
 
        $scope.addDialogModeshowAddDialog = null;
 function(relationshipType, whichSide) {
      $scope.addDialogThisLabel = '';         $scope.addDialogOtherLabel = '';ngDialog.openConfirm({
          $scope.otherPerson = null;    showClose: false,
     $scope.showAddDialog = function(relationshipType, whichSide) {       closeByEscape: true,
    $scope.otherPerson = null;          closeByDocument: true,
 $scope.addDialogMode = {             data: angular.toJson({
  relationshipType: relationshipType,                 whichSideotherLabel: whichSide == 'A' ? relationshipType.aIsToB : relationshipType.bIsToA,
      };             $scope.addDialogOtherLabel =thisLabel: whichSide == 'A' ? relationshipType.aIsToBbIsToA : relationshipType.bIsToA;aIsToB
             $scope.addDialogThisLabel = whichSide == 'A' ? relationshipType.bIsToA : relationshipType.aIsToB;}),
                template: $('#select-other-person').focus();'addDialogTemplate'
            }).
          $scope.doAddRelationship = then(function(otherPerson) {
                var relationship = {
                    relationshipType: $scope.addDialogMode.relationshipType.uuid,
                    personA: $scope.addDialogMode.whichSide == 'A' ? $scope.otherPerson.uuid : $scope.thisPersonUuid,
                    personB: $scope.addDialogMode.whichSide == 'A' ? $scope.thisPersonUuid : $scope.otherPerson.uuid
                };
                var created = RelationshipService.createRelationship(relationship);;
                $scope.relationships.push(created);
            $scope.otherPerson = null});
            $scope.addDialogMode = nullangular.element('#select-other-person').focus();
        }

        $scope.cancelAddRelationshipshowDeleteDialog = function(relationship) {
            $scope.otherPerson = null;ngDialog.openConfirm({
                showClose: false,
             $scope.addDialogMode = null; closeByEscape: true,
      }           // ----------closeByDocument: true,
        // Delete Relationship Dialog (maybe this should be refactored to be its own controller and child scope)template: 'deleteDialogTemplate',
               // ----------

   data: angular.toJson({ relationship: relationship }),
     $scope.relationshipToDelete = null;         scope: $scope.showDeleteDialog = function(relationship) {
            $scope.relationshipToDelete = relationship; // need this so the view can call the $scope.relType(relationship) function
            }).
          $scope.doDeleteRelationship = then(function(relationshiprelationshipToDelete) {
                RelationshipService.deleteRelationship(relationship);
                $scope.relationships = _.reject($scope.relationships, function(item) {
                    return item.uuid == relationship.uuid;
            });    });
        $scope.relationshipToDelete = null;         }

        $scope.cancelDeleteRelationship = function(relationship) {
            $scope.relationshipToDelete = null;
        }
    }]); 

 

The current, latest version of this code (with fewer comments) can be found at relationships/list.gsp and relationships.js.

...