->setChain([
'get' => ['$name', 'getActions', ['where' => [['name', '=', 'get']]], ['params']],
])->execute();
- $getFields = ['name', 'label', 'description', 'options', 'input_type', 'input_attrs', 'data_type', 'serialize'];
+ $getFields = ['name', 'label', 'description', 'options', 'input_type', 'input_attrs', 'data_type', 'serialize', 'fk_entity'];
foreach ($schema as $entity) {
// Skip if entity doesn't have a 'get' action or the user doesn't have permission to use get
if ($entity['get']) {
(function(angular, $, _) {
"use strict";
- angular.module('search').controller('SaveSmartGroup', function ($scope, $element, crmApi4, dialogService) {
+ angular.module('search').controller('SaveSmartGroup', function ($scope, $element, $timeout, crmApi4, dialogService, searchMeta) {
var ts = $scope.ts = CRM.ts(),
- model = $scope.model;
+ model = $scope.model,
+ joins = _.pluck((model.api_params.join || []), 0),
+ entityCount = {};
$scope.groupEntityRefParams = {
entity: 'Group',
api: {
- params: {is_hidden: 0, is_active: 1, 'saved_search_id.api_entity': model.entity},
+ params: {is_hidden: 0, is_active: 1, 'saved_search_id.api_entity': model.api_entity},
extra: ['saved_search_id', 'description', 'visibility', 'group_type']
},
select: {
placeholder: ts('Select existing group')
}
};
+ // Find all possible search columns that could serve as contact_id for the smart group
+ $scope.columns = _.transform([model.api_entity].concat(joins), function(columns, joinExpr) {
+ var joinName = joinExpr.split(' AS '),
+ entityName = joinName[0],
+ entity = searchMeta.getEntity(entityName),
+ prefix = joinName[1] ? joinName[1] + '.' : '';
+ _.each(entity.fields, function(field) {
+ if ((entityName === 'Contact' && field.name === 'id') || field.fk_entity === 'Contact') {
+ columns.push({
+ id: prefix + field.name,
+ text: entity.titlePlural + (entityCount[entityName] ? ' ' + entityCount[entityName] : '') + ': ' + field.label,
+ icon: entity.icon
+ });
+ }
+ });
+ entityCount[entityName] = 1 + (entityCount[entityName] || 1);
+ });
+
+ if (!$scope.columns.length) {
+ CRM.alert(ts('Cannot create smart group; search does not include any contacts.'), ts('Error'));
+ $timeout(function() {
+ dialogService.cancel('saveSearchDialog');
+ });
+ return;
+ }
+
+ // Pick the first applicable column for contact id
+ model.api_params.select[0] = _.intersection(model.api_params.select, _.pluck($scope.columns, 'id'))[0] || $scope.columns[0].name;
+ model.api_params.select.length = 1;
+
if (!CRM.checkPerm('administer reserved groups')) {
$scope.groupEntityRefParams.api.params.is_reserved = 0;
}
group.group_type = model.group_type;
group.saved_search_id = '$id';
var savedSearch = {
- api_entity: model.entity,
- api_params: model.params
+ api_entity: model.api_entity,
+ api_params: model.api_params
};
if (group.id) {
savedSearch.id = model.saved_search_id;
};
$scope.saveGroup = function() {
- var selectField = ctrl.entity === 'Contact' ? 'id' : 'contact_id';
- if (ctrl.entity !== 'Contact' && !searchMeta.getField('contact_id')) {
- CRM.alert(ts('Cannot create smart group from %1.', {1: searchMeta.getEntity(true).titlePlural}), ts('Missing contact_id'), 'error', {expires: 5000});
- return;
- }
var model = {
title: '',
description: '',
visibility: 'User and User Admin Only',
group_type: [],
id: ctrl.load ? ctrl.load.id : null,
- entity: ctrl.entity,
- params: angular.extend({}, ctrl.params, {version: 4})
+ api_entity: ctrl.entity,
+ api_params: _.cloneDeep(angular.extend({}, ctrl.params, {version: 4}))
};
- delete model.params.orderBy;
+ delete model.api_params.orderBy;
+ if (ctrl.load && ctrl.load.api_params) {
+ model.api_params.select = ctrl.load.api_params.select;
+ }
var options = CRM.utils.adjustDialogDefaults({
autoOpen: false,
title: ts('Save smart group')
<form id="bootstrap-theme">
<div ng-controller="SaveSmartGroup">
+ <div crm-ui-debug="model"></div>
<input class="form-control" id="api-save-search-select-group" ng-model="model.id" crm-entityref="groupEntityRefParams" >
<label ng-show="!model.id">{{:: ts('Or') }}</label>
- <input class="form-control" placeholder="Create new group" ng-model="model.title" ng-show="!model.id">
+ <input class="form-control" placeholder="{{:: ts('Create new group') }}" ng-model="model.title" ng-show="!model.id">
+ <hr />
+ <div class="form-inline">
+ <label for="api-save-search-select-column">{{:: ts('Contact Column:') }}</label>
+ <input id="api-save-search-select-column" ng-model="model.api_params.select[0]" class="form-control" crm-ui-select="{data: columns}"/>
+ </div>
<hr />
<label>{{:: ts('Description:') }}</label>
<textarea class="form-control" ng-model="model.description"></textarea>
- <label>{{:: ts('Group Type:') }}</label>
<div class="form-inline">
- <div class="checkbox" ng-repeat="option in groupFields.group_type.options track by option.id">
+ <label>{{:: ts('Group Type:') }} </label>
+ <div class="checkbox" ng-repeat="option in groupFields.group_type.options track by option.id">
<label>
<input type="checkbox" checklist-model="model.group_type" checklist-value="option.id">
{{ option.label }}
- </label>
+ </label>
</div>
</div>
- <label>{{:: ts('Visibility:') }}</label>
- <select class="form-control" ng-model="model.visibility" ng-options="item.id as item.label for item in groupFields.visibility.options track by item.id"></select>
+ <div class="form-inline">
+ <label>{{:: ts('Visibility:') }}</label>
+ <select class="form-control" ng-model="model.visibility" ng-options="item.id as item.label for item in groupFields.visibility.options track by item.id" crm-ui-select></select>
+ </div>
<hr />
<div class="buttons pull-right">
<button type="button" ng-click="cancel()" class="btn btn-danger">{{:: ts('Cancel') }}</button>