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
@@ -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