Skip to content
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

SearchKit and Afform UI improvements #20348

Merged
merged 9 commits into from
May 20, 2021
2 changes: 2 additions & 0 deletions CRM/Contact/BAO/SavedSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ public static function create(&$params) {
}
$params['modified_id'] = $loggedInContactID;
}
// Set by mysql
unset($params['modified_date']);

// Flush angular caches to refresh search displays
if (isset($params['api_params'])) {
Expand Down
4 changes: 3 additions & 1 deletion CRM/Contact/DAO/SavedSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*
* Generated from xml/schema/CRM/Contact/SavedSearch.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
* (GenCodeChecksum:fe46c2b4900f1fdde4a90f4858710fde)
* (GenCodeChecksum:8a25df5165c48a42f0280efe9eb262d5)
*/

/**
Expand Down Expand Up @@ -306,6 +306,7 @@ public static function &fields() {
'html' => [
'label' => ts("Created By"),
],
'readonly' => TRUE,
'add' => '5.36',
],
'modified_id' => [
Expand Down Expand Up @@ -350,6 +351,7 @@ public static function &fields() {
'entity' => 'SavedSearch',
'bao' => 'CRM_Contact_BAO_SavedSearch',
'localizable' => 0,
'readonly' => TRUE,
'add' => '5.36',
],
'modified_date' => [
Expand Down
3 changes: 1 addition & 2 deletions ext/afform/admin/ang/afAdmin.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
// Load data for lists
afforms: function(crmApi4) {
return crmApi4('Afform', 'get', {
select: ['name', 'title', 'type', 'is_public', 'server_route', 'has_local', 'has_base'],
orderBy: {title: 'ASC'}
select: ['name', 'title', 'type', 'server_route', 'has_local', 'has_base', 'is_dashlet', 'contact_summary:label']
});
}
}
Expand Down
16 changes: 16 additions & 0 deletions ext/afform/admin/ang/afAdmin/afAdminList.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
angular.module('afAdmin').controller('afAdminList', function($scope, afforms, crmApi4, crmStatus) {
var ts = $scope.ts = CRM.ts('org.civicrm.afform_admin'),
ctrl = $scope.$ctrl = this;
this.sortField = 'title';
this.sortDir = false;

$scope.crmUrl = CRM.url;

Expand All @@ -22,10 +24,24 @@

this.afforms = _.transform(afforms, function(afforms, afform) {
afform.type = afform.type || 'system';
// Aggregate a couple fields for the "Placement" column
afform.placement = [];
if (afform.is_dashlet) {
afform.placement.push(ts('Dashboard'));
}
if (afform['contact_summary:label']) {
afform.placement.push(afform['contact_summary:label']);
}
afforms[afform.type] = afforms[afform.type] || [];
afforms[afform.type].push(afform);
}, {});

// Change sort field/direction when clicking a column header
this.sortBy = function(col) {
ctrl.sortDir = ctrl.sortField === col ? !ctrl.sortDir : false;
ctrl.sortField = col;
};

$scope.$bindToRoute({
expr: '$ctrl.tab',
param: 'tab',
Expand Down
38 changes: 27 additions & 11 deletions ext/afform/admin/ang/afAdmin/afAdminList.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,44 @@ <h1 crm-page-title>{{:: ts('Form Builder') }}</h1>
<table>
<thead>
<tr>
<th>{{:: ts('Title') }}</th>
<th>{{:: ts('Name') }}</th>
<th>{{:: ts('Page') }}</th>
<th>{{:: ts('Style') }}</th>
<th title="{{:: ts('Click to sort') }}" ng-click="$ctrl.sortBy('title')">
<i class="crm-i fa-sort disabled" ng-if="$ctrl.sortField !== 'title'"></i>
<i class="crm-i fa-sort-{{ $ctrl.sortDir ? 'asc' : 'desc' }}" ng-if="$ctrl.sortField === 'title'"></i>
{{:: ts('Title') }}
</th>
<th title="{{:: ts('Click to sort') }}" ng-click="$ctrl.sortBy('name')">
<i class="crm-i fa-sort disabled" ng-if="$ctrl.sortField !== 'name'"></i>
<i class="crm-i fa-sort-{{ $ctrl.sortDir ? 'asc' : 'desc' }}" ng-if="$ctrl.sortField === 'name'"></i>
{{:: ts('Name') }}
</th>
<th title="{{:: ts('Click to sort') }}" ng-click="$ctrl.sortBy('server_route')">
<i class="crm-i fa-sort disabled" ng-if="$ctrl.sortField !== 'server_route'"></i>
<i class="crm-i fa-sort-{{ $ctrl.sortDir ? 'asc' : 'desc' }}" ng-if="$ctrl.sortField === 'server_route'"></i>
{{:: ts('Page') }}
</th>
<th title="{{:: ts('Click to sort') }}" ng-click="$ctrl.sortBy('placement.length')">
<i class="crm-i fa-sort disabled" ng-if="$ctrl.sortField !== 'placement.length'"></i>
<i class="crm-i fa-sort-{{ $ctrl.sortDir ? 'asc' : 'desc' }}" ng-if="$ctrl.sortField === 'placement.length'"></i>
{{:: ts('Placement') }}
</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="afform in $ctrl.afforms[$ctrl.tab] | filter:$ctrl.searchAfformList">
<td>{{afform.title}}</td>
<tr ng-repeat="afform in $ctrl.afforms[$ctrl.tab] | filter:$ctrl.searchAfformList | orderBy:$ctrl.sortField:$ctrl.sortDir">
<td>{{ afform.title }}</td>
<td>
<code>{{afform.name}}</code>
<code>{{ afform.name }}</code>
</td>
<td>
<a ng-if="afform.server_route" ng-href="{{ crmUrl(afform.server_route) }}" target="_blank">
<code>{{afform.server_route}}</code>
<code>{{ afform.server_route }}</code>
</a>
</td>
<td>{{afform.is_public ? ts('Frontend') : ts('Backend')}}</td>
<td>{{ afform.placement.join(', ') }}</td>
<td class="text-right">
<a ng-if="afform.type !== 'system'" href="#/edit/{{ afform.name }}" class="btn btn-xs btn-primary">{{ ts('Edit') }}</a>
<a ng-if="afform.type !== 'system'" href="#/clone/{{ afform.name }}" class="btn btn-xs btn-primary">{{ ts('Clone') }}</a>
<a ng-if="afform.type !== 'system'" href="#/edit/{{ afform.name }}" class="btn btn-xs btn-primary">{{:: ts('Edit') }}</a>
<a ng-if="afform.type !== 'system'" href="#/clone/{{ afform.name }}" class="btn btn-xs btn-primary">{{:: ts('Clone') }}</a>
<a href ng-if="afform.has_local" class="btn btn-xs btn-danger" crm-confirm="{type: afform.has_base ? 'revert' : 'delete', obj: afform}" on-yes="$ctrl.revert(afform)">
{{ afform.has_base ? ts('Revert') : ts('Delete') }}
</a>
Expand Down
15 changes: 15 additions & 0 deletions ext/afform/admin/ang/afGuiEditor.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
#bootstrap-theme.afadmin-list th[ng-click] {
cursor: pointer;
}
#bootstrap-theme.afadmin-list th i.fa-sort-desc,
#bootstrap-theme.afadmin-list th i.fa-sort-asc {
color: #1a5a82;
}
#bootstrap-theme.afadmin-list th:not(:hover) i.fa-sort {
opacity: .5;
}

#afGuiEditor #afGuiEditor-palette {
margin-right: 5px;
height: 100%;
Expand Down Expand Up @@ -163,6 +174,10 @@ body.af-gui-dragging {
color: #696969;
font-style: italic;
}
#afGuiEditor .af-gui-bar > .form-inline > select {
height: 21px;
min-height: 21px;
}

#afGuiEditor .af-gui-element {
position: relative;
Expand Down
14 changes: 7 additions & 7 deletions ext/afform/admin/ang/afGuiEditor/config-form.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

<div class="form-group">
<label for="af_config_form_title">
{{:: ts('Title:') }} <span class="crm-marker">*</span>
{{:: ts('Title') }} <span class="crm-marker">*</span>
</label>
<p class="help-block">{{:: ts('Public title (usually displayed at the top of the form).') }}</p>
<input ng-model="afform.title" class="form-control" id="af_config_form_title" required title="{{:: ts('Required') }}" />
</div>

<div class="form-group">
<label for="af_config_form_description">
{{:: ts('Description:') }}
{{:: ts('Description') }}
</label>
<textarea ng-model="afform.description" class="form-control" id="af_config_form_description"></textarea>
<p class="help-block">{{:: ts("Internal note about the form's purpose (not displayed on form).") }}</p>
Expand All @@ -19,7 +19,7 @@

<div class="form-group">
<label for="af_config_form_permission">
{{:: ts('Permission:') }}
{{:: ts('Permission') }}
</label>
<input ng-model="afform.permission" class="form-control" id="af_config_form_permission" crm-ui-select="{data: editor.meta.permissions}" />
<p class="help-block">{{:: ts('What permission is required to use this form?') }}</p>
Expand All @@ -30,7 +30,7 @@

<div class="form-group" ng-class="{'has-error': !!config_form.server_route.$error.pattern}">
<label for="af_config_form_server_route">
{{:: ts('Page:') }}
{{:: ts('Page') }}
</label>
<input ng-model="afform.server_route" name="server_route" class="form-control" id="af_config_form_server_route" pattern="^civicrm\/[-0-9a-zA-Z\/_]+$" onfocus="this.value = this.value || 'civicrm/'" onblur="if (this.value === 'civicrm/') this.value = ''" title="{{:: ts('Path must begin with &quot;civicrm/&quot;') }}">
<p class="help-block">{{:: ts('Expose the form as a standalone webpage. (Example: "civicrm/my-form")') }}</p>
Expand All @@ -46,15 +46,15 @@
<div class="form-group" ng-if="!!afform.server_route">
<label>
<input type="checkbox" ng-model="afform.is_token">
{{:: ts('Provide email token') }}
{{:: ts('Provide Email Token') }}
</label>
<p class="help-block">{{:: ts('Allows CiviMail authors to easily link to this page') }}</p>
</div>

<div class="form-group">
<label>
<input type="checkbox" ng-model="afform.is_dashlet">
{{:: ts('Add to dashboard') }}
{{:: ts('Add to Dashboard') }}
</label>
<p class="help-block">{{:: ts('Allow CiviCRM users to add the form to their home dashboard.') }}</p>
</div>
Expand All @@ -63,7 +63,7 @@
<div class="form-inline">
<label>
<input type="checkbox" ng-checked="afform.contact_summary" ng-click="editor.toggleContactSummary()">
{{:: ts('Add to contact summary page') }}
{{:: ts('Add to Contact Summary Page') }}
</label>
<select class="form-control" ng-model="afform.contact_summary" ng-if="afform.contact_summary">
<option value="block">{{:: ts('As Block') }}</option>
Expand Down
2 changes: 1 addition & 1 deletion ext/afform/admin/ang/afGuiEditor/entityConfig/Contact.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div ng-include="'~/afGuiEditor/entityConfig/Generic.html'"></div>
<div class="form-inline">
<label>
{{:: ts('Autofill as:') }}
{{:: ts('Autofill as') }}
</label>
<select ng-model="$ctrl.entity.autofill" class="form-control">
<option value="">{{:: ts('None') }}</option>
Expand Down
8 changes: 4 additions & 4 deletions ext/afform/admin/ang/afGuiEditor/entityConfig/Generic.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
{{:: ts('Security') }}
</label>
<select ng-model="$ctrl.entity.security" class="form-control">
<option value="RBAC">{{:: ts('Role-based')}}</option>
<option value="FBAC">{{:: ts('Form-based')}}</option>
<option value="RBAC">{{:: ts('Role-Based')}}</option>
<option value="FBAC">{{:: ts('Form-Based')}}</option>
</select>
</div>
<div class="form-group">
<label>
{{:: ts('Actions:') }}
{{:: ts('Allowed Actions') }}
</label>
<div class="checkbox-inline">
<label><input type="checkbox" ng-model="$ctrl.entity.actions.create">{{:: ts('Create') }}</label>
Expand All @@ -21,6 +21,6 @@
<div class="checkbox">
<label>
<input type="checkbox" ng-model="$ctrl.entity['url-autofill']" ng-true-value="'1'" ng-false-value="'0'" />
{{:: ts('Allow url autofill') }}
{{:: ts('Allow URL Autofill') }}
</label>
</div>
2 changes: 1 addition & 1 deletion ext/afform/admin/ang/afGuiEditor/saveBlock.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
&nbsp;
<label>
<input type="radio" name="save-as" ng-value="null" ng-model="model.name" />
{{:: ts('Save new block') }}
{{:: ts('Save New Block') }}
</label>
</div>
<div class="alert alert-warning" ng-show="model.name">
Expand Down
4 changes: 4 additions & 0 deletions ext/afform/core/Civi/Api4/Afform.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ public static function getFields($checkPermissions = TRUE) {
[
'name' => 'contact_summary',
'data_type' => 'String',
'options' => [
'block' => ts('Contact Summary Block'),
'tab' => ts('Contact Summary Tab'),
],
],
[
'name' => 'repeat',
Expand Down
2 changes: 1 addition & 1 deletion ext/search_kit/ang/crmSearchAdmin/compose/pager.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</div>
<div class="form-inline text-right">
<label for="crm-search-results-page-size" >
{{:: ts('Page size:') }}
{{:: ts('Page Size') }}
</label>
<input class="form-control" id="crm-search-results-page-size" type="number" ng-model="$ctrl.limit" min="10" step="10" ng-change="onChangeLimit()">
</div>
Expand Down
2 changes: 1 addition & 1 deletion ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ <h1 crm-page-title>{{ $ctrl.entityTitle + ': ' + $ctrl.savedSearch.label }}</h1>
<input id="crm-saved-search-label" class="form-control" ng-model="$ctrl.savedSearch.label" type="text" required placeholder="{{ ts('Untitled Search') }}" />
</div>
<div class="crm-flex-4 form-inline">
<label for="crm-search-main-entity">{{:: ts('Search for:') }}</label>
<label for="crm-search-main-entity">{{:: ts('Search for') }}</label>
<input id="crm-search-main-entity" class="form-control huge" ng-model="$ctrl.savedSearch.api_entity" crm-ui-select="::{allowClear: false, data: entities}" ng-disabled="$ctrl.savedSearch.id" />
<div class="btn-group btn-group-md pull-right">
<button type="button" class="btn" ng-class="{'btn-primary': status === 'unsaved', 'btn-warning': status === 'saving', 'btn-success': status === 'saved'}" ng-disabled="status !== 'unsaved'" ng-click="$ctrl.save()">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@
},
};

this.toggleLimit = function() {
if (ctrl.display.settings.limit) {
ctrl.display.settings.limit = 0;
if (ctrl.display.settings.pager) {
ctrl.display.settings.pager = false;
}
} else {
ctrl.display.settings.limit = CRM.crmSearchAdmin.defaultPagerSize;
}
};

// Drag-n-drop settings for reordering columns
this.sortableOptions = {
connectWith: '.crm-search-admin-edit-columns',
Expand Down
4 changes: 2 additions & 2 deletions ext/search_kit/ang/crmSearchAdmin/crmSearchAdminDisplay.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<fieldset>
<div class="form-inline">
<label for="crm-search-admin-display-label">{{:: ts('Name:') }} <span class="crm-marker">*</span></label>
<input id="crm-search-admin-display-label" type="text" class="form-control" ng-model="$ctrl.display.label" required placeholder="{{ ts('Untitled') }}"/>
<label for="crm-search-admin-display-label">{{:: ts('Name') }} <span class="crm-marker">*</span></label>
<input id="crm-search-admin-display-label" type="text" class="form-control" ng-model="$ctrl.display.label" required placeholder="{{:: ts('Untitled') }}"/>
</div>
</fieldset>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="form-inline" ng-repeat="sort in $ctrl.display.settings.sort">
<label for="crm-search-display-sort-{{$index}}">{{ $index ? ts('Also by:') : ts('Sort by:') }}</label>
<label for="crm-search-display-sort-{{$index}}">{{ $index ? ts('Also by') : ts('Sort by') }}</label>
<input id="crm-search-display-sort-{{$index}}" class="form-control huge" ng-model="sort[0]" crm-ui-select="{data: $ctrl.parent.fieldsForSort}" />
<select class="form-control" ng-model="sort[1]">
<option value="ASC">{{ ts('Ascending') }}</option>
Expand All @@ -8,6 +8,6 @@
<a href class="crm-hover-button" title="{{:: ts('Clear') }}" ng-click="$ctrl.display.settings.sort.splice($index, 1)"><i class="crm-i fa-times" aria-hidden="true"></i></a>
</div>
<div class="form-inline">
<label for="crm-search-display-add-sort">{{ $ctrl.display.settings.sort.length ? ts('Also by:') : ts('Sort by:') }}</label>
<label for="crm-search-display-add-sort">{{ $ctrl.display.settings.sort.length ? ts('Also by') : ts('Sort by') }}</label>
<input id="crm-search-display-add-sort" class="form-control crm-action-menu fa-plus huge" ng-model="controls.sort" crm-ui-select="{placeholder: ts('Select field'), data: $ctrl.parent.fieldsForSort}" ng-change="$ctrl.parent.pushSetting('sort', [controls.sort, 'ASC']); controls.sort = '';"/>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="form-inline">
<label for="crm-search-admin-col-size-{{$index}}">
{{:: ts('Button Size:') }}
{{:: ts('Button Size') }}
</label>
<select id="crm-search-admin-col-size-{{$index}}" class="form-control" ng-model="col.size">
<option value="btn-lg">{{:: ts('Large') }}</option>
Expand Down
10 changes: 5 additions & 5 deletions ext/search_kit/ang/crmSearchAdmin/displays/colType/field.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="form-inline crm-search-admin-flex-row">
<label title="{{ ts('Display as clickable link') }}" >
<input type="checkbox" ng-checked="col.link" ng-click="$ctrl.parent.toggleLink(col)" >
{{ col.link ? ts('Link:') : ts('Link') }}
{{:: ts('Link') }}
</label>
<select class="form-control" ng-model="$ctrl.link.target" ng-if="col.link">
<option value>{{:: ts('Open normally') }}</option>
Expand All @@ -14,26 +14,26 @@
<div class="form-inline crm-search-admin-flex-row">
<label>
<input type="checkbox" ng-checked="col.title" ng-click="col.title = col.title ? null : $ctrl.parent.getFieldLabel(col.key)" >
{{ col.title ? ts('Tooltip:') : ts('Tooltip') }}
{{:: ts('Tooltip') }}
</label>
<input class="form-control crm-flex-1" type="text" ng-model="col.title" ng-if="col.title" ng-model-options="{updateOn: 'blur'}" />
<crm-search-admin-token-select ng-if="col.title" api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" model="col" field="title"></crm-search-admin-token-select>
</div>
<div class="form-inline crm-search-admin-flex-row">
<label title="{{ ts('Change the contents of this field, or combine multiple field values.') }}">
<input type="checkbox" ng-checked="col.rewrite" ng-click="$ctrl.parent.toggleRewrite(col)" >
{{ col.rewrite ? ts('Rewrite:') : ts('Rewrite') }}
{{:: ts('Rewrite') }}
</label>
<input type="text" class="form-control crm-flex-1" ng-if="col.rewrite" ng-model="col.rewrite" ng-model-options="{updateOn: 'blur'}">
<crm-search-admin-token-select ng-if="col.rewrite" api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" model="col" field="rewrite"></crm-search-admin-token-select>
</div>
<div class="form-inline">
<label ng-if="$ctrl.parent.isEditable(col)" title="{{:: ts('Users will be able to click to edit this field.') }}">
<input type="checkbox" ng-checked="col.editable" ng-click="$ctrl.parent.toggleEditable(col)">
{{:: ts('In-place edit') }}
{{:: ts('In-Place Edit') }}
</label>
<label ng-if="!$ctrl.parent.isEditable(col)" class="disabled" title="{{:: ts('Read-only or rewritten fields cannot be editable.') }}">
<input type="checkbox" disabled>
{{:: ts('In-place edit') }}
{{:: ts('In-Place Edit') }}
</label>
</div>
Loading