Use PrematureExit exception instead of weird hack in tests
[civicrm-core.git] / js / view / crm.profile-selector.js
1 (function($, _, Backbone) {
2 if (!CRM.ProfileSelector) CRM.ProfileSelector = {};
3
4 CRM.ProfileSelector.Option = Backbone.Marionette.ItemView.extend({
5 template: '#profile_selector_option_template',
6 tagName: 'option',
7 modelEvents: {
8 'change:title': 'render'
9 },
10 onRender: function() {
11 this.$el.attr('value', this.model.get('id'));
12 }
13 });
14
15 CRM.ProfileSelector.Select = Backbone.Marionette.CollectionView.extend({
16 tagName: 'select',
17 itemView: CRM.ProfileSelector.Option
18 });
19
20 /**
21 * Render a pane with 'Select/Preview/Edit/Copy/Create' functionality for profiles.
22 *
23 * Note: This view works with a ufGroupCollection, and it creates popups for a
24 * ufGroupModel. These are related but not facilely. The ufGroupModels in the
25 * ufGroupCollection are never passed to the popup, and the models from the
26 * popup are never added to the collection. This is because the popup works
27 * with temporary, local copies -- but the collection reflects the actual list
28 * on the server.
29 *
30 * options:
31 * - ufGroupId: int, the default selection
32 * - ufGroupCollection: the profiles which can be selected
33 * - ufEntities: hard-coded entity list used with any new/existing forms
34 * (this may be removed when the form-runtime is updated to support hand-picking
35 * entities for each form)
36 */
37 CRM.ProfileSelector.View = Backbone.Marionette.Layout.extend({
38 template: '#profile_selector_template',
39 regions: {
40 selectRegion: '.crm-profile-selector-select'
41 },
42 events: {
43 'change .crm-profile-selector-select select': 'onChangeUfGroupId',
44 'click .crm-profile-selector-edit': 'doEdit',
45 'click .crm-profile-selector-copy': 'doCopy',
46 'click .crm-profile-selector-create': 'doCreate',
47 'click .crm-profile-selector-preview': 'doShowPreview',
48 // prevent interaction with preview form
49 'click .crm-profile-selector-preview-pane': false,
50 'crmLoad .crm-profile-selector-preview-pane': 'disableForm'
51 },
52 /** @var Marionette.View which specifically builds on jQuery-UI's dialog */
53 activeDialog: null,
54 onRender: function() {
55 var view = new CRM.ProfileSelector.Select({
56 collection: this.options.ufGroupCollection
57 });
58 this.selectRegion.show(view);
59 this.setUfGroupId(this.options.ufGroupId, {silent: true});
60 this.toggleButtons();
61 this.$('.crm-profile-selector-select select').css('width', '25em').crmSelect2();
62 this.doShowPreview();
63 },
64 onChangeUfGroupId: function(event) {
65 this.options.ufGroupId = $(event.target).val();
66 this.trigger('change:ufGroupId', this);
67 this.toggleButtons();
68 this.doPreview();
69 },
70 toggleButtons: function() {
71 this.$('.crm-profile-selector-edit,.crm-profile-selector-copy').prop('disabled', !this.hasUfGroupId());
72 },
73 hasUfGroupId: function() {
74 return (this.getUfGroupId() && this.getUfGroupId() !== '') ? true : false;
75 },
76 setUfGroupId: function(value, options) {
77 this.options.ufGroupId = value;
78 this.$('.crm-profile-selector-select select').val(value);
79 this.$('.crm-profile-selector-select select').select2('val', value, (!options || !options.silent));
80 },
81 getUfGroupId: function() {
82 return this.options.ufGroupId;
83 },
84 doPreview: function() {
85 var $pane = this.$('.crm-profile-selector-preview-pane');
86 if (!this.hasUfGroupId()) {
87 $pane.html($('#profile_selector_empty_preview_template').html());
88 } else {
89 CRM.loadPage(CRM.url("civicrm/ajax/inline", {class_name: 'CRM_UF_Form_Inline_PreviewById', id: this.getUfGroupId()}), {target: $pane});
90 }
91 },
92 doShowPreview: function() {
93 var $preview = this.$('.crm-profile-selector-preview');
94 var $pane = this.$('.crm-profile-selector-preview-pane');
95 if ($preview.hasClass('crm-profile-selector-preview-show')) {
96 $preview.removeClass('crm-profile-selector-preview-show');
97 $preview.find('.crm-i').removeClass('fa-television').addClass('fa-times');
98 $pane.show();
99 } else {
100 $preview.addClass('crm-profile-selector-preview-show');
101 $preview.find('.crm-i').removeClass('fa-times').addClass('fa-television');
102 $pane.hide();
103 }
104 },
105 disableForm: function() {
106 this.$(':input', '.crm-profile-selector-preview-pane').not('.select2-input').prop('readOnly', true);
107 },
108 doEdit: function(e) {
109 e.preventDefault();
110 var profileSelectorView = this;
111 var designerDialog = new CRM.Designer.DesignerDialog({
112 findCreateUfGroupModel: function(options) {
113 var ufId = profileSelectorView.getUfGroupId();
114 // Retrieve UF group and fields from the api
115 CRM.api('UFGroup', 'getsingle', {id: ufId, "api.UFField.get": 1}, {
116 success: function(formData) {
117 // Note: With chaining, API returns some extraneous keys that aren't part of UFGroupModel
118 var ufGroupModel = new CRM.UF.UFGroupModel(_.pick(formData, _.keys(CRM.UF.UFGroupModel.prototype.schema)));
119 ufGroupModel.setUFGroupModel(ufGroupModel.calculateContactEntityType(), profileSelectorView.options.ufEntities);
120 ufGroupModel.getRel('ufFieldCollection').reset(_.values(formData["api.UFField.get"].values));
121 options.onLoad(ufGroupModel);
122 }
123 });
124 }
125 });
126 CRM.designerApp.vent.on('ufSaved', this.onSave, this);
127 this.setDialog(designerDialog);
128 },
129 doCopy: function(e) {
130 e.preventDefault();
131 // This is largely the same as doEdit, but we ultimately pass in a deepCopy of the ufGroupModel.
132 var profileSelectorView = this;
133 var designerDialog = new CRM.Designer.DesignerDialog({
134 findCreateUfGroupModel: function(options) {
135 var ufId = profileSelectorView.getUfGroupId();
136 // Retrieve UF group and fields from the api
137 CRM.api('UFGroup', 'getsingle', {id: ufId, "api.UFField.get": 1}, {
138 success: function(formData) {
139 // Note: With chaining, API returns some extraneous keys that aren't part of UFGroupModel
140 var ufGroupModel = new CRM.UF.UFGroupModel(_.pick(formData, _.keys(CRM.UF.UFGroupModel.prototype.schema)));
141 ufGroupModel.setUFGroupModel(ufGroupModel.calculateContactEntityType(), profileSelectorView.options.ufEntities);
142 ufGroupModel.getRel('ufFieldCollection').reset(_.values(formData["api.UFField.get"].values));
143 options.onLoad(ufGroupModel.deepCopy());
144 }
145 });
146 }
147 });
148 CRM.designerApp.vent.on('ufSaved', this.onSave, this);
149 this.setDialog(designerDialog);
150 },
151 doCreate: function(e) {
152 e.preventDefault();
153 var profileSelectorView = this;
154 var designerDialog = new CRM.Designer.DesignerDialog({
155 findCreateUfGroupModel: function(options) {
156 // Initialize new UF group
157 var ufGroupModel = new CRM.UF.UFGroupModel();
158 ufGroupModel.getRel('ufEntityCollection').reset(profileSelectorView.options.ufEntities);
159 options.onLoad(ufGroupModel);
160 }
161 });
162 CRM.designerApp.vent.on('ufSaved', this.onSave, this);
163 this.setDialog(designerDialog);
164 },
165 onSave: function() {
166 CRM.designerApp.vent.off('ufSaved', this.onSave, this);
167 var ufGroupId = this.activeDialog.model.get('id');
168 var modelFromCollection = this.options.ufGroupCollection.get(ufGroupId);
169 if (modelFromCollection) {
170 // copy in changes to UFGroup
171 modelFromCollection.set(this.activeDialog.model.toStrictJSON());
172 } else {
173 // add in new UFGroup
174 modelFromCollection = new CRM.UF.UFGroupModel(this.activeDialog.model.toStrictJSON());
175 this.options.ufGroupCollection.add(modelFromCollection);
176 }
177 this.setUfGroupId(ufGroupId);
178 this.doPreview();
179 },
180 setDialog: function(view) {
181 if (this.activeDialog) {
182 this.activeDialog.close();
183 }
184 this.activeDialog = view;
185 view.render();
186 }
187 });
188 })(CRM.$, CRM._, CRM.BB);