Skip to content

Commit

Permalink
CRM-19690 - crmMailing - Pick editor layout using template_type
Browse files Browse the repository at this point in the history
General notes:

 1. Template types can be declared (along with preferred editor) using
    hook_civicrm_mailingTemplateTypes.
 2. When creating a mailing, use the path `civicrm/a/#/mailing/new` to create
    a mailing with the default `template_type` (aka first-preferred, by weight).
 3. When creating a mailing, use the path `civicrm/a/#/mailing/new/{template_type}`
    to create a mailing with a specific `template_type`.
 4. When editing a mailing, check the `template_type` and load the
    appropriate editor.
 5. Some of hte boilerplate from `2step.html`, `unified.html`, etal has been
    moved to `base.html`.

Note that this breaks a hidden feature -- before, you could switch among a
few different layouts (`2step`, `unified`, `unified2`, `wizard`) by manually
editing the URL (e.g.  `civicrm/a/#/mailing/2/unified`). Now, to change
the layout of the traditional-style mailings, you can implement a hook, e.g.

```
function mymod_civicrm_mailingTemplateTypes(&$types) {
  foreach ($types as &$typeDef) {
    if ($typeDef['name'] === 'traditional') {
      $typeDef['editorUrl'] = '~/crmMailing/EditMailingCtrl/unified.html';
    }
  }
}
```
  • Loading branch information
