diff --git a/CRM/FormProcessor/BAO/FormProcessor.php b/CRM/FormProcessor/BAO/FormProcessor.php index a6d963e005ee3a3db3fa4628e295d0057a079cb8..b355b1d771511d9633d5d72de54ed927847d09bd 100644 --- a/CRM/FormProcessor/BAO/FormProcessor.php +++ b/CRM/FormProcessor/BAO/FormProcessor.php @@ -100,6 +100,8 @@ // First delete all inputs CRM_FormProcessor_BAO_FormProcessorInput::deleteWithFormProcessorId($id); + // And all actions + CRM_FormProcessor_BAO_FormProcessorAction::deleteWithFormProcessorId($id); $rule = new CRM_FormProcessor_BAO_FormProcessor(); $rule->id = $id; diff --git a/CRM/FormProcessor/BAO/FormProcessorAction.php b/CRM/FormProcessor/BAO/FormProcessorAction.php index 8ba8d60a1f806831fd0eeaa614e28e5a4343a4a5..d7600d9194bea3b824a47418d455391f62e31807 100644 --- a/CRM/FormProcessor/BAO/FormProcessorAction.php +++ b/CRM/FormProcessor/BAO/FormProcessorAction.php @@ -33,7 +33,7 @@ class CRM_FormProcessor_BAO_FormProcessorAction extends CRM_FormProcessor_DAO_Fo self::storeValues($action, $row); if (!empty($row['form_processor_id'])) { $provider = form_processor_get_action_provider(); - $action_type = $provider->getActionByName($name); + $action_type = $provider->getActionByName($row['type']); if ($action_type) { $configuration = $action_type->getDefaultConfiguration(); @@ -44,12 +44,20 @@ class CRM_FormProcessor_BAO_FormProcessorAction extends CRM_FormProcessor_DAO_Fo $row['configuration'] = array(); } foreach($row['configuration'] as $name => $value) { - $configuration->set($name, $value); + $configuration->setParameter($name, $value); } $action_type->setConfiguration($configuration); - $row['type'] = $action_type->toArray(); + $row['type'] = $action_type; } + + if (isset($row['mapping']) && is_string($row['mapping'])) { + $row['mapping'] = json_decode($row['mapping'], true); + } + if (empty($row['mapping']) || !is_array($row['mapping'])) { + $row['mapping'] = array(); + } + $result[$row['id']] = $row; } else { //invalid input because no there is no form processor @@ -88,9 +96,13 @@ class CRM_FormProcessor_BAO_FormProcessorAction extends CRM_FormProcessor_DAO_Fo $action->$key = $value; } } + if (is_array($action->configuration)) { $action->configuration = json_encode($action->configuration); } + if (is_array($action->mapping)) { + $action->mapping = json_encode($action->mapping); + } $action->save(); self::storeValues($action, $result); diff --git a/CRM/FormProcessor/BAO/FormProcessorInput.php b/CRM/FormProcessor/BAO/FormProcessorInput.php index 415cb72e7a77f49a194195f14e3f2d49b94bc16d..1191b622e8524ecf86905c9dd34f5882002e0a7b 100644 --- a/CRM/FormProcessor/BAO/FormProcessorInput.php +++ b/CRM/FormProcessor/BAO/FormProcessorInput.php @@ -45,7 +45,7 @@ class CRM_FormProcessor_BAO_FormProcessorInput extends CRM_FormProcessor_DAO_For } $type->setConfiguration($configuration); - $row['type'] = $type->toArray(); + $row['type'] = $type; } $result[$row['id']] = $row; } else { diff --git a/CRM/FormProcessor/DAO/FormProcessorAction.php b/CRM/FormProcessor/DAO/FormProcessorAction.php index 4b29fde389410e61e0cd2c0d179c108903634503..aeef77ecf525c17f06ea6e53f2d9361fb1314ca3 100644 --- a/CRM/FormProcessor/DAO/FormProcessorAction.php +++ b/CRM/FormProcessor/DAO/FormProcessorAction.php @@ -68,6 +68,11 @@ class CRM_FormProcessor_DAO_FormProcessorAction extends CRM_Core_DAO { 'title' => E::ts('Configuration'), 'type' => CRM_Utils_Type::T_TEXT, ), + 'mapping' => array( + 'name' => 'mapping', + 'title' => E::ts('Mapping'), + 'type' => CRM_Utils_Type::T_TEXT, + ), ); } return self::$_fields; @@ -88,6 +93,7 @@ class CRM_FormProcessor_DAO_FormProcessorAction extends CRM_Core_DAO { 'title' => 'title', 'type' => 'type', 'configuration' => 'configuration', + 'mapping' => 'mapping', ); } return self::$_fieldKeys; diff --git a/Civi/FormProcessor/API/Provider.php b/Civi/FormProcessor/API/Provider.php index ca9a210e8abb08b0f2cc943af08762441f7f9473..2b54f9cfdecb3011726b0172d32bba8553ccdf40 100644 --- a/Civi/FormProcessor/API/Provider.php +++ b/Civi/FormProcessor/API/Provider.php @@ -6,18 +6,34 @@ namespace Civi\FormProcessor\API; - use \Civi\API\Provider\ProviderInterface as API_ProviderInterface; + use Civi\API\Event\ResolveEvent; + use Civi\API\Events; + use Civi\API\Provider\ProviderInterface as API_ProviderInterface; + use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * This class connects the enabled form processors to * the the api interface of CiviCRM. That way the form processors * could be executed over the api. */ - class Provider implements API_ProviderInterface { + class Provider implements API_ProviderInterface, EventSubscriberInterface { public function __construct() { } + + /** + * @return array + */ + public static function getSubscribedEvents() { + return array( + Events::RESOLVE => array('onApiResolve'), + ); + } + + public function onApiResolve(ResolveEvent $event) { + $event->setApiProvider($this); + } /** * @param array $apiRequest @@ -28,7 +44,45 @@ * @throws \API_Exception */ public function invoke($apiRequest) { - // Run the api + $actionProvider = form_processor_get_action_provider(); + $params = $apiRequest['params']; + + // Find the form processor + $formProcessors = \CRM_FormProcessor_BAO_FormProcessor::getValues(array('name' => $apiRequest['action'])); + if (count($formProcessors) != 1) { + throw new \API_Exception('Could not find a form processor'); + } + $formProcessor = reset($formProcessors);; + + // Validate the parameters. + foreach($formProcessor['inputs'] as $input) { + if ($input['is_required'] && !isset($params[$input['name']])) { + throw new \API_Exception('Parameter '.$input['name'].' is required'); + } + if (!$input['type']->validateValue($params[$input['name']])) { + throw new \API_Exception('Parameter '.$input['name'].' is required'); + } + } + + // Execute the actions + $actionParams = array(); + foreach($formProcessor['actions'] as $action) { + // Create a parameter bag for the action + $parameterBag = $actionProvider->createParameterBag(); + foreach($action['mapping'] as $field => $mapping) { + $splittedMapping = explode('.', $mapping); + if ($splittedMapping[0] == 'input' && isset($params[$splittedMapping[1]])) { + $parameterBag->setParameter($field, $params[$splittedMapping[1]]); + } elseif ($splittedMapping[0] == 'action' && isset($actionParams[$splittedMapping[1]]) && isset($actionParams[$splittedMapping[1]][$splittedMapping[2]])) { + $parameterBag->setParameter($field, $actionParams[$splittedMapping[1]][$splittedMapping[2]]); + } + } + + $outputBag = $action['type']->execute($parameterBag); + // @Todo catch the output of the action + } + + return array('succes' => 1); } /** diff --git a/ang/form_processor/ActionDialogCtrl.html b/ang/form_processor/ActionDialogCtrl.html new file mode 100644 index 0000000000000000000000000000000000000000..f4af01cf0bb35d05438ed9a8a84feef8974c02ba --- /dev/null +++ b/ang/form_processor/ActionDialogCtrl.html @@ -0,0 +1,33 @@ +<div ng-controller="ActionDialogCtrl" class="crm-block crm-form-block"> + <div class="crm-block crm-form-block" ng-form="ActionForm" crm-ui-id-scope> + <div class="crm-group"> + + <div crm-ui-field="{name: 'ActionForm.type', title: ts('Type')}"> + <div>{{model.action.type.title}}</div> + </div> + + <div crm-ui-field="{name: 'ActionForm.title', title: ts('Title')}"> + <input + crm-ui-id="addActionForm.title" + type="text" + name="title" + ng-model="model.action.title" + class="big crm-form-text" + required + autofocus + /> + </div> + + <crm-ap-action-configuration + configuration="model.action.configuration" + action="model.action.type" + fields="model.formProcessor.fields" + mapping="model.action.mapping" + ></crm-ap-action-configuration> + + <button crm-icon="fa-check" ng-click="saveClick()" ng-disabled="addActionForm.$invalid">{{ts('Save and close')}}</button> + <button crm-icon="fa-times" ng-click="cancelClick()">{{ts('Cancel')}}</button> + + </div> + </div> +</div> diff --git a/ang/form_processor/AddActionDialogCtrl.html b/ang/form_processor/AddActionDialogCtrl.html deleted file mode 100644 index f9090349b974eba96e9d1f13bd55653cf3680a5a..0000000000000000000000000000000000000000 --- a/ang/form_processor/AddActionDialogCtrl.html +++ /dev/null @@ -1,30 +0,0 @@ -<div ng-controller="ActionDialogCtrl" class=""> - <div class="crm-block" ng-form="addActionForm" crm-ui-id-scope> - <div class="crm-group"> - - <div crm-ui-field="{name: 'addActionForm.type', title: ts('Type')}"> - <div>{{model.action.type.title}}</div> - </div> - - <div crm-ui-field="{name: 'addActionForm.title', title: ts('Title')}"> - <input - crm-ui-id="addActionForm.title" - type="text" - name="title" - ng-model="model.action.title" - class="big crm-form-text" - required - autofocus - /> - </div> - - <!--crm-form-processor-type-configuration - type=model.input.type - ></crm-form-processor-type-configuration--> - - <button crm-icon="fa-check" ng-click="saveClick()">{{ts('Add action')}}</button> - <button crm-icon="fa-times" ng-click="cancelClick()">{{ts('Cancel')}}</button> - - </div> - </div> -</div> diff --git a/ang/form_processor/EditInputDialogCtrl.html b/ang/form_processor/EditInputDialogCtrl.html deleted file mode 100644 index c81858b2650f4ccb15e94f5cc8ac3827fb1d5afe..0000000000000000000000000000000000000000 --- a/ang/form_processor/EditInputDialogCtrl.html +++ /dev/null @@ -1,50 +0,0 @@ -<div ng-controller="InputDialogCtrl" class=""> - <div class="crm-block" ng-form="editInputForm" crm-ui-id-scope> - <div class="crm-group"> - - <div crm-ui-field="{name: 'formProcessorDetailForm.type', title: ts('Type')}"> - <div>{{model.input.type.label}}</div> - </div> - - <div crm-ui-field="{name: 'editInputForm.name', title: ts('Name')}"> - <input - crm-ui-id="editInputForm.name" - type="text" - name="name" - ng-model="model.input.name" - class="big crm-form-text" - required - autofocus - /> - <div ng-show="invalidName"> - <em>{{ts('WARNING: The name of the formprocessor is invalid (Only lowercase characters and _ are allowed).')}}</em> - </div> - <div ng-show="nameExists"> - <em>{{ts('WARNING: The name of the formprocessor already exists.')}}</em> - </div> - </div> - - <div crm-ui-field="{title: ts('Is required?')}"> - <input name="is_required" type="checkbox" ng-model="model.input.is_required" ng-true-value="'1'" ng-false-value="'0'"/> - </div> - - <div crm-ui-field="{name: 'editInputForm.default_value', title: ts('Default value')}"> - <input - crm-ui-id="editInputForm.default_value" - type="text" - name="title" - ng-model="model.input.default_value" - class="big crm-form-text" - /> - </div> - - <crm-form-processor-type-configuration - type=model.input.type - ></crm-form-processor-type-configuration> - - <button crm-icon="fa-check" ng-click="saveClick()">{{ts('Update input')}}</button> - <button crm-icon="fa-times" ng-click="cancelClick()">{{ts('Cancel')}}</button> - - </div> - </div> -</div> diff --git a/ang/form_processor/edit.html b/ang/form_processor/FormProcessorEditCtrl.html similarity index 73% rename from ang/form_processor/edit.html rename to ang/form_processor/FormProcessorEditCtrl.html index 436c7c35ad2f72661cf4ec5a2708d24be5cc7cfb..9d1298486b1c9605f342c2a96bdd7c2626bf9b77 100644 --- a/ang/form_processor/edit.html +++ b/ang/form_processor/FormProcessorEditCtrl.html @@ -9,11 +9,11 @@ Required vars: formProcessor <form name="editFormProcessorForm" unsaved-warning-form> <div class="crm-block crm-form-block crmFormProcessor"> - <div ng-include="'~/form_processor/formProcessorDetails.html'"></div> + <div ng-include="'~/form_processor/FormProcessorEditCtrl/Details.html'"></div> - <div ng-include="'~/form_processor/formProcessorInputTable.html'"></div> + <div ng-include="'~/form_processor/FormProcessorEditCtrl/InputTable.html'"></div> - <div ng-include="'~/form_processor/formProcessorActionTable.html'"></div> + <div ng-include="'~/form_processor/FormProcessorEditCtrl/ActionTable.html'"></div> <div class="crm-submit-buttons"> <button crm-icon="fa-check" ng-click="editFormProcessorForm.$setPristine(); save()" ng-disabled="editFormProcessorForm.$invalid || !isNameValid"> diff --git a/ang/form_processor/FormProcessors.js b/ang/form_processor/FormProcessorEditCtrl.js similarity index 51% rename from ang/form_processor/FormProcessors.js rename to ang/form_processor/FormProcessorEditCtrl.js index a50e55ac155b507b14760bca8ea0836a7909c5e9..7f48fe74a7264f9cce1885da8466d36d63c98cec 100644 --- a/ang/form_processor/FormProcessors.js +++ b/ang/form_processor/FormProcessorEditCtrl.js @@ -1,21 +1,9 @@ (function(angular, $, _) { angular.module('form_processor').config(function($routeProvider) { - $routeProvider.when('/formProcessors', { - controller: 'FormProcessorListCtrl', - templateUrl: '~/form_processor/list.html', - - // If you need to look up data when opening the page, list it out - // under "resolve". - resolve: { - formProcessors: function($route, crmApi) { - return crmApi('FormProcessor', 'get', {options: {limit: 0}}); - } - } - }); $routeProvider.when('/formProcessor/new', { - templateUrl: '~/form_processor/edit.html', - controller: 'FormProcessorCtrl', + templateUrl: '~/form_processor/FormProcessorEditCtrl.html', + controller: 'FormProcessorEditCtrl', resolve: { apiCalls: function($route, crmApi) { reqs = {}; @@ -30,8 +18,8 @@ } }); $routeProvider.when('/formProcessor/:id', { - templateUrl: '~/form_processor/edit.html', - controller: 'FormProcessorCtrl', + templateUrl: '~/form_processor/FormProcessorEditCtrl.html', + controller: 'FormProcessorEditCtrl', resolve: { apiCalls: function($route, crmApi) { var reqs = {}; @@ -47,22 +35,13 @@ } ); - angular.module('form_processor').directive('crmFormProcessorTypeConfiguration', function() { - return { - restrict: 'E', - scope: { - type: '=type', - }, - templateUrl: '~/form_processor/TypeConfiguration.html', - }; - }); - - angular.module('form_processor').controller('FormProcessorCtrl', function($scope, dialogService, crmApi, apiCalls) { + angular.module('form_processor').controller('FormProcessorEditCtrl', function($scope, dialogService, crmApi, apiCalls, $q) { var ts = $scope.ts = CRM.ts(null); $scope.formProcessor = apiCalls.formProcessor; $scope.locks = {name: true}; $scope.isNameValid = false; + $scope.new_id = -1; $scope.inputTypes = CRM.form_processor.inputTypes; for(var i=0; i<$scope.inputTypes.length; i++) { @@ -106,11 +85,13 @@ var result = crmApi('FormProcessor', 'create', $scope.formProcessor, true); result.then(function(data) { if (data.is_error === 0 || data.is_error == '0') { - $scope.formProcessor.id = data.id; + $scope.formProcessor.id = data.id; + + var apiCalls = []; angular.forEach($scope.deletedInputs, function(input, key) { - if (input.id) { - crmApi('FormProcessorInput', 'delete', {'id': input.id}, true); + if (input.id) { + apiCalls.push(crmApi('FormProcessorInput', 'delete', {'id': input.id}, true)); } }); @@ -118,9 +99,56 @@ input.form_processor_id = $scope.formProcessor.id; input.configuration = input.type.configuration; input.type = input.type.name; - crmApi('FormProcessorInput', 'create', input, true); + apiCalls.push(crmApi('FormProcessorInput', 'create', input, true)); + }); + + angular.forEach($scope.deletedActions, function(action, key) { + if (action.id) { + apiCalls.push(crmApi('FormProcessorAction', 'delete', {'id': action.id}, true)); + } + }); + + var newActions = []; + var actionWeight = 0; + angular.forEach($scope.formProcessor.actions, function(action, key) { + var old_id = action.id; + if (action.id < 0) { + delete action.id; + } + action.form_processor_id = $scope.formProcessor.id; + action.type = action.type.name; + action.weight = actionWeight; + console.log(action); + apiCalls.push(crmApi('FormProcessorAction', 'create', action, true).then(function(action_result) { + action.id = action_result.id; + if (old_id < 0) { + newActions[old_id] = action.id; + } + })); + actionWeight++; }); - window.location.href = '#/formProcessors'; + + // Update the mapping + $q.all(apiCalls).then(function(result){ + // We have saved the last action. + // Lets fix the mapping of the actions so that the mapping with an id < 0 + // will be resolved to their new id + angular.forEach($scope.formProcessor.actions, function(action, key) { + var actionChanged = false; + angular.forEach(action.mapping, function (field, parameter) { + var splitted_field = field.split('.'); + if (splitted_field[0] == 'action' && splitted_field[1] < 0) { + action.mapping[parameter] = 'action.'+newActions[splitted_field[1]]+'.'+splitted_field[2]; + actionChanged = true; + } + }); + if (actionChanged) { + crmApi('FormProcessorAction', 'create', action, true); + } + }); + }); + + window.location.href = '#/formprocessors'; } }); }; @@ -138,26 +166,14 @@ if (!inputType) { return; } - var options = CRM.utils.adjustDialogDefaults({ - autoOpen: false, - width: '40%', - height: 'auto', - title: ts('Add input') - }); - var model = { - formProcessor: $scope.formProcessor, - input: { - type: angular.copy(inputType), - 'name': '', - 'is_required': 0, - 'default_value': '', - } - }; - dialogService.open('InputDialog', '~/form_processor/AddInputDialogCtrl.html', model, options) - .then( - function(data) { - $scope.formProcessor.inputs.push(data.input); - }); + var input = { + 'id': $scope.new_id, + 'type': angular.copy(inputType), + 'name': '', + 'is_required': 0, + 'default_value': '', + }; + $scope.editInput(input); }; // Open a dialog for editting an input @@ -166,13 +182,20 @@ autoOpen: false, width: '40%', height: 'auto', - title: ts('Add input') + title: ts('Edit input') }); var model = { formProcessor: $scope.formProcessor, input: input }; - dialogService.open('InputDialog', '~/form_processor/EditInputDialogCtrl.html', model, options); + dialogService.open('InputDialog', '~/form_processor/InputDialogCtrl.html', model, options) + .then( + function(data) { + if ($scope.new_id == data.input.id) { + $scope.formProcessor.inputs.push(data.input); + $scope.new_id --; + } + }); }; $scope.removeAction = function removeAction(action) { @@ -188,25 +211,14 @@ if (!actionType) { return; } - var options = CRM.utils.adjustDialogDefaults({ - autoOpen: false, - width: '40%', - height: 'auto', - title: ts('Add action') - }); - var model = { - formProcessor: $scope.formProcessor, - action: { - type: angular.copy(actionType), - 'title': '', - 'configuration': angular.copy(actionType.default_configuration) - } + var action = { + id: $scope.new_id, + type: angular.copy(actionType), + 'title': '', + 'configuration': angular.copy(actionType.default_configuration), + 'mapping': {} }; - dialogService.open('ActionDialog', '~/form_processor/AddActionDialogCtrl.html', model, options) - .then( - function(data) { - $scope.formProcessor.actions.push(data.action); - }); + $scope.editAction(action); }; // Open a dialog for editting an action @@ -217,37 +229,49 @@ height: 'auto', title: ts('Edit action') }); + + $scope.updateFields($scope.formProcessor, action); + var model = { formProcessor: $scope.formProcessor, action: action }; - dialogService.open('ActionDialog', '~/form_processor/EditActionDialogCtrl.html', model, options); + dialogService.open('ActionDialog', '~/form_processor/ActionDialogCtrl.html', model, options) + .then(function(data) { + if ($scope.new_id == data.action.id) { + $scope.formProcessor.actions.push(data.action); + $scope.new_id --; + } + }); }; - }); - angular.module('form_processor').controller('FormProcessorListCtrl', function($scope, crmApi, formProcessors) { - var ts = $scope.ts = CRM.ts(null); - - $scope.formProcessors = formProcessors.values; - $scope.toggleFormProcessor = function (formProcessor) { - formProcessor.is_active = (formProcessor.is_active == '1') ? '0' : '1'; - crmApi('FormProcessor', 'create', formProcessor, true) - .catch(function (data) { - formProcessor.is_active = (formProcessor.is_active == '1') ? '0' : '1'; // revert - $scope.$digest(); - }); - }; - $scope.deleteFormProcessor = function (formProcessor) { - crmApi('FormProcessor', 'delete', {id: formProcessor.id}, { - error: function (data) { - CRM.alert(data.error_message, ts('Error'), 'error'); - } - }) - .then(function (data) { - delete formProcessors.values[formProcessor.id]; - $scope.$digest(); - }); - }; + $scope.updateFields = function updateFields(formProcessor, selectedAction) { + formProcessor.fields = []; + angular.forEach(formProcessor.inputs, function(input, key) { + var field = { + 'name': 'input.'+input.name, + 'label': 'Input::'+input.name + }; + formProcessor.fields.push(field); + }); + + var skipAfter = false; + angular.forEach(formProcessor.actions, function(action, key) { + if (selectedAction == action) { + skipAfter = true; + } + if (!skipAfter) { + angular.forEach(action.type.output_spec, function(output_field, output_field_key) { + var field = { + 'name': 'action.'+action.id+'.'+output_field.name, + 'label': 'Action::'+action.title+'::'+output_field.title + }; + formProcessor.fields.push(field); + }); + } + }); + }; + }); })(angular, CRM.$, CRM._); diff --git a/ang/form_processor/formProcessorActionTable.html b/ang/form_processor/FormProcessorEditCtrl/ActionTable.html similarity index 90% rename from ang/form_processor/formProcessorActionTable.html rename to ang/form_processor/FormProcessorEditCtrl/ActionTable.html index 69cdad7ab760c0de9d8a80f89ad8299a73233776..9cabd5576dd01ad98fa82bc44f030b88e7d23e6b 100644 --- a/ang/form_processor/formProcessorActionTable.html +++ b/ang/form_processor/FormProcessorEditCtrl/ActionTable.html @@ -17,8 +17,8 @@ Required vars: formProcessor <td>{{action.title}}</td> <td>{{action.type.title}}</td> <td> - <a crm-icon="fa-edit" class="crm-hover-button" ng-click="editAction(input)" title="{{ts('Edit')}}">{{ts('Edit')}}</a> - <a crm-icon="fa-trash" class="crm-hover-button" ng-click="removeAction(input)" title="{{ts('Remove')}}">{{ts('Remove')}}</a> + <a crm-icon="fa-edit" class="crm-hover-button" ng-click="editAction(action)" title="{{ts('Edit')}}">{{ts('Edit')}}</a> + <a crm-icon="fa-trash" class="crm-hover-button" ng-click="removeAction(action)" title="{{ts('Remove')}}">{{ts('Remove')}}</a> </td> </tr> </tbody> diff --git a/ang/form_processor/formProcessorDetails.html b/ang/form_processor/FormProcessorEditCtrl/Details.html similarity index 100% rename from ang/form_processor/formProcessorDetails.html rename to ang/form_processor/FormProcessorEditCtrl/Details.html diff --git a/ang/form_processor/formProcessorInputTable.html b/ang/form_processor/FormProcessorEditCtrl/InputTable.html similarity index 100% rename from ang/form_processor/formProcessorInputTable.html rename to ang/form_processor/FormProcessorEditCtrl/InputTable.html diff --git a/ang/form_processor/list.html b/ang/form_processor/FormProcessorListCtrl.html similarity index 100% rename from ang/form_processor/list.html rename to ang/form_processor/FormProcessorListCtrl.html diff --git a/ang/form_processor/FormProcessorListCtrl.js b/ang/form_processor/FormProcessorListCtrl.js new file mode 100644 index 0000000000000000000000000000000000000000..4f09122983acbfa8fe0bf9a421019223d006bde6 --- /dev/null +++ b/ang/form_processor/FormProcessorListCtrl.js @@ -0,0 +1,44 @@ +(function(angular, $, _) { + + angular.module('form_processor').config(function($routeProvider) { + $routeProvider.when('/formprocessors', { + controller: 'FormProcessorListCtrl', + templateUrl: '~/form_processor/FormProcessorListCtrl.html', + + // If you need to look up data when opening the page, list it out + // under "resolve". + resolve: { + formProcessors: function($route, crmApi) { + return crmApi('FormProcessor', 'get', {options: {limit: 0}}); + } + } + }); + } + ); + + angular.module('form_processor').controller('FormProcessorListCtrl', function($scope, crmApi, formProcessors) { + var ts = $scope.ts = CRM.ts(null); + + $scope.formProcessors = formProcessors.values; + $scope.toggleFormProcessor = function (formProcessor) { + formProcessor.is_active = (formProcessor.is_active == '1') ? '0' : '1'; + crmApi('FormProcessor', 'create', formProcessor, true) + .catch(function (data) { + formProcessor.is_active = (formProcessor.is_active == '1') ? '0' : '1'; // revert + $scope.$digest(); + }); + }; + $scope.deleteFormProcessor = function (formProcessor) { + crmApi('FormProcessor', 'delete', {id: formProcessor.id}, { + error: function (data) { + CRM.alert(data.error_message, ts('Error'), 'error'); + } + }) + .then(function (data) { + delete formProcessors.values[formProcessor.id]; + $scope.$digest(); + }); + }; + }); + +})(angular, CRM.$, CRM._); \ No newline at end of file diff --git a/ang/form_processor/AddInputDialogCtrl.html b/ang/form_processor/InputDialogCtrl.html similarity index 76% rename from ang/form_processor/AddInputDialogCtrl.html rename to ang/form_processor/InputDialogCtrl.html index 07b88c5e7993677c04ccda4db6205ea261030640..e68e365d9f1aa85dfce17028d6287020e3ac324f 100644 --- a/ang/form_processor/AddInputDialogCtrl.html +++ b/ang/form_processor/InputDialogCtrl.html @@ -1,14 +1,14 @@ <div ng-controller="InputDialogCtrl" class=""> - <div class="crm-block" ng-form="addInputForm" crm-ui-id-scope> + <div class="crm-block" ng-form="InputForm" crm-ui-id-scope> <div class="crm-group"> <div crm-ui-field="{name: 'formProcessorDetailForm.type', title: ts('Type')}"> <div>{{model.input.type.label}}</div> </div> - <div crm-ui-field="{name: 'addInputForm.name', title: ts('Name')}"> + <div crm-ui-field="{name: 'InputForm.name', title: ts('Name')}"> <input - crm-ui-id="addInputForm.name" + crm-ui-id="InputForm.name" type="text" name="name" ng-model="model.input.name" @@ -28,9 +28,9 @@ <input name="is_required" type="checkbox" ng-model="model.input.is_required" ng-true-value="'1'" ng-false-value="'0'"/> </div> - <div crm-ui-field="{name: 'addInputForm.default_value', title: ts('Default value')}"> + <div crm-ui-field="{name: 'InputForm.default_value', title: ts('Default value')}"> <input - crm-ui-id="addInputForm.default_value" + crm-ui-id="InputForm.default_value" type="text" name="title" ng-model="model.input.default_value" @@ -42,7 +42,7 @@ type=model.input.type ></crm-form-processor-type-configuration> - <button crm-icon="fa-check" ng-click="saveClick()">{{ts('Add input')}}</button> + <button crm-icon="fa-check" ng-click="saveClick()">{{ts('Save and Close')}}</button> <button crm-icon="fa-times" ng-click="cancelClick()">{{ts('Cancel')}}</button> </div> diff --git a/ang/form_processor/TypeConfiguration.html b/ang/form_processor/crmFormProcessorTypeConfiguration.html similarity index 100% rename from ang/form_processor/TypeConfiguration.html rename to ang/form_processor/crmFormProcessorTypeConfiguration.html diff --git a/ang/form_processor/crmFormProcessorTypeConfiguration.js b/ang/form_processor/crmFormProcessorTypeConfiguration.js new file mode 100644 index 0000000000000000000000000000000000000000..8bec3b1d16de58e2b0df3fd62b935788b8ee0e6d --- /dev/null +++ b/ang/form_processor/crmFormProcessorTypeConfiguration.js @@ -0,0 +1,13 @@ +(function(angular, $, _) { + + angular.module('form_processor').directive('crmFormProcessorTypeConfiguration', function() { + return { + restrict: 'E', + scope: { + type: '=type', + }, + templateUrl: '~/form_processor/crmFormProcessorTypeConfiguration.html', + }; + }); + +})(angular, CRM.$, CRM._); \ No newline at end of file diff --git a/api/v3/FormProcessor/Get.php b/api/v3/FormProcessor/Get.php index 43bf53e8f8a83bd203f1d0b0372c92b5d268e7a8..589d0b8ab9069fc0f3e5db2fc1b4d9a47db3e33c 100644 --- a/api/v3/FormProcessor/Get.php +++ b/api/v3/FormProcessor/Get.php @@ -10,6 +10,14 @@ */ function civicrm_api3_form_processor_get($params) { $returnValues = CRM_FormProcessor_BAO_FormProcessor::getValues($params); + foreach($returnValues as $index => $formProcessor) { + foreach($formProcessor['inputs'] as $key => $input) { + $returnValues[$index]['inputs'][$key]['type'] = $input['type']->toArray(); + } + foreach($formProcessor['actions'] as $key => $action) { + $returnValues[$index]['actions'][$key]['type'] = $action['type']->toArray(); + } + } return civicrm_api3_create_success($returnValues, $params, 'FormProcessor', 'Get'); } diff --git a/api/v3/FormProcessorAction/Create.php b/api/v3/FormProcessorAction/Create.php index 44230e39874fa4617d2df19a3fd590eb2a89520c..17abf812afcdc8e146e4af9931b18c85d8131211 100644 --- a/api/v3/FormProcessorAction/Create.php +++ b/api/v3/FormProcessorAction/Create.php @@ -42,6 +42,11 @@ function _civicrm_api3_form_processor_action_create_spec(&$spec) { 'type' => CRM_Utils_Type::T_TEXT, 'api_required' => false ); + $spec['mapping'] = array( + 'title' => E::ts('Mapping'), + 'type' => CRM_Utils_Type::T_TEXT, + 'api_required' => false + ); } /** diff --git a/sql/create_civicrm_form_processor.sql b/sql/create_civicrm_form_processor.sql index f9550018edccea6bb38a07ea3f26d35e5a9994dc..97ee8565151d128ed1a912fb77bf7018b5bdc9af 100644 --- a/sql/create_civicrm_form_processor.sql +++ b/sql/create_civicrm_form_processor.sql @@ -31,5 +31,6 @@ CREATE TABLE IF NOT EXISTS `civicrm_form_processor_action` ( `title` VARCHAR(80) NOT NULL, `type` VARCHAR(80) NOT NULL, `configuration` TEXT NULL, + `mapping` TEXT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB;