erp_forms 2.0.6 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/app/controllers/erp_forms/erp_app/desktop/dynamic_forms/base_controller.rb +4 -37
  2. data/app/controllers/erp_forms/erp_app/desktop/dynamic_forms/data_controller.rb +348 -82
  3. data/app/controllers/erp_forms/erp_app/desktop/dynamic_forms/forms_controller.rb +110 -15
  4. data/app/controllers/erp_forms/erp_app/desktop/dynamic_forms/models_controller.rb +19 -3
  5. data/app/mailers/dynamic_form_mailer.rb +35 -0
  6. data/app/models/dynamic_datum.rb +97 -22
  7. data/app/models/dynamic_form.rb +172 -98
  8. data/app/models/dynamic_form_document.rb +4 -11
  9. data/app/models/dynamic_form_model.rb +46 -22
  10. data/app/models/ticket.rb +4 -0
  11. data/app/views/dynamic_form_mailer/widget_email_with_attachments.html.erb +3 -0
  12. data/app/views/dynamic_form_mailer/widget_email_with_attachments.text.erb +3 -0
  13. data/app/widgets/dynamic_forms/base.rb +101 -19
  14. data/app/widgets/dynamic_forms/javascript/dynamic_forms.js +40 -38
  15. data/app/widgets/dynamic_forms/views/error.html.erb +1 -0
  16. data/db/data_migrations/20110608185830_create_default_dynamic_models_and_forms.rb +2 -0
  17. data/db/data_migrations/20120824013449_create_ticket_form.rb +1 -0
  18. data/db/data_migrations/20121026013449_update_ticket_form.rb +64 -0
  19. data/db/data_migrations/{20120904191738_update_contact_form.rb → 20121026191738_update_contact_form.rb} +4 -0
  20. data/db/migrate/20110530193446_dynamic_forms.rb +12 -0
  21. data/db/migrate/20121007022323_upgrade_dynamic_forms_table.rb +31 -0
  22. data/lib/erp_forms.rb +4 -0
  23. data/lib/erp_forms/dynamic_form_field.rb +31 -28
  24. data/lib/erp_forms/dynamic_grid_column.rb +2 -2
  25. data/lib/erp_forms/engine.rb +5 -0
  26. data/lib/erp_forms/extensions/active_record/acts_as_commentable.rb +33 -0
  27. data/lib/erp_forms/extensions/active_record/acts_as_dynamic_form_model.rb +80 -0
  28. data/lib/erp_forms/extensions/active_record/has_dynamic_forms.rb +4 -4
  29. data/lib/erp_forms/extensions/extensions.rb +2 -0
  30. data/lib/erp_forms/extensions/railties/action_view.rb +2 -2
  31. data/lib/erp_forms/version.rb +2 -2
  32. data/public/javascripts/erp_app/desktop/applications/dynamic_forms/center_region.js +2 -1
  33. data/public/javascripts/erp_app/desktop/applications/dynamic_forms/dynamic_data_grid.js +264 -82
  34. data/public/javascripts/erp_app/desktop/applications/dynamic_forms/form_builder.js +1476 -58
  35. data/public/javascripts/erp_app/desktop/applications/dynamic_forms/module.js +24 -1
  36. data/public/javascripts/erp_app/desktop/applications/dynamic_forms/west_region.js +493 -210
  37. data/public/javascripts/erp_app/shared/dynamic_forms/dynamic_form_fields.js +82 -20
  38. data/public/javascripts/erp_app/shared/dynamic_forms/dynamic_forms_validation.js +23 -3
  39. data/spec/dummy/config/application.rb +6 -2
  40. data/spec/dummy/config/environments/spec.rb +3 -0
  41. data/spec/dummy/db/data_migrations/20110109173616_create_capability_scope_types.erp_tech_svcs.rb +15 -0
  42. data/spec/dummy/db/data_migrations/20110525001935_add_usd_currency.erp_base_erp_svcs.rb +12 -0
  43. data/spec/dummy/db/data_migrations/20110608185830_create_default_dynamic_models_and_forms.erp_forms.rb +33 -0
  44. data/spec/dummy/db/data_migrations/20110609150135_add_iso_codes.erp_base_erp_svcs.rb +19 -0
  45. data/spec/dummy/db/data_migrations/20110728201729_erp_app_setup.erp_app.rb +252 -0
  46. data/spec/dummy/db/data_migrations/20110728201733_update_preferences.erp_app.rb +53 -0
  47. data/spec/dummy/db/data_migrations/20110802200222_schedule_delete_expired_sessions_job.erp_tech_svcs.rb +16 -0
  48. data/spec/dummy/db/data_migrations/20110816161238_create_desktop_app_audit_log_viewer.erp_app.rb +21 -0
  49. data/spec/dummy/db/data_migrations/20110817160743_add_file_manager_application.erp_app.rb +32 -0
  50. data/spec/dummy/db/data_migrations/20110828190913_create_desktop_app_dynamic_forms.erp_forms.rb +19 -0
  51. data/spec/dummy/db/data_migrations/20110913145838_setup_compass_ae_instance.erp_base_erp_svcs.rb +12 -0
  52. data/spec/dummy/db/data_migrations/20111108183739_add_default_capabilities.erp_app.rb +23 -0
  53. data/spec/dummy/db/data_migrations/20111108183740_add_new_contact_widgets.erp_app.rb +42 -0
  54. data/spec/dummy/db/data_migrations/20111111144706_setup_audit_log_types.erp_tech_svcs.rb +22 -0
  55. data/spec/dummy/db/data_migrations/20120109173616_create_download_capability_type.erp_tech_svcs.rb +14 -0
  56. data/spec/dummy/db/data_migrations/20120229160222_add_userinfo_widget.erp_app.rb +29 -0
  57. data/spec/dummy/db/data_migrations/20120405193721_create_party_and_role_type_for_communication_events.erp_app.rb +11 -0
  58. data/spec/dummy/db/data_migrations/20120411180756_create_user_management_mobile_application.erp_app.rb +19 -0
  59. data/spec/dummy/db/data_migrations/20120418164215_create_configuration_management_desktop_application.erp_app.rb +23 -0
  60. data/spec/dummy/db/data_migrations/20120824013449_create_ticket_form.erp_forms.rb +67 -0
  61. data/spec/dummy/db/data_migrations/20121026013449_update_ticket_form.erp_forms.rb +65 -0
  62. data/spec/dummy/db/data_migrations/20121026191738_update_contact_form.erp_forms.rb +27 -0
  63. data/spec/dummy/db/data_migrations/20121116155018_create_group_relationship_and_role_types.erp_tech_svcs.rb +20 -0
  64. data/spec/dummy/db/data_migrations/20121130201859_upgrade_remove_system_mgmt_app.erp_app.rb +16 -0
  65. data/spec/dummy/db/data_migrations/20121130212146_note_capabilities.erp_tech_svcs.rb +24 -0
  66. data/spec/dummy/db/data_migrations/20121218175028_create_security_management_desktop_application.erp_app.rb +23 -0
  67. data/spec/dummy/db/migrate/20121213234847_base_erp_services.erp_base_erp_svcs.rb +461 -0
  68. data/spec/dummy/db/migrate/20121213234848_base_tech_services.erp_tech_svcs.rb +255 -0
  69. data/spec/dummy/db/migrate/20121213234849_create_has_attribute_tables.erp_tech_svcs.rb +39 -0
  70. data/spec/dummy/db/migrate/20121213234850_base_app_framework.erp_app.rb +276 -0
  71. data/spec/dummy/db/migrate/20121213234851_dynamic_forms.erp_forms.rb +95 -0
  72. data/spec/dummy/db/migrate/20121213234852_create_tickets.erp_forms.rb +19 -0
  73. data/spec/dummy/db/migrate/20121213234853_upgrade_dynamic_forms_table.erp_forms.rb +32 -0
  74. data/spec/dummy/db/migrate/20130107181041_create_groups.erp_tech_svcs.rb +19 -0
  75. data/spec/dummy/db/migrate/20130107181042_upgrade_security.erp_tech_svcs.rb +54 -0
  76. data/spec/dummy/db/migrate/20130107181043_upgrade_security2.erp_tech_svcs.rb +270 -0
  77. data/spec/dummy/db/schema.rb +879 -0
  78. data/spec/dummy/db/spec.sqlite3 +0 -0
  79. data/spec/dummy/log/spec.log +13580 -0
  80. data/spec/models/dynamic_form_model_spec.rb +1 -1
  81. data/spec/spec_helper.rb +11 -3
  82. metadata +136 -14
