Afform - Post-submit redirect tokens
authorColeman Watts <coleman@civicrm.org>
Mon, 18 Jul 2022 23:54:47 +0000 (19:54 -0400)
committerColeman Watts <coleman@civicrm.org>
Mon, 18 Jul 2022 23:55:42 +0000 (19:55 -0400)
ext/afform/admin/ang/afGuiEditor.css
ext/afform/admin/ang/afGuiEditor/afGuiTokenSelect.html [new file with mode: 0644]
ext/afform/admin/ang/afGuiEditor/afGuiTokenSelect.js [new file with mode: 0644]
ext/afform/admin/ang/afGuiEditor/config-form.html
ext/afform/core/Civi/Api4/Action/Afform/Submit.php
ext/afform/core/ang/af/afForm.component.js

index 585a397845953e61974d11bcbaa1ec5c6066747e..3aa53d4bbc68a84fbc59a9a0c643358ec231715d 100644 (file)
@@ -483,6 +483,10 @@ body.af-gui-dragging {
   right: 0;
 }
 
+#afGuiEditor .input-group-addon {
+  padding: 0;
+}
+
 #afGuiEditor .af-gui-text-h1 {
   font-weight: bolder;
   font-size: 16px;
diff --git a/ext/afform/admin/ang/afGuiEditor/afGuiTokenSelect.html b/ext/afform/admin/ang/afGuiEditor/afGuiTokenSelect.html
new file mode 100644 (file)
index 0000000..1f37c9a
--- /dev/null
@@ -0,0 +1,6 @@
+<span title="{{:: ts('Insert Token') }}">
+  <input class="form-control crm-action-menu fa-code collapsible-optgroups"
+         crm-ui-select="$ctrl.tokenSelectSettings"
+         on-crm-ui-select="$ctrl.insertToken(selection)"
+  />
+</span>
diff --git a/ext/afform/admin/ang/afGuiEditor/afGuiTokenSelect.js b/ext/afform/admin/ang/afGuiEditor/afGuiTokenSelect.js
new file mode 100644 (file)
index 0000000..30e349e
--- /dev/null
@@ -0,0 +1,52 @@
+(function(angular, $, _) {
+  "use strict";
+
+  angular.module('afGuiEditor').component('afGuiTokenSelect', {
+    bindings: {
+      model: '<',
+      field: '@'
+    },
+    require: {
+      editor: '^afGuiEditor'
+    },
+    templateUrl: '~/afGuiEditor/afGuiTokenSelect.html',
+    controller: function ($scope, $element) {
+      var ts = $scope.ts = CRM.ts('org.civicrm.afform_admin'),
+        ctrl = this;
+
+      this.$onInit = function() {
+        // Because this widget is so small, some placeholder text is helpful once it's open
+        $element.on('select2-open', function() {
+          $('#select2-drop > .select2-search > input').attr('placeholder', ts('Insert Token'));
+        });
+      };
+
+      this.insertToken = function(key) {
+        ctrl.model[ctrl.field] = (ctrl.model[ctrl.field] || '') + '[' + key + ']';
+      };
+
+      this.getTokens = function() {
+        var tokens = _.transform(ctrl.editor.getEntities(), function(tokens, entity) {
+          tokens.push({id: entity.name + '.0.id', text: entity.label + ' ' + ts('ID')});
+        }, []);
+        tokens.push({id: 'token', text: ts('Submission JWT')});
+        return {
+          results: tokens
+        };
+      };
+
+      this.tokenSelectSettings = {
+        data: this.getTokens,
+        // The crm-action-menu icon doesn't show without a placeholder
+        placeholder: ' ',
+        // Make this widget very compact
+        width: '52px',
+        containerCss: {minWidth: '52px'},
+        // Make the dropdown wider than the widget
+        dropdownCss: {width: '250px'}
+      };
+
+    }
+  });
+
+})(angular, CRM.$, CRM._);
index ca85a02cb13460507b20c273f2309922c6eeeccf..aa7563f09ad94f6b5047727751ad3cac317f4e4a 100644 (file)
       <label for="af_config_redirect">
         {{:: ts('Post-Submit Page') }}
       </label>
-      <input ng-model="editor.afform.redirect" name="redirect" class="form-control" id="af_config_redirect" title="{{:: ts('Post-Submit Page') }}" pattern="^((http|https):\/\/|\/|civicrm\/)[-0-9a-zA-Z\/_.]\S+$" title="{{:: ts('Post-Submit Page must be either an absolute url, a relative url or a path starting with CiviCRM') }}" ng-model-options="editor.debounceMode" >
+      <div class="input-group">
+        <input ng-model="editor.afform.redirect" name="redirect" class="form-control" id="af_config_redirect" title="{{:: ts('Post-Submit Page') }}" pattern="^((http|https):\/\/|\/|civicrm\/)[-0-9a-zA-Z\/_.]\S+$" title="{{:: ts('Post-Submit Page must be either an absolute url, a relative url or a path starting with CiviCRM') }}" ng-model-options="editor.debounceMode" >
+        <af-gui-token-select class="input-group-addon" model="editor.afform" field="redirect"></af-gui-token-select>
+      </div>
       <p class="help-block">{{:: ts('Enter a URL or path that the form should redirect to following a successful submission.') }}</p>
     </div>
   </fieldset>
index 068fc657dbed652363075e65663ce3b735853a56..3e453c52ea1fd680a711fccca5aa63fcad87af9b 100644 (file)
@@ -78,9 +78,7 @@ class Submit extends AbstractProcessor {
 
     // Return ids and a token for uploading files
     return [
-      [
-        'token' => $this->generatePostSubmitToken(),
-      ],
+      ['token' => $this->generatePostSubmitToken()] + $this->_entityIds,
     ];
   }
 
index 7abbf65a59d11902f06b7e740f1588cb6affaa13..79514948a479e6f5aad17c0358083711a9826312 100644 (file)
@@ -4,11 +4,12 @@
     bindings: {
       ctrl: '@'
     },
-    controller: function($scope, $element, $timeout, crmApi4, crmStatus, $window, $location, FileUploader) {
+    controller: function($scope, $element, $timeout, crmApi4, crmStatus, $window, $location, $parse, FileUploader) {
       var schema = {},
         data = {},
         status,
         args,
+        submissionResponse,
         ctrl = this;
 
       this.$onInit = function() {
@@ -84,7 +85,7 @@
         }
 
         else if (metaData.redirect) {
-          var url = metaData.redirect;
+          var url = replaceTokens(metaData.redirect, submissionResponse[0]);
           if (url.indexOf('civicrm/') === 0) {
             url = CRM.url(url);
           } else if (url.indexOf('/') === 0) {
         }
       }
 
+      function replaceTokens(str, vars) {
+        function recurse(stack, values) {
+          _.each(values, function(value, key) {
+            console.log('value:' + value, stack);
+            if (_.isArray(value) || _.isPlainObject(value)) {
+              recurse(stack.concat([key]), value);
+            } else {
+              var token = (stack.length ? stack.join('.') + '.' : '') + key;
+              str = str.replace(new RegExp(_.escapeRegExp('[' + token + ']'), 'g'), value);
+            }
+          });
+        }
+        recurse([], vars);
+        return str;
+      }
+
       this.submit = function() {
         status = CRM.status({});
         $element.block();
           args: args,
           values: data}
         ).then(function(response) {
+          submissionResponse = response;
           if (ctrl.fileUploader.getNotUploadedItems().length) {
             _.each(ctrl.fileUploader.getNotUploadedItems(), function(file) {
               file.formData.push({