erp_forms 2.0.6 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -2,7 +2,7 @@ class ErpForms::ErpApp::Desktop::DynamicForms::FormsController < ErpForms::ErpAp
2
2
 
3
3
  # get tree of dynamic models and forms
4
4
  def get_tree
5
- models = params[:node] == "root" ? DynamicFormModel.all(:order => :model_name) : DynamicFormModel.find_all_by_id(id)
5
+ models = params[:node] == "root" ? DynamicFormModel.all(:order => :model_name) : DynamicFormModel.find_all_by_id(params[:id])
6
6
  tree = []
7
7
 
8
8
  models.each do |form_model|
@@ -13,10 +13,15 @@ class ErpForms::ErpApp::Desktop::DynamicForms::FormsController < ErpForms::ErpAp
13
13
  :text => form_model.model_name,
14
14
  :iconCls => 'icon-data',
15
15
  :id => "form_model_#{form_model.id}",
16
- :modelId => form_model.id,
17
- :isModel => true,
16
+ :formModelId => form_model.id,
17
+ :isFormModel => true,
18
+ :allow_comments => form_model.allow_comments,
19
+ :allow_files => form_model.allow_files,
20
+ :file_security_default => form_model.file_security_default,
21
+ :show_in_multitask => form_model.show_in_multitask,
18
22
  :isForm => false,
19
23
  :leaf => false,
24
+ :expanded => true,
20
25
  :children => []
21
26
  }
22
27
 
@@ -27,9 +32,9 @@ class ErpForms::ErpApp::Desktop::DynamicForms::FormsController < ErpForms::ErpAp
27
32
  :iconCls => (form.default ? 'icon-document_ok' : 'icon-document'),
28
33
  :id => "form_#{form.id}",
29
34
  :formId => form.id,
30
- :isModel => false,
31
- :isDefault => form.default,
32
- :modelName => form_model.model_name,
35
+ :isFormModel => false,
36
+ :isDefaultForm => form.default,
37
+ :formModelName => form_model.model_name,
33
38
  :isForm => true,
34
39
  :leaf => true
35
40
  }
@@ -46,15 +51,34 @@ class ErpForms::ErpApp::Desktop::DynamicForms::FormsController < ErpForms::ErpAp
46
51
 
47
52
  # get a single form definition
48
53
  def get_definition
49
- form = DynamicForm.get_form(params[:model_name], params[:internal_identifier])
54
+ dform = DynamicForm.find_by_id(params[:id]) if params[:id]
55
+ dform = DynamicForm.get_form(params[:model_name], params[:internal_identifier]) if dform.nil? and params[:model_name]
56
+
57
+ if dform.nil?
58
+ render :json => {:success => false}
59
+ else
60
+ render :json => dform.definition
61
+ end
62
+ end
50
63
 
51
- render :json => form.definition
64
+ # get a single form record
65
+ def get_record
66
+ dform = DynamicForm.find(params[:id]) rescue nil
67
+
68
+ unless dform.nil?
69
+ dform_hash = dform.to_hash
70
+ dform_hash[:created_by] = dform.created_by.username rescue 'Unknown'
71
+ dform_hash[:updated_by] = dform.updated_by.username rescue 'Unknown'
72
+ dform_hash[:created_at] = dform.created_at.getlocal.strftime(@@datetime_format)
73
+ dform_hash[:updated_at] = dform.updated_at.getlocal.strftime(@@datetime_format)
74
+ end
75
+ render :json => [dform_hash]
52
76
  end
53
77
 
54
78
  # get a single form
55
79
  def get
56
80
  dform = DynamicForm.find_by_id(params[:id]) if params[:id]
57
- dform = DynamicForm.get_form(params[:model_name]) if dform.nil? and params[:model_name]
81
+ dform = DynamicForm.get_form(params[:model_name], params[:internal_identifier]) if dform.nil? and params[:model_name]
58
82
 
59
83
  if dform.nil?
60
84
  render :json => {:success => false, :error => "Don't know how to find form"} and return
@@ -70,25 +94,96 @@ class ErpForms::ErpApp::Desktop::DynamicForms::FormsController < ErpForms::ErpAp
70
94
 
71
95
  # get related data for a related field
72
96
  def related_field