@@ -1,6 +1,169 @@
1
+ Ext.define('DynamicForm', {
2
+ extend: 'Ext.data.Model',
3
+ fields: [
4
+ {name: 'id', type: 'number'},
5
+ {name: 'description', type: 'string'},
6
+ {name: 'model_name', type: 'string'},
7
+ {name: 'definition', type: 'string'},
8
+ {name: 'internal_identifier', type: 'string'},
9
+ {name: 'widget_action', type: 'string'},
10
+ {name: 'widget_email_recipients', type: 'string'},
11
+ {name: 'focus_first_field', type: 'boolean'},
12
+ {name: 'submit_empty_text', type: 'boolean'},
13
+ {name: 'msg_target', type: 'string'},
14
+ {name: 'submit_button_label', type: 'string'},
15
+ {name: 'cancel_button_label', type: 'string'},
16
+ {name: 'comment', type: 'string'},
17
+ {name: 'created_at', type: 'string'},
18
+ {name: 'updated_at', type: 'string'},
19
+ {name: 'created_by', type: 'string'},
20
+ {name: 'updated_by', type: 'string'}
21
+ ]
22
+ });
23
+
24
+ // get a single form and fire openFormTab
25
+ Ext.create('Ext.data.Store', {
26
+ model: 'DynamicForm',
27
+ storeId: 'dynamicFormStore',
28
+ timeout : 90000,
29
+ proxy: {
30
+ type: 'ajax',
31
+ url: '/erp_forms/erp_app/desktop/dynamic_forms/forms/get_record',
32
+ method: 'POST'
33
+ },
34
+ listeners:{
35
+ 'load':function(store, records){
36
+ var record = store.getAt(0);
37
+ Ext.getCmp('dynamic_forms_westregion').openFormTab(record);
38
+ }
39
+ },
40
+ autoLoad: false
41
+ });
42
+
43
+ Ext.define('FieldType', {
44
+ extend: 'Ext.data.Model',
45
+ fields: [
46
+ {name: 'text', type: 'string'},
47
+ {name: 'field_xtype', type: 'string'},
48
+ {name: 'fieldLabel', type: 'string'},
49
+ {name: 'leaf', type: 'boolean'}
50
+ ]
51
+ });
52
+
53
+ var fieldStore = Ext.create('Ext.data.TreeStore', {
54
+ autoLoad:false,
55
+ model: 'FieldType',
56
+ proxy: {
57
+ type: 'memory'
58
+ },
59
+ folderSort: true
60
+ });
61
+
62
+ var fieldData = {
63
+ text:"Field Types",
64
+ expanded: true,
65
+ expandable: false,
66
+ children: [
67
+ {
68
+ text: 'Checkbox',
69
+ field_xtype: 'checkbox',
70
+ leaf: true
71
+ },
72
+ {
73
+ text: 'Combo Box',
74
+ field_xtype: 'combobox',
75
+ leaf: true
76
+ },
77
+ {
78
+ text: 'Date Field',
79
+ field_xtype: 'datefield',
80
+ leaf: true
81
+ },
82
+ {
83
+ text: 'Display Field',
84
+ field_xtype: 'displayfield',
85
+ leaf: true
86
+ },
87
+ {
88
+ text: 'Email Field',
89
+ field_xtype: 'email',
90
+ leaf: true
91
+ },
92
+ {
93
+ text: 'File Upload',
94
+ field_xtype: 'filefield',
95
+ leaf: true,
96
+ vtype: 'file'
97
+ },
98
+ {
99
+ text: 'Hidden Field',
100
+ field_xtype: 'hiddenfield',
101
+ leaf: true
102
+ },
103
+ {
104
+ text: 'Number Field',
105
+ field_xtype: 'numberfield',
106
+ leaf: true
107
+ },
108
+ {
109
+ text: 'Password Field',
110
+ field_xtype: 'password',
111
+ leaf: true
112
+ },
113
+ {
114
+ text: 'Related Combo Box',
115
+ field_xtype: 'related_combobox',
116
+ leaf: true,
117
+ qtip: 'Combo Box with dynamic store. Use with small data sets. Use limited to secure pages.'
118
+ },
119
+ {
120
+ text: 'Related Search Box',
121
+ field_xtype: 'related_searchbox',
122
+ leaf: true,
123
+ qtip: 'Combo Box with dynamic store. Use with large data sets. Use limited to secure pages.'
124
+ },
125
+ {
126
+ text: 'Text Field',
127
+ field_xtype: 'textfield',
128
+ leaf: true
129
+ },
130
+ {
131
+ text: 'Text Area',
132
+ field_xtype: 'textarea',
133
+ leaf: true
134
+ },
135
+ {
136
+ text: 'Time Field',
137
+ field_xtype: 'timefield',
138
+ leaf: true
139
+ },
140
+ {
141
+ text: 'Yes / No',
142
+ field_xtype: 'yesno',
143
+ leaf: true
144
+ }
145
+ ]};
146
+
147
+ var fieldTreeRootNode = fieldStore.setRootNode(fieldData);
148
+
1
149
  Ext.define("Compass.ErpApp.Desktop.Applications.DynamicForms.FormBuilder",{
2
- extend:"Ext.window.Window",
150
+ extend:"Ext.panel.Panel",
3
151
  alias:'widget.dynamic_forms_FormBuilder',
152
+
153
+ height: 458,
154
+ width: 811,
155
+ layout: {
156
+ type: 'border'
157
+ },
158
+
159
+ setWindowStatus : function(status){
160
+ this.findParentByType('statuswindow').setStatus(status);
161
+ },
162
+
163
+ clearWindowStatus : function(){
164
+ this.findParentByType('statuswindow').clearStatus();
165
+ },
166
+
4
167
  initComponent : function() {
5
168
 
6
169
  this.addEvents(
@@ -23,71 +186,1326 @@ Ext.define("Compass.ErpApp.Desktop.Applications.DynamicForms.FormBuilder",{
23
186
  this.callParent(arguments);
24
187
  },
25
188
 
26
- constructor : function(config) {
27
- config = Ext.apply({
28
- layout:'fit',
29
- title:'Form Builder',
30
- autoHeight:true,
31
- iconCls:'icon-document',
32
- width:400,
33
- height:300,
34
- buttonAlign:'center',
35
- plain: true,
36
- items: new Ext.form.FormPanel({
37
- timeout: 130000,
38
- // baseParams:config['baseParams'],
39
- autoHeight:true,
40
- labelWidth:110,
41
- frame:false,
42
- layout:'fit',
43
- // url:config['url'],
44
- defaults: {
45
- width: 225
46
- },
47
- items: [{
48
- xtype: 'textarea',
49
- hideLabel:true,
50
- name:'comment'
51
- }]
52
- }),
53
- buttons: [{
54
- text:'Submit',
189
+ getFieldOptionsForField : function(field){
190
+ var xtype = field.xtype;
191
+ var field_xtype = field.field_xtype; // used to determine if it is a hidden field
192
+
193
+ var updateFieldType = {
194
+ fieldLabel: 'Type',
195
+ name: 'updateFieldType',
196
+ xtype: 'displayfield',
197
+ allowBlank: false
198
+ };
199
+
200
+ var updateName = {
201
+ fieldLabel: 'Name',
202
+ name: 'updateName',
203
+ xtype: 'textfield',
204
+ allowBlank: false
205
+ };
206
+
207
+ if (xtype == 'filefield') updateName.readOnly = true;
208
+
209
+ //console.log(xtype);
210
+ var base_top = [
211
+ updateFieldType,
212
+ updateName,
213
+ {
214
+ fieldLabel: 'Label',
215
+ name: 'updateLabel',
216
+ xtype: 'textfield',
217
+ allowBlank: false
218
+ }
219
+ ];
220
+
221
+ var common = [
222
+ {
223
+ fieldLabel: 'Label Alignment',
224
+ name: 'updateLabelAlign',
225
+ xtype: 'combobox',
226
+ allowBlank: false,
227
+ editable: true,
228
+ forceSelection:true,
229
+ value: 'left',
230
+ store: [
231
+ ['left', 'Left of Field'],
232
+ ['top', 'Above Field']
233
+ ]
234
+ },
235
+ {
236
+ fieldLabel: 'Label Width',
237
+ name: 'updateLabelWidth',
238
+ xtype: 'numberfield'
239
+ },
240
+ {
241
+ fieldLabel: 'Width',
242
+ name: 'updateWidth',
243
+ xtype: 'numberfield'
244
+ },
245
+ {
246
+ fieldLabel: 'Height',
247
+ name: 'updateHeight',
248
+ xtype: 'numberfield'
249
+ },
250
+ {
251
+ fieldLabel: 'Empty Text',
252
+ name: 'updateEmptyText',
253
+ xtype: 'textfield'
254
+ },
255
+ {
256
+ fieldLabel: 'Help Text',
257
+ name: 'updateHelpQtip',
258
+ xtype: 'textfield',
259
+ plugins: [new helpQtip("Add help text via a mouseover icon to the right of the field.")]
260
+ },
261
+ {
262
+ fieldLabel: 'Allow Blank',
263
+ name: 'updateAllowBlank',
264
+ xtype: 'checkbox'
265
+ }
266
+ ];
267
+
268
+ var base_bottom = [
269
+ {
270
+ fieldLabel: 'Default Value',
271
+ name: 'updateValue',
272
+ xtype: 'textfield'
273
+ },
274
+ {
275
+ fieldLabel: 'Read Only',
276
+ name: 'updateReadOnly',
277
+ xtype: 'checkbox'
278
+ },
279
+ {
280
+ fieldLabel: 'Display In Grid',
281
+ name: 'updateDisplayInGrid',
282
+ xtype: 'checkbox'
283
+ },
284
+ {
285
+ fieldLabel: 'Searchable',
286
+ name: 'updateSearchable',
287
+ xtype: 'checkbox',
288
+ plugins: [new helpQtip("Make this field searchable. Requires Solr via Compass AE's erp_search engine.")]
289
+ }
290
+ ];
291
+
292
+ var filefield = [
293
+ {
294
+ fieldLabel: 'Button Text',
295
+ name: 'updateButtonText',
296
+ xtype: 'textfield'
297
+ }
298
+ ];
299
+
300
+ var common_combobox = [
301
+ {
302
+ fieldLabel: 'Editable',
303
+ name: 'updateEditable',
304
+ xtype: 'checkbox'
305
+ },
306
+ {
307
+ fieldLabel: 'Force Selection',
308
+ name: 'updateForceSelection',
309
+ xtype: 'checkbox'
310
+ },
311
+ {
312
+ fieldLabel: 'Multi Select',
313
+ name: 'updateMultiSelect',
314
+ xtype: 'checkbox'
315
+ }
316
+ ];
317
+
318
+ var combobox = [
319
+ {
320
+ fieldLabel: 'Options',
321
+ name: 'updateOptions',
322
+ xtype: 'textarea',
323
+ labelAlign: 'top',
324
+ labelWidth: 50,
325
+ allowBlank: false,
326
+ width: 235,
327
+ height: 175,
328
+ plugins: [new helpQtip('Add options with a comma separated list. Example: value,Description,option2,Option 2')]
329
+ }
330
+ ];
331
+
332
+ var related_common = [
333
+ {
334
+ fieldLabel: 'Related Model',
335
+ name: 'updateRelatedModel',
336
+ xtype: 'textfield',
337
+ allowBlank: false,
338
+ vtype: 'alphanum',
339
+ plugins: [new helpQtip('Needs to be a valid camel case model class name.')]
340
+ }
341
+ ];
342
+
343
+ var related_combobox = [
344
+ {
345
+ fieldLabel: 'Display Field',
346
+ name: 'updateDisplayField',
347
+ xtype: 'textfield',
348
+ allowBlank: false,
349
+ plugins: [new helpQtip('Needs to be a valid column name on the related model.')]
350
+ }
351
+ ];
352
+
353
+ var related_searchbox = [
354
+ {
355
+ fieldLabel: 'Search Fields',
356
+ name: 'updateSearchFields',
357
+ xtype: 'textfield',
358
+ allowBlank: false,
359
+ plugins: [new helpQtip("Comma separated list of valid columns on the related model. Fields will be searched using OR. Example: 'first_name, last_name'")]
360
+ },
361
+ {
362
+ fieldLabel: 'Display Fields',
363
+ name: 'updateDisplayFields',
364
+ xtype: 'textfield',
365
+ allowBlank: false,
366
+ plugins: [new helpQtip("Comma separated list of valid columns on the related model. Fields are displayed using Display Template. Example: 'first_name, last_name'")]
367
+ },
368
+ {
369
+ fieldLabel: 'Display Template',
370
+ name: 'updateDisplayTemplate',
371
+ xtype: 'textfield',
372
+ allowBlank: false,
373
+ plugins: [new helpQtip("Multiple fields can be displayed as option value. Fields must be included in the list of Display Fields. Example: '{last_name}, {first_name}'")]
374
+ },
375
+ {
376
+ fieldLabel: 'Page Size',
377
+ name: 'updatePageSize',
378
+ xtype: 'numberfield',
379
+ allowBlank: false,
380
+ value: 10,
381
+ plugins: [new helpQtip('Number of results per page.')]
382
+ }
383
+ // {
384
+ // fieldLabel: 'Type Ahead',
385
+ // name: 'updateTypeAhead',
386
+ // xtype: 'checkbox',
387
+ // value: false,
388
+ // plugins: [new helpQtip('Populate and autoselect the remainder of the text being typed after 250 milliseconds if it matches a known value.')]
389
+ // }
390
+ ];
391
+
392
+ var minMaxLength = [
393
+ {
394
+ fieldLabel: 'Min Length',
395
+ name: 'updateMinLength',
396
+ xtype: 'numberfield'
397
+ },
398
+ {
399
+ fieldLabel: 'Max Length',
400
+ name: 'updateMaxLength',
401
+ xtype: 'numberfield'
402
+ }
403
+ ];
404
+
405
+ var numberMinMaxValue = [
406
+ {
407
+ fieldLabel: 'Min Value',
408
+ name: 'updateMinValue',
409
+ xtype: 'numberfield'
410
+ },
411
+ {
412
+ fieldLabel: 'Max Value',
413
+ name: 'updateMaxValue',
414
+ xtype: 'numberfield'
415
+ }
416
+ ];
417
+
418
+ var dateMinMaxValue = [
419
+ {
420
+ fieldLabel: 'Min Value',
421
+ name: 'updateMinValue',
422
+ xtype: 'datefield'
423
+ },
424
+ {
425
+ fieldLabel: 'Max Value',
426
+ name: 'updateMaxValue',
427
+ xtype: 'datefield'
428
+ }
429
+ ];
430
+
431
+ var timeMinMaxValue = [
432
+ {
433
+ fieldLabel: 'Min Value',
434
+ name: 'updateMinValue',
435
+ xtype: 'timefield'
436
+ },
437
+ {
438
+ fieldLabel: 'Max Value',
439
+ name: 'updateMaxValue',
440
+ xtype: 'timefield'
441
+ }
442
+ ];
443
+
444
+ var validation = [
445
+ {
446
+ fieldLabel: 'Validation Type',
447
+ name: 'updateValidationType',
448
+ xtype: 'combobox',
449
+ queryMode: 'local',
450
+ store:[
451
+ ['none','None'],
452
+ ['regex','Regular Expression'],
453
+ ['function','Custom Function'],
454
+ ['vtype','VType']
455
+ ],
456
+ value: 'none',
457
+ forceSelection: true,
458
+ allowBlank: false,
55
459
  listeners:{
56
- 'click':function(button){
57
- var win = button.findParentByType('dynamic_forms_form_builer');
58
- var formPanel = win.findByType('form')[0];
59
- formPanel.getForm().submit({
60
- method:'POST',
61
- waitMsg:'Publishing...',
62
- success:function(form, action){
63
- var response = Ext.util.JSON.decode(action.response.responseText);
64
- win.fireEvent('publish_success', win, response);
65
- win.close();
66
- },
67
- failure:function(form, action){
68
- var response = Ext.util.JSON.decode(action.response.responseText);
69
- win.fireEvent('publish_failure', win, response);
70
- win.close();
71
- }
72
- });
460
+ change: function(field, newValue, oldValue, eOpts){
461
+ var field_props = this.findParentByType('form');
462
+ var updateValidationRegex = field_props.getForm().findField('updateValidationRegex');
463
+ var updateValidationRegexText = field_props.getForm().findField('updateValidationRegexText');
464
+ var updateValidationFunction = field_props.getForm().findField('updateValidationFunction');
465
+ var updateValidationVType = field_props.getForm().findField('updateValidationVType');
466
+ if (newValue == 'regex'){
467
+ updateValidationRegex.show();
468
+ updateValidationRegex.enable();
469
+ updateValidationRegexText.show();
470
+ updateValidationRegexText.enable();
471
+ updateValidationFunction.hide();
472
+ updateValidationFunction.disable();
473
+ updateValidationVType.hide();
474
+ updateValidationVType.disable();
475
+ }else if (newValue == 'function'){
476
+ updateValidationFunction.show();
477
+ updateValidationFunction.enable();
478
+ updateValidationRegex.hide();
479
+ updateValidationRegex.disable();
480
+ updateValidationRegexText.hide();
481
+ updateValidationRegexText.disable();
482
+ updateValidationVType.hide();
483
+ updateValidationVType.disable();
484
+ }else if (newValue == 'vtype'){
485
+ updateValidationVType.show();
486
+ updateValidationVType.enable();
487
+ updateValidationRegex.hide();
488
+ updateValidationRegex.disable();
489
+ updateValidationRegexText.hide();
490
+ updateValidationRegexText.disable();
491
+ updateValidationFunction.hide();
492
+ updateValidationFunction.disable();
493
+ }else{
494
+ updateValidationFunction.hide();
495
+ updateValidationFunction.disable();
496
+ updateValidationRegex.hide();
497
+ updateValidationRegex.disable();
498
+ updateValidationRegexText.disable();
499
+ updateValidationRegexText.hide();
500
+ updateValidationVType.hide();
501
+ updateValidationVType.disable();
502
+ }
73
503
  }
74
504
  }
75
505
  },
76
506
  {
77
- text: 'Cancel',
78
- listeners:{
79
- 'click':function(button){
80
- var win = button.findParentByType('dynamic_forms_form_builer');
81
- var form = win.findByType('form')[0];
82
- form.getForm().reset();
83
- win.close();
507
+ fieldLabel: 'Regex',
508
+ name: 'updateValidationRegex',
509
+ xtype: 'textfield',
510
+ allowBlank: true,
511
+ hidden: true,
512
+ disabled: true
513
+ },
514
+ {
515
+ fieldLabel: 'Regex Text',
516
+ name: 'updateValidationRegexText',
517
+ xtype: 'textfield',
518
+ allowBlank: true,
519
+ hidden: true,
520
+ disabled: true
521
+ },
522
+ {
523
+ fieldLabel: 'Function',
524
+ name: 'updateValidationFunction',
525
+ plugins: [new helpQtip('Call a pre-existing JavaScript function for custom validation. Field value must be passed in using variable v. No semicolon required. Example: customFunction(v)')],
526
+ xtype: 'textfield',
527
+ allowBlank: true,
528
+ hidden: true,
529
+ disabled: true,
530
+ emptyText: 'customFunction(v)'
531
+ },
532
+ {
533
+ fieldLabel: 'VType',
534
+ name: 'updateValidationVType',
535
+ xtype: 'combobox',
536
+ queryMode: 'local',
537
+ store:[
538
+ ['alpha','Alpha'],
539
+ ['alphanum','Alphanumeric'],
540
+ ['email','Email'],
541
+ ['IPAddress','IP Address'],
542
+ ['url','URL']
543
+ ],
544
+ plugins: [new helpQtip('Use a built-in or custom ExtJS VType.')],
545
+ editable: true,
546
+ forceSelection: false,
547
+ hidden: true,
548
+ disabled: true,
549
+ allowBlank: true
550
+ }
551
+ ];
552
+
553
+ var hideMode = [
554
+ {
555
+ fieldLabel: 'Hide Mode',
556
+ name: 'updateHideMode',
557
+ xtype: 'combobox',
558
+ queryMode: 'local',
559
+ store:[
560
+ ['display','Display'],
561
+ ['visibility','Visibility'],
562
+ ['offsets','Offsets']
563
+ ],
564
+ value: 'display',
565
+ plugins: [new helpQtip("A String which specifies how this Component's encapsulating DOM element will be hidden. Values may be:<br /> 'display' : The Component will be hidden using the display: none style.<br /> 'visibility' : The Component will be hidden using the visibility: hidden style.<br /> 'offsets' : The Component will be hidden by absolutely positioning it out of the visible area of the document. This is useful when a hidden Component must maintain measurable dimensions. Hiding using display results in a Component having zero dimensions.<br /> Defaults to: 'display'")],
566
+ editable: false,
567
+ forceSelection: true,
568
+ allowBlank: true
569
+ }
570
+ ];
571
+
572
+ var hideTrigger = [
573
+ {
574
+ fieldLabel: 'Hide Trigger',
575
+ name: 'updateHideTrigger',
576
+ xtype: 'checkbox',
577
+ plugins: [new helpQtip('Hide the trigger element and display only the base text field.')]
578
+ }
579
+ ];
580
+
581
+ var result = [];
582
+ if (Ext.isEmpty(field_xtype)){
583
+ result = result.concat(base_top);
584
+ result = result.concat(common);
585
+ result = result.concat(base_bottom);
586
+ }else if (field_xtype == 'hiddenfield'){
587
+ result = result.concat(base_top);
588
+ result = result.concat(base_bottom);
589
+ result = result.concat(hideMode);
590
+ return result;
591
+ }
592
+ switch(xtype){
593
+ case 'related_combobox':
594
+ result = result.concat(common_combobox);
595
+ result = result.concat(hideTrigger);
596
+ result = result.concat(related_common);
597
+ result = result.concat(related_combobox);
598
+ break;
599
+ case 'related_searchbox':
600
+ result = result.concat(common_combobox);
601
+ result = result.concat(related_common);
602
+ result = result.concat(related_searchbox);
603
+ break;
604
+ case 'combo':
605
+ result = result.concat(common_combobox);
606
+ result = result.concat(hideTrigger);
607
+ result = result.concat(combobox);
608
+ break;
609
+ case 'combobox':
610
+ result = result.concat(common_combobox);
611
+ result = result.concat(hideTrigger);
612
+ result = result.concat(combobox);
613
+ break;
614
+ case 'datefield':
615
+ result = result.concat(hideTrigger);
616
+ result = result.concat(dateMinMaxValue);
617
+ result = result.concat(validation);
618
+ break;
619
+ case 'email':
620
+ result = result.concat(minMaxLength);
621
+ result = result.concat(validation);
622
+ break;
623
+ case 'filefield':
624
+ result = result.concat(filefield);
625
+ result = result.concat(hideTrigger);
626
+ result = result.concat(validation);
627
+ break;
628
+ case 'numberfield':
629
+ result = result.concat(hideTrigger);
630
+ result = result.concat(minMaxLength);
631
+ result = result.concat(numberMinMaxValue);
632
+ result = result.concat(validation);
633
+ break;
634
+ case 'password':
635
+ result = result.concat(minMaxLength);
636
+ result = result.concat(validation);
637
+ break;
638
+ case 'textfield':
639
+ result = result.concat(minMaxLength);
640
+ result = result.concat(validation);
641
+ break;
642
+ case 'textarea':
643
+ result = result.concat(minMaxLength);
644
+ result = result.concat(validation);
645
+ break;
646
+ case 'timefield':
647
+ result = result.concat(hideTrigger);
648
+ result = result.concat(timeMinMaxValue);
649
+ result = result.concat(validation);
650
+ break;
651
+ default:
652
+ }
653
+
654
+ return result;
655
+ },
656
+
657
+ validateFieldNameUnique : function(formPanel, fieldName){
658
+ return ((this.getIndexOfFieldByName(formPanel, fieldName) < 0) ? true : false);
659
+ },
660
+
661
+ getIndexOfFieldByName : function(formPanel, fieldName){
662
+ for (var i = 0; i < formPanel.form_definition.length; i++) {
663
+ if (formPanel.form_definition[i].name == fieldName){
664
+ return i;
665
+ }
666
+ }
667
+ return -1;
668
+ },
669
+
670
+ moveField : function(formPanel, direction){
671
+ if (Ext.isEmpty(formPanel.selected_field)){
672
+ Ext.Msg.alert('Error', 'Please select a field to move.');
673
+ }else{
674
+ var i = 0;
675
+ var field_in_definition = null;
676
+ // find selected field in definition to remove it
677
+ Ext.each(formPanel.form_definition, function(field){
678
+ if (field.name == formPanel.selected_field.name){
679
+ idx = i;
680
+ field_in_definition = field;
681
+ }
682
+ i++;
683
+ });
684
+ if (direction == 'up' && idx === 0){
685
+ Ext.Msg.alert('Error', 'Cannot move. Field is already at top.');
686
+ }else if (direction == 'down' && idx == (formPanel.form_definition.length-1)){
687
+ Ext.Msg.alert('Error', 'Cannot move. Field is already at bottom.');
688
+ }else{
689
+ var new_index = (direction == 'up' ? idx-1 : idx+1);
690
+ formPanel.form_definition.splice(idx, 1); // remove field from definition
691
+ formPanel.form_definition.splice(new_index, 0, field_in_definition); // add field to definition
692
+ formPanel.findParentByType('dynamic_forms_FormBuilder').reloadForm(formPanel); // redraw form from definition
693
+ formPanel.getForm().findField(formPanel.selected_field.name).getEl().dom.click(); // highlight selected field
694
+ }
695
+ }
696
+ },
697
+
698
+ emailRegex : function(){
699
+ return ErpTechSvcs.Config.email_regex;
700
+ },
701
+
702
+ addFieldToForm : function(formPanel, fieldDefinition){
703
+ if (fieldDefinition) formPanel.form_definition.push(fieldDefinition);
704
+ this.reloadForm(formPanel);
705
+ // highlight newly added field
706
+ if (fieldDefinition) formPanel.getForm().findField(fieldDefinition.name).getEl().dom.click();
707
+ },
708
+
709
+ addValidationToField : function(field){
710
+ if(!Ext.isEmpty(field.validation_regex)){
711
+ field.regex = initRegex(field.validation_regex);
712
+ }else if(!Ext.isEmpty(field.validator_function)){
713
+ field.validator = function(v){ return eval(field.validator_function); };
714
+ }
715
+ return field;
716
+ },
717
+
718
+ addHelpQtipToField : function(field){
719
+ if(!Ext.isEmpty(field.help_qtip)){
720
+ field.plugins = [new helpQtip(field.help_qtip)];
721
+ }
722
+ return field;
723
+ },
724
+
725
+ convertHiddenFieldToDisplayFieldForUi : function(field){
726
+ if (field.xtype == 'hiddenfield'){
727
+ field.xtype = 'displayfield';
728
+ field.field_xtype = 'hiddenfield';
729
+ }
730
+ return field;
731
+ },
732
+
733
+ // alterFileUploadField : function(field){
734
+ // if (field.xtype == 'filefield'){
735
+ // console.log('filefield');
736
+ // field.listeners = {
737
+ // 'render': function(field){
738
+ // console.log('listener');
739
+ // field.inputEl.dom.size = 20;
740
+ // }
741
+ // };
742
+ // }
743
+ // return field;
744
+ // },
745
+
746
+ reloadForm : function(formPanel){
747
+ var self = this;
748
+ formPanel.removeAll();
749
+ var form_definition_copy = Ext.clone(formPanel.form_definition); // make independent copy
750
+ Ext.each(form_definition_copy, function(field){
751
+ field = self.convertHiddenFieldToDisplayFieldForUi(field);
752
+ field = self.addValidationToField(field);
753
+ field = self.addHelpQtipToField(field);
754
+ //field = self.alterFileUploadField(field);
755
+ field = self.addHighlightListenerForSelectedField(field);
756
+ });
757
+ formPanel.add(form_definition_copy);
758
+ },
759
+
760
+ addHighlightListenerForSelectedField : function(field){
761
+ field.listeners = {
762
+ render: function(item){
763
+ var el = item.getEl();
764
+ el.addListener('click', function(e, t, eOpts){
765
+ var formPanel = item.findParentByType('form');
766
+ var highlight_border = '1px solid green';
767
+ //console.log(el.dom.style.border);
768
+ if (el.dom.style.border != highlight_border){
769
+ Ext.each(formPanel.items.items, function(i){
770
+ //console.log(i.getEl().getStyle('border'));
771
+ if (item != i && i.getEl().dom.style.border == highlight_border){
772
+ var label = i.getEl().query('label').first();
773
+ label.style.width = (parseInt(label.style.width, 10) + 2) + 'px';
774
+ i.getEl().setStyle('border', 'none');
775
+ }
776
+ });
777
+ var label = el.query('label').first();
778
+ label.style.width = (parseInt(label.style.width, 10) - 2) + 'px';
779
+ el.setStyle('border', highlight_border);
780
+ el.highlight();
781
+
782
+ // set field properties as active tab
783
+ var formBuilder = formPanel.findParentByType('dynamic_forms_FormBuilder');
784
+ var east_tabs = formBuilder.query('#east_tabs').first();
785
+ east_tabs.setActiveTab('field_props');
786
+
787
+ formPanel.selected_field = item;
788
+
789
+ // populate field properties
790
+ var prop_formPanel = east_tabs.query('#field_props').first();
791
+ var prop_form = prop_formPanel.getForm();
792
+ prop_formPanel.removeAll();
793
+ prop_formPanel.add(formBuilder.getFieldOptionsForField(item));
794
+
795
+ // common
796
+ try { prop_form.findField('updateFieldType').setValue(item.xtype); } catch(e) {}
797
+ try { prop_form.findField('updateName').setValue(item.name); } catch(e) {}
798
+ try { prop_form.findField('updateLabel').setValue(item.fieldLabel); } catch(e) {}
799
+ try { prop_form.findField('updateLabelAlign').setValue(item.labelAlign); } catch(e) {}
800
+ try { var updateValue = ((item.xtype == 'related_combobox') ? item.default_value : item.value);
801
+ prop_form.findField('updateValue').setValue(updateValue); } catch(e) {}
802
+ try { var updateValue = ((item.xtype == 'related_searchbox') ? item.default_value : item.value);
803
+ prop_form.findField('updateValue').setValue(updateValue); } catch(e) {}
804
+ try { prop_form.findField('updateEmptyText').setValue(item.emptyText); } catch(e) {}
805
+ try { prop_form.findField('updateHelpQtip').setValue(item.help_qtip); } catch(e) {}
806
+ try { prop_form.findField('updateAllowBlank').setValue(item.allowBlank); } catch(e) {}
807
+ try { prop_form.findField('updateDisplayInGrid').setValue(item.display_in_grid); } catch(e) {}
808
+ try { prop_form.findField('updateSearchable').setValue(item.searchable); } catch(e) {}
809
+ try { prop_form.findField('updateReadOnly').setValue(item.readOnly); } catch(e) {}
810
+ try { prop_form.findField('updateWidth').setValue(item.width); } catch(e) {}
811
+ try { prop_form.findField('updateHeight').setValue(item.height); } catch(e) {}
812
+ try { prop_form.findField('updateLabelWidth').setValue(item.labelWidth); } catch(e) {}
813
+ try { prop_form.findField('updateHideTrigger').setValue(item.hideTrigger); } catch(e) {}
814
+ try { prop_form.findField('updateHideMode').setValue(item.hideMode); } catch(e) {}
815
+
816
+ if (item.xtype == 'datefield' || item.xtype == 'timefield'){
817
+ prop_form.findField('updateMinValue').setValue(item.minValue);
818
+ prop_form.findField('updateMaxValue').setValue(item.maxValue);
819
+ }
820
+
821
+ if(!Ext.isEmpty(item.regex)){
822
+ prop_form.findField('updateValidationType').setValue('regex');
823
+ prop_form.findField('updateValidationRegex').setValue(item.regex);
824
+ if(!Ext.isEmpty(item.regexText)) prop_form.findField('updateValidationRegexText').setValue(item.regexText);
825
+ }else if(!Ext.isEmpty(item.validator_function)){
826
+ prop_form.findField('updateValidationType').setValue('function');
827
+ prop_form.findField('updateValidationFunction').setValue(item.validator_function);
828
+ }else if(!Ext.isEmpty(item.vtype)){
829
+ prop_form.findField('updateValidationType').setValue('vtype');
830
+ prop_form.findField('updateValidationVType').setValue(item.vtype);
831
+ }
832
+
833
+ if (item.xtype == 'numberfield'){
834
+ if (item.minValue != Number.NEGATIVE_INFINITY){
835
+ prop_form.findField('updateMinValue').setValue(item.minValue);
836
+ }
837
+ if (item.maxValue != Number.MAX_VALUE){
838
+ prop_form.findField('updateMaxValue').setValue(item.maxValue);
839
+ }
840
+ }
841
+
842
+ if (item.xtype == 'textfield' || item.xtype == 'textarea' || item.xtype == 'numberfield'){
843
+ prop_form.findField('updateMinLength').setValue(item.minLength);
844
+ if (item.maxLength != Number.MAX_VALUE){
845
+ prop_form.findField('updateMaxLength').setValue(item.maxLength);
846
+ }
847
+ }
848
+
849
+ if (item.xtype == 'related_combobox' || item.xtype == 'related_searchbox'){
850
+ prop_form.findField('updateEditable').setValue(item.editable);
851
+ prop_form.findField('updateForceSelection').setValue(item.forceSelection);
852
+ prop_form.findField('updateMultiSelect').setValue(item.multiSelect);
853
+ try { prop_form.findField('updateRelatedModel').setValue(item.extraParams.model); } catch(e) {}
854
+ if (item.xtype == 'related_combobox'){
855
+ prop_form.findField('updateDisplayField').setValue(item.displayField);
856
+ }else{
857
+ prop_form.findField('updateSearchFields').setValue(item.search_fields);
858
+ prop_form.findField('updateDisplayFields').setValue(item.display_fields);
859
+ prop_form.findField('updateDisplayTemplate').setValue(item.display_template);
860
+ //prop_form.findField('updateTypeAhead').setValue(item.typeAhead);
861
+ prop_form.findField('updatePageSize').setValue(item.pageSize);
862
+ }
863
+ }else if (item.xtype == 'combobox' || item.xtype == 'combo'){
864
+ var options = Ext.encode(item.getStore().proxy.reader.rawData).replace(/\"/g,'').replace(/\[/g,'').replace(/\]/g,'');
865
+ prop_form.findField('updateOptions').setValue(options == 'null' ? '' : options);
866
+ prop_form.findField('updateEditable').setValue(item.editable);
867
+ prop_form.findField('updateForceSelection').setValue(item.forceSelection);
868
+ prop_form.findField('updateMultiSelect').setValue(item.multiSelect);
869
+ }
870
+
871
+ if (item.xtype == 'filefield'){
872
+ prop_form.findField('updateButtonText').setValue(item.buttonText);
873
+ }
874
+
84
875
  }
876
+ });
877
+ }
878
+ };
879
+
880
+ return field;
881
+ },
882
+
883
+ constructor : function(config) {
884
+ if (Ext.isEmpty(config.form_definition)) config.form_definition = [];
885
+
886
+ config = Ext.apply({
887
+ id: 'formBuilder_'+config.title,
888
+ layout:'border',
889
+ title: config.title || 'New Form',
890
+ border: false,
891
+ closable: true,
892
+ autoHeight:true,
893
+ buttonAlign:'center',
894
+ items: [{
895
+ xtype: 'form',
896
+ itemId: 'dynamicForm',
897
+ region: 'center',
898
+ autoScroll: true,
899
+ bodyPadding: 10,
900
+ form_definition: config.form_definition,
901
+ form_id: (Ext.isEmpty(config.form_id) ? null : config.form_id),
902
+ defaults:{
903
+ msgTarget: (Ext.isEmpty(config.msg_target) ? 'left' : config.msg_target)
904
+ },
905
+ tbar: [
906
+ { xtype: 'button',
907
+ text: 'Save Form',
908
+ iconCls: 'icon-save',
909
+ listeners:{
910
+ click: function(button){
911
+ var formPanel = button.findParentByType('form');
912
+ var formBuilder = formPanel.findParentByType('dynamic_forms_FormBuilder');
913
+ var form_props = formBuilder.query('#form_props').first().getForm();
914
+
915
+ if (form_props.isValid()){
916
+ var create = Ext.isEmpty(config.form_id);
917
+ formBuilder.setWindowStatus('Saving form ...');
918
+ Ext.Ajax.request({
919
+ url: (create === true ? '/erp_forms/erp_app/desktop/dynamic_forms/forms/create' : '/erp_forms/erp_app/desktop/dynamic_forms/forms/update'),
920
+ method: 'POST',
921
+ params:{
922
+ id:config.form_id,
923
+ form_definition:Ext.JSON.encode(formPanel.form_definition),
924
+ description: form_props.findField('description').getValue(),
925
+ model_name: config.model_name,
926
+ widget_action: form_props.findField('widget_action').getValue(),
927
+ widget_email_recipients: form_props.findField('widget_email_recipients').getValue(),
928
+ focus_first_field: form_props.findField('focus_first_field').getValue(),
929
+ submit_empty_text: form_props.findField('submit_empty_text').getValue(),
930
+ msg_target: form_props.findField('msg_target').getValue(),
931
+ submit_button_label: form_props.findField('submit_button_label').getValue(),
932
+ cancel_button_label: form_props.findField('cancel_button_label').getValue(),
933
+ comment: form_props.findField('comment').getValue()
934
+ },
935
+ success: function(response) {
936
+ formBuilder.clearWindowStatus();
937
+ var obj = Ext.decode(response.responseText);
938
+ if(obj.success){
939
+ if (create === true){
940
+ Ext.getCmp('dynamic_formsTabPanel').remove(formBuilder);
941
+ Ext.getStore('dynamicFormStore').load({ params:{ id: obj.id } });
942
+ Ext.getStore('formsTreeStore').load();
943
+ }else{
944
+ formBuilder.setTitle(form_props.findField('description').getValue());
945
+ //Ext.Msg.alert('Success', 'Form saved.');
946
+ }
947
+ }
948
+ else{
949
+ Ext.Msg.alert('Error', 'Error saving form.');
950
+ }
951
+ },
952
+ failure: function(response) {
953
+ formBuilder.clearWindowStatus();
954
+ Ext.Msg.alert('Error', 'Error saving form');
955
+ }
956
+ });
957
+ }else{
958
+ var east_tabs = formBuilder.query('#east_tabs').first();
959
+ east_tabs.setActiveTab('form_props');
960
+ Ext.Msg.alert('Error', "There is a validation error with this form's properties. Please correct fields marked red.");
961
+ }
962
+ }
963
+ }
964
+ },
965
+ { xtype: 'button',
966
+ text: 'View Definition',
967
+ iconCls: 'icon-document',
968
+ listeners:{
969
+ click: function(button){
970
+ var formPanel = button.findParentByType('form');
971
+ var form_definition = Ext.encode(formPanel.form_definition).replace(/,/gi,', ').replace(/\},/gi,'},<br />');
972
+ // popup window panel with form definition
973
+ //Ext.MessageBox.minWidth = 600;
974
+ //var alertBox = Ext.create("Ext.MessageBox",{ width: 600 });
975
+ //Ext.MessageBox.alert('Form Definition', );
976
+
977
+ var defWindow = Ext.create("Ext.window.Window",{
978
+ layout:'fit',
979
+ title:'Form Definition',
980
+ //plain: true,
981
+ buttonAlign:'center',
982
+ items: Ext.create("Ext.panel.Panel",{
983
+ bodyStyle:'padding:5px 5px 0',
984
+ html: form_definition
985
+ }),
986
+ buttons: [{
987
+ text:'Close',
988
+ listeners:{
989
+ 'click':function(button){
990
+ defWindow.close();
991
+ }
992
+ }
993
+ }]
994
+ });
995
+ defWindow.show();
996
+ }
997
+ }
998
+ },
999
+ { xtype: 'button',
1000
+ text: 'Move Field Up',
1001
+ iconCls: 'icon-arrow-up-blue',
1002
+ listeners:{
1003
+ click: function(button){
1004
+ var formPanel = button.findParentByType('form');
1005
+ formPanel.findParentByType('dynamic_forms_FormBuilder').moveField(formPanel, 'up');
1006
+ }
1007
+ }
1008
+ },
1009
+ { xtype: 'button',
1010
+ text: 'Move Field Down',
1011
+ iconCls: 'icon-arrow-down-blue',
1012
+ listeners:{
1013
+ click: function(button){
1014
+ var formPanel = button.findParentByType('form');
1015
+ formPanel.findParentByType('dynamic_forms_FormBuilder').moveField(formPanel, 'down');
1016
+ }
1017
+ }
1018
+ },
1019
+ { xtype: 'button',
1020
+ text: 'Remove Field',
1021
+ iconCls: 'icon-delete',
1022
+ listeners:{
1023
+ click: function(button){
1024
+ var formPanel = button.findParentByType('form');
1025
+
1026
+ if (Ext.isEmpty(formPanel.selected_field)){
1027
+ Ext.Msg.alert('Error', 'Please select a field to remove.');
1028
+ }else{
1029
+ Ext.MessageBox.confirm('Confirm', 'Are you sure you want to remove this field?',
1030
+ function(btn){
1031
+ if(btn == 'no'){
1032
+ return false;
1033
+ }
1034
+ else if(btn == 'yes')
1035
+ {
1036
+ var i = 0;
1037
+ // find selected field in definition to remove it
1038
+ Ext.each(formPanel.form_definition, function(field){
1039
+ if (field.name == formPanel.selected_field.name){ idx = i; }
1040
+ i++;
1041
+ });
1042
+ formPanel.form_definition.splice(idx, 1); // remove field from definition
1043
+ formPanel.selected_field = null; // deselect field that was removed
1044
+ formPanel.findParentByType('dynamic_forms_FormBuilder').reloadForm(formPanel); // redraw form from definition
1045
+ }
1046
+ }
1047
+ );
1048
+ }
1049
+ }
1050
+ }
1051
+ }
1052
+ ],
1053
+ listeners:{
1054
+ render:function(formPanel){
1055
+ formPanel.findParentByType('dynamic_forms_FormBuilder').reloadForm(formPanel);
1056
+ var formPanelDropTargetEl = formPanel.body.dom;
1057
+ var formPanelDropTarget = Ext.create('Ext.dd.DropTarget', formPanelDropTargetEl, {
1058
+ ddGroup: 'fieldsDDGroup',
1059
+ notifyEnter: function(ddSource, e, data) {
1060
+ formPanel.body.stopAnimation();
1061
+ formPanel.body.highlight();
1062
+ },
1063
+ notifyDrop : function(ddSource, e, data){
1064
+ var droppedField = data.records[0];
1065
+
1066
+ var addFieldWindow = Ext.create("Ext.window.Window",{
1067
+ layout:'fit',
1068
+ width:375,
1069
+ title:'Add Field to Form',
1070
+ height:100,
1071
+ plain: true,
1072
+ buttonAlign:'center',
1073
+ items: Ext.create("Ext.form.Panel",{
1074
+ labelWidth: 110,
1075
+ frame:false,
1076
+ bodyStyle:'padding:5px 5px 0',
1077
+ defaults: {
1078
+ width: 225
1079
+ },
1080
+ items: [
1081
+ {
1082
+ xtype:'textfield',
1083
+ fieldLabel:'Field Name',
1084
+ allowBlank:false,
1085
+ name:'field_name',
1086
+ value: (droppedField.get('field_xtype') == 'filefield' ? 'file' : ''),
1087
+ readOnly: (droppedField.get('field_xtype') == 'filefield' ? true : false),
1088
+ maskRe: /^\w+$/,
1089
+ regex: /^\w+$/,
1090
+ plugins: [new helpQtip('Only letters, numbers and underscores are valid. Field Names must be unique. A File Upload field must be named "file".')],
1091
+ listeners:{
1092
+ afterrender:function(field){
1093
+ field.focus(false, 200);
1094
+ },
1095
+ 'specialkey': function(field, e){
1096
+ if (e.getKey() == e.ENTER) {
1097
+ var button = field.findParentByType('window').query('#submitButton').first();
1098
+ button.fireEvent('click', button);
1099
+ }
1100
+ }
1101
+ }
1102
+ }
1103
+ ]
1104
+ }),
1105
+ buttons: [{
1106
+ itemId: 'submitButton',
1107
+ text:'Submit',
1108
+ listeners:{
1109
+ 'click':function(button){
1110
+ var window = button.findParentByType('window');
1111
+ var addFieldFormPanel = window.query('form')[0];
1112
+ var field_name = addFieldFormPanel.getForm().findField('field_name').getValue();
1113
+ var formBuilder = formPanel.findParentByType('dynamic_forms_FormBuilder');
1114
+
1115
+ if (!addFieldFormPanel.getForm().isValid()){
1116
+ Ext.Msg.alert('Error', 'Please correct form.');
1117
+ return;
1118
+ } else if (field_name == 'text'){
1119
+ Ext.Msg.alert('Error', 'Field Name cannot be "text".');
1120
+ return;
1121
+ } else if (!formBuilder.validateFieldNameUnique(formPanel, field_name)){
1122
+ Ext.Msg.alert('Error', 'Field Name must be unique.');
1123
+ return;
1124
+ }
1125
+
1126
+ var fieldDefinition = {
1127
+ xtype: droppedField.get('field_xtype'),
1128
+ name: field_name,
1129
+ fieldLabel: (droppedField.get('field_xtype') == 'hiddenfield' ? 'Hidden Field' : field_name.titleize()),
1130
+ display_in_grid: true,
1131
+ searchable: true,
1132
+ labelWidth: 75
1133
+ };
1134
+
1135
+ switch(fieldDefinition.xtype){
1136
+ case 'hiddenfield':
1137
+ fieldDefinition.display_in_grid = false;
1138
+ fieldDefinition.searchable = false;
1139
+ break;
1140
+ case 'related_combobox':
1141
+ fieldDefinition.width = 175;
1142
+ fieldDefinition.editable = true;
1143
+ fieldDefinition.forceSelection = true;
1144
+ break;
1145
+ case 'related_searchbox':
1146
+ fieldDefinition.width = 350;
1147
+ fieldDefinition.editable = true;
1148
+ fieldDefinition.forceSelection = true;
1149
+ //fieldDefinition.typeAhead = true;
1150
+ fieldDefinition.pageSize = 10;
1151
+ break;
1152
+ case 'checkbox':
1153
+ fieldDefinition.inputValue = true;
1154
+ fieldDefinition.uncheckedValue = false;
1155
+ break;
1156
+ case 'combobox':
1157
+ fieldDefinition.editable = true;
1158
+ fieldDefinition.forceSelection = true;
1159
+ break;
1160
+ case 'yesno':
1161
+ fieldDefinition.xtype = 'combobox';
1162
+ fieldDefinition.forceSelection = true;
1163
+ fieldDefinition.store = [['no','No'],['yes','Yes']];
1164
+ break;
1165
+ case 'email':
1166
+ fieldDefinition.xtype = 'textfield';
1167
+ fieldDefinition.validator_function = 'validateEmail(v)';
1168
+ break;
1169
+ case 'password':
1170
+ fieldDefinition.xtype = 'textfield';
1171
+ fieldDefinition.inputType = 'password';
1172
+ break;
1173
+ case 'filefield':
1174
+ fieldDefinition.vtype = 'file';
1175
+ fieldDefinition.name = 'file';
1176
+ // fieldDefinition.inputType = 'file'; // needed for fileSize validation but it causes some cosmetic problems
1177
+ // fieldDefinition.buttonConfig = {hidden: true};
1178
+ break;
1179
+ default:
1180
+ }
1181
+
1182
+ formBuilder.addFieldToForm(formPanel, fieldDefinition);
1183
+
1184
+ addFieldWindow.close();
1185
+ }
1186
+ }
1187
+ },{
1188
+ text: 'Close',
1189
+ handler: function(){
1190
+ addFieldWindow.close();
1191
+ }
1192
+ }]
1193
+ });
1194
+ addFieldWindow.show();
1195
+
1196
+ return true;
1197
+ }
1198
+ });
1199
+ }
1200
+ }
1201
+ },
1202
+ {
1203
+ xtype: 'tabpanel',
1204
+ itemId: 'east_tabs',
1205
+ region: 'east',
1206
+ width: 275,
1207
+ activeTab: 0,
1208
+ defaults:{
1209
+ width: 255
1210
+ },
1211
+ items: [
1212
+ {
1213
+ xtype: 'form',
1214
+ title: 'Field Properties',
1215
+ itemId: 'field_props',
1216
+ autoScroll: true,
1217
+ bodyPadding: 10,
1218
+ tbar: [
1219
+ { xtype: 'button',
1220
+ text: 'Update Field',
1221
+ iconCls: 'icon-edit',
1222
+
1223
+ listeners:{
1224
+ click: function(button){
1225
+ // get formPanel
1226
+ var updateFieldForm = button.findParentByType('form').getForm();
1227
+ if (updateFieldForm.isValid()){
1228
+ var formPanel = Ext.getCmp('formBuilder_'+config.title).query('#dynamicForm').first();
1229
+ var formBuilder = formPanel.findParentByType('dynamic_forms_FormBuilder');
1230
+ var selected_field = formPanel.selected_field;
1231
+ var updateName = updateFieldForm.findField('updateName').getValue();
1232
+
1233
+ // build field json
1234
+ var fieldDefinition = {
1235
+ xtype: (selected_field.field_xtype == 'hiddenfield' ? 'hiddenfield' : selected_field.xtype),
1236
+ name: updateName,
1237
+ fieldLabel: updateFieldForm.findField('updateLabel').getValue()
1238
+ };
1239
+ if (selected_field.field_xtype == 'hiddenfield'){
1240
+ try { var updateHideMode = updateFieldForm.findField('updateHideMode').getValue();
1241
+ if (!Ext.isEmpty(updateHideMode)) fieldDefinition.hideMode = updateHideMode; } catch(e){}
1242
+ }
1243
+ try { fieldDefinition.labelAlign = updateFieldForm.findField('updateLabelAlign').getValue(); } catch(e){}
1244
+ try { fieldDefinition.readOnly = updateFieldForm.findField('updateReadOnly').getValue(); } catch(e){}
1245
+ try { fieldDefinition.hideTrigger = updateFieldForm.findField('updateHideTrigger').getValue(); } catch(e){}
1246
+ try { var updateEmptyText = updateFieldForm.findField('updateEmptyText').getValue();
1247
+ if (!Ext.isEmpty(updateEmptyText)) fieldDefinition.emptyText = updateEmptyText; } catch(e){}
1248
+ try { var updateHelpQtip = updateFieldForm.findField('updateHelpQtip').getValue();
1249
+ if (!Ext.isEmpty(updateHelpQtip)) fieldDefinition.help_qtip = updateHelpQtip; } catch(e){}
1250
+
1251
+ try { fieldDefinition.allowBlank = updateFieldForm.findField('updateAllowBlank').getValue(); } catch(e){}
1252
+ try { fieldDefinition.display_in_grid = updateFieldForm.findField('updateDisplayInGrid').getValue(); } catch(e){}
1253
+ try { fieldDefinition.searchable = updateFieldForm.findField('updateSearchable').getValue(); } catch(e){}
1254
+ try { var updateValue = updateFieldForm.findField('updateValue').getValue();
1255
+ if (selected_field.xtype == 'related_combobox' || selected_field.xtype == 'related_searchbox') {
1256
+ if (!Ext.isEmpty(updateValue)) fieldDefinition.default_value = parseInt(updateValue, 10);
1257
+ }else{
1258
+ if (!Ext.isEmpty(updateValue)) fieldDefinition.value = updateValue;
1259
+ }
1260
+ } catch(e){}
1261
+ try { var updateLabelWidth = updateFieldForm.findField('updateLabelWidth').getValue();
1262
+ if (!Ext.isEmpty(updateLabelWidth)) fieldDefinition.labelWidth = updateLabelWidth; } catch(e){}
1263
+ try { var updateWidth = updateFieldForm.findField('updateWidth').getValue();
1264
+ if (!Ext.isEmpty(updateWidth)) fieldDefinition.width = updateWidth; } catch(e){}
1265
+ try { var updateHeight = updateFieldForm.findField('updateHeight').getValue();
1266
+ if (!Ext.isEmpty(updateHeight)) fieldDefinition.height = updateHeight; } catch(e){}
1267
+
1268
+ if (Ext.isEmpty(selected_field.field_xtype) && !Ext.Array.indexOf(['related_combobox','related_searchbox','combobox','combo'], selected_field.xtype)){
1269
+ switch(updateFieldForm.findField('updateValidationType').getValue()){
1270
+ case 'regex':
1271
+ var validationRegex = updateFieldForm.findField('updateValidationRegex').getValue();
1272
+ if(!Ext.isEmpty(validationRegex)) fieldDefinition.validation_regex = validationRegex;
1273
+ fieldDefinition.regexText = updateFieldForm.findField('updateValidationRegexText').getValue();
1274
+ break;
1275
+ case 'function':
1276
+ fieldDefinition.validator_function = updateFieldForm.findField('updateValidationFunction').getValue();
1277
+ break;
1278
+ case 'vtype':
1279
+ fieldDefinition.vtype = updateFieldForm.findField('updateValidationVType').getValue();
1280
+ break;
1281
+ default:
1282
+ }
1283
+ }
1284
+
1285
+ if (selected_field.xtype == 'datefield' || selected_field.xtype == 'timefield' || selected_field.xtype == 'numberfield'){
1286
+ var updateMinValue = updateFieldForm.findField('updateMinValue').getValue();
1287
+ var updateMaxValue = updateFieldForm.findField('updateMaxValue').getValue();
1288
+ if(!Ext.isEmpty(updateMinValue)) fieldDefinition.minValue = updateMinValue;
1289
+ if(!Ext.isEmpty(updateMaxValue)) fieldDefinition.maxValue = updateMaxValue;
1290
+ }
1291
+
1292
+ if (selected_field.xtype == 'textfield' || selected_field.xtype == 'textarea' || selected_field.xtype == 'numberfield'){
1293
+ var updateMinLength = updateFieldForm.findField('updateMinLength').getValue();
1294
+ var updateMaxLength = updateFieldForm.findField('updateMaxLength').getValue();
1295
+ if(!Ext.isEmpty(updateMinLength)) fieldDefinition.minLength = updateMinLength;
1296
+ if(!Ext.isEmpty(updateMaxLength)) fieldDefinition.maxLength = updateMaxLength;
1297
+ }
1298
+
1299
+ if (selected_field.xtype == 'filefield'){
1300
+ fieldDefinition.buttonText = updateFieldForm.findField('updateButtonText').getValue();
1301
+ fieldDefinition.vtype = 'file';
1302
+ // fieldDefinition.inputType = 'file'; // needed for fileSize validation but it causes some cosmetic problems
1303
+ // fieldDefinition.buttonConfig = {hidden: true};
1304
+ }
1305
+
1306
+ if (selected_field.xtype == 'related_combobox' || selected_field.xtype == 'related_searchbox'){
1307
+ fieldDefinition.editable = updateFieldForm.findField('updateEditable').getValue();
1308
+ fieldDefinition.forceSelection = updateFieldForm.findField('updateForceSelection').getValue();
1309
+ fieldDefinition.multiSelect = updateFieldForm.findField('updateMultiSelect').getValue();
1310
+ fieldDefinition.extraParams = {
1311
+ model: updateFieldForm.findField('updateRelatedModel').getValue()
1312
+ };
1313
+ if (selected_field.xtype == 'related_combobox'){
1314
+ fieldDefinition.fields = [
1315
+ { name: 'id' },
1316
+ { name: fieldDefinition.displayField }
1317
+ ];
1318
+ fieldDefinition.displayField = updateFieldForm.findField('updateDisplayField').getValue();
1319
+ fieldDefinition.extraParams.displayField = fieldDefinition.displayField;
1320
+ }else if (selected_field.xtype == 'related_searchbox'){
1321
+ fieldDefinition.search_fields = updateFieldForm.findField('updateSearchFields').getValue().replace(/\s/g,'');
1322
+ fieldDefinition.display_fields = updateFieldForm.findField('updateDisplayFields').getValue().replace(/\s/g,'');
1323
+ fieldDefinition.display_template = updateFieldForm.findField('updateDisplayTemplate').getValue();
1324
+ //fieldDefinition.typeAhead = updateFieldForm.findField('updateTypeAhead').getValue();
1325
+ fieldDefinition.pageSize = updateFieldForm.findField('updatePageSize').getValue();
1326
+ fieldDefinition.fields = [{ name: 'id' }];
1327
+ Ext.each(fieldDefinition.display_fields.split(','), function(f){
1328
+ fieldDefinition.fields.push({ name: f });
1329
+ });
1330
+ fieldDefinition.extraParams.search_fields = fieldDefinition.search_fields;
1331
+ fieldDefinition.extraParams.display_fields = fieldDefinition.display_fields;
1332
+ }
1333
+ }else if (selected_field.xtype == 'combobox' || selected_field.xtype == 'combo'){
1334
+ var updateOptions = updateFieldForm.findField('updateOptions').getValue();
1335
+ if(updateOptions){
1336
+ var options = updateOptions.split(',');
1337
+ var optionsArray = [], subArray = [], i = 1;
1338
+ Ext.each(options, function(option){
1339
+ subArray.push(option.trim());
1340
+ if (i%2 === 0){
1341
+ optionsArray.push(subArray);
1342
+ subArray = [];
1343
+ }
1344
+ i++;
1345
+ });
1346
+
1347
+ fieldDefinition.store = optionsArray;
1348
+ }
1349
+ fieldDefinition.editable = updateFieldForm.findField('updateEditable').getValue();
1350
+ fieldDefinition.forceSelection = updateFieldForm.findField('updateForceSelection').getValue();
1351
+ fieldDefinition.multiSelect = updateFieldForm.findField('updateMultiSelect').getValue();
1352
+ }
1353
+
1354
+ //console.log(fieldDefinition);
1355
+
1356
+ // use getIndexOfFieldByName and splice to replace field in definition to preserve field order
1357
+ var indexOfField = formBuilder.getIndexOfFieldByName(formPanel, formPanel.selected_field.name);
1358
+ //console.log(indexOfField);
1359
+
1360
+ formPanel.form_definition.splice(indexOfField, 1, fieldDefinition);
1361
+ //console.log(formPanel.form_definition);
1362
+
1363
+ // reload form from definition
1364
+ formBuilder.reloadForm(formPanel);
1365
+
1366
+ // re-highlight form item
1367
+ formPanel.getForm().findField(updateName).getEl().dom.click();
1368
+ }
1369
+ }
1370
+ }
1371
+ }
1372
+ ],
1373
+ defaults:{
1374
+ width: 230,
1375
+ labelWidth: 85
1376
+ },
1377
+ items:[]
1378
+ },
1379
+ {
1380
+ xtype: 'form',
1381
+ title: 'Form Properties',
1382
+ itemId: 'form_props',
1383
+ autoScroll: true,
1384
+ bodyPadding: 10,
1385
+ defaults:{
1386
+ width: 230,
1387
+ labelWidth: 85
1388
+ },
1389
+ items:[{
1390
+ fieldLabel: 'Form Title',
1391
+ name: 'description',
1392
+ xtype: 'textfield',
1393
+ allowBlank: false
1394
+ },
1395
+ {
1396
+ fieldLabel: 'Internal ID',
1397
+ name: 'internal_identifier',
1398
+ xtype: 'displayfield'
1399
+ },
1400
+ {
1401
+ fieldLabel: 'Widget Action',
1402
+ name: 'widget_action',
1403
+ xtype: 'combobox',
1404
+ width: 215,
1405
+ allowBlank: false,
1406
+ forceSelection:true,
1407
+ store: [
1408
+ ['email', 'Email Only'],
1409
+ ['save', 'Save Only'],
1410
+ ['both', 'Email & Save Data']
1411
+ ],
1412
+ listeners:{
1413
+ change:function(field, newValue, oldValue){
1414
+ var widget_email_recipients = field.findParentByType('form').getForm().findField('widget_email_recipients');
1415
+ widget_email_recipients.allowBlank = (field.getValue() == 'save');
1416
+ }
1417
+ },
1418
+ plugins: [new helpQtip("Configure the action to be taken when a form is submitted via Knitkit's Dynamic Forms Widget.<br /> Email Only will email but not save the data to the database.<br /> Save Only will save the data to the database but not email.<br /> Email & Save Data will do both.<br /> NOTE: The Contact Us Widget uses Knitkit's website configuration options for email behavior & not the Dynamic Forms Widget Action setting.")]
1419
+ },
1420
+ {
1421
+ fieldLabel: 'Email Recipients',
1422
+ name: 'widget_email_recipients',
1423
+ xtype: 'textfield',
1424
+ vtype: 'emailList',
1425
+ width: 215,
1426
+ listeners:{
1427
+ render:function(field){
1428
+ field.allowBlank = (field.findParentByType('form').getForm().findField('widget_action').getValue() == 'save');
1429
+ }
1430
+ },
1431
+ plugins: [new helpQtip('When Widget Action is set to Email only or Email & Save Data, this field is required. Enter a comma separated list of email addresses to receive data submitted with this form via the Knitkit Dynamic Forms widget.')]
1432
+ },
1433
+ {
1434
+ fieldLabel: 'Focus Field',
1435
+ name: 'focus_first_field',
1436
+ xtype: 'checkbox',
1437
+ width: 105,
1438
+ plugins: [new helpQtip('Do you want the cursor to autmatically focus the first form field? If there is text it will also automatically highlight.')]
1439
+ },
1440
+ {
1441
+ fieldLabel: 'Submit Button Label',
1442
+ name: 'submit_button_label',
1443
+ xtype: 'textfield',
1444
+ allowBlank: false
1445
+ },
1446
+ {
1447
+ fieldLabel: 'Cancel Button Label',
1448
+ name: 'cancel_button_label',
1449
+ xtype: 'textfield',
1450
+ allowBlank: false
1451
+ },
1452
+ {
1453
+ fieldLabel: 'Submit Empty Text',
1454
+ name: 'submit_empty_text',
1455
+ xtype: 'checkbox',
1456
+ width: 105,
1457
+ plugins: [new helpQtip('Empty Text is example text. Do you want to submit these example values if they are unchanged by the user?')]
1458
+ },
1459
+ {
1460
+ fieldLabel: 'Message Target',
1461
+ name: 'msg_target',
1462
+ xtype: 'combobox',
1463
+ allowBlank: false,
1464
+ editable: true,
1465
+ forceSelection:false,
1466
+ value: 'qtip',
1467
+ store: [
1468
+ ['qtip', 'Quick Tip'],
1469
+ ['side', 'Right of Field'],
1470
+ ['title', 'Title'],
1471
+ ['under', 'Under Field'],
1472
+ ['none', 'None']
1473
+ ]
1474
+ },
1475
+ {
1476
+ fieldLabel: 'Comment',
1477
+ labelAlign: 'top',
1478
+ name: 'comment',
1479
+ xtype: 'textarea'
1480
+ },
1481
+ {
1482
+ fieldLabel: 'Created At',
1483
+ name: 'created_at',
1484
+ xtype: 'displayfield'
1485
+ },
1486
+ {
1487
+ fieldLabel: 'Created By',
1488
+ name: 'created_by',
1489
+ xtype: 'displayfield'
1490
+ },
1491
+ {
1492
+ fieldLabel: 'Updated At',
1493
+ name: 'updated_at',
1494
+ xtype: 'displayfield'
1495
+ },
1496
+ {
1497
+ fieldLabel: 'Updated By',
1498
+ name: 'updated_by',
1499
+ xtype: 'displayfield'
1500
+ }
1501
+ ]
1502
+ }
1503
+ ]
85
1504
  }
86
- }]
1505
+ ]
1506
+
87
1507
  }, config);
88
1508
 
89
1509
  this.callParent([config]);
90
1510
  }
91
-
92
- });
93
-
1511
+ });