From 2e2aaaea59a3a3485686cd57fd91f89a86b5b91c Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Wed, 6 Jan 2021 21:36:04 -0500 Subject: [PATCH] Afform - Refactor afGuiEditor to a component and rename af files --- ext/afform/admin/CRM/AfformAdmin/Utils.php | 173 +++++++++ ext/afform/admin/afform_admin.php | 183 --------- ext/afform/admin/ang/afAdmin.aff.html | 7 + .../{afGuiAdmin.aff.json => afAdmin.aff.json} | 3 +- ...fGuiList.aff.html => afAdminList.aff.html} | 0 ext/afform/admin/ang/afGuiAdmin.aff.html | 7 - ext/afform/admin/ang/afGuiEditor.ang.php | 6 +- ext/afform/admin/ang/afGuiEditor.js | 351 +++++++++--------- 8 files changed, 359 insertions(+), 371 deletions(-) create mode 100644 ext/afform/admin/CRM/AfformAdmin/Utils.php create mode 100644 ext/afform/admin/ang/afAdmin.aff.html rename ext/afform/admin/ang/{afGuiAdmin.aff.json => afAdmin.aff.json} (79%) rename ext/afform/admin/ang/{afGuiList.aff.html => afAdminList.aff.html} (100%) delete mode 100644 ext/afform/admin/ang/afGuiAdmin.aff.html diff --git a/ext/afform/admin/CRM/AfformAdmin/Utils.php b/ext/afform/admin/CRM/AfformAdmin/Utils.php new file mode 100644 index 0000000000..f34f739b4f --- /dev/null +++ b/ext/afform/admin/CRM/AfformAdmin/Utils.php @@ -0,0 +1,173 @@ + FALSE, + 'includeCustom' => TRUE, + 'loadOptions' => TRUE, + 'action' => 'create', + 'select' => ['name', 'label', 'input_type', 'input_attrs', 'required', 'options', 'help_pre', 'help_post', 'serialize', 'data_type'], + 'where' => [['input_type', 'IS NOT NULL']], + ]; + + $data = [ + 'entities' => [ + 'Contact' => [ + 'entity' => 'Contact', + 'label' => E::ts('Contact'), + 'fields' => (array) civicrm_api4('Contact', 'getFields', $getFieldParams, 'name'), + ], + ], + 'blocks' => [], + ]; + + $contactTypes = CRM_Contact_BAO_ContactType::basicTypeInfo(); + + // Scan all extensions for our list of supported entities + foreach (CRM_Extension_System::singleton()->getMapper()->getActiveModuleFiles() as $ext) { + $dir = CRM_Utils_File::addTrailingSlash(dirname($ext['filePath'])) . 'afformEntities'; + if (is_dir($dir)) { + foreach (glob($dir . '/*.php') as $file) { + $entity = include $file; + // Skip disabled contact types + if (!empty($entity['contact_type']) && !isset($contactTypes[$entity['contact_type']])) { + continue; + } + if (!empty($entity['contact_type'])) { + $entity['label'] = $contactTypes[$entity['contact_type']]['label']; + } + // For Contact pseudo-entities (Individual, Organization, Household) + $values = array_intersect_key($entity, ['contact_type' => NULL]); + $afformEntity = $entity['contact_type'] ?? $entity['entity']; + $entity['fields'] = (array) civicrm_api4($entity['entity'], 'getFields', $getFieldParams + ['values' => $values], 'name'); + $data['entities'][$afformEntity] = $entity; + } + } + } + + // Load fields from afform blocks with joins + $blockData = \Civi\Api4\Afform::get() + ->setCheckPermissions(FALSE) + ->addWhere('join', 'IS NOT NULL') + ->setSelect(['join']) + ->execute(); + foreach ($blockData as $block) { + if (!isset($data['entities'][$block['join']]['fields'])) { + $data['entities'][$block['join']]['entity'] = $block['join']; + // Normally you shouldn't pass variables to ts() but very common strings like "Email" should already exist + $data['entities'][$block['join']]['label'] = E::ts($block['join']); + $data['entities'][$block['join']]['fields'] = (array) civicrm_api4($block['join'], 'getFields', $getFieldParams, 'name'); + } + } + + // Todo: add method for extensions to define other elements + $data['elements'] = [ + 'container' => [ + 'title' => E::ts('Container'), + 'element' => [ + '#tag' => 'div', + 'class' => 'af-container', + '#children' => [], + ], + ], + 'text' => [ + 'title' => E::ts('Text box'), + 'element' => [ + '#tag' => 'p', + 'class' => 'af-text', + '#children' => [ + ['#text' => E::ts('Enter text')], + ], + ], + ], + 'markup' => [ + 'title' => E::ts('Rich content'), + 'element' => [ + '#tag' => 'div', + 'class' => 'af-markup', + '#markup' => FALSE, + ], + ], + 'submit' => [ + 'title' => E::ts('Submit Button'), + 'element' => [ + '#tag' => 'button', + 'class' => 'af-button btn-primary', + 'crm-icon' => 'fa-check', + 'ng-click' => 'afform.submit()', + '#children' => [ + ['#text' => E::ts('Submit')], + ], + ], + ], + 'fieldset' => [ + 'title' => E::ts('Fieldset'), + 'element' => [ + '#tag' => 'fieldset', + 'af-fieldset' => NULL, + '#children' => [ + [ + '#tag' => 'legend', + 'class' => 'af-text', + '#children' => [ + [ + '#text' => E::ts('Enter title'), + ], + ], + ], + ], + ], + ], + ]; + + // Reformat options + // TODO: Teach the api to return options in this format + foreach ($data['entities'] as $entityName => $entity) { + foreach ($entity['fields'] as $name => $field) { + if (!empty($field['options'])) { + $data['entities'][$entityName]['fields'][$name]['options'] = CRM_Utils_Array::makeNonAssociative($field['options'], 'key', 'label'); + } + else { + unset($data['entities'][$entityName]['fields'][$name]['options']); + } + } + } + + // Scan for input types + // FIXME: Need a way to load this from other extensions too + foreach (glob(__DIR__ . '/ang/afGuiEditor/inputType/*.html') as $file) { + $matches = []; + preg_match('/([-a-z_A-Z0-9]*).html/', $file, $matches); + $data['inputType'][$matches[1]] = $matches[1]; + } + + $data['styles'] = [ + 'default' => E::ts('Default'), + 'primary' => E::ts('Primary'), + 'success' => E::ts('Success'), + 'info' => E::ts('Info'), + 'warning' => E::ts('Warning'), + 'danger' => E::ts('Danger'), + ]; + + $data['permissions'] = []; + foreach (CRM_Core_Permission::basicPermissions(TRUE, TRUE) as $name => $perm) { + $data['permissions'][] = [ + 'id' => $name, + 'text' => $perm[0], + 'description' => $perm[1] ?? NULL, + ]; + } + + return $data; + } + +} diff --git a/ext/afform/admin/afform_admin.php b/ext/afform/admin/afform_admin.php index c217efadf3..9799e8e91b 100644 --- a/ext/afform/admin/afform_admin.php +++ b/ext/afform/admin/afform_admin.php @@ -140,186 +140,3 @@ function afform_admin_civicrm_entityTypes(&$entityTypes) { function afform_admin_civicrm_themes(&$themes) { _afform_admin_civix_civicrm_themes($themes); } - -/** - * Implements hook_civicrm_pageRun(). - */ -function afform_admin_civicrm_pageRun(&$page) { - if (get_class($page) == 'CRM_Afform_Page_AfformBase' && $page->get('afModule') == 'afGuiAdmin') { - Civi::resources()->addScriptUrl(Civi::service('asset_builder')->getUrl('af-gui-vars.js')); - } -} - -/** - * Implements hook_civicrm_buildAsset(). - * - * Loads metadata to send to the gui editor. - * - * FIXME: This is a prototype and should get broken out into separate callbacks with hooks, events, etc. - */ -function afform_admin_civicrm_buildAsset($asset, $params, &$mimeType, &$content) { - if ($asset !== 'af-gui-vars.js') { - return; - } - - $getFieldParams = [ - 'checkPermissions' => FALSE, - 'includeCustom' => TRUE, - 'loadOptions' => TRUE, - 'action' => 'create', - 'select' => ['name', 'label', 'input_type', 'input_attrs', 'required', 'options', 'help_pre', 'help_post', 'serialize', 'data_type'], - 'where' => [['input_type', 'IS NOT NULL']], - ]; - - $data = [ - 'entities' => [ - 'Contact' => [ - 'entity' => 'Contact', - 'label' => E::ts('Contact'), - 'fields' => (array) civicrm_api4('Contact', 'getFields', $getFieldParams, 'name'), - ], - ], - 'blocks' => [], - ]; - - $contactTypes = CRM_Contact_BAO_ContactType::basicTypeInfo(); - - // Scan all extensions for our list of supported entities - foreach (CRM_Extension_System::singleton()->getMapper()->getActiveModuleFiles() as $ext) { - $dir = CRM_Utils_File::addTrailingSlash(dirname($ext['filePath'])) . 'afformEntities'; - if (is_dir($dir)) { - foreach (glob($dir . '/*.php') as $file) { - $entity = include $file; - // Skip disabled contact types - if (!empty($entity['contact_type']) && !isset($contactTypes[$entity['contact_type']])) { - continue; - } - if (!empty($entity['contact_type'])) { - $entity['label'] = $contactTypes[$entity['contact_type']]['label']; - } - // For Contact pseudo-entities (Individual, Organization, Household) - $values = array_intersect_key($entity, ['contact_type' => NULL]); - $afformEntity = $entity['contact_type'] ?? $entity['entity']; - $entity['fields'] = (array) civicrm_api4($entity['entity'], 'getFields', $getFieldParams + ['values' => $values], 'name'); - $data['entities'][$afformEntity] = $entity; - } - } - } - - // Load fields from afform blocks with joins - $blockData = \Civi\Api4\Afform::get() - ->setCheckPermissions(FALSE) - ->addWhere('join', 'IS NOT NULL') - ->setSelect(['join']) - ->execute(); - foreach ($blockData as $block) { - if (!isset($data['entities'][$block['join']]['fields'])) { - $data['entities'][$block['join']]['entity'] = $block['join']; - // Normally you shouldn't pass variables to ts() but very common strings like "Email" should already exist - $data['entities'][$block['join']]['label'] = E::ts($block['join']); - $data['entities'][$block['join']]['fields'] = (array) civicrm_api4($block['join'], 'getFields', $getFieldParams, 'name'); - } - } - - // Todo: add method for extensions to define other elements - $data['elements'] = [ - 'container' => [ - 'title' => E::ts('Container'), - 'element' => [ - '#tag' => 'div', - 'class' => 'af-container', - '#children' => [], - ], - ], - 'text' => [ - 'title' => E::ts('Text box'), - 'element' => [ - '#tag' => 'p', - 'class' => 'af-text', - '#children' => [ - ['#text' => E::ts('Enter text')], - ], - ], - ], - 'markup' => [ - 'title' => E::ts('Rich content'), - 'element' => [ - '#tag' => 'div', - 'class' => 'af-markup', - '#markup' => FALSE, - ], - ], - 'submit' => [ - 'title' => E::ts('Submit Button'), - 'element' => [ - '#tag' => 'button', - 'class' => 'af-button btn-primary', - 'crm-icon' => 'fa-check', - 'ng-click' => 'afform.submit()', - '#children' => [ - ['#text' => E::ts('Submit')], - ], - ], - ], - 'fieldset' => [ - 'title' => E::ts('Fieldset'), - 'element' => [ - '#tag' => 'fieldset', - 'af-fieldset' => NULL, - '#children' => [ - [ - '#tag' => 'legend', - 'class' => 'af-text', - '#children' => [ - [ - '#text' => E::ts('Enter title'), - ], - ], - ], - ], - ], - ], - ]; - - // Reformat options - // TODO: Teach the api to return options in this format - foreach ($data['entities'] as $entityName => $entity) { - foreach ($entity['fields'] as $name => $field) { - if (!empty($field['options'])) { - $data['entities'][$entityName]['fields'][$name]['options'] = CRM_Utils_Array::makeNonAssociative($field['options'], 'key', 'label'); - } - else { - unset($data['entities'][$entityName]['fields'][$name]['options']); - } - } - } - - // Scan for input types - // FIXME: Need a way to load this from other extensions too - foreach (glob(__DIR__ . '/ang/afGuiEditor/inputType/*.html') as $file) { - $matches = []; - preg_match('/([-a-z_A-Z0-9]*).html/', $file, $matches); - $data['inputType'][$matches[1]] = $matches[1]; - } - - $data['styles'] = [ - 'default' => E::ts('Default'), - 'primary' => E::ts('Primary'), - 'success' => E::ts('Success'), - 'info' => E::ts('Info'), - 'warning' => E::ts('Warning'), - 'danger' => E::ts('Danger'), - ]; - - $data['permissions'] = []; - foreach (CRM_Core_Permission::basicPermissions(TRUE, TRUE) as $name => $perm) { - $data['permissions'][] = [ - 'id' => $name, - 'text' => $perm[0], - 'description' => $perm[1] ?? NULL, - ]; - } - - $mimeType = 'text/javascript'; - $content = "CRM.afformAdminData=" . json_encode($data, JSON_UNESCAPED_SLASHES) . ';'; -} diff --git a/ext/afform/admin/ang/afAdmin.aff.html b/ext/afform/admin/ang/afAdmin.aff.html new file mode 100644 index 0000000000..ad443fe3e6 --- /dev/null +++ b/ext/afform/admin/ang/afAdmin.aff.html @@ -0,0 +1,7 @@ +
+ +
+ +
+ +
diff --git a/ext/afform/admin/ang/afGuiAdmin.aff.json b/ext/afform/admin/ang/afAdmin.aff.json similarity index 79% rename from ext/afform/admin/ang/afGuiAdmin.aff.json rename to ext/afform/admin/ang/afAdmin.aff.json index 2ad6e8c107..22078f8bed 100644 --- a/ext/afform/admin/ang/afGuiAdmin.aff.json +++ b/ext/afform/admin/ang/afAdmin.aff.json @@ -3,7 +3,6 @@ "server_route": "civicrm/admin/afform", "permission": "administer CiviCRM", "requires": [ - "afGuiEditor", - "ui.sortable" + "afGuiEditor" ] } diff --git a/ext/afform/admin/ang/afGuiList.aff.html b/ext/afform/admin/ang/afAdminList.aff.html similarity index 100% rename from ext/afform/admin/ang/afGuiList.aff.html rename to ext/afform/admin/ang/afAdminList.aff.html diff --git a/ext/afform/admin/ang/afGuiAdmin.aff.html b/ext/afform/admin/ang/afGuiAdmin.aff.html deleted file mode 100644 index a87be4db0f..0000000000 --- a/ext/afform/admin/ang/afGuiAdmin.aff.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
-
- -
-
-
diff --git a/ext/afform/admin/ang/afGuiEditor.ang.php b/ext/afform/admin/ang/afGuiEditor.ang.php index 09e0a2c95b..38d8ffea48 100644 --- a/ext/afform/admin/ang/afGuiEditor.ang.php +++ b/ext/afform/admin/ang/afGuiEditor.ang.php @@ -7,10 +7,10 @@ return [ ], 'css' => ['ang/afGuiEditor.css'], 'partials' => ['ang/afGuiEditor'], - 'requires' => ['crmUi', 'crmUtil', 'dialogService', 'api4', 'crmMonaco'], - 'settings' => [], + 'requires' => ['crmUi', 'crmUtil', 'dialogService', 'api4', 'crmMonaco', 'ui.sortable'], + 'settingsFactory' => ['CRM_AfformAdmin_Utils', 'getAngularSettings'], 'basePages' => [], 'exports' => [ - 'af-gui-editor' => 'A', + 'af-gui-editor' => 'E', ], ]; diff --git a/ext/afform/admin/ang/afGuiEditor.js b/ext/afform/admin/ang/afGuiEditor.js index cf67d84e85..00373d0376 100644 --- a/ext/afform/admin/ang/afGuiEditor.js +++ b/ext/afform/admin/ang/afGuiEditor.js @@ -2,14 +2,31 @@ "use strict"; angular.module('afGuiEditor', CRM.angRequires('afGuiEditor')); - angular.module('afGuiEditor').directive('afGuiEditor', function(crmApi4, $parse, $timeout, $location) { - return { - restrict: 'A', - templateUrl: '~/afGuiEditor/main.html', - scope: { - afGuiEditor: '=' - }, - link: function($scope, element, attrs) { + angular.module('afGuiEditor').component('afGuiEditor', { + templateUrl: '~/afGuiEditor/main.html', + bindings: { + name: '<' + }, + controllerAs: 'editor', + controller: function($scope, crmApi4, $parse, $timeout, $location) { + var ts = $scope.ts = CRM.ts(); + $scope.afform = null; + $scope.saving = false; + $scope.selectedEntityName = null; + $scope.meta = this.meta = CRM.afGuiEditor; + this.scope = $scope; + var editor = this; + var newForm = { + title: '', + permission: 'access CiviCRM', + layout: [{ + '#tag': 'af-form', + ctrl: 'afform', + '#children': [] + }] + }; + + this.$onInit = function() { // Shoehorn in a non-angular widget for picking icons CRM.loadScript(CRM.config.resourceBase + 'js/jquery/jquery.crmIconPicker.js').done(function() { $('#af-gui-icon-picker').crmIconPicker().change(function() { @@ -22,198 +39,180 @@ } }); }); - }, - controller: function($scope) { - var ts = $scope.ts = CRM.ts(); - $scope.afform = null; - $scope.saving = false; - $scope.selectedEntityName = null; - $scope.meta = this.meta = CRM.afformAdminData; - this.scope = $scope; - var editor = $scope.editor = this; - var newForm = { - title: '', - permission: 'access CiviCRM', - layout: [{ - '#tag': 'af-form', - ctrl: 'afform', - '#children': [] - }] - }; // Fetch the current form plus all blocks - crmApi4('Afform', 'get', {where: [["OR", [["name", "=", $scope.afGuiEditor.name], ["block", "IS NOT NULL"]]]], layoutFormat: 'shallow', formatWhitespace: true}) + crmApi4('Afform', 'get', {where: [["OR", [["name", "=", editor.name], ["block", "IS NOT NULL"]]]], layoutFormat: 'shallow', formatWhitespace: true}) .then(initialize); + }; - // Initialize the current form + list of blocks - function initialize(afforms) { - $scope.meta.blocks = {}; - _.each(afforms, function(form) { - evaluate(form.layout); - if (form.block) { - $scope.meta.blocks[form.directive_name] = form; - } - if (form.name === $scope.afGuiEditor.name) { - $scope.afform = form; - } - }); - if (!$scope.afform) { - $scope.afform = _.cloneDeep(newForm); - if ($scope.afGuiEditor.name != '0') { - alert('Error: unknown form "' + $scope.afGuiEditor.name + '"'); - } + + // Initialize the current form + list of blocks + function initialize(afforms) { + $scope.meta.blocks = {}; + _.each(afforms, function(form) { + evaluate(form.layout); + if (form.block) { + $scope.meta.blocks[form.directive_name] = form; } - $scope.canvasTab = 'layout'; - $scope.layoutHtml = ''; - $scope.layout = findRecursive($scope.afform.layout, {'#tag': 'af-form'})[0]; - $scope.entities = findRecursive($scope.layout['#children'], {'#tag': 'af-entity'}, 'name'); - - if ($scope.afGuiEditor.name == '0') { - editor.addEntity('Individual'); - $scope.layout['#children'].push($scope.meta.elements.submit.element); + if (form.name === editor.name) { + $scope.afform = form; } - - // Set changesSaved to true on initial load, false thereafter whenever changes are made to the model - $scope.changesSaved = $scope.afGuiEditor.name == '0' ? false : 1; - $scope.$watch('afform', function () { - $scope.changesSaved = $scope.changesSaved === 1; - }, true); + }); + if (!$scope.afform) { + $scope.afform = _.cloneDeep(newForm); + if (editor.name != '0') { + alert('Error: unknown form "' + editor.name + '"'); + } + } + $scope.canvasTab = 'layout'; + $scope.layoutHtml = ''; + $scope.layout = findRecursive($scope.afform.layout, {'#tag': 'af-form'})[0]; + $scope.entities = findRecursive($scope.layout['#children'], {'#tag': 'af-entity'}, 'name'); + + if (editor.name == '0') { + editor.addEntity('Individual'); + $scope.layout['#children'].push($scope.meta.elements.submit.element); } - $scope.updateLayoutHtml = function() { - $scope.layoutHtml = '...Loading...'; - crmApi4('Afform', 'convert', {layout: [$scope.layout], from: 'deep', to: 'html', formatWhitespace: true}) - .then(function(r){ - $scope.layoutHtml = r[0].layout || '(Error)'; - }) - .catch(function(r){ - $scope.layoutHtml = '(Error)'; - }); - }; + // Set changesSaved to true on initial load, false thereafter whenever changes are made to the model + $scope.changesSaved = editor.name == '0' ? false : 1; + $scope.$watch('afform', function () { + $scope.changesSaved = $scope.changesSaved === 1; + }, true); + } - this.addEntity = function(type) { - var meta = editor.meta.entities[type], - num = 1; - // Give this new entity a unique name - while (!!$scope.entities[type + num]) { - num++; - } - $scope.entities[type + num] = _.assign($parse(meta.defaults)($scope), { - '#tag': 'af-entity', - type: meta.entity, - name: type + num, - label: meta.label + ' ' + num + $scope.updateLayoutHtml = function() { + $scope.layoutHtml = '...Loading...'; + crmApi4('Afform', 'convert', {layout: [$scope.layout], from: 'deep', to: 'html', formatWhitespace: true}) + .then(function(r){ + $scope.layoutHtml = r[0].layout || '(Error)'; + }) + .catch(function(r){ + $scope.layoutHtml = '(Error)'; }); - // Add this af-entity tag after the last existing one - var pos = 1 + _.findLastIndex($scope.layout['#children'], {'#tag': 'af-entity'}); - $scope.layout['#children'].splice(pos, 0, $scope.entities[type + num]); - // Create a new af-fieldset container for the entity - var fieldset = _.cloneDeep(editor.meta.elements.fieldset.element); - fieldset['af-fieldset'] = type + num; - fieldset['#children'][0]['#children'][0]['#text'] = meta.label + ' ' + num; - // Add default contact name block - if (meta.entity === 'Contact') { - fieldset['#children'].push({'#tag': 'afblock-name-' + type.toLowerCase()}); - } - // Attempt to place the new af-fieldset after the last one on the form - pos = 1 + _.findLastIndex($scope.layout['#children'], 'af-fieldset'); - if (pos) { - $scope.layout['#children'].splice(pos, 0, fieldset); - } else { - $scope.layout['#children'].push(fieldset); - } - return type + num; - }; + }; - this.removeEntity = function(entityName) { - delete $scope.entities[entityName]; - removeRecursive($scope.layout['#children'], {'#tag': 'af-entity', name: entityName}); - removeRecursive($scope.layout['#children'], {'af-fieldset': entityName}); - this.selectEntity(null); - }; + this.addEntity = function(type) { + var meta = editor.meta.entities[type], + num = 1; + // Give this new entity a unique name + while (!!$scope.entities[type + num]) { + num++; + } + $scope.entities[type + num] = _.assign($parse(meta.defaults)($scope), { + '#tag': 'af-entity', + type: meta.entity, + name: type + num, + label: meta.label + ' ' + num + }); + // Add this af-entity tag after the last existing one + var pos = 1 + _.findLastIndex($scope.layout['#children'], {'#tag': 'af-entity'}); + $scope.layout['#children'].splice(pos, 0, $scope.entities[type + num]); + // Create a new af-fieldset container for the entity + var fieldset = _.cloneDeep(editor.meta.elements.fieldset.element); + fieldset['af-fieldset'] = type + num; + fieldset['#children'][0]['#children'][0]['#text'] = meta.label + ' ' + num; + // Add default contact name block + if (meta.entity === 'Contact') { + fieldset['#children'].push({'#tag': 'afblock-name-' + type.toLowerCase()}); + } + // Attempt to place the new af-fieldset after the last one on the form + pos = 1 + _.findLastIndex($scope.layout['#children'], 'af-fieldset'); + if (pos) { + $scope.layout['#children'].splice(pos, 0, fieldset); + } else { + $scope.layout['#children'].push(fieldset); + } + return type + num; + }; - this.selectEntity = function(entityName) { - $scope.selectedEntityName = entityName; - }; + this.removeEntity = function(entityName) { + delete $scope.entities[entityName]; + removeRecursive($scope.layout['#children'], {'#tag': 'af-entity', name: entityName}); + removeRecursive($scope.layout['#children'], {'af-fieldset': entityName}); + this.selectEntity(null); + }; - this.getField = function(entityType, fieldName) { - return $scope.meta.entities[entityType].fields[fieldName]; - }; + this.selectEntity = function(entityName) { + $scope.selectedEntityName = entityName; + }; - this.getEntity = function(entityName) { - return $scope.entities[entityName]; - }; + this.getField = function(entityType, fieldName) { + return $scope.meta.entities[entityType].fields[fieldName]; + }; - this.getSelectedEntityName = function() { - return $scope.selectedEntityName; - }; + this.getEntity = function(entityName) { + return $scope.entities[entityName]; + }; - // Validates that a drag-n-drop action is allowed - this.onDrop = function(event, ui) { - var sort = ui.item.sortable; - // Check if this is a callback for an item dropped into a different container - // @see https://github.com/angular-ui/ui-sortable notes on canceling - if (!sort.received && sort.source[0] !== sort.droptarget[0]) { - var $source = $(sort.source[0]), - $target = $(sort.droptarget[0]), - $item = $(ui.item[0]); - // Fields cannot be dropped outside their own entity - if ($item.is('[af-gui-field]') || $item.has('[af-gui-field]').length) { - if ($source.closest('[data-entity]').attr('data-entity') !== $target.closest('[data-entity]').attr('data-entity')) { - return sort.cancel(); - } - } - // Entity-fieldsets cannot be dropped into other entity-fieldsets - if ((sort.model['af-fieldset'] || $item.has('.af-gui-fieldset').length) && $target.closest('.af-gui-fieldset').length) { + this.getSelectedEntityName = function() { + return $scope.selectedEntityName; + }; + + // Validates that a drag-n-drop action is allowed + this.onDrop = function(event, ui) { + var sort = ui.item.sortable; + // Check if this is a callback for an item dropped into a different container + // @see https://github.com/angular-ui/ui-sortable notes on canceling + if (!sort.received && sort.source[0] !== sort.droptarget[0]) { + var $source = $(sort.source[0]), + $target = $(sort.droptarget[0]), + $item = $(ui.item[0]); + // Fields cannot be dropped outside their own entity + if ($item.is('[af-gui-field]') || $item.has('[af-gui-field]').length) { + if ($source.closest('[data-entity]').attr('data-entity') !== $target.closest('[data-entity]').attr('data-entity')) { return sort.cancel(); } } - }; - - $scope.addEntity = function(entityType) { - var entityName = editor.addEntity(entityType); - editor.selectEntity(entityName); - }; + // Entity-fieldsets cannot be dropped into other entity-fieldsets + if ((sort.model['af-fieldset'] || $item.has('.af-gui-fieldset').length) && $target.closest('.af-gui-fieldset').length) { + return sort.cancel(); + } + } + }; - $scope.save = function() { - $scope.saving = $scope.changesSaved = true; - crmApi4('Afform', 'save', {formatWhitespace: true, records: [JSON.parse(angular.toJson($scope.afform))]}) - .then(function (data) { - $scope.saving = false; - $scope.afform.name = data[0].name; - // FIXME: This causes an unnecessary reload when saving a new form - $location.search('name', data[0].name); - }); - }; + $scope.addEntity = function(entityType) { + var entityName = editor.addEntity(entityType); + editor.selectEntity(entityName); + }; - $scope.$watch('afform.title', function(newTitle, oldTitle) { - if (typeof oldTitle === 'string') { - _.each($scope.entities, function(entity) { - if (entity.data && entity.data.source === oldTitle) { - entity.data.source = newTitle; - } - }); - } - }); + $scope.save = function() { + $scope.saving = $scope.changesSaved = true; + crmApi4('Afform', 'save', {formatWhitespace: true, records: [JSON.parse(angular.toJson($scope.afform))]}) + .then(function (data) { + $scope.saving = false; + $scope.afform.name = data[0].name; + // FIXME: This causes an unnecessary reload when saving a new form + $location.search('name', data[0].name); + }); + }; - // Parse strings of javascript that php couldn't interpret - function evaluate(collection) { - _.each(collection, function(item) { - if (_.isPlainObject(item)) { - evaluate(item['#children']); - _.each(item, function(node, idx) { - if (_.isString(node)) { - var str = _.trim(node); - if (str[0] === '{' || str[0] === '[' || str.slice(0, 3) === 'ts(') { - item[idx] = $parse(str)({ts: $scope.ts}); - } - } - }); + $scope.$watch('afform.title', function(newTitle, oldTitle) { + if (typeof oldTitle === 'string') { + _.each($scope.entities, function(entity) { + if (entity.data && entity.data.source === oldTitle) { + entity.data.source = newTitle; } }); } + }); + // Parse strings of javascript that php couldn't interpret + function evaluate(collection) { + _.each(collection, function(item) { + if (_.isPlainObject(item)) { + evaluate(item['#children']); + _.each(item, function(node, idx) { + if (_.isString(node)) { + var str = _.trim(node); + if (str[0] === '{' || str[0] === '[' || str.slice(0, 3) === 'ts(') { + item[idx] = $parse(str)({ts: $scope.ts}); + } + } + }); + } + }); } - }; + } }); // Recursively searches a collection and its children using _.filter @@ -970,7 +969,7 @@ modifyClasses($scope.node, _.keys($scope.alignments), val === 'text-left' ? null : val); }; - $scope.styles = _.transform(CRM.afformAdminData.styles, function(styles, val, key) { + $scope.styles = _.transform(CRM.afGuiEditor.styles, function(styles, val, key) { styles['text-' + key] = val; }); @@ -1060,7 +1059,7 @@ // "afform.submit()": ts('Submit Form') // }; - $scope.styles = _.transform(CRM.afformAdminData.styles, function(styles, val, key) { + $scope.styles = _.transform(CRM.afGuiEditor.styles, function(styles, val, key) { styles['btn-' + key] = val; }); -- 2.25.1