73
- related_model = params[:model].camelize.constantize
74
- data = related_model.all
97
+ if params[:model].blank? or (params[:displayField].blank? and params[:search_fields].blank?)
98
+ render :inline => '[]'
99
+ else
100
+ related_model = params[:model].camelize.constantize
101
+ query = related_model
102
+
103
+ unless params[:search_fields].blank?
104
+ #related_searchbox
105
+ search_fields = params[:search_fields].split(',')
106
+ unless params[:query].blank?
107
+ sql = ''
108
+ search_fields.each_with_index do |f,i|
109
+ sql += " OR " if i > 0
110
+ sql += "UPPER(#{f}) LIKE UPPER('%#{params[:query]}%')"
111
+ end
112
+ query = query.where(sql)
113
+ end
114
+ query = query.paginate(:page => page, :per_page => per_page)
115
+ end
75
116
 
76
- render :inline => data.to_json(:only => [:id, params[:displayField].to_sym])
117
+ total = query.count
118
+ data = query.all
119
+ render :inline => { :data => data, :total => total}.to_json
120
+ end
77
121
  end
78
122
 
79
123
  # delete dynamic form
80
124
  def delete
81
-
125
+ dform = DynamicForm.find_by_id(params[:id])
126
+ unless dform.nil?
127
+ begin
128
+ dform.destroy
129
+ render :json => {:success => true}
130
+ rescue Exception => e
131
+ render :json => {:success => false, :error => e.message}
132
+ end
133
+ else
134
+ render :json => {:success => false, :error => 'Could not find form.'}
135
+ end
82
136
  end
83
137
 
84
138
  # update dynamic form
85
139
  def update
86
-
140
+ dform = DynamicForm.find_by_id(params[:id])
141
+ dform = assign_form_attributes(dform)
142
+ dform.updated_by_id = current_user.id
143
+
144
+ # update solr config for model (doesn't work yet)
145
+ # DynamicFormModel.get_constant(dform.model_name).sunspot_setup if $USE_SOLR_FOR_DYNAMIC_FORM_MODELS
146
+
147
+ if dform.save
148
+ render :json => {:success => true}
149
+ else
150
+ render :json => {:success => false}
151
+ end
87
152
  end
88
153
 
89
154
  # create dynamic form
90
155
  def create
91
-
156
+ if params[:form_definition] and params[:description] and params[:model_name]
157
+ dform = DynamicForm.new
158
+ dform = assign_form_attributes(dform)
159
+ dform.dynamic_form_model_id = DynamicFormModel.find_by_model_name(params[:model_name]).id
160
+ dform.default = false
161
+ dform.created_by_id = current_user.id
162
+ if dform.save
163
+ render :json => {:success => true, :id => dform.id}
164
+ else
165
+ render :json => {:success => false}
166
+ end
167
+ else
168
+ render :json => {:success => false, :error => 'Insufficient info to create form.'}
169
+ end
92
170
  end
93
171
 
172
+ protected
173
+ def assign_form_attributes(dform)
174
+ dform.description = params[:description] unless params[:description].nil?
175
+ dform.definition = params[:form_definition] unless params[:form_definition].nil?
176
+ dform.model_name = params[:model_name] unless params[:model_name].nil?
177
+ dform.widget_action = params[:widget_action] unless params[:widget_action].nil?
178
+ dform.widget_email_recipients = params[:widget_email_recipients] unless params[:widget_email_recipients].nil?
179
+ dform.focus_first_field = params[:focus_first_field] unless params[:focus_first_field].nil?
180
+ dform.show_in_multitask = params[:show_in_multitask] unless params[:show_in_multitask].nil?
181
+ dform.msg_target = params[:msg_target] unless params[:msg_target].nil?
182
+ dform.submit_empty_text = params[:submit_empty_text] unless params[:submit_empty_text].nil?
183
+ dform.submit_button_label = params[:submit_button_label] unless params[:submit_button_label].nil?
184
+ dform.cancel_button_label = params[:cancel_button_label] unless params[:cancel_button_label].nil?
185
+ dform.comment = params[:comment] unless params[:comment].nil?
186
+ dform
187
+ end
188
+
94
189
  end
@@ -8,7 +8,9 @@ class ErpForms::ErpApp::Desktop::DynamicForms::ModelsController < ErpForms::ErpA
8
8
  dynamic_form_models.each do |m|
