SearchKit - Organize ON clause field selectors with joined entity first
authorColeman Watts <coleman@civicrm.org>
Mon, 31 May 2021 19:20:24 +0000 (15:20 -0400)
committerColeman Watts <coleman@civicrm.org>
Mon, 31 May 2021 19:20:24 +0000 (15:20 -0400)
ext/search_kit/ang/crmSearchAdmin/compose/criteria.html
ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.component.js
ext/search_kit/ang/crmSearchAdmin/crmSearchClause.component.js
ext/search_kit/ang/crmSearchAdmin/crmSearchClause.html

index 732b1f4aebc66f87c639a6e9f605fb74be9fcf75..b45e138e0057dccb7fd8171f6593fb2aa80d7f15 100644 (file)
@@ -9,9 +9,9 @@
             <i class="crm-i fa-trash" aria-hidden="true"></i>
           </button>
         </div>
-        <fieldset class="api4-clause-fieldset">
-          <crm-search-clause clauses="join" format="json" skip="2 + getJoin(join[0]).conditions.length" op="AND" label="{{:: ts('If') }}" fields="fieldsForWhere" ></crm-search-clause>
-        </fieldset>
+        <div class="api4-clause-fieldset">
+          <crm-search-clause clauses="join" format="json" skip="2 + getJoin(join[0]).conditions.length" op="AND" label="{{:: ts('If') }}" hide-label="true" placeholder="ts('Add Condition')" fields="fieldsForJoin(join[0])" ></crm-search-clause>
+        </div>
       </fieldset>
       <fieldset>
         <div class="form-inline">
index 75373b9b15b3e60ad645785fe15c713f297c9690..a318ef8b2dca6e60ef36c54703fcf80257feb65f 100644 (file)
@@ -8,7 +8,8 @@
     templateUrl: '~/crmSearchAdmin/crmSearchAdmin.html',
     controller: function($scope, $element, $location, $timeout, crmApi4, dialogService, searchMeta, formatForSelect2) {
       var ts = $scope.ts = CRM.ts('org.civicrm.search_kit'),
-        ctrl = this;
+        ctrl = this,
+        fieldsForJoinGetters = {};
 
       this.DEFAULT_AGGREGATE_FN = 'GROUP_CONCAT';
 
         };
       };
 
+      function getFieldsForJoin(joinEntity) {
+        return {results: ctrl.getAllFields(':name', null, joinEntity)};
+      }
+
+      $scope.fieldsForJoin = function(joinEntity) {
+        if (!fieldsForJoinGetters[joinEntity]) {
+          fieldsForJoinGetters[joinEntity] = _.wrap(joinEntity, getFieldsForJoin);
+        }
+        return fieldsForJoinGetters[joinEntity];
+      };
+
       $scope.fieldsForWhere = function() {
         return {results: ctrl.getAllFields(':name')};
       };
         });
       }
 
-      this.getAllFields = function(suffix, disabledIf) {
+      this.getAllFields = function(suffix, disabledIf, topJoin) {
         disabledIf = disabledIf || _.noop;
         function formatFields(entityName, join) {
           var prefix = join ? join.alias + '.' : '',
         }
 
         var mainEntity = searchMeta.getEntity(ctrl.savedSearch.api_entity),
-          result = [{
-            text: mainEntity.title_plural,
-            icon: mainEntity.icon,
-            children: formatFields(ctrl.savedSearch.api_entity)
-          }];
-        _.each(ctrl.savedSearch.api_params.join, function(join) {
-          var joinInfo = searchMeta.getJoin(join[0]),
+          joinEntities = _.map(ctrl.savedSearch.api_params.join, 0),
+          result = [];
+
+        function addJoin(join) {
+          var joinInfo = searchMeta.getJoin(join),
             joinEntity = searchMeta.getEntity(joinInfo.entity);
           result.push({
             text: joinInfo.label,
             icon: joinEntity.icon,
             children: formatFields(joinEntity.name, joinInfo)
           });
+        }
+
+        // Place specified join at top of list
+        if (topJoin) {
+          addJoin(topJoin);
+          _.pull(joinEntities, topJoin);
+        }
+
+        result.push({
+          text: mainEntity.title_plural,
+          icon: mainEntity.icon,
+          children: formatFields(ctrl.savedSearch.api_entity)
         });
+        _.each(joinEntities, addJoin);
         return result;
       };
 
index 6c0b6378dce96ed4cdaed904e799d5b63a6a6b65..9d6cbc6139d34f144cdc01cacde9da556f9baf58 100644 (file)
@@ -9,6 +9,8 @@
       op: '@',
       skip: '<',
       label: '@',
+      hideLabel: '@',
+      placeholder: '<',
       deleteGroup: '&'
     },
     templateUrl: '~/crmSearchAdmin/crmSearchClause.html',
index 73d2ba64a9a342f148e9d14b2747040cae1f89db..09363b721ab19dc48905ca65e8da33fe02e14ee5 100644 (file)
@@ -1,4 +1,4 @@
-<legend>{{ $ctrl.label || ts('%1 group', {1: $ctrl.conjunctions[$ctrl.op]}) }}</legend>
+<legend ng-if="!$ctrl.hideLabel">{{ $ctrl.label || ts('%1 group', {1: $ctrl.conjunctions[$ctrl.op]}) }}</legend>
 <div class="btn-group btn-group-xs" ng-if=":: $ctrl.hasParent">
   <button type="button" class="btn btn-danger-outline" ng-click="$ctrl.deleteGroup()" title="{{:: ts('Remove group') }}">
     <i class="crm-i fa-trash" aria-hidden="true"></i>
@@ -15,7 +15,7 @@
         </span>
       </div>
       <div ng-if="!$ctrl.conjunctions[clause[0]]" class="api4-input-group">
-        <input class="form-control" ng-model="clause[0]" crm-ui-select="{data: $ctrl.fields, allowClear: true, placeholder: 'Field'}" ng-change="$ctrl.changeClauseField(clause, index)" />
+        <input class="form-control collapsible-optgroups" ng-model="clause[0]" crm-ui-select="{data: $ctrl.fields, allowClear: true, placeholder: 'Field'}" ng-change="$ctrl.changeClauseField(clause, index)" />
         <select class="form-control api4-operator" ng-model="clause[1]" ng-options="o.key as o.value for o in $ctrl.operators" ng-change="$ctrl.changeClauseOperator(clause)" ></select>
         <crm-search-input ng-if="$ctrl.operatorTakesInput(clause[1])" ng-model="clause[2]" field="$ctrl.getField(clause[0])" option-key="$ctrl.getOptionKey(clause[0])" op="clause[1]" format="$ctrl.format" class="form-group"></crm-search-input>
       </div>
@@ -38,5 +38,5 @@
       </ul>
     </div>
   </div>
-  <input class="form-control" ng-model="$ctrl.newClause" ng-change="$ctrl.addClause()" crm-ui-select="{data: $ctrl.fields, placeholder: ts('Select field')}" />
+  <input class="form-control collapsible-optgroups" ng-model="$ctrl.newClause" ng-change="$ctrl.addClause()" crm-ui-select="{data: $ctrl.fields, placeholder: $ctrl.placeholder || ts('Select field')}" />
 </div>