Commit | Line | Data |
---|---|---|
b844d2ca CW |
1 | // https://civicrm.org/licensing |
2 | (function(angular, $, _) { | |
3 | "use strict"; | |
4 | ||
5 | angular.module('afGuiEditor').component('afGuiEntity', { | |
6 | templateUrl: '~/afGuiEditor/afGuiEntity.html', | |
7 | bindings: { | |
8 | entity: '<' | |
9 | }, | |
10 | require: {editor: '^^afGuiEditor'}, | |
23fd8685 | 11 | controller: function ($scope, $timeout, afGui) { |
67d666c6 | 12 | var ts = $scope.ts = CRM.ts('org.civicrm.afform_admin'); |
b844d2ca CW |
13 | var ctrl = this; |
14 | $scope.controls = {}; | |
15 | $scope.fieldList = []; | |
16 | $scope.blockList = []; | |
17 | $scope.blockTitles = []; | |
18 | $scope.elementList = []; | |
19 | $scope.elementTitles = []; | |
20 | ||
e73f06cd | 21 | this.getEntityType = function() { |
de9fdf9f | 22 | return (ctrl.entity.type === 'Contact' && ctrl.entity.data) ? ctrl.entity.data.contact_type || 'Contact' : ctrl.entity.type; |
e73f06cd | 23 | }; |
b844d2ca CW |
24 | |
25 | $scope.getMeta = function() { | |
e73f06cd | 26 | return afGui.meta.entities[ctrl.getEntityType()]; |
b844d2ca CW |
27 | }; |
28 | ||
229a3e39 CW |
29 | $scope.getAdminTpl = function() { |
30 | return $scope.getMeta().admin_tpl || '~/afGuiEditor/entityConfig/Generic.html'; | |
31 | }; | |
32 | ||
23fd8685 | 33 | $scope.getField = afGui.getField; |
b844d2ca CW |
34 | |
35 | $scope.valuesFields = function() { | |
36 | var fields = _.transform($scope.getMeta().fields, function(fields, field) { | |
37 | fields.push({id: field.name, text: field.label, disabled: $scope.fieldInUse(field.name)}); | |
38 | }, []); | |
39 | return {results: fields}; | |
40 | }; | |
41 | ||
42 | $scope.removeValue = function(entity, fieldName) { | |
43 | delete entity.data[fieldName]; | |
44 | }; | |
45 | ||
46730a23 | 46 | this.buildPaletteLists = function() { |
b844d2ca CW |
47 | var search = $scope.controls.fieldSearch ? $scope.controls.fieldSearch.toLowerCase() : null; |
48 | buildFieldList(search); | |
49 | buildBlockList(search); | |
50 | buildElementList(search); | |
46730a23 | 51 | }; |
b844d2ca CW |
52 | |
53 | function buildFieldList(search) { | |
54 | $scope.fieldList.length = 0; | |
55 | $scope.fieldList.push({ | |
56 | entityName: ctrl.entity.name, | |
e73f06cd | 57 | entityType: ctrl.getEntityType(), |
b844d2ca CW |
58 | label: ts('%1 Fields', {1: $scope.getMeta().label}), |
59 | fields: filterFields($scope.getMeta().fields) | |
60 | }); | |
d4e2c9ff | 61 | // Add fields for af-join blocks |
23fd8685 | 62 | _.each(afGui.meta.entities, function(entity, entityName) { |
b844d2ca CW |
63 | if (check(ctrl.editor.layout['#children'], {'af-join': entityName})) { |
64 | $scope.fieldList.push({ | |
65 | entityName: ctrl.entity.name + '-join-' + entityName, | |
66 | entityType: entityName, | |
67 | label: ts('%1 Fields', {1: entity.label}), | |
68 | fields: filterFields(entity.fields) | |
69 | }); | |
70 | } | |
71 | }); | |
72 | ||
73 | function filterFields(fields) { | |
74 | return _.transform(fields, function(fieldList, field) { | |
da5e820b CW |
75 | if (!field.readonly && |
76 | (!search || _.contains(field.name, search) || _.contains(field.label.toLowerCase(), search)) | |
77 | ) { | |
d4e2c9ff | 78 | fieldList.push(fieldDefaults(field)); |
b844d2ca CW |
79 | } |
80 | }, []); | |
81 | } | |
d4e2c9ff CW |
82 | |
83 | function fieldDefaults(field) { | |
84 | var tag = { | |
85 | "#tag": "af-field", | |
86 | name: field.name | |
87 | }; | |
88 | return tag; | |
89 | } | |
b844d2ca CW |
90 | } |
91 | ||
92 | function buildBlockList(search) { | |
93 | $scope.blockList.length = 0; | |
94 | $scope.blockTitles.length = 0; | |
23fd8685 | 95 | _.each(afGui.meta.blocks, function(block, directive) { |
b844d2ca | 96 | if ((!search || _.contains(directive, search) || _.contains(block.name.toLowerCase(), search) || _.contains(block.title.toLowerCase(), search)) && |
fa8dc3f2 | 97 | (block.entity_type === '*' || block.entity_type === ctrl.entity.type || (ctrl.entity.type === 'Contact' && block.entity_type === ctrl.entity.data.contact_type)) && |
2652d11b | 98 | block.name !== ctrl.editor.getAfform().name |
b844d2ca | 99 | ) { |
fa8dc3f2 CW |
100 | var item = {"#tag": block.join_entity ? "div" : directive}; |
101 | if (block.join_entity) { | |
102 | item['af-join'] = block.join_entity; | |
b844d2ca CW |
103 | item['#children'] = [{"#tag": directive}]; |
104 | } | |
105 | if (block.repeat) { | |
106 | item['af-repeat'] = ts('Add'); | |
107 | item.min = '1'; | |
108 | if (typeof block.repeat === 'number') { | |
109 | item.max = '' + block.repeat; | |
110 | } | |
111 | } | |
112 | $scope.blockList.push(item); | |
113 | $scope.blockTitles.push(block.title); | |
114 | } | |
115 | }); | |
116 | } | |
117 | ||
118 | function buildElementList(search) { | |
119 | $scope.elementList.length = 0; | |
120 | $scope.elementTitles.length = 0; | |
23fd8685 | 121 | _.each(afGui.meta.elements, function(element, name) { |
b844d2ca CW |
122 | if (!search || _.contains(name, search) || _.contains(element.title.toLowerCase(), search)) { |
123 | var node = _.cloneDeep(element.element); | |
124 | if (name === 'fieldset') { | |
fbcd8c17 CW |
125 | if (!ctrl.editor.allowEntityConfig) { |
126 | return; | |
127 | } | |
b844d2ca CW |
128 | node['af-fieldset'] = ctrl.entity.name; |
129 | } | |
130 | $scope.elementList.push(node); | |
131 | $scope.elementTitles.push(name === 'fieldset' ? ts('Fieldset for %1', {1: ctrl.entity.label}) : element.title); | |
132 | } | |
133 | }); | |
134 | } | |
135 | ||
b844d2ca CW |
136 | // This gets called from jquery-ui so we have to manually apply changes to scope |
137 | $scope.buildPaletteLists = function() { | |
138 | $timeout(function() { | |
139 | $scope.$apply(function() { | |
46730a23 | 140 | ctrl.buildPaletteLists(); |
b844d2ca CW |
141 | }); |
142 | }); | |
143 | }; | |
144 | ||
145 | // Checks if a field is on the form or set as a value | |
146 | $scope.fieldInUse = function(fieldName) { | |
147 | var data = ctrl.entity.data || {}; | |
148 | if (fieldName in data) { | |
149 | return true; | |
150 | } | |
151 | return check(ctrl.editor.layout['#children'], {'#tag': 'af-field', name: fieldName}); | |
152 | }; | |
153 | ||
46730a23 CW |
154 | // Checks if fields in a block are already in use on the form. |
155 | // Note that if a block contains no fields it can be used repeatedly, so this will always return false for those. | |
b844d2ca CW |
156 | $scope.blockInUse = function(block) { |
157 | if (block['af-join']) { | |
158 | return check(ctrl.editor.layout['#children'], {'af-join': block['af-join']}); | |
159 | } | |
23fd8685 | 160 | var fieldsInBlock = _.pluck(afGui.findRecursive(afGui.meta.blocks[block['#tag']].layout, {'#tag': 'af-field'}), 'name'); |
b844d2ca CW |
161 | return check(ctrl.editor.layout['#children'], function(item) { |
162 | return item['#tag'] === 'af-field' && _.includes(fieldsInBlock, item.name); | |
163 | }); | |
164 | }; | |
165 | ||
166 | // Check for a matching item for this entity | |
167 | // Recursively checks the form layout, including block directives | |
168 | function check(group, criteria, found) { | |
169 | if (!found) { | |
170 | found = {}; | |
171 | } | |
172 | if (_.find(group, criteria)) { | |
173 | found.match = true; | |
174 | return true; | |
175 | } | |
176 | _.each(group, function(item) { | |
177 | if (found.match) { | |
178 | return false; | |
179 | } | |
180 | if (_.isPlainObject(item)) { | |
181 | // Recurse through everything but skip fieldsets for other entities | |
182 | if ((!item['af-fieldset'] || (item['af-fieldset'] === ctrl.entity.name)) && item['#children']) { | |
183 | check(item['#children'], criteria, found); | |
184 | } | |
185 | // Recurse into block directives | |
23fd8685 CW |
186 | else if (item['#tag'] && item['#tag'] in afGui.meta.blocks) { |
187 | check(afGui.meta.blocks[item['#tag']].layout, criteria, found); | |
b844d2ca CW |
188 | } |
189 | } | |
190 | }); | |
191 | return found.match; | |
192 | } | |
193 | ||
46730a23 CW |
194 | this.$onInit = function() { |
195 | // When a new block is saved, update the list | |
196 | this.meta = afGui.meta; | |
197 | $scope.$watchCollection('$ctrl.meta.blocks', function() { | |
198 | $scope.controls.fieldSearch = ''; | |
199 | ctrl.buildPaletteLists(); | |
200 | }); | |
b844d2ca | 201 | |
46730a23 CW |
202 | $scope.$watch('controls.addValue', function(fieldName) { |
203 | if (fieldName) { | |
204 | if (!ctrl.entity.data) { | |
205 | ctrl.entity.data = {}; | |
206 | } | |
207 | ctrl.entity.data[fieldName] = ''; | |
208 | $scope.controls.addValue = ''; | |
209 | } | |
210 | }); | |
211 | }; | |
b844d2ca CW |
212 | } |
213 | }); | |
214 | ||
215 | })(angular, CRM.$, CRM._); |