9
9
  model_hash = {
10
10
  :id => m.id,
11
- :model_name => m.model_name
11
+ :model_name => m.model_name,
12
+ :file_security_default => m.file_security_default,
13
+ :show_in_multitask => m.show_in_multitask
12
14
  }
13
15
 
14
16
  models << model_hash
@@ -34,12 +36,26 @@ class ErpForms::ErpApp::Desktop::DynamicForms::ModelsController < ErpForms::ErpA
34
36
 
35
37
  # create a dynamic form model
36
38
  def create
37
- model_name = params[:model_name]
38
39
  DynamicFormModel.create({
39
- :model_name => model_name
40
+ :model_name => params[:model_name],
41
+ :allow_comments => params[:allow_comments],
42
+ :allow_files => params[:allow_files],
43
+ :file_security_default => params[:file_security_default]
40
44
  })
41
45
 
42
46
  render :json => {:success => true}
43
47
  end
48
+
49
+ # update a dynamic form model
50
+ def update
51
+ m = DynamicFormModel.find(params[:id])
52
+ m.allow_comments = params[:allow_comments] unless params[:allow_comments].nil?
53
+ m.allow_files = params[:allow_files] unless params[:allow_files].nil?
54
+ m.file_security_default = params[:file_security_default] unless params[:file_security_default].blank?
55
+ m.show_in_multitask = params[:show_in_multitask] unless params[:show_in_multitask].nil?
56
+ m.save
57
+
58
+ render :json => {:success => true}
59
+ end
44
60
 
45
61
  end
@@ -0,0 +1,35 @@
1
+ class DynamicFormMailer < ActionMailer::Base
2
+
3
+ # def widget_email(form, dynamicObject, subject='')
4
+ # subject = "#{model_name} Submission" if subject.blank?
5
+ # @dynamicObject = dynamicObject
6
+
7
+ # mail( :to => form.widget_email_recipients,
8
+ # :from => ErpTechSvcs::Config.email_notifications_from,
9
+ # :subject => subject,
10
+ # :content_type => 'text/plain'
11
+ # )
12
+ # end
13
+
14
+ # uses mail_alternatives_with_attachments gem
15
+ # ActionMailer doesn't handle attachments well without this gem
16
+ def widget_email_with_attachments(form, dynamicObject, subject='', files=[])
17
+ related_fields = dynamicObject.form.related_fields rescue []
18
+ @dynamicData = dynamicObject.data.dynamic_attributes_with_related_data(related_fields, true)
19
+ subject = "#{model_name} Submission" if subject.blank?
20
+ message = prepare_message to: form.widget_email_recipients, from: ErpTechSvcs::Config.email_notifications_from, subject: subject, :content_type => "multipart/mixed"
21
+
22
+ message.alternative_content_types_with_attachment(
23
+ :text => render_to_string(:template => "dynamic_form_mailer/widget_email_with_attachments.text"),
24
+ :html => render_to_string(:template => "dynamic_form_mailer/widget_email_with_attachments.html")
25
+ ) do |inline_attachments|
26
+ files.each do |f|
27
+ attachments.inline[f.original_filename] = f.tempfile.read
28
+ end
29
+ end
30
+
31
+ message
32
+ end
33
+
34
+ end
35
+
@@ -1,4 +1,6 @@
1
1
  class DynamicDatum < ActiveRecord::Base
2
+ attr_protected :created_at, :updated_at
3
+
2
4
  DYNAMIC_ATTRIBUTE_PREFIX = 'dyn_'
3
5
 
4
6
  has_dynamic_attributes :dynamic_attribute_prefix => DYNAMIC_ATTRIBUTE_PREFIX, :destroy_dynamic_attribute_for_nil => false
@@ -20,11 +22,19 @@ class DynamicDatum < ActiveRecord::Base
20
22
 
21
23
  def dynamic_attributes_with_related_data(related_fields=[], use_label=false)
22
24
  key = (use_label ? :fieldLabel : :name)
23
- data = sorted_dynamic_attributes(false, use_label)
25
+ data = sorted_dynamic_attributes(:use_label => use_label)
24
26
  related_fields.each do |r|
25
27
  data.each do |k,v|
