This allows extensions (e.g. ReCaptcha) to provide new element types. They are editable in the GUI
via a generic template, and exensions can provide their own templates for further
configurability.
position: relative;
padding: 0 3px 3px;
display: block;
+ min-height: 21px;
}
#afGuiEditor .af-gui-container {
controller: function($scope, $element, crmApi4, dialogService, afGui) {
var ts = $scope.ts = CRM.ts('org.civicrm.afform_admin'),
ctrl = this;
+ var genericElements = [];
this.$onInit = function() {
if (ctrl.node['#tag'] && ((ctrl.node['#tag'] in afGui.meta.blocks) || ctrl.join)) {
}
initializeBlockContainer();
}
+ _.each(afGui.meta.elements, function(element) {
+ if (element.directive) {
+ genericElements.push(element.directive);
+ }
+ });
};
this.sortableOptions = {
if (node['#tag'] && (node['#tag'].slice(0, 19) === 'crm-search-display-')) {
return 'searchDisplay';
}
+ if (node['#tag'] && _.includes(genericElements, node['#tag'])) {
+ return 'generic';
+ }
var classes = afGui.splitClass(node['class']),
types = ['af-container', 'af-text', 'af-button', 'af-markup'],
type = _.intersection(types, classes);
<af-gui-button ng-switch-when="button" node="item" delete-this="$ctrl.removeElement(item)" class="af-gui-element af-gui-button" ></af-gui-button>
<af-gui-container ng-switch-when="searchFieldset" node="item" delete-this="$ctrl.removeElement(item)" style="{{ item.style }}" class="af-gui-container af-gui-fieldset af-gui-container-type-{{ item['#tag'] + ' ' + item['class'] }}" ng-class="{'af-entity-selected': isSelectedSearchFieldset(item)}" data-entity="{{ getSearchKey(item) }}" ></af-gui-container>
<af-gui-search-display ng-switch-when="searchDisplay" node="item" class="af-gui-element"></af-gui-search-display>
+ <af-gui-generic-element ng-switch-when="generic" node="item" delete-this="$ctrl.removeElement(item)" class="af-gui-element af-gui-generic" ></af-gui-generic-element>
</div>
</div>
</div>
--- /dev/null
+<li><a href ng-click="$ctrl.deleteThis()"><span class="text-danger"><i class="crm-i fa-trash"></i> {{:: ts('Remove %1', {1: $ctrl.getTitle()}) }}</span></a></li>
--- /dev/null
+<div class="af-gui-element">
+ <div class="af-gui-bar">
+ <div class="form-inline">
+ <span>{{:: $ctrl.getTitle() }}</span>
+ <div class="btn-group pull-right" af-gui-menu>
+ <button type="button" class="btn btn-default btn-xs dropdown-toggle af-gui-add-element-button" data-toggle="dropdown" title="{{:: ts('Configure') }}">
+ <span><i class="crm-i fa-gear"></i></span>
+ </button>
+ <ul class="dropdown-menu" ng-if="menu.open" ng-include="'~/afGuiEditor/elements/afGuiGenericElement-menu.html'"></ul>
+ </div>
+ </div>
+ </div>
+</div>
+
--- /dev/null
+// https://civicrm.org/licensing
+(function(angular, $, _) {
+ "use strict";
+
+ // Generic element handler for element types supplied by 3rd-party extensions
+ // If they have no configuration options they can use the generic template,
+ // or they can supply their own `admin_tpl` path.
+ angular.module('afGuiEditor').component('afGuiGenericElement', {
+ template: '<div ng-include="$ctrl.getTemplate()"></div>',
+ bindings: {
+ node: '=',
+ deleteThis: '&'
+ },
+ controller: function($scope, afGui) {
+ var ts = $scope.ts = CRM.ts('org.civicrm.afform_admin'),
+ ctrl = this,
+ elementType = {};
+
+ this.$onInit = function() {
+ elementType = _.findWhere(afGui.meta.elements, {directive: ctrl.node['#tag']});
+ };
+
+ this.getTemplate = function() {
+ return elementType.admin_tpl || '~/afGuiEditor/elements/afGuiGenericElement.html';
+ };
+
+ this.getTitle = function() {
+ return elementType.title;
+ };
+ }
+ });
+
+})(angular, CRM.$, CRM._);
},
controller: function($scope, $element, $timeout, crmApi4, crmStatus, $window, $location, $parse, FileUploader) {
var schema = {},
- data = {},
+ data = {extra: {}},
status,
args,
submissionResponse,