totten committed Dec 7, 2016
1 parent 423b3d1 commit 2cd9e5b
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 85 deletions.
40 changes: 40 additions & 0 deletions CRM/Mailing/Info.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ public function getAngularModules() {
CRM_Core_Resources::singleton()
->addSetting(array(
'crmMailing' => array(
'templateTypes' => $this->getTemplateTypes(),
'civiMails' => $civiMails['values'],
'campaignEnabled' => in_array('CiviCampaign', $config->enableComponents),
'groupNames' => $groupNames['values'],
Expand Down Expand Up @@ -331,4 +332,43 @@ public function getActivityTypes() {
public function creatNewShortcut(&$shortCuts) {
}

/**
* @return array
* A list of template-types, keyed by name. Each defines:
* - editorUrl: string, Angular template name
*
* Ex: $templateTypes['mosaico']['editorUrl'] = '~/crmMosaico/editor.html'.
*/
public static function getTemplateTypes() {
$types = array();
$types[] = array(
'name' => 'traditional',
'editorUrl' => CRM_Mailing_Info::workflowEnabled() ? '~/crmMailing/EditMailingCtrl/workflow.html' : '~/crmMailing/EditMailingCtrl/2step.html',
'weight' => 0,
);

//foreach(array('2step', 'unified', 'unified2', 'wizard') as $t) {
// $types[] = array(
// 'name' => $t,
// 'editorUrl' => CRM_Mailing_Info::workflowEnabled() ? '~/crmMailing/EditMailingCtrl/workflow.html' : "~/crmMailing/EditMailingCtrl/{$t}.html",
// 'weight' => 0,
// );
//}

CRM_Utils_Hook::mailingTemplateTypes($types);

$defaults = array('weight' => 0);
foreach (array_keys($types) as $typeName) {
$types[$typeName] = array_merge($defaults, $types[$typeName]);
}
usort($types, function ($a, $b) {
if ($a['weight'] === $b['weight']) {
return 0;
}
return $a['weight'] < $b['weight'] ? -1 : 1;
});

return $types;
}

}
17 changes: 17 additions & 0 deletions CRM/Utils/Hook.php
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,23 @@ public static function mailingGroups(&$form, &$groups, &$mailings) {
);
}

/**
* (Experimental) Modify the list of template-types used for CiviMail composition.
*
* @param array $types
* Sequentially indexed list of template types. Each type specifies:
* - name: string
* - editorUrl: string, Angular template URL
* - weight: int, priority when picking a default value for new mailings
* @return mixed
*/
public static function mailingTemplateTypes(&$types) {
return self::singleton()->invoke(1, $types, self::$_nullObject, self::$_nullObject,
self::$_nullObject, self::$_nullObject, self::$_nullObject,
'civicrm_mailingTemplateTypes'
);
}

/**
* This hook is called when composing the array of membershipTypes and their cost during a membership registration
* (new or renewal).
Expand Down
73 changes: 41 additions & 32 deletions ang/crmMailing.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,50 @@
controller: 'ListMailingsCtrl'
});

var editorPaths = {
'': '~/crmMailing/EditMailingCtrl/2step.html',
'/unified': '~/crmMailing/EditMailingCtrl/unified.html',
'/unified2': '~/crmMailing/EditMailingCtrl/unified2.html',
'/wizard': '~/crmMailing/EditMailingCtrl/wizard.html'
};
angular.forEach(editorPaths, function(editTemplate, pathSuffix) {
if (CRM && CRM.crmMailing && CRM.crmMailing.workflowEnabled) {
editTemplate = '~/crmMailing/EditMailingCtrl/workflow.html'; // override
if (!CRM || !CRM.crmMailing) {
return;
}

$routeProvider.when('/mailing/new', {
template: '<p>' + ts('Initializing...') + '</p>',
controller: 'CreateMailingCtrl',
resolve: {
selectedMail: function(crmMailingMgr) {
var m = crmMailingMgr.create({
template_type: CRM.crmMailing.templateTypes[0].name
});
return crmMailingMgr.save(m);
}
}
$routeProvider.when('/mailing/new' + pathSuffix, {
template: '<p>' + ts('Initializing...') + '</p>',
controller: 'CreateMailingCtrl',
resolve: {
selectedMail: function(crmMailingMgr) {
var m = crmMailingMgr.create();
return crmMailingMgr.save(m);
}
});

$routeProvider.when('/mailing/new/:templateType', {
template: '<p>' + ts('Initializing...') + '</p>',
controller: 'CreateMailingCtrl',
resolve: {
selectedMail: function($route, crmMailingMgr) {
var m = crmMailingMgr.create({
template_type: $route.current.params.templateType
});
return crmMailingMgr.save(m);
}
});
$routeProvider.when('/mailing/:id' + pathSuffix, {
templateUrl: editTemplate,
controller: 'EditMailingCtrl',
resolve: {
selectedMail: function($route, crmMailingMgr) {
return crmMailingMgr.get($route.current.params.id);
},
attachments: function($route, CrmAttachments) {
var attachments = new CrmAttachments(function () {
return {entity_table: 'civicrm_mailing', entity_id: $route.current.params.id};
});
return attachments.load();
}
}
});

$routeProvider.when('/mailing/:id', {
templateUrl: '~/crmMailing/EditMailingCtrl/base.html',
controller: 'EditMailingCtrl',
resolve: {
selectedMail: function($route, crmMailingMgr) {
return crmMailingMgr.get($route.current.params.id);
},
attachments: function($route, CrmAttachments) {
var attachments = new CrmAttachments(function () {
return {entity_table: 'civicrm_mailing', entity_id: $route.current.params.id};
});
return attachments.load();
}
});
}
});
}
]);
Expand Down
5 changes: 1 addition & 4 deletions ang/crmMailing/CreateMailingCtrl.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
(function(angular, $, _) {

angular.module('crmMailing').controller('CreateMailingCtrl', function EditMailingCtrl($scope, selectedMail, $location) {
// Transition URL "/mailing/new/foo" => "/mailing/123/foo"
var parts = $location.path().split('/'); // e.g. "/mailing/new" or "/mailing/123/wizard"
parts[2] = selectedMail.id;
$location.path(parts.join('/'));
$location.path("/mailing/" + selectedMail.id);
$location.replace();
});

Expand Down
6 changes: 5 additions & 1 deletion ang/crmMailing/EditMailingCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
var block = $scope.block = crmBlocker();
var myAutosave = null;

var templateTypes = _.where(CRM.crmMailing.templateTypes, {name: selectedMail.template_type});
if (!templateTypes[0]) throw 'Unrecognized template type: ' + selectedMail.template_type;
$scope.mailingEditorUrl = templateTypes[0].editorUrl;

$scope.isSubmitted = function isSubmitted() {
return _.size($scope.mailing.jobs) > 0;
};
Expand Down Expand Up @@ -43,7 +47,7 @@
// @return Promise
$scope.submit = function submit(options) {
options = options || {};
if (block.check() || $scope.crmMailing.$invalid) {
if (block.check()) {
return;
}

Expand Down
13 changes: 3 additions & 10 deletions ang/crmMailing/EditMailingCtrl/2step.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
<div crm-ui-debug="mailing"></div>

<div ng-show="isSubmitted()">
{{ts('This mailing has been submitted.')}}
</div>

<form name="crmMailing" novalidate ng-hide="isSubmitted()">

<div ng-form="crmMailingSubform">
<div class="crm-block crm-form-block crmMailing">
<div crm-ui-wizard>
<div crm-ui-wizard-step crm-title="ts('Define Mailing')" ng-form="defineForm">
Expand Down Expand Up @@ -49,7 +42,7 @@
<div crm-mailing-block-schedule crm-mailing="mailing"/>
</div>
<center>
<a class="button crmMailing-submit-button" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailing.$invalid}">
<a class="button crmMailing-submit-button" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">
<div>{{ts('Submit Mailing')}}</div>
</a>
</center>
Expand All @@ -66,4 +59,4 @@
</span>
</div>
</div>
</form>
</div>
8 changes: 8 additions & 0 deletions ang/crmMailing/EditMailingCtrl/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div crm-ui-debug="mailing"></div>

<div ng-show="isSubmitted()">
{{ts('This mailing has been submitted.')}}
</div>

<form name="crmMailing" novalidate ng-hide="isSubmitted()" ng-include="mailingEditorUrl">
</form>
12 changes: 3 additions & 9 deletions ang/crmMailing/EditMailingCtrl/unified.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
<div crm-ui-debug="mailing"></div>

<div ng-show="isSubmitted()">
{{ts('This mailing has been submitted.')}}
</div>

<form name="crmMailing" novalidate ng-hide="isSubmitted()">
<div ng-form="crmMailingSubform">
<div class="crm-block crm-form-block crmMailing">

<div crm-mailing-block-summary crm-mailing="mailing"/>
Expand Down Expand Up @@ -43,7 +37,7 @@
<div crm-mailing-block-schedule crm-mailing="mailing"/>
</div>

<button crm-icon="fa-paper-plane" ng-disabled="block.check() || crmMailing.$invalid" ng-click="submit()">{{ts('Submit Mailing')}}</button>
<button crm-icon="fa-paper-plane" ng-disabled="block.check() || crmMailingSubform.$invalid" ng-click="submit()">{{ts('Submit Mailing')}}</button>
<button crm-icon="fa-floppy-o" ng-disabled="block.check()" ng-click="save().then(leave)">{{ts('Save Draft')}}</button>
<button
crm-icon="fa-trash"
Expand All @@ -52,4 +46,4 @@
crm-confirm="{title:ts('Delete Draft'), message:ts('Are you sure you want to permanently delete this mailing?')}"
on-yes="delete()">{{ts('Delete Draft')}}</button>
</div>
</form>
</div>
12 changes: 3 additions & 9 deletions ang/crmMailing/EditMailingCtrl/unified2.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
<div crm-ui-debug="mailing"></div>

<div ng-show="isSubmitted()">
{{ts('This mailing has been submitted.')}}
</div>

<form name="crmMailing" novalidate ng-hide="isSubmitted()">
<div ng-form="crmMailingSubform">
<div class="crm-block crm-form-block crmMailing">

<div crm-mailing-block-summary crm-mailing="mailing"/>
Expand Down Expand Up @@ -39,7 +33,7 @@
<div crm-mailing-block-schedule crm-mailing="mailing"/>
</div>

<button crm-icon="fa-paper-plane" ng-disabled="block.check() || crmMailing.$invalid" ng-click="submit()">{{ts('Submit Mailing')}}</button>
<button crm-icon="fa-paper-plane" ng-disabled="block.check() || crmMailingSubform.$invalid" ng-click="submit()">{{ts('Submit Mailing')}}</button>
<button crm-icon="fa-floppy-o" ng-disabled="block.check()" ng-click="save().then(leave)">{{ts('Save Draft')}}</button>
<button
crm-icon="fa-trash"
Expand All @@ -48,4 +42,4 @@
crm-confirm="{title:ts('Delete Draft'), message:ts('Are you sure you want to permanently delete this mailing?')}"
on-yes="delete()">{{ts('Delete Draft')}}</button>
</div>
</form>
</div>
12 changes: 3 additions & 9 deletions ang/crmMailing/EditMailingCtrl/wizard.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
<div crm-ui-debug="mailing"></div>

<div ng-show="isSubmitted()">
{{ts('This mailing has been submitted.')}}
</div>

<form name="crmMailing" novalidate ng-hide="isSubmitted()">
<div ng-form="crmMailingSubform">
<div class="crm-block crm-form-block crmMailing">

<div crm-ui-wizard>
Expand Down Expand Up @@ -51,7 +45,7 @@
<div crm-mailing-block-review crm-mailing="mailing" crm-mailing-attachments="attachments"/>
</div>
<center>
<a class="button crmMailing-submit-button" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailing.$invalid}">
<a class="button crmMailing-submit-button" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">
<div>{{ts('Submit Mailing')}}</div>
</a>
</center>
Expand All @@ -68,4 +62,4 @@
</span>
</div>
</div>
</form>
</div>
14 changes: 4 additions & 10 deletions ang/crmMailing/EditMailingCtrl/workflow.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
<div crm-ui-debug="mailing"></div>

<div ng-show="isSubmitted()">
{{ts('This mailing has been submitted.')}}
</div>

<form name="crmMailing" novalidate ng-hide="isSubmitted()">
<div ng-form="crmMailingSubform">
<div class="crm-block crm-form-block crmMailing">

<div crm-ui-wizard>
Expand Down Expand Up @@ -53,12 +47,12 @@
<div crm-mailing-block-approve crm-mailing="mailing"/>
</div>
<center ng-if="!checkPerm('approve mailings') && !checkPerm('access CiviMail')">
<a class="button crmMailing-submit-button" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailing.$invalid}">
<a class="button crmMailing-submit-button" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">
<div>{{ts('Submit Mailing')}}</div>
</a>
</center>
<center ng-if="checkPerm('approve mailings') || checkPerm('access CiviMail')">
<a class="button crmMailing-submit-button" ng-click="approve('Approved')" ng-class="{blocking: block.check(), disabled: crmMailing.$invalid}">
<a class="button crmMailing-submit-button" ng-click="approve('Approved')" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">
<div>{{ts('Submit and Approve Mailing')}}</div>
</a>
</center>
Expand All @@ -75,4 +69,4 @@
</span>
</div>
</div>
</form>
</div>
2 changes: 2 additions & 0 deletions ang/crmMailing/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@
groups: {include: [], exclude: [], base: []},
mailings: {include: [], exclude: []}
},
template_type: "traditional",
template_options: "",
name: "",
campaign_id: null,
replyto_email: "",
Expand Down
2 changes: 1 addition & 1 deletion tests/phpunit/Civi/Angular/ManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public function testGetModules() {
*/
public function testGetPartials() {
$partials = $this->angular->getPartials('crmMailing');
$this->assertRegExp('/\<form.*name="crmMailing"/', $partials['~/crmMailing/EditMailingCtrl/2step.html']);
$this->assertRegExp('/ng-form="crmMailing/', $partials['~/crmMailing/EditMailingCtrl/2step.html']);
// If crmMailing changes, feel free to use a different example.
}

Expand Down

0 comments on commit 2cd9e5b

Please sign in to comment.