26
28
  if k == r[key]
27
- data[k] = r[:extraParams]['model'].camelize.constantize.find(v).send(r[:displayField]) rescue nil
29
+ if r[:xtype] == 'related_combobox'
30
+ d = r[:displayField]
31
+ t = nil
32
+ else
33
+ #related_searchbox
34
+ d = r[:display_fields].split(',')
35
+ t = r[:display_template]
36
+ end
37
+ data[k] = DynamicDatum.related_data_value(r[:extraParams]['model'], v, d, t)
28
38
  end
29
39
  end
30
40
  end
@@ -32,44 +42,109 @@ class DynamicDatum < ActiveRecord::Base
32
42
  data
33
43
  end
34
44
 
45
+ #column can be a string or array of strings
46
+ def self.related_data_value(model, id, column, template=nil)
47
+ if column.is_a?(String)
48
+ return model.camelize.constantize.find(id).send(column) rescue nil
49
+ else
50
+ final_display = template
51
+ column.each do |c|
52
+ value = model.camelize.constantize.find(id).send(c) rescue nil
53
+ final_display = final_display.gsub(c, value)
54
+ end
55
+ return final_display.gsub('{','').gsub('}','')
56
+ end
57
+ end
58
+
35
59
  # we cannot assume that dynamic attributes are stored in order in the database as this is often not the case
36
60
  # this method will sort them according to the order of the fields in the form definition
37
61
  # method returns an ordered hash
38
- # if with_prefix is false, you may choose to use the fieldLabel as the hash key, this is useful displaying data on a view screen
39
- def sorted_dynamic_attributes(with_prefix=false, use_label=false)
40
- form = self.updated_with_form if form.nil? and !self.updated_with_form.nil?
62
+ # options = {:with_prefix => false, :use_label => false, :all => false}
63
+ # :with_prefix = false will remove the dyn_ from the attribute key
64
+ # if :with_prefix is false, you may choose to use the fieldLabel as the hash key by setting :use_label = true
65
+ # :use_label is useful displaying data on a view screen or formatting an email
66
+ # :all = false will only return attributes that are in the form definition
67
+ # :all = true will return all attributes with those not in the form definition last
68
+ # you can set :all = true and :use_label = true, but attributes not in definition will use key.titleize
69
+ # if for some reason a form cannot be found, sorting will not be attempted
70
+ def sorted_dynamic_attributes(options={})
71
+ options[:with_prefix] = false if options[:with_prefix].nil?
72
+ options[:use_label] = false if options[:use_label].nil?
73
+ options[:all] = true if options[:all].nil?
74
+
75
+ form = self.updated_with_form !self.updated_with_form.nil?
41
76
  form = self.created_with_form if form.nil? and !self.created_with_form.nil?
42
77
  form = DynamicForm.get_form(self.reference_type) if form.nil?
43
78
 
44
79
  unless form.nil?
45
- if with_prefix
46
- keys = form.definition_object.collect{|f| DYNAMIC_ATTRIBUTE_PREFIX + f[:name]}
80
+ fields = form.definition_object
81
+
82
+ fields_and_values = {}
83
+ if options[:with_prefix]
84
+ fields.each do |f|
85
+ k = DYNAMIC_ATTRIBUTE_PREFIX + f[:name]
86
+ next if k == DYNAMIC_ATTRIBUTE_PREFIX + 'file' # we dont want to show file upload fields
87
+ fields_and_values[k] = {}
88
+ fields_and_values[k][:value] = self.dynamic_attributes[k]
89
+ fields_and_values[k][:xtype] = f[:xtype]
90
+ end
47
91
  else
48
- labels = form.definition_object.collect{|f| f[:fieldLabel]} if use_label
49
- keys = form.definition_object.collect{|f| f[:name]}
92
+ fields.each do |f|
93
+ k = f[:name]
94
+ next if k == 'file' # we dont want to show file upload fields
95
+ fields_and_values[k] = {}
96
+ fields_and_values[k][:value] = self.dynamic_attributes_without_prefix[k]
97
+ fields_and_values[k][:xtype] = f[:xtype]
98
+ fields_and_values[k][:fieldLabel] = f[:fieldLabel] if options[:use_label]
99
+ end
50
100
  end
51
101
 
