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) { |
b844d2ca CW |
12 | var ts = $scope.ts = CRM.ts(); |
13 | var ctrl = this; | |
14 | $scope.controls = {}; | |
15 | $scope.fieldList = []; | |
16 | $scope.blockList = []; | |
17 | $scope.blockTitles = []; | |
18 | $scope.elementList = []; | |
19 | $scope.elementTitles = []; | |
20 | ||
21 | function getEntityType() { | |
22 | return ctrl.entity.type === 'Contact' ? ctrl.entity.data.contact_type : ctrl.entity.type; | |
23 | } | |
24 | ||
25 | $scope.getMeta = function() { | |
23fd8685 | 26 | return afGui.meta.entities[getEntityType()]; |
b844d2ca CW |
27 | }; |
28 | ||
23fd8685 | 29 | $scope.getField = afGui.getField; |
b844d2ca CW |
30 | |
31 | $scope.valuesFields = function() { | |
32 | var fields = _.transform($scope.getMeta().fields, function(fields, field) { | |
33 | fields.push({id: field.name, text: field.label, disabled: $scope.fieldInUse(field.name)}); | |
34 | }, []); | |
35 | return {results: fields}; | |
36 | }; | |
37 | ||
38 | $scope.removeValue = function(entity, fieldName) { | |
39 | delete entity.data[fieldName]; | |
40 | }; | |
41 | ||
42 | function buildPaletteLists() { | |
43 | var search = $scope.controls.fieldSearch ? $scope.controls.fieldSearch.toLowerCase() : null; | |
44 | buildFieldList(search); | |
45 | buildBlockList(search); | |
46 | buildElementList(search); | |
47 | } | |
48 | ||
49 | function buildFieldList(search) { | |
50 | $scope.fieldList.length = 0; | |
51 | $scope.fieldList.push({ | |
52 | entityName: ctrl.entity.name, | |
53 | entityType: getEntityType(), | |
54 | label: ts('%1 Fields', {1: $scope.getMeta().label}), | |
55 | fields: filterFields($scope.getMeta().fields) | |
56 | }); | |
57 | ||
23fd8685 | 58 | _.each(afGui.meta.entities, function(entity, entityName) { |
b844d2ca CW |
59 | if (check(ctrl.editor.layout['#children'], {'af-join': entityName})) { |
60 | $scope.fieldList.push({ | |
61 | entityName: ctrl.entity.name + '-join-' + entityName, | |
62 | entityType: entityName, | |
63 | label: ts('%1 Fields', {1: entity.label}), | |
64 | fields: filterFields(entity.fields) | |
65 | }); | |
66 | } | |
67 | }); | |
68 | ||
69 | function filterFields(fields) { | |
70 | return _.transform(fields, function(fieldList, field) { | |
71 | if (!search || _.contains(field.name, search) || _.contains(field.label.toLowerCase(), search)) { | |
72 | fieldList.push({ | |
73 | "#tag": "af-field", | |
74 | name: field.name | |
75 | }); | |
76 | } | |
77 | }, []); | |
78 | } | |
79 | } | |
80 | ||
81 | function buildBlockList(search) { | |
82 | $scope.blockList.length = 0; | |
83 | $scope.blockTitles.length = 0; | |
23fd8685 | 84 | _.each(afGui.meta.blocks, function(block, directive) { |
b844d2ca CW |
85 | if ((!search || _.contains(directive, search) || _.contains(block.name.toLowerCase(), search) || _.contains(block.title.toLowerCase(), search)) && |
86 | (block.block === '*' || block.block === ctrl.entity.type || (ctrl.entity.type === 'Contact' && block.block === ctrl.entity.data.contact_type)) | |
87 | ) { | |
88 | var item = {"#tag": block.join ? "div" : directive}; | |
89 | if (block.join) { | |
90 | item['af-join'] = block.join; | |
91 | item['#children'] = [{"#tag": directive}]; | |
92 | } | |
93 | if (block.repeat) { | |
94 | item['af-repeat'] = ts('Add'); | |
95 | item.min = '1'; | |
96 | if (typeof block.repeat === 'number') { | |
97 | item.max = '' + block.repeat; | |
98 | } | |
99 | } | |
100 | $scope.blockList.push(item); | |
101 | $scope.blockTitles.push(block.title); | |
102 | } | |
103 | }); | |
104 | } | |
105 | ||
106 | function buildElementList(search) { | |
107 | $scope.elementList.length = 0; | |
108 | $scope.elementTitles.length = 0; | |
23fd8685 | 109 | _.each(afGui.meta.elements, function(element, name) { |
b844d2ca CW |
110 | if (!search || _.contains(name, search) || _.contains(element.title.toLowerCase(), search)) { |
111 | var node = _.cloneDeep(element.element); | |
112 | if (name === 'fieldset') { | |
fbcd8c17 CW |
113 | if (!ctrl.editor.allowEntityConfig) { |
114 | return; | |
115 | } | |
b844d2ca CW |
116 | node['af-fieldset'] = ctrl.entity.name; |
117 | } | |
118 | $scope.elementList.push(node); | |
119 | $scope.elementTitles.push(name === 'fieldset' ? ts('Fieldset for %1', {1: ctrl.entity.label}) : element.title); | |
120 | } | |
121 | }); | |
122 | } | |
123 | ||
124 | $scope.clearSearch = function() { | |
125 | $scope.controls.fieldSearch = ''; | |
126 | }; | |
127 | ||
128 | // This gets called from jquery-ui so we have to manually apply changes to scope | |
129 | $scope.buildPaletteLists = function() { | |
130 | $timeout(function() { | |
131 | $scope.$apply(function() { | |
132 | buildPaletteLists(); | |
133 | }); | |
134 | }); | |
135 | }; | |
136 | ||
137 | // Checks if a field is on the form or set as a value | |
138 | $scope.fieldInUse = function(fieldName) { | |
139 | var data = ctrl.entity.data || {}; | |
140 | if (fieldName in data) { | |
141 | return true; | |
142 | } | |
143 | return check(ctrl.editor.layout['#children'], {'#tag': 'af-field', name: fieldName}); | |
144 | }; | |
145 | ||
146 | $scope.blockInUse = function(block) { | |
147 | if (block['af-join']) { | |
148 | return check(ctrl.editor.layout['#children'], {'af-join': block['af-join']}); | |
149 | } | |
23fd8685 | 150 | var fieldsInBlock = _.pluck(afGui.findRecursive(afGui.meta.blocks[block['#tag']].layout, {'#tag': 'af-field'}), 'name'); |
b844d2ca CW |
151 | return check(ctrl.editor.layout['#children'], function(item) { |
152 | return item['#tag'] === 'af-field' && _.includes(fieldsInBlock, item.name); | |
153 | }); | |
154 | }; | |
155 | ||
156 | // Check for a matching item for this entity | |
157 | // Recursively checks the form layout, including block directives | |
158 | function check(group, criteria, found) { | |
159 | if (!found) { | |
160 | found = {}; | |
161 | } | |
162 | if (_.find(group, criteria)) { | |
163 | found.match = true; | |
164 | return true; | |
165 | } | |
166 | _.each(group, function(item) { | |
167 | if (found.match) { | |
168 | return false; | |
169 | } | |
170 | if (_.isPlainObject(item)) { | |
171 | // Recurse through everything but skip fieldsets for other entities | |
172 | if ((!item['af-fieldset'] || (item['af-fieldset'] === ctrl.entity.name)) && item['#children']) { | |
173 | check(item['#children'], criteria, found); | |
174 | } | |
175 | // Recurse into block directives | |
23fd8685 CW |
176 | else if (item['#tag'] && item['#tag'] in afGui.meta.blocks) { |
177 | check(afGui.meta.blocks[item['#tag']].layout, criteria, found); | |
b844d2ca CW |
178 | } |
179 | } | |
180 | }); | |
181 | return found.match; | |
182 | } | |
183 | ||
184 | $scope.$watch('controls.addValue', function(fieldName) { | |
185 | if (fieldName) { | |
186 | if (!ctrl.entity.data) { | |
187 | ctrl.entity.data = {}; | |
188 | } | |
189 | ctrl.entity.data[fieldName] = ''; | |
190 | $scope.controls.addValue = ''; | |
191 | } | |
192 | }); | |
193 | ||
194 | $scope.$watch('controls.fieldSearch', buildPaletteLists); | |
195 | } | |
196 | }); | |
197 | ||
198 | })(angular, CRM.$, CRM._); |