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.
- data/app/controllers/erp_forms/erp_app/desktop/dynamic_forms/base_controller.rb +4 -37
- data/app/controllers/erp_forms/erp_app/desktop/dynamic_forms/data_controller.rb +348 -82
- data/app/controllers/erp_forms/erp_app/desktop/dynamic_forms/forms_controller.rb +110 -15
- data/app/controllers/erp_forms/erp_app/desktop/dynamic_forms/models_controller.rb +19 -3
- data/app/mailers/dynamic_form_mailer.rb +35 -0
- data/app/models/dynamic_datum.rb +97 -22
- data/app/models/dynamic_form.rb +172 -98
- data/app/models/dynamic_form_document.rb +4 -11
- data/app/models/dynamic_form_model.rb +46 -22
- data/app/models/ticket.rb +4 -0
- data/app/views/dynamic_form_mailer/widget_email_with_attachments.html.erb +3 -0
- data/app/views/dynamic_form_mailer/widget_email_with_attachments.text.erb +3 -0
- data/app/widgets/dynamic_forms/base.rb +101 -19
- data/app/widgets/dynamic_forms/javascript/dynamic_forms.js +40 -38
- data/app/widgets/dynamic_forms/views/error.html.erb +1 -0
- data/db/data_migrations/20110608185830_create_default_dynamic_models_and_forms.rb +2 -0
- data/db/data_migrations/20120824013449_create_ticket_form.rb +1 -0
- data/db/data_migrations/20121026013449_update_ticket_form.rb +64 -0
- data/db/data_migrations/{20120904191738_update_contact_form.rb → 20121026191738_update_contact_form.rb} +4 -0
- data/db/migrate/20110530193446_dynamic_forms.rb +12 -0
- data/db/migrate/20121007022323_upgrade_dynamic_forms_table.rb +31 -0
- data/lib/erp_forms.rb +4 -0
- data/lib/erp_forms/dynamic_form_field.rb +31 -28
- data/lib/erp_forms/dynamic_grid_column.rb +2 -2
- data/lib/erp_forms/engine.rb +5 -0
- data/lib/erp_forms/extensions/active_record/acts_as_commentable.rb +33 -0
- data/lib/erp_forms/extensions/active_record/acts_as_dynamic_form_model.rb +80 -0
- data/lib/erp_forms/extensions/active_record/has_dynamic_forms.rb +4 -4
- data/lib/erp_forms/extensions/extensions.rb +2 -0
- data/lib/erp_forms/extensions/railties/action_view.rb +2 -2
- data/lib/erp_forms/version.rb +2 -2
- data/public/javascripts/erp_app/desktop/applications/dynamic_forms/center_region.js +2 -1
- data/public/javascripts/erp_app/desktop/applications/dynamic_forms/dynamic_data_grid.js +264 -82
- data/public/javascripts/erp_app/desktop/applications/dynamic_forms/form_builder.js +1476 -58
- data/public/javascripts/erp_app/desktop/applications/dynamic_forms/module.js +24 -1
- data/public/javascripts/erp_app/desktop/applications/dynamic_forms/west_region.js +493 -210
- data/public/javascripts/erp_app/shared/dynamic_forms/dynamic_form_fields.js +82 -20
- data/public/javascripts/erp_app/shared/dynamic_forms/dynamic_forms_validation.js +23 -3
- data/spec/dummy/config/application.rb +6 -2
- data/spec/dummy/config/environments/spec.rb +3 -0
- data/spec/dummy/db/data_migrations/20110109173616_create_capability_scope_types.erp_tech_svcs.rb +15 -0
- data/spec/dummy/db/data_migrations/20110525001935_add_usd_currency.erp_base_erp_svcs.rb +12 -0
- data/spec/dummy/db/data_migrations/20110608185830_create_default_dynamic_models_and_forms.erp_forms.rb +33 -0
- data/spec/dummy/db/data_migrations/20110609150135_add_iso_codes.erp_base_erp_svcs.rb +19 -0
- data/spec/dummy/db/data_migrations/20110728201729_erp_app_setup.erp_app.rb +252 -0
- data/spec/dummy/db/data_migrations/20110728201733_update_preferences.erp_app.rb +53 -0
- data/spec/dummy/db/data_migrations/20110802200222_schedule_delete_expired_sessions_job.erp_tech_svcs.rb +16 -0
- data/spec/dummy/db/data_migrations/20110816161238_create_desktop_app_audit_log_viewer.erp_app.rb +21 -0
- data/spec/dummy/db/data_migrations/20110817160743_add_file_manager_application.erp_app.rb +32 -0
- data/spec/dummy/db/data_migrations/20110828190913_create_desktop_app_dynamic_forms.erp_forms.rb +19 -0
- data/spec/dummy/db/data_migrations/20110913145838_setup_compass_ae_instance.erp_base_erp_svcs.rb +12 -0
- data/spec/dummy/db/data_migrations/20111108183739_add_default_capabilities.erp_app.rb +23 -0
- data/spec/dummy/db/data_migrations/20111108183740_add_new_contact_widgets.erp_app.rb +42 -0
- data/spec/dummy/db/data_migrations/20111111144706_setup_audit_log_types.erp_tech_svcs.rb +22 -0
- data/spec/dummy/db/data_migrations/20120109173616_create_download_capability_type.erp_tech_svcs.rb +14 -0
- data/spec/dummy/db/data_migrations/20120229160222_add_userinfo_widget.erp_app.rb +29 -0
- data/spec/dummy/db/data_migrations/20120405193721_create_party_and_role_type_for_communication_events.erp_app.rb +11 -0
- data/spec/dummy/db/data_migrations/20120411180756_create_user_management_mobile_application.erp_app.rb +19 -0
- data/spec/dummy/db/data_migrations/20120418164215_create_configuration_management_desktop_application.erp_app.rb +23 -0
- data/spec/dummy/db/data_migrations/20120824013449_create_ticket_form.erp_forms.rb +67 -0
- data/spec/dummy/db/data_migrations/20121026013449_update_ticket_form.erp_forms.rb +65 -0
- data/spec/dummy/db/data_migrations/20121026191738_update_contact_form.erp_forms.rb +27 -0
- data/spec/dummy/db/data_migrations/20121116155018_create_group_relationship_and_role_types.erp_tech_svcs.rb +20 -0
- data/spec/dummy/db/data_migrations/20121130201859_upgrade_remove_system_mgmt_app.erp_app.rb +16 -0
- data/spec/dummy/db/data_migrations/20121130212146_note_capabilities.erp_tech_svcs.rb +24 -0
- data/spec/dummy/db/data_migrations/20121218175028_create_security_management_desktop_application.erp_app.rb +23 -0
- data/spec/dummy/db/migrate/20121213234847_base_erp_services.erp_base_erp_svcs.rb +461 -0
- data/spec/dummy/db/migrate/20121213234848_base_tech_services.erp_tech_svcs.rb +255 -0
- data/spec/dummy/db/migrate/20121213234849_create_has_attribute_tables.erp_tech_svcs.rb +39 -0
- data/spec/dummy/db/migrate/20121213234850_base_app_framework.erp_app.rb +276 -0
- data/spec/dummy/db/migrate/20121213234851_dynamic_forms.erp_forms.rb +95 -0
- data/spec/dummy/db/migrate/20121213234852_create_tickets.erp_forms.rb +19 -0
- data/spec/dummy/db/migrate/20121213234853_upgrade_dynamic_forms_table.erp_forms.rb +32 -0
- data/spec/dummy/db/migrate/20130107181041_create_groups.erp_tech_svcs.rb +19 -0
- data/spec/dummy/db/migrate/20130107181042_upgrade_security.erp_tech_svcs.rb +54 -0
- data/spec/dummy/db/migrate/20130107181043_upgrade_security2.erp_tech_svcs.rb +270 -0
- data/spec/dummy/db/schema.rb +879 -0
- data/spec/dummy/db/spec.sqlite3 +0 -0
- data/spec/dummy/log/spec.log +13580 -0
- data/spec/models/dynamic_form_model_spec.rb +1 -1
- data/spec/spec_helper.rb +11 -3
- 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
|
-
:
|
|
17
|
-
:
|
|
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
|
-
:
|
|
31
|
-
:
|
|
32
|
-
:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
74
|
-
|
|
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
|
-
|
|
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
|
+
|
data/app/models/dynamic_datum.rb
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
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
|
-
#
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
46
|
-
|
|
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
|
-
|
|
49
|
-
|
|
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
|
-
|
|
55
|
-
if with_prefix
|
|
56
|
-
sorted[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 ?
|
|
59
|
-
sorted[index] =
|
|
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
|
-
|
|
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
|
data/app/models/dynamic_form.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
20
|
-
|
|
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[:
|
|
43
|
-
item[:
|
|
44
|
-
elsif item[:
|
|
45
|
-
item[:validator] = NonEscapeJsonString.new("function(v){ return
|
|
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]
|
|
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
|
|
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 => '
|
|
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) {
|
|
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]
|
|
99
|
-
:text =>
|
|
130
|
+
form_hash[:buttons] << {
|
|
131
|
+
:text => self.submit_button_label,
|
|
100
132
|
:listeners => NonEscapeJsonString.new("{
|
|
101
|
-
|
|
102
|
-
var
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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]
|
|
120
|
-
:text =>
|
|
174
|
+
form_hash[:buttons] << {
|
|
175
|
+
:text => self.cancel_button_label,
|
|
121
176
|
:listeners => NonEscapeJsonString.new("{
|
|
122
177
|
\"click\":function(button){
|
|
123
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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
|
|