102
+ # although we try and save integers as integers, we ensure here they are integers so that combobox value is selected
103
+ related_fields = form.related_fields
104
+ if related_fields.length > 0
105
+ related_fields.collect{|f| f[:name]}.each do |k|
106
+ k = DYNAMIC_ATTRIBUTE_PREFIX+k if options[:with_prefix]
107
+ fields_and_values[k][:value] = fields_and_values[k][:value].to_i
108
+ end
109
+ end
110
+
52
111
  sorted = {}
53
112
  i=0
54
- keys.each do |key|
55
- if with_prefix
56
- sorted[key] = self.dynamic_attributes[key]
113
+ fields_and_values.each do |key, field|
114
+ if options[:with_prefix]
115
+ sorted[key] = field[:value]
57
116
  else
58
- index = (use_label ? labels[i] : key)
59
- sorted[index] = self.dynamic_attributes_without_prefix[key]
60
- end
61
-
117
+ index = (options[:use_label] ? field[:fieldLabel] : key)
118
+ sorted[index] = field[:value]
119
+ end
62
120
  i += 1
63
121
  end
64
122
 
123
+ if options[:all]
124
+ # append attributes not in definition
125
+ attrs = (options[:with_prefix] ? self.dynamic_attributes : self.dynamic_attributes_without_prefix)
126
+ keys = fields_and_values.collect{|k,v| k}
127
+
128
+ i=0
129
+ sorted.each do |k,v|
130
+ index = (options[:use_label] ? keys[i] : k)
131
+ attrs.delete(index)
132
+ i += 1
133
+ end
134
+
135
+ attrs.each do |k,v|
136
+ if options[:with_prefix]
137
+ sorted[k] = self.dynamic_attributes[k]
138
+ else
139
+ index = (options[:use_label] ? k.titleize : k)
140
+ sorted[index] = self.dynamic_attributes_without_prefix[k]
141
+ end
142
+ end
143
+ end
144
+
65
145
  return sorted
66
146
  else
67
- if with_prefix
68
- return self.dynamic_attributes
69
- else
70
- return self.dynamic_attributes_without_prefix
71
- end
147
+ return (options[:with_prefix] ? self.dynamic_attributes : self.dynamic_attributes_without_prefix)
72
148
  end
73
149
  end
74
-
75
150
  end
@@ -1,5 +1,15 @@
1
1
  class DynamicForm < ActiveRecord::Base
2
+ attr_protected :created_at, :updated_at
3
+
2
4
  belongs_to :dynamic_form_model
5
+ belongs_to :created_by, :class_name => "User"
6
+ belongs_to :updated_by, :class_name => "User"
7
+
8
+ extend FriendlyId
9
+ friendly_id :description, :use => [:slugged], :slug_column => :internal_identifier
10
+ def should_generate_new_friendly_id?
11
+ new_record?
12
+ end
3
13
 
4
14
  validates_uniqueness_of :internal_identifier, :scope => :model_name, :case_sensitive => false
5
15
 
@@ -7,7 +17,7 @@ class DynamicForm < ActiveRecord::Base
7
17
  result = nil
8
18
  begin
9
19
  klass = Module.const_get(class_name)
10
- result = klass.is_a?(Class) ? ((klass.superclass == ActiveRecord::Base or klass.superclass == DynamicModel) ? true : nil) : nil
20
+ result = (klass.is_a?(Class) ? ((klass.superclass == ActiveRecord::Base or klass.superclass == DynamicModel) ? true : nil) : nil)
11
21
  rescue NameError
12
22
  result = nil
13
23
  end
@@ -15,12 +25,9 @@ class DynamicForm < ActiveRecord::Base
15
25
  end
16
26
 
17
27
  def self.get_form(klass_name, internal_identifier='')
18
- result = nil
19
- unless internal_identifier.blank?
20
- result = DynamicForm.find_by_model_name_and_internal_identifier(klass_name, internal_identifier)
21
- else
22
- result = DynamicForm.find_by_model_name_and_default(klass_name, true)
23
- end
28
+ result = nil
29
+ result = DynamicForm.find_by_model_name_and_internal_identifier(klass_name, internal_identifier) unless internal_identifier.blank?
30
+ result = DynamicForm.find_by_model_name_and_default(klass_name, true) if result.nil?
24
31
  result
25
32
  end
26
33
 
@@ -38,22 +45,30 @@ class DynamicForm < ActiveRecord::Base
38
45
  end
39
46
 
40
47
  def add_validation(def_object)
41
- def_object.each do |item|
42
- if item[:validator_function] and item[:validator_function] != ""
43
- item[:validator] = NonEscapeJsonString.new("function(v){ regex = this.initialConfig.validation_regex; return #{item[:validator_function]}; }")
44
- elsif item[:validation_regex] and item[:validation_regex] != ""
45
- item[:validator] = NonEscapeJsonString.new("function(v){ return validate_regex(v, this.initialConfig.validation_regex); }")
48
+ def_object.each do |item|
49
+ if !item[:validation_regex].blank?
50
+ item[:regex] = NonEscapeJsonString.new(item[:validation_regex].match('^\/') ? item[:validation_regex] : '/'+item[:validation_regex]+'/')
51
+ elsif !item[:validator_function].blank?
52
+ item[:validator] = NonEscapeJsonString.new("function(v){ return #{item[:validator_function]}; }")
46
53
  end
47
54
  end
48
55
 
49
56
  def_object
50
57
  end
58
+
59
+ def add_help_qtip(def_object)
60
+ def_object.each do |item|
61
+ item[:plugins] = NonEscapeJsonString.new('[new helpQtip("'+item[:help_qtip].gsub(/\"/,'\"')+'")]') unless item[:help_qtip].blank?
62
+ end
63
+
64
+ def_object
65
+ end
51
66
 
52
67
  # will return an array of field names that are of xtype 'related_combobox'
53
68
  def related_fields
54
69
  related_fields = []
55
70
  definition_object.each do |f|
56
- related_fields << f if f[:xtype] == 'related_combobox'
71
+ related_fields << f if ['related_combobox','related_searchbox'].include?(f[:xtype])
57
72
  end
58
73
 
59
74
  related_fields
@@ -74,53 +89,98 @@ class DynamicForm < ActiveRecord::Base
74
89
  array_of_fields.to_json
75
90
  end
76
91
 
77
- def to_extjs_formpanel(options={})
92
+ def focus_first_field_js
93
+ if self.focus_first_field
94
+ return "form.getComponent(0).focus(true, 200);"
95
+ else
96
+ return ''
97
+ end
98
+ end
99
+
100
+ def submit_empty_text_js
101
+ if self.submit_empty_text
102
+ return "submitEmptyText: true,"
103
+ else
104
+ return ''
105
+ end
106
+ end
107
+
108
+ def to_extjs_formpanel(options={})
78
109
  form_hash = {
79
- :xtype => 'form',
80
- :id => "dynamic_form_panel_#{model_name}",
110
+ :xtype => 'dynamic_form_panel',
81
111
  :url => options[:url],
82
112
  :title => self.description,
83
113
  :frame => true,
84
- :bodyStyle => 'padding: 5px 5px 0;'
114
+ :bodyStyle => 'padding: 5px 5px 0;',
115
+ :baseParams => {
116
+ :dynamic_form_id => self.id,
117
+ :dynamic_form_model_id => self.dynamic_form_model_id,
118
+ :model_name => self.model_name
119
+ },
120
+ :defaults => {},
121
+ :items => add_help_qtip(definition_with_validation)
85
122
  }
86
-
123
+ form_hash[:defaults][:msgTarget] = self.msg_target unless self.msg_target.blank?
87
124
  form_hash[:width] = options[:width] if options[:width]
88
- form_hash[:baseParams] = {}
89
125
  form_hash[:baseParams][:id] = options[:record_id] if options[:record_id]
90
- form_hash[:baseParams][:dynamic_form_id] = self.id
91
- form_hash[:baseParams][:dynamic_form_model_id] = self.dynamic_form_model_id
92
- form_hash[:baseParams][:model_name] = self.model_name
93
126
  form_hash[:listeners] = {
94
- :afterrender => NonEscapeJsonString.new("function(form) {Ext.getCmp('dynamic_form_panel_#{model_name}').getComponent(0).focus(false);}")
127
+ :afterrender => NonEscapeJsonString.new("function(form) { #{focus_first_field_js} }")
95
128
  }
96
- form_hash[:items] = definition_with_validation
97
129
  form_hash[:buttons] = []
98
- form_hash[:buttons][0] = {
99
- :text => 'Submit',
130
+ form_hash[:buttons] << {
131
+ :text => self.submit_button_label,
100
132
  :listeners => NonEscapeJsonString.new("{
101
- \"click\":function(button){
102
- var formPanel = Ext.getCmp('dynamic_form_panel_#{model_name}');
103
- formPanel.getForm().submit({
104
- reset:true,
105
- success:function(form, action){
106
- Ext.getCmp('dynamic_form_panel_#{model_name}').findParentByType('window').close();
107
-
108
- if (Ext.getCmp('#{model_name}')){
109
- Ext.getCmp('#{model_name}').query('shared_dynamiceditablegrid')[0].store.load();
110
- }
111
- },
112
- failure:function(form, action){
113
- Ext.Msg.alert(action.response.responseText);
114
- }
133
+ click:function(button){
134
+ var form = button.findParentByType('form').getForm();
135
+ //jsonSubmit option only works when there is no filefield so we have to do it ourselves
136
+ //JSON is important to preserve data types (ie. we want integers to save as integers not strings)
137
+ var form_data = {};
138
+ Ext.each(form.getFields().items, function(field) {
139
+ if (Ext.Array.indexOf(['filefield','fileuploadfield'], field.xtype) < 0){
140
+ form_data[field.name] = field.getValue();
141
+ }
115
142
  });
143
+ if (form.isValid()){
144
+ form.submit({
145
+ #{submit_empty_text_js}
146
+ reset:false,
147
+ params:{
148
+ form_data_json: Ext.encode(form_data)
149
+ },
150
+ success:function(form, action){
151
+ var obj = Ext.decode(action.response.responseText);
152
+ if(obj.success){
153
+ if (form.getRecord()){
154
+ form.owner.fireEvent('afterupdate');
155
+ }else{
156
+ form.owner.fireEvent('aftercreate', {
157
+ record: obj
158
+ });
159
+ }
160
+ }else{
161
+ Ext.Msg.alert('Error', obj.message);
162
+ }
163
+ },
164
+ failure:function(form, action){
165
+ Ext.Msg.alert('Error', action.response.responseText);
166
+ }
167
+ });
168
+ }else{
169
+ Ext.Msg.alert('Error','Please complete form.');
170
+ }
116
171
  }
117
172
  }")
118
173
  }
119
- form_hash[:buttons][1] = {
120
- :text => 'Cancel',
174
+ form_hash[:buttons] << {
175
+ :text => self.cancel_button_label,
121
176
  :listeners => NonEscapeJsonString.new("{
122
177
  \"click\":function(button){
123
- Ext.getCmp('dynamic_form_panel_#{model_name}').findParentByType('window').close();
178
+ var form = button.findParentByType('form');
179
+ if (form.close_selector){
180
+ form.up(form.close_selector).close();
181
+ }else{
182
+ form.up('window').close();
183
+ }
124
184
  }
125
185
  }")
126
186
  }
@@ -136,62 +196,76 @@ class DynamicForm < ActiveRecord::Base
136
196
  # :widget_result_id =>
137
197
  # :width =>
138
198
  def to_extjs_widget(options={})
139
- options[:width] = "'auto'" if options[:width].nil?
140
-
141
- #NOTE: The random nbsp; forces IE to eval this javascript!
142
- javascript = "Ext.QuickTips.init();
143
-
144
- Ext.create('Ext.form.Panel',{
145
- id: 'dynamic_form_panel_#{model_name}',
146
- url:'#{options[:url]}',
147
- title: '#{self.description}',"
148
-
149
- javascript += "\"width\": #{options[:width]}," if options[:width]
150
-
151
- javascript += "frame: true,
152
- bodyStyle:'padding: 5px 5px 0;',
153
- renderTo: 'dynamic_form_target',
154
- baseParams: {
155
- dynamic_form_id: #{self.id},
156
- dynamic_form_model_id: #{self.dynamic_form_model_id},
157
- model_name: '#{self.model_name}'
158
- },
159
- items: #{definition_with_validation.to_json},
160
- listeners: {
161
- afterrender: function(form) {
162
- Ext.getCmp('dynamic_form_panel_#{model_name}').getComponent(0).focus(false);
163
- }
164
- },
165
- buttons: [{
166
- text: 'Submit',
167
- listeners:{
168
- 'click':function(button){
169
- var formPanel = Ext.getCmp('dynamic_form_panel_#{model_name}');
170
- formPanel.getForm().submit({
171
- reset:true,
172
- success:function(form, action){
173
- json_hash = Ext.decode(action.response.responseText);
174
- Ext.get('#{options[:widget_result_id]}').dom.innerHTML = json_hash.response;
175
- var scriptTags = Ext.get('#{options[:widget_result_id]}').dom.getElementsByTagName('script');
176
- Ext.each(scriptTags, function(scriptTag){
177
- eval(scriptTag.text);
178
- });
179
- },
180
- failure:function(form, action){
181
- if (action.response){
182
- json_hash = Ext.decode(action.response.responseText);
183
- Ext.get('#{options[:widget_result_id]}').dom.innerHTML = json_hash.response;
184
- }
185
- }
186
- });
187
- }
199
+ javascript = "Ext.QuickTips.init(); Ext.create('Ext.form.Panel',"
200
+
201
+ config_hash = {
202
+ :url => "#{options[:url]}",
203
+ :title => "#{self.description}",
204
+ :frame => true,
205
+ :bodyStyle => 'padding: 5px 5px 0;',
206
+ :renderTo => 'dynamic_form_target',
207
+ :baseParams => {
208
+ :dynamic_form_id => self.id,
209
+ :dynamic_form_model_id => self.dynamic_form_model_id,
210
+ :model_name => self.model_name
211
+ },
212
+ :items => add_help_qtip(definition_with_validation),
213
+ :defaults => {},
214
+ :listeners => {
215
+ :afterrender => NonEscapeJsonString.new("function(form) { #{focus_first_field_js} }")
216
+ }
217
+ }
218
+ config_hash[:defaults][:msgTarget] = self.msg_target unless self.msg_target.blank?
219
+ config_hash[:width] = options[:width] if options[:width]
220
+ config_hash[:buttons] = []
221
+ config_hash[:buttons] << {
222
+ :text => self.submit_button_label,
223
+ :listeners => NonEscapeJsonString.new("{
224
+ \"click\":function(button){
225
+ var form = button.findParentByType('form').getForm();
226
+ //jsonSubmit option only works when there is no filefield so we have to do it ourselves
227
+ //JSON is important to preserve data types (ie. we want integers to save as integers not strings)
228
+ var form_data = {};
229
+ Ext.each(form.getFields().items, function(field) {
230
+ if (Ext.Array.indexOf(['filefield','fileuploadfield'], field.xtype) < 0){
231
+ form_data[field.name] = field.getValue();
232
+ }
233
+ });
234
+ form.submit({
235
+ #{submit_empty_text_js}
236
+ reset:true,
237
+ params:{
238
+ form_data_json: Ext.encode(form_data)
239
+ },
240
+ success:function(form, action){
241
+ json_hash = Ext.decode(action.response.responseText);
242
+ Ext.get('#{options[:widget_result_id]}').dom.innerHTML = json_hash.response;
243
+ var scriptTags = Ext.get('#{options[:widget_result_id]}').dom.getElementsByTagName('script');
244
+ Ext.each(scriptTags, function(scriptTag){
245
+ eval(scriptTag.text);
246
+ });
247
+ },
248
+ failure:function(form, action){
249
+ if (action.response){
250
+ json_hash = Ext.decode(action.response.responseText);
251
+ Ext.get('#{options[:widget_result_id]}').dom.innerHTML = json_hash.response;
252
+ }
188
253
  }
189
-
190
- },{
191
- text: 'Cancel'
192
- }]
193
- });"
194
- #logger.info javascript
254
+ });
255
+ }
256
+ }")
257
+ }
258
+ config_hash[:buttons] << {
259
+ :text => 'Reset',
260
+ :listeners => NonEscapeJsonString.new("{
261
+ \"click\":function(button){
262
+ button.findParentByType('form').getForm().reset();
263
+ }
264
+ }")
265
+ }
266
+
267
+ javascript += "#{config_hash.to_json});"
268
+ #logger.info javascript
195
269
  javascript
196
270
  end
197
271