drg_cms 0.6.0.1 → 0.6.1.1.1
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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/drg_cms/drg_cms.js +454 -145
- data/app/assets/javascripts/drg_cms_application.js +1 -1
- data/app/assets/stylesheets/drg_cms/drg_cms.css +635 -244
- data/app/assets/stylesheets/drg_cms/select-multiple.css +18 -12
- data/app/assets/stylesheets/drg_cms_cms.css +1 -1
- data/app/controllers/cmsedit_controller.rb +515 -335
- data/app/controllers/dc_application_controller.rb +378 -111
- data/app/controllers/dc_common_controller.rb +105 -14
- data/app/{controllers → controls}/browse_models_control.rb +0 -0
- data/app/controls/dc_help_control.rb +126 -0
- data/app/{controllers → controls}/dc_page_control.rb +24 -8
- data/app/controls/dc_poll_result_control.rb +88 -0
- data/app/controls/dc_report.rb +223 -0
- data/app/{controllers → controls}/design_element_settings_control.rb +0 -0
- data/app/forms/all_options.yml +44 -9
- data/app/forms/cms_menu.yml +28 -18
- data/app/forms/dc_ad.yml +11 -22
- data/app/forms/dc_big_table.yml +1 -0
- data/app/forms/dc_big_table_value.yml +1 -0
- data/app/forms/dc_category.yml +2 -1
- data/app/forms/dc_design.yml +20 -16
- data/app/forms/dc_filter.yml +3 -6
- data/app/forms/dc_help_1.yml +109 -0
- data/app/forms/dc_journal.yml +3 -1
- data/app/forms/dc_json_ld.yml +59 -0
- data/app/forms/dc_key_value.yml +32 -0
- data/app/forms/dc_link.yml +1 -1
- data/app/forms/dc_menu.yml +2 -0
- data/app/forms/dc_menu_item.yml +2 -0
- data/app/forms/dc_page.yml +3 -5
- data/app/forms/dc_part.yml +1 -0
- data/app/forms/dc_piece.yml +1 -0
- data/app/forms/dc_poll.yml +15 -5
- data/app/forms/dc_poll_item.yml +2 -1
- data/app/forms/dc_poll_result.yml +83 -0
- data/app/forms/dc_poll_result_export.yml +35 -0
- data/app/forms/dc_seo.yml +33 -0
- data/app/forms/dc_simple_menu.yml +2 -0
- data/app/forms/dc_site.yml +4 -12
- data/app/forms/dc_user.yml +27 -11
- data/app/forms/dc_user_role.yml +3 -0
- data/app/forms/json_ld_schema.yml +168 -0
- data/app/helpers/cms_common_helper.rb +375 -0
- data/app/helpers/cms_edit_helper.rb +506 -0
- data/app/helpers/cms_helper.rb +268 -0
- data/app/helpers/cms_index_helper.rb +580 -0
- data/app/helpers/dc_application_helper.rb +218 -306
- data/app/models/concerns/dc_page_concern.rb +40 -6
- data/app/models/concerns/dc_policy_rule_concern.rb +20 -8
- data/app/models/concerns/dc_seo_concern.rb +66 -0
- data/app/models/concerns/dc_site_concern.rb +67 -44
- data/app/models/concerns/dc_user_concern.rb +57 -18
- data/app/models/dc_design.rb +30 -18
- data/app/models/dc_filter.rb +22 -13
- data/app/models/dc_json_ld.rb +152 -0
- data/app/models/dc_key_value.rb +48 -0
- data/app/models/dc_key_value_store.rb +1 -0
- data/app/models/dc_memory.rb +8 -1
- data/app/models/dc_page.rb +0 -1
- data/app/models/dc_permission.rb +49 -9
- data/app/models/dc_policy.rb +25 -14
- data/app/models/dc_policy_role.rb +22 -11
- data/app/models/dc_poll.rb +39 -19
- data/app/models/dc_poll_result.rb +46 -0
- data/app/models/dc_temp.rb +140 -0
- data/app/models/dc_user_role.rb +2 -2
- data/app/models/drgcms_form_fields.rb +12 -1
- data/app/models/drgcms_form_fields/action.rb +61 -0
- data/app/models/drgcms_form_fields/comment.rb +8 -4
- data/app/models/drgcms_form_fields/date_picker.rb +11 -9
- data/app/models/drgcms_form_fields/date_select.rb +1 -1
- data/app/models/drgcms_form_fields/datetime_picker.rb +12 -10
- data/app/models/drgcms_form_fields/datetime_select.rb +1 -1
- data/app/models/drgcms_form_fields/drgcms_field.rb +55 -9
- data/app/models/drgcms_form_fields/embedded.rb +26 -16
- data/app/models/drgcms_form_fields/file_field.rb +52 -0
- data/app/models/drgcms_form_fields/file_select.rb +2 -2
- data/app/models/drgcms_form_fields/hash_field.rb +90 -0
- data/app/models/drgcms_form_fields/hidden_field.rb +1 -1
- data/app/models/drgcms_form_fields/html_field.rb +1 -1
- data/app/models/drgcms_form_fields/link_to.rb +2 -2
- data/app/models/drgcms_form_fields/method.rb +66 -0
- data/app/models/drgcms_form_fields/multitext_autocomplete.rb +23 -14
- data/app/models/drgcms_form_fields/number_field.rb +15 -6
- data/app/models/drgcms_form_fields/radio.rb +96 -0
- data/app/models/drgcms_form_fields/readonly.rb +2 -2
- data/app/models/drgcms_form_fields/select.rb +92 -29
- data/app/models/drgcms_form_fields/text_area.rb +1 -1
- data/app/models/drgcms_form_fields/text_autocomplete.rb +31 -17
- data/app/models/drgcms_form_fields/text_field.rb +1 -1
- data/app/models/drgcms_form_fields/text_with_select.rb +6 -3
- data/app/models/drgcms_form_fields/tree_select.rb +15 -4
- data/app/{helpers → renderers}/dc_ad_renderer.rb +0 -0
- data/app/{helpers → renderers}/dc_big_menu_renderer.rb +1 -0
- data/app/{helpers → renderers}/dc_captcha_renderer.rb +0 -0
- data/app/{helpers → renderers}/dc_common_renderer.rb +0 -0
- data/app/{helpers → renderers}/dc_gallery_renderer.rb +1 -0
- data/app/{helpers → renderers}/dc_menu_renderer.rb +11 -4
- data/app/{helpers → renderers}/dc_page_renderer.rb +1 -0
- data/app/{helpers → renderers}/dc_part_renderer.rb +5 -4
- data/app/{helpers → renderers}/dc_piece_renderer.rb +1 -1
- data/app/{helpers → renderers}/dc_poll_renderer.rb +91 -64
- data/app/{helpers → renderers}/dc_renderer.rb +1 -0
- data/app/{helpers → renderers}/dc_simple_menu_renderer.rb +1 -0
- data/app/views/cmsedit/{remove_edit_stuff.js.erb → __remove_edit_stuff.js.erb} +0 -0
- data/app/views/cmsedit/{show.html.erb → __show.html.erb} +0 -0
- data/app/views/cmsedit/_edit_stuff.html.erb +4 -25
- data/app/views/cmsedit/_form.html.erb +4 -3
- data/app/views/cmsedit/_result.html.erb +2 -3
- data/app/views/cmsedit/edit.html.erb +4 -1
- data/app/views/cmsedit/index.html.erb +7 -1
- data/app/views/cmsedit/new.html.erb +3 -1
- data/app/views/dc_common/_help.html.erb +17 -0
- data/app/views/layouts/models.html.erb +2 -1
- data/config/locales/drgcms_en.yml +27 -3
- data/config/locales/drgcms_sl.yml +32 -5
- data/config/locales/models_en.yml +65 -17
- data/config/locales/models_sl.yml +69 -18
- data/drg_cms.gemspec +1 -1
- data/lib/drg_cms.rb +61 -1
- data/lib/drg_cms/version.rb +1 -1
- data/lib/generators/new_drg_form/new_drg_form_generator.rb +9 -2
- data/lib/tasks/database.rake +6 -56
- metadata +73 -54
- data/app/assets/stylesheets/drg_cms/__jquery-ui.css +0 -339
- data/app/helpers/application_helper.rb +0 -2
- data/app/helpers/cmsedit_helper.rb +0 -888
- data/app/models/dc_dummy.rb +0 -102
- data/test/fixtures/drg_cms_test_data.rb +0 -87
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
-ms-transition: border linear 0.2s, box-shadow linear 0.2s;
|
|
29
29
|
-o-transition: border linear 0.2s, box-shadow linear 0.2s;
|
|
30
30
|
transition: border linear 0.2s, box-shadow linear 0.2s;
|
|
31
|
-
border:
|
|
32
|
-
-webkit-border-radius:
|
|
33
|
-
-moz-border-radius:
|
|
34
|
-
border-radius:
|
|
31
|
+
border: 1px dashed #888;
|
|
32
|
+
-webkit-border-radius: 1px;
|
|
33
|
+
-moz-border-radius: 1px;
|
|
34
|
+
border-radius: 1px;
|
|
35
35
|
position: relative;
|
|
36
36
|
height: 200px;
|
|
37
37
|
padding: 0;
|
|
@@ -39,12 +39,9 @@
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
.ms-container .ms-list.ms-focus{
|
|
42
|
-
border
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
|
|
46
|
-
outline: 0;
|
|
47
|
-
outline: thin dotted \9;
|
|
42
|
+
border: 1px solid rgba(76,154,255, 1);
|
|
43
|
+
outline: 1px solid rgba(76,154,255, 1);
|
|
44
|
+
border-radius: 1px;
|
|
48
45
|
}
|
|
49
46
|
|
|
50
47
|
.ms-container ul{
|
|
@@ -65,12 +62,15 @@
|
|
|
65
62
|
}
|
|
66
63
|
|
|
67
64
|
.ms-container .ms-selectable li.ms-elem-selectable{
|
|
68
|
-
border-bottom: 1px #eee solid;
|
|
69
65
|
padding: 2px 10px;
|
|
70
|
-
color: #
|
|
66
|
+
color: #444;
|
|
71
67
|
font-size: 14px;
|
|
72
68
|
}
|
|
73
69
|
|
|
70
|
+
.ms-container .ms-selectable li:nth-child(odd) {
|
|
71
|
+
background-color: #f4f4f4;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
74
|
.ms-container .ms-selectable li.ms-hover{
|
|
75
75
|
cursor: pointer;
|
|
76
76
|
color: #fff;
|
|
@@ -88,6 +88,12 @@
|
|
|
88
88
|
display: none;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
|
|
92
|
+
.ms-container .ms-selected {
|
|
93
|
+
font-weight: 600;
|
|
94
|
+
}
|
|
95
|
+
|
|
91
96
|
.pull-right.ms-elem-selected{
|
|
92
97
|
float: right;
|
|
98
|
+
font-size: smaller;
|
|
93
99
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#coding: utf-8
|
|
2
1
|
#--
|
|
3
2
|
# Copyright (c) 2012+ Damjan Rems
|
|
4
3
|
#
|
|
@@ -76,211 +75,20 @@
|
|
|
76
75
|
# If filter method returns false user will be presented with flash error.
|
|
77
76
|
########################################################################
|
|
78
77
|
class CmseditController < DcApplicationController
|
|
79
|
-
before_action :check_authorization, :except => [:login, :logout, :test]
|
|
78
|
+
before_action :check_authorization, :except => [:login, :logout, :test, :run]
|
|
80
79
|
before_action :dc_reload_patches if Rails.env.development?
|
|
80
|
+
protect_from_forgery with: :null_session, only: Proc.new { |c| c.request.format.json? }
|
|
81
81
|
|
|
82
82
|
layout 'cms'
|
|
83
83
|
|
|
84
84
|
########################################################################
|
|
85
|
-
#
|
|
86
|
-
########################################################################
|
|
87
|
-
def check_sort_options() #:nodoc:
|
|
88
|
-
table_name = @tables.first[1]
|
|
89
|
-
old_sort = session[table_name][:sort].to_s
|
|
90
|
-
sort, direction = old_sort.split(' ')
|
|
91
|
-
# sort is requested
|
|
92
|
-
if params['sort']
|
|
93
|
-
# reverse sort if same selected
|
|
94
|
-
if params['sort'] == sort
|
|
95
|
-
direction = (direction == '1') ? '-1' : '1'
|
|
96
|
-
end
|
|
97
|
-
direction ||= 1
|
|
98
|
-
sort = params[:sort]
|
|
99
|
-
session[table_name][:sort] = "#{params['sort']} #{direction}"
|
|
100
|
-
session[table_name][:page] = 1
|
|
101
|
-
end
|
|
102
|
-
@records.sort( sort => direction.to_i ) if session[table_name][:sort]
|
|
103
|
-
params['sort'] = nil # otherwise there is problem with other links
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
########################################################################
|
|
107
|
-
# Set aditional filter options when filter is defined by filter method in control object.
|
|
108
|
-
########################################################################
|
|
109
|
-
def user_filter_options(model) #:nodoc:
|
|
110
|
-
table_name = @tables.first[1]
|
|
111
|
-
if session[table_name]
|
|
112
|
-
DcFilter.get_filter(session[table_name][:filter]) || model
|
|
113
|
-
else
|
|
114
|
-
model
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
########################################################################
|
|
119
|
-
# Will set session[table_name][:filter] and save last filter settings to session.
|
|
120
|
-
# subroutine of check_filter_options.
|
|
121
|
-
########################################################################
|
|
122
|
-
def set_session_filter(table_name)
|
|
123
|
-
if params[:filter] == 'off' # clear all values
|
|
124
|
-
session[table_name][:filter] = nil
|
|
125
|
-
return
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
filter_value = if params[:filter_value].nil?
|
|
129
|
-
# NIL indicates that no filtering is needed
|
|
130
|
-
'#NIL'
|
|
131
|
-
else
|
|
132
|
-
if params[:filter_value].class == String and params[:filter_value][0] == '@'
|
|
133
|
-
# Internal value. Remove leading @ and evaluate expression
|
|
134
|
-
expression = DcInternals.get(params[:filter_value])
|
|
135
|
-
eval(expression) rescue nil
|
|
136
|
-
else
|
|
137
|
-
# No filter when empty
|
|
138
|
-
params[:filter_value] == '' ? '#NIL' : params[:filter_value]
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
# if filter field parameter is omitted then just set filter value
|
|
142
|
-
session[table_name][:filter] =
|
|
143
|
-
if params[:filter_field].nil?
|
|
144
|
-
saved = YAML.load(session[table_name][:filter])
|
|
145
|
-
saved['value'] = filter_value
|
|
146
|
-
saved.to_yaml
|
|
147
|
-
else
|
|
148
|
-
# As field defined. Split name and alternative input field
|
|
149
|
-
field = if params[:filter_field].match(' as ')
|
|
150
|
-
params[:filter_input] = params[:filter_field].split(' as ').last.strip
|
|
151
|
-
params[:filter_field].split(' as ').first.strip
|
|
152
|
-
else
|
|
153
|
-
params[:filter_field]
|
|
154
|
-
end
|
|
155
|
-
#
|
|
156
|
-
{'field' => field,
|
|
157
|
-
'operation' => params[:filter_oper],
|
|
158
|
-
'value' => filter_value,
|
|
159
|
-
'input' => params[:filter_input],
|
|
160
|
-
'table' => table_name }.to_yaml
|
|
161
|
-
end
|
|
162
|
-
# must be. Otherwise kaminari includes parameter on paging
|
|
163
|
-
params[:filter] = nil
|
|
164
|
-
params[:filter_id] = nil
|
|
165
|
-
params[:filter_oper] = nil
|
|
166
|
-
params[:filter_input] = nil
|
|
167
|
-
params[:filter_field] = nil
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
########################################################################
|
|
171
|
-
# Will check and set current filter options for result set. Subroutine of index method.
|
|
172
|
-
########################################################################
|
|
173
|
-
def check_filter_options() #:nodoc:
|
|
174
|
-
table_name = @tables.first[1]
|
|
175
|
-
model = @tables.first[0]
|
|
176
|
-
session[table_name] ||= {}
|
|
177
|
-
# process page
|
|
178
|
-
session[table_name][:page] = params[:page] if params[:page]
|
|
179
|
-
# new filter is applied
|
|
180
|
-
if params[:filter]
|
|
181
|
-
set_session_filter(table_name)
|
|
182
|
-
session[table_name][:page] = 1
|
|
183
|
-
end
|
|
184
|
-
# if data model has field dc_site_id ensure that only documents which belong to the site are selected.
|
|
185
|
-
site_id = dc_get_site._id if dc_get_site
|
|
186
|
-
# dont't filter site if no dc_site_id field or user is ADMIN
|
|
187
|
-
site_id = nil if !model.method_defined?('dc_site_id') or dc_user_can(DcPermission::CAN_ADMIN)
|
|
188
|
-
site_id = nil if session[table_name][:filter].to_s.match('dc_site_id')
|
|
189
|
-
#
|
|
190
|
-
if @records = DcFilter.get_filter(session[table_name][:filter])
|
|
191
|
-
@records = @records.and(dc_site_id: site_id) if site_id
|
|
192
|
-
else
|
|
193
|
-
@records = if site_id
|
|
194
|
-
model.where(dc_site_id: site_id)
|
|
195
|
-
else
|
|
196
|
-
model
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
=begin
|
|
200
|
-
# TODO Use only fields requested. Higly experimental but necessary in some scenarios
|
|
201
|
-
if (columns = @form['result_set']['columns'])
|
|
202
|
-
cols = []
|
|
203
|
-
columns.each { |k,v| cols << v['name'] }
|
|
204
|
-
p '*',cols,'*'
|
|
205
|
-
@records = @records.only(cols)
|
|
206
|
-
end
|
|
207
|
-
=end
|
|
208
|
-
# pagination if required
|
|
209
|
-
per_page = (@form['result_set']['per_page'] || 30).to_i
|
|
210
|
-
@records = @records.page(session[table_name][:page]).per(per_page) if per_page > 0
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
########################################################################
|
|
214
|
-
# Process index action for normal collections.
|
|
215
|
-
########################################################################
|
|
216
|
-
def process_collections #:nodoc
|
|
217
|
-
# If result_set is not defined on form, then it will fail. :return_to should know where to go
|
|
218
|
-
if @form['result_set'].nil?
|
|
219
|
-
process_return_to(params[:return_to] || 'reload')
|
|
220
|
-
return true
|
|
221
|
-
end
|
|
222
|
-
# for now enable only filtering of top level documents
|
|
223
|
-
if @tables.size == 1
|
|
224
|
-
check_filter_options()
|
|
225
|
-
check_sort_options()
|
|
226
|
-
end
|
|
227
|
-
# result set is defined by filter method in control object
|
|
228
|
-
if @form['result_set']['filter']
|
|
229
|
-
if respond_to?(@form['result_set']['filter'])
|
|
230
|
-
@records = send @form['result_set']['filter']
|
|
231
|
-
# something iz wrong. flash[] should have explanation.
|
|
232
|
-
if @records.class == FalseClass
|
|
233
|
-
@records = []
|
|
234
|
-
render(action: :index)
|
|
235
|
-
return true
|
|
236
|
-
end
|
|
237
|
-
# pagination but only if not already set
|
|
238
|
-
unless (@form['table'] == 'dc_memory' or @records.options[:limit])
|
|
239
|
-
per_page = (@form['result_set']['per_page'] || 30).to_i
|
|
240
|
-
@records = @records.page(params[:page]).per(per_page) if per_page > 0
|
|
241
|
-
end
|
|
242
|
-
else
|
|
243
|
-
Rails.logger.error "Error: result_set:filter: #{@form['result_set']['filter']} not found in controls!"
|
|
244
|
-
end
|
|
245
|
-
else
|
|
246
|
-
if @tables.size > 1
|
|
247
|
-
rec = @tables.first[0].find(@ids.first) # top most document.id
|
|
248
|
-
1.upto(@tables.size - 2) { |i| rec = rec.send(@tables[i][1].pluralize).find(@ids[i]) } # find embedded childrens by ids
|
|
249
|
-
@records = rec.send(@tables.last[1].pluralize) # current embedded set
|
|
250
|
-
# sort by order if order field is present in model
|
|
251
|
-
if @tables.last[1].classify.constantize.respond_to?(:order)
|
|
252
|
-
@records = @records.order_by('order asc')
|
|
253
|
-
end
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
false
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
########################################################################
|
|
260
|
-
# Process index action for in memory data.
|
|
261
|
-
########################################################################
|
|
262
|
-
def process_in_memory #:nodoc
|
|
263
|
-
@records = []
|
|
264
|
-
# result set is defined by filter method in control object
|
|
265
|
-
if (method = @form['result_set']['filter'])
|
|
266
|
-
send(method) if respond_to?(method)
|
|
267
|
-
end
|
|
268
|
-
# result set is defined by class method
|
|
269
|
-
if (klass_method = @form['result_set']['filter_method'])
|
|
270
|
-
_klass, method = klass_method.split('.')
|
|
271
|
-
klass = _klass.classify.constantize
|
|
272
|
-
@records = klass.send(method) if klass.respond_to?(method)
|
|
273
|
-
end
|
|
274
|
-
false
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
########################################################################
|
|
278
|
-
# Indx action
|
|
85
|
+
# Index action
|
|
279
86
|
########################################################################
|
|
280
87
|
def index
|
|
88
|
+
@form['result_set'] ||= {}
|
|
281
89
|
redirected = (@form['table'] == 'dc_memory' ? process_in_memory : process_collections)
|
|
282
90
|
return if redirected
|
|
283
|
-
|
|
91
|
+
|
|
284
92
|
call_callback_method(@form['result_set']['footer'] || 'dc_footer')
|
|
285
93
|
respond_to do |format|
|
|
286
94
|
format.html { render action: :index }
|
|
@@ -300,9 +108,9 @@ end
|
|
|
300
108
|
########################################################################
|
|
301
109
|
def show
|
|
302
110
|
find_record
|
|
111
|
+
# before_show callback
|
|
303
112
|
if (m = callback_method('before_show') )
|
|
304
113
|
ret = call_callback_method(m)
|
|
305
|
-
# Don't do anything if return is false
|
|
306
114
|
if ret.class == FalseClass
|
|
307
115
|
@form['readonly'] = nil # must be
|
|
308
116
|
return index
|
|
@@ -321,7 +129,7 @@ end
|
|
|
321
129
|
########################################################################
|
|
322
130
|
def login
|
|
323
131
|
if params[:id] == 'test' then set_test_site
|
|
324
|
-
elsif params[:ok] then
|
|
132
|
+
elsif params[:ok] then render action: 'login', layout: 'cms'
|
|
325
133
|
else
|
|
326
134
|
session[:edit_mode] = 0
|
|
327
135
|
render action: 'login', layout: 'cms'
|
|
@@ -340,20 +148,21 @@ def logout
|
|
|
340
148
|
end
|
|
341
149
|
|
|
342
150
|
########################################################################
|
|
343
|
-
#
|
|
344
|
-
#
|
|
345
|
-
#
|
|
151
|
+
# Shortcut for setting currently selected site in development. Will search
|
|
152
|
+
# for dc_site document with site name 'test' and set alias_for to site
|
|
153
|
+
# url parameter.
|
|
346
154
|
########################################################################
|
|
347
155
|
def set_test_site
|
|
348
156
|
# only in development
|
|
349
|
-
return dc_render_404
|
|
157
|
+
return dc_render_404 unless Rails.env.development?
|
|
158
|
+
|
|
350
159
|
alias_site = DcSite.find_by(:name => params[:site])
|
|
351
160
|
return dc_render_404 unless alias_site
|
|
161
|
+
|
|
352
162
|
# update alias for
|
|
353
|
-
site
|
|
163
|
+
site = DcSite.find_by(:name => 'test')
|
|
354
164
|
site.alias_for = params[:site]
|
|
355
165
|
site.save
|
|
356
|
-
# redirect to root
|
|
357
166
|
redirect_to '/'
|
|
358
167
|
end
|
|
359
168
|
|
|
@@ -361,17 +170,17 @@ end
|
|
|
361
170
|
# New action.
|
|
362
171
|
########################################################################
|
|
363
172
|
def new
|
|
364
|
-
# clear flash messages.
|
|
173
|
+
# clear flash messages.
|
|
365
174
|
flash[:error] = flash[:warning] = flash[:info] = nil
|
|
366
175
|
create_new_empty_record
|
|
176
|
+
# before_new callback
|
|
367
177
|
if (m = callback_method('before_new') )
|
|
368
178
|
ret = call_callback_method(m)
|
|
369
|
-
# Don't do anything if return is false
|
|
370
179
|
return index if ret.class == FalseClass
|
|
371
180
|
end
|
|
372
181
|
table = @tables.last[1] + '.'
|
|
373
|
-
# initial values set on page
|
|
374
|
-
if cookies[:record]
|
|
182
|
+
# initial values set on page
|
|
183
|
+
if cookies[:record] && cookies[:record].size > 0
|
|
375
184
|
Marshal.load(cookies[:record]).each do |k,v|
|
|
376
185
|
k = k.to_s
|
|
377
186
|
if k.match(table)
|
|
@@ -380,63 +189,71 @@ def new
|
|
|
380
189
|
end
|
|
381
190
|
end
|
|
382
191
|
end
|
|
383
|
-
# initial values set in url
|
|
192
|
+
# initial values set in url (params)
|
|
384
193
|
params.each do |k,v|
|
|
385
194
|
if k.match(table)
|
|
386
195
|
field = k.split('.').last
|
|
387
196
|
@record.send("#{field}=", v) if @record.respond_to?(field)
|
|
388
197
|
end
|
|
389
198
|
end
|
|
390
|
-
#
|
|
391
|
-
|
|
199
|
+
# new_record callback. Set default values for new record
|
|
200
|
+
if (m = callback_method('new_record') ) then call_callback_method(m) end
|
|
392
201
|
@parms['action'] = 'create'
|
|
393
202
|
end
|
|
394
203
|
|
|
395
204
|
########################################################################
|
|
396
205
|
# Duplicate embedded document. Since embedded documents are returned differently
|
|
397
206
|
# then top level document. Subroutine of duplicate_socument.
|
|
207
|
+
#
|
|
208
|
+
#TODO Works for two embedded levels. Dies with third and more levels.
|
|
398
209
|
########################################################################
|
|
399
210
|
def duplicate_embedded(source) #:nodoc:
|
|
400
|
-
# TODO Works for two embedded levels. Dies with third and more levels.
|
|
401
211
|
dest = {}
|
|
402
212
|
source.each do |attribute_name, value|
|
|
403
213
|
next if attribute_name == '_id' # don't duplicate _id
|
|
214
|
+
|
|
404
215
|
if value.class == Array
|
|
405
216
|
dest[attribute_name] = []
|
|
406
217
|
value.each do |ar|
|
|
407
218
|
dest[attribute_name] << duplicate_embedded(ar)
|
|
408
219
|
end
|
|
409
|
-
else
|
|
410
|
-
# if duplicate string
|
|
220
|
+
else
|
|
221
|
+
# if duplicate, string dup is added. For unique fields
|
|
411
222
|
add_duplicate = params['dup_fields'].to_s.match(attribute_name + ',')
|
|
412
223
|
dest[attribute_name] = value
|
|
413
224
|
dest[attribute_name] << ' dup' if add_duplicate
|
|
414
225
|
end
|
|
415
226
|
end
|
|
227
|
+
dest['created_at'] = Time.now if dest['created_at']
|
|
228
|
+
dest['updated_at'] = Time.now if dest['updated_at']
|
|
416
229
|
dest
|
|
417
230
|
end
|
|
418
231
|
|
|
419
232
|
########################################################################
|
|
420
233
|
# Will create duplicate document of source document. This method is used for
|
|
421
|
-
# duplicating document and is
|
|
234
|
+
# duplicating document and is subroutine of create action.
|
|
422
235
|
########################################################################
|
|
423
236
|
def duplicate_document(source)
|
|
424
237
|
dest = {}
|
|
425
238
|
source.attribute_names.each do |attribute_name|
|
|
426
239
|
next if attribute_name == '_id' # don't duplicate _id
|
|
427
|
-
|
|
240
|
+
|
|
241
|
+
# if duplicate, string dup is added. For unique fields
|
|
428
242
|
add_duplicate = params['dup_fields'].to_s.match(attribute_name + ',')
|
|
429
243
|
dest[attribute_name] = source[attribute_name]
|
|
430
244
|
dest[attribute_name] << ' dup' if add_duplicate
|
|
431
245
|
end
|
|
432
|
-
# embedded documents
|
|
246
|
+
# embedded documents
|
|
433
247
|
source.embedded_relations.keys.each do |embedded_name|
|
|
434
248
|
next if source[embedded_name].nil? # it happens
|
|
249
|
+
|
|
435
250
|
dest[embedded_name] = []
|
|
436
251
|
source[embedded_name].each do |embedded|
|
|
437
252
|
dest[embedded_name] << duplicate_embedded(embedded)
|
|
438
253
|
end
|
|
439
254
|
end
|
|
255
|
+
dest['created_at'] = Time.now if dest['created_at']
|
|
256
|
+
dest['updated_at'] = Time.now if dest['updated_at']
|
|
440
257
|
dest
|
|
441
258
|
end
|
|
442
259
|
|
|
@@ -444,33 +261,35 @@ end
|
|
|
444
261
|
# Create (or duplicate) action. Action is also used for turning filter on.
|
|
445
262
|
########################################################################
|
|
446
263
|
def create
|
|
447
|
-
# abusing create for turning filter on
|
|
264
|
+
# abusing create for turning filter on
|
|
448
265
|
return index if params[:filter].to_s == 'on'
|
|
449
|
-
|
|
266
|
+
|
|
267
|
+
# not authorized
|
|
450
268
|
unless dc_user_can(DcPermission::CAN_CREATE)
|
|
451
269
|
flash[:error] = t('drgcms.not_authorized')
|
|
452
270
|
return index
|
|
453
271
|
end
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
272
|
+
|
|
273
|
+
# create document
|
|
274
|
+
if params['id'].nil?
|
|
275
|
+
# Prevent double form submit
|
|
457
276
|
params[:form_time_stamp] = params[:form_time_stamp].to_i
|
|
458
277
|
session[:form_time_stamp] ||= 0
|
|
459
278
|
return index if params[:form_time_stamp] <= session[:form_time_stamp]
|
|
279
|
+
|
|
460
280
|
session[:form_time_stamp] = params[:form_time_stamp]
|
|
461
|
-
#
|
|
462
281
|
create_new_empty_record
|
|
463
|
-
params[:return_to] = 'index' if params[:commit] == t('drgcms.save&back') # save & back
|
|
464
282
|
if save_data
|
|
465
|
-
flash[:info]
|
|
283
|
+
flash[:info] = t('drgcms.doc_saved')
|
|
284
|
+
params[:return_to] = 'index' if params[:commit] == t('drgcms.save&back') # save & back
|
|
466
285
|
return process_return_to(params[:return_to]) if params[:return_to]
|
|
467
286
|
|
|
468
|
-
@parms['id']
|
|
469
|
-
params[:id]
|
|
287
|
+
@parms['id'] = @record.id # must be set, for proper update link
|
|
288
|
+
params[:id] = @record.id # must be set, for find_record
|
|
470
289
|
edit
|
|
471
|
-
# render action: :edit
|
|
472
290
|
else # error
|
|
473
291
|
return process_return_to(params[:return_to]) if params[:return_to]
|
|
292
|
+
|
|
474
293
|
render action: :new
|
|
475
294
|
end
|
|
476
295
|
else # duplicate record
|
|
@@ -492,9 +311,9 @@ def edit
|
|
|
492
311
|
find_record
|
|
493
312
|
if (m = callback_method('before_edit') )
|
|
494
313
|
ret = call_callback_method(m)
|
|
495
|
-
#
|
|
314
|
+
# don't do anything if return is false
|
|
496
315
|
return index if ret.class == FalseClass
|
|
497
|
-
end
|
|
316
|
+
end
|
|
498
317
|
@parms['action'] = 'update'
|
|
499
318
|
render action: :edit
|
|
500
319
|
end
|
|
@@ -504,25 +323,27 @@ end
|
|
|
504
323
|
########################################################################
|
|
505
324
|
def update
|
|
506
325
|
find_record
|
|
507
|
-
# check if record was not updated in mean time
|
|
326
|
+
# check if record was not updated in mean time
|
|
508
327
|
if @record.respond_to?(:updated_at)
|
|
509
328
|
if params[:last_updated_at].to_i != @record.updated_at.to_i
|
|
510
329
|
flash[:error] = t('drgcms.updated_by_other')
|
|
511
330
|
return render(action: :edit)
|
|
512
331
|
end
|
|
513
332
|
end
|
|
514
|
-
|
|
333
|
+
|
|
515
334
|
if dc_user_can(DcPermission::CAN_EDIT_ALL) or
|
|
516
335
|
( @record.respond_to?('created_by') and
|
|
517
336
|
@record.created_by == session[:user_id] and
|
|
518
337
|
dc_user_can(DcPermission::CAN_EDIT) )
|
|
519
|
-
|
|
338
|
+
|
|
520
339
|
if save_data
|
|
521
340
|
params[:return_to] = 'index' if params[:commit] == t('drgcms.save&back') # save & back
|
|
522
341
|
@parms['action'] = 'update'
|
|
523
|
-
# Process return_to
|
|
342
|
+
# Process return_to
|
|
524
343
|
return process_return_to(params[:return_to]) if params[:return_to]
|
|
525
344
|
else
|
|
345
|
+
# do not forget before_edit callback
|
|
346
|
+
if m = callback_method('before_edit') then call_callback_method(m) end
|
|
526
347
|
return render action: :edit
|
|
527
348
|
end
|
|
528
349
|
else
|
|
@@ -536,7 +357,7 @@ end
|
|
|
536
357
|
########################################################################
|
|
537
358
|
def destroy
|
|
538
359
|
find_record
|
|
539
|
-
#
|
|
360
|
+
# check permission required to delete
|
|
540
361
|
permission = if params['operation'].nil?
|
|
541
362
|
if @record.respond_to?('created_by') # needs can_delete_all if created_by is present and not owner
|
|
542
363
|
(@record.created_by == session[:user_id]) ? DcPermission::CAN_DELETE : DcPermission::CAN_DELETE_ALL
|
|
@@ -551,38 +372,39 @@ def destroy
|
|
|
551
372
|
end
|
|
552
373
|
end
|
|
553
374
|
ok2delete = dc_user_can(permission)
|
|
554
|
-
|
|
375
|
+
|
|
555
376
|
case
|
|
556
|
-
# not authorized
|
|
377
|
+
# not authorized
|
|
557
378
|
when !ok2delete then
|
|
558
379
|
flash[:error] = t('drgcms.not_authorized')
|
|
559
380
|
return index
|
|
560
|
-
|
|
381
|
+
|
|
382
|
+
# delete document
|
|
561
383
|
when params['operation'].nil? then
|
|
562
|
-
#
|
|
384
|
+
# before_delete callback
|
|
563
385
|
if (m = callback_method('before_delete') )
|
|
564
386
|
ret = call_callback_method(m)
|
|
565
|
-
#
|
|
387
|
+
# don't do anything if return is false
|
|
566
388
|
return index if ret.class == FalseClass
|
|
567
389
|
end
|
|
568
|
-
|
|
390
|
+
|
|
569
391
|
if @record.destroy
|
|
570
392
|
save_journal(:delete)
|
|
571
393
|
flash[:info] = t('drgcms.record_deleted')
|
|
572
|
-
#
|
|
394
|
+
# after_delete callback
|
|
573
395
|
if (m = callback_method('after_delete') )
|
|
574
396
|
call_callback_method(m)
|
|
575
397
|
elsif params['after-delete'].to_s.match('return_to')
|
|
576
398
|
params[:return_to] = params['after-delete']
|
|
577
399
|
end
|
|
578
|
-
# Process return_to link
|
|
400
|
+
# Process return_to link
|
|
579
401
|
return process_return_to(params[:return_to]) if params[:return_to]
|
|
580
402
|
else
|
|
581
403
|
flash[:error] = dc_error_messages_for(@record)
|
|
582
404
|
end
|
|
583
405
|
return index
|
|
584
406
|
|
|
585
|
-
#
|
|
407
|
+
# deactivate document
|
|
586
408
|
when params['operation'] == 'disable' then
|
|
587
409
|
if @record.respond_to?('active')
|
|
588
410
|
@record.active = false
|
|
@@ -592,7 +414,7 @@ def destroy
|
|
|
592
414
|
flash[:info] = t('drgcms.doc_disabled')
|
|
593
415
|
end
|
|
594
416
|
|
|
595
|
-
#
|
|
417
|
+
# reactivate document
|
|
596
418
|
when params['operation'] == 'enable' then
|
|
597
419
|
if @record.respond_to?('active')
|
|
598
420
|
@record.active = true
|
|
@@ -602,34 +424,90 @@ def destroy
|
|
|
602
424
|
flash[:info] = t('drgcms.doc_enabled')
|
|
603
425
|
end
|
|
604
426
|
|
|
605
|
-
# reorder documents
|
|
427
|
+
#TODO reorder documents
|
|
606
428
|
when params['operation'] == 'reorder' then
|
|
607
429
|
|
|
608
430
|
end
|
|
609
|
-
|
|
431
|
+
|
|
610
432
|
@parms['action'] = 'update'
|
|
611
433
|
render action: :edit
|
|
612
434
|
end
|
|
613
435
|
|
|
436
|
+
########################################################################
|
|
437
|
+
# Run action
|
|
438
|
+
########################################################################
|
|
439
|
+
def run
|
|
440
|
+
# determine control file name and method
|
|
441
|
+
control_name, method_name = params[:control].split('.')
|
|
442
|
+
if method_name.nil?
|
|
443
|
+
method_name = control_name
|
|
444
|
+
control_name = params[:table]
|
|
445
|
+
end
|
|
446
|
+
# extend with control methods
|
|
447
|
+
extend_with_control_module(control_name)
|
|
448
|
+
if respond_to?(method_name)
|
|
449
|
+
# can it be called
|
|
450
|
+
return return_run_error t('drgcms.not_authorized') unless can_process_run
|
|
451
|
+
# call method
|
|
452
|
+
respond_to do |format|
|
|
453
|
+
format.json { send method_name }
|
|
454
|
+
format.html { send method_name }
|
|
455
|
+
end
|
|
456
|
+
else # Error message
|
|
457
|
+
return_run_error "Method #{method_name} not defined in #{control_name}_control"
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
|
|
614
461
|
protected
|
|
615
462
|
|
|
616
|
-
=begin
|
|
617
463
|
########################################################################
|
|
618
|
-
#
|
|
619
|
-
|
|
464
|
+
# Respond with error on run action
|
|
465
|
+
########################################################################
|
|
466
|
+
def return_run_error(text)
|
|
467
|
+
respond_to do |format|
|
|
468
|
+
format.json { render json: { msg_error: text } }
|
|
469
|
+
format.html { render plain: text }
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
########################################################################
|
|
474
|
+
# Can run call be processed
|
|
475
|
+
########################################################################
|
|
476
|
+
def can_process_run
|
|
477
|
+
if respond_to?(:dc_can_process)
|
|
478
|
+
response = send(:dc_can_process)
|
|
479
|
+
return response unless response.class == Array
|
|
480
|
+
else
|
|
481
|
+
response = [DcPermission::CAN_VIEW, params[:table] || 'dc_memory']
|
|
482
|
+
end
|
|
483
|
+
dc_user_can *response
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
########################################################################
|
|
487
|
+
# Checks if user has permissions to perform operation on table and if not
|
|
488
|
+
# prepares response for not authorized message.
|
|
489
|
+
#
|
|
490
|
+
# @param [Integer] permission : Permission level defined in DcPermission constants eg. DcPermission::CAN_EDIT
|
|
491
|
+
# @param [String] collection_name : Table name on which user must have permission
|
|
492
|
+
#
|
|
493
|
+
# @return [Boolean] true when user has required permission otherwise false
|
|
620
494
|
########################################################################
|
|
621
|
-
def
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
495
|
+
def user_has_permission?(permission, collection_name)
|
|
496
|
+
unless dc_user_can(permission, collection_name.to_s)
|
|
497
|
+
respond_to do |format|
|
|
498
|
+
format.json { render json: {msg_error: t('drgcms.not_authorized') } }
|
|
499
|
+
format.html { render plain: t('drgcms.not_authorized') }
|
|
500
|
+
end
|
|
501
|
+
return false
|
|
502
|
+
end
|
|
503
|
+
true
|
|
625
504
|
end
|
|
626
|
-
=end
|
|
627
505
|
|
|
628
506
|
########################################################################
|
|
629
|
-
# Merges two forms when current form extends other form. Subroutine of
|
|
507
|
+
# Merges two forms when current form extends other form. Subroutine of read_drg_form.
|
|
630
508
|
# With a little help of https://www.ruby-forum.com/topic/142809
|
|
631
509
|
########################################################################
|
|
632
|
-
def forms_merge(hash1, hash2)
|
|
510
|
+
def forms_merge(hash1, hash2)
|
|
633
511
|
target = hash1.dup
|
|
634
512
|
hash2.keys.each do |key|
|
|
635
513
|
if hash2[key].is_a? Hash and hash1[key].is_a? Hash
|
|
@@ -638,75 +516,152 @@ def forms_merge(hash1, hash2)
|
|
|
638
516
|
end
|
|
639
517
|
target[key] = hash2[key] == '/' ? nil : hash2[key]
|
|
640
518
|
end
|
|
641
|
-
# delete keys with nil value
|
|
642
|
-
target.delete_if{ |k,v| v.nil? }
|
|
519
|
+
# delete keys with nil value
|
|
520
|
+
target.delete_if { |k, v| v.nil? }
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
########################################################################
|
|
524
|
+
# Extends DRGCMS form file. Extended file is processed first and then merged
|
|
525
|
+
# with code in this form file. Form can extend only single form file.
|
|
526
|
+
#
|
|
527
|
+
# [Parameters:]
|
|
528
|
+
# [extend_option] : Value of @form['extend'] option
|
|
529
|
+
########################################################################
|
|
530
|
+
def extend_drg_form(extend_option)
|
|
531
|
+
form_file_name = dc_find_form_file(extend_option)
|
|
532
|
+
@form_js << read_js_drg_form(form_file_name)
|
|
533
|
+
form = YAML.load_file( form_file_name )
|
|
534
|
+
@form = forms_merge(form, @form)
|
|
535
|
+
# If combined form contains tabs and fields options, merge fields into tabs
|
|
536
|
+
if @form['form']['tabs'] && @form['form']['fields']
|
|
537
|
+
@form['form']['tabs']['fields'] = @form['form']['fields']
|
|
538
|
+
@form['form']['fields'] = nil
|
|
539
|
+
end
|
|
643
540
|
end
|
|
644
541
|
|
|
645
542
|
########################################################################
|
|
646
|
-
#
|
|
543
|
+
# Include code from another DRGCMS form file. Included code is merged
|
|
544
|
+
# with current form file code. Form can include more than one other DRGCMS forms.
|
|
545
|
+
#
|
|
546
|
+
# [Parameters:]
|
|
547
|
+
# [include_option] : Value of @form['include'] option
|
|
548
|
+
########################################################################
|
|
549
|
+
def include_drg_form(include_option)
|
|
550
|
+
includes = include_option.class == Array ? include_option : include_option.split(/\,|\;/)
|
|
551
|
+
includes.each do |include_file|
|
|
552
|
+
form_file_name = dc_find_form_file(include_file)
|
|
553
|
+
@form_js << read_js_drg_form(form_file_name)
|
|
554
|
+
form = YAML.load_file(form_file_name)
|
|
555
|
+
@form = forms_merge(@form, form)
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
########################################################################
|
|
560
|
+
# Will read data from form_file_name.js if exists.
|
|
561
|
+
#
|
|
562
|
+
# [Parameters:]
|
|
563
|
+
# [form_file_name] : Physical form filename
|
|
564
|
+
########################################################################
|
|
565
|
+
def read_js_drg_form(form_file_name)
|
|
566
|
+
js_form_file_name = form_file_name.sub('.yml','.js')
|
|
567
|
+
File.read(js_form_file_name) rescue ''
|
|
568
|
+
end
|
|
569
|
+
|
|
647
570
|
########################################################################
|
|
648
|
-
|
|
571
|
+
# Read DRG form into @form object. Subroutine of check_authorization.
|
|
572
|
+
########################################################################
|
|
573
|
+
def read_drg_form
|
|
649
574
|
table_name = decamelize_type(params[:table].strip)
|
|
650
|
-
@tables = table_name.split(';').inject([]) { |r,v| r << [v.classify.constantize, v] }
|
|
651
|
-
|
|
575
|
+
@tables = table_name.split(';').inject([]) { |r,v| r << [(v.classify.constantize rescue nil), v] }
|
|
576
|
+
|
|
577
|
+
# split ids passed when embedded document
|
|
652
578
|
ids = params[:ids].to_s.strip.downcase
|
|
653
579
|
@ids = ids.split(';').inject([]) { |r,v| r << v }
|
|
654
|
-
|
|
580
|
+
|
|
581
|
+
# form_name defaults to last table specified
|
|
655
582
|
form_name = params[:form_name] || @tables.last[1]
|
|
656
|
-
@
|
|
657
|
-
|
|
658
|
-
#
|
|
659
|
-
if
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
583
|
+
@form_js = ''
|
|
584
|
+
|
|
585
|
+
# dynamically generated form
|
|
586
|
+
@form = if params[:form_name] == 'method'
|
|
587
|
+
dc_eval_class_method(params[:form_method], params)
|
|
588
|
+
else
|
|
589
|
+
form_file_name = dc_find_form_file(form_name)
|
|
590
|
+
@form_js = read_js_drg_form(form_file_name)
|
|
591
|
+
YAML.load_file(form_file_name)
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
# form includes or extends another form file
|
|
595
|
+
include_drg_form(@form['include']) if @form['include']
|
|
596
|
+
extend_drg_form(@form['extend']) if @form['extend']
|
|
597
|
+
@form['script'] = (@form['script'].blank? ? @form_js : @form['script'] + @form_js)
|
|
598
|
+
# add readonly key to form if readonly parameter is passed in url
|
|
669
599
|
@form['readonly'] = 1 if params['readonly'] #and %w(1 yes true).include?(params['readonly'].to_s.downcase.strip)
|
|
670
|
-
|
|
600
|
+
|
|
601
|
+
# !!!!!! Always use strings for key names since @parms['table'] != @parms[:table]
|
|
671
602
|
@parms = { 'table' => table_name, 'ids' => params[:ids], 'form_name' => form_name,
|
|
672
603
|
'return_to' => params['return_to'], 'edit_only' => params['edit_only'],
|
|
673
604
|
'readonly' => params['readonly']
|
|
674
605
|
}
|
|
675
606
|
end
|
|
676
607
|
|
|
608
|
+
############################################################################
|
|
609
|
+
# Load module if available. Try not to mask errors in control module
|
|
610
|
+
############################################################################
|
|
611
|
+
def load_controls_module(controls_string)
|
|
612
|
+
begin
|
|
613
|
+
controls_string.classify.constantize
|
|
614
|
+
rescue NameError => e
|
|
615
|
+
return nil if e.message.match('uninitialized constant') || e.message.match('wrong constant name')
|
|
616
|
+
# report errors when loading existing module
|
|
617
|
+
raise e
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
############################################################################
|
|
622
|
+
# Dynamically extend cmsedit class with methods defined in controls module.
|
|
623
|
+
############################################################################
|
|
624
|
+
def extend_with_control_module(control_name = @form['controls'] || @form['control'])
|
|
625
|
+
# May include embedded forms so ; => _
|
|
626
|
+
control_name ||= params[:table].gsub(';','_')
|
|
627
|
+
control_name += '_control' unless control_name.match(/control$|report$/i)
|
|
628
|
+
# p '************', control_name
|
|
629
|
+
controls = load_controls_module(control_name)
|
|
630
|
+
if controls
|
|
631
|
+
# extend first with dc_report when report
|
|
632
|
+
if control_name.match(/report$/i)
|
|
633
|
+
extend DcReport
|
|
634
|
+
init_report(control_name)
|
|
635
|
+
end
|
|
636
|
+
extend controls
|
|
637
|
+
# Form may be dynamically updated before processed
|
|
638
|
+
send(:dc_update_form) if respond_to?(:dc_update_form)
|
|
639
|
+
end
|
|
640
|
+
end
|
|
641
|
+
|
|
677
642
|
############################################################################
|
|
678
643
|
# Check if user is authorized for the action. If authorization is in order it will also
|
|
679
644
|
# load DRG form.
|
|
680
645
|
############################################################################
|
|
681
646
|
def check_authorization
|
|
682
647
|
params[:table] ||= params[:form_name]
|
|
683
|
-
#
|
|
684
|
-
# return show if params[:action] == 'show'
|
|
648
|
+
# Only show menu
|
|
685
649
|
return login if params[:id].in?(%w(login logout test))
|
|
686
650
|
table = params[:table].to_s.strip.downcase
|
|
687
|
-
|
|
651
|
+
set_default_guest_user_role if session[:user_roles].nil?
|
|
652
|
+
# request shouldn't pass
|
|
688
653
|
if table != 'dc_memory' and
|
|
689
|
-
(
|
|
654
|
+
(table.size < 3 or !dc_user_can(DcPermission::CAN_VIEW))
|
|
690
655
|
return render(action: 'error', locals: { error: t('drgcms.not_authorized')} )
|
|
691
656
|
end
|
|
657
|
+
read_drg_form
|
|
658
|
+
return render( plain: t('drgcms.form_error') ) if @form.nil?
|
|
692
659
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
if
|
|
697
|
-
|
|
698
|
-
#TODO So far only can_view is used. Think about if using other permissions has sense
|
|
699
|
-
elsif @form['permissions'].nil? or @form['permissions']['can_view'].nil? or
|
|
700
|
-
dc_user_has_role(@form['permissions']['can_view'])
|
|
701
|
-
# Extend class with methods defined in drgcms_controls module. May include embedded forms therefor ; => _
|
|
702
|
-
controls_string = (@form['controls'] ? @form['controls'] : params[:table].gsub(';','_')) + '_control'
|
|
703
|
-
controls = "DrgcmsControls::#{controls_string.classify}".constantize rescue nil
|
|
704
|
-
# version next
|
|
705
|
-
if controls.nil?
|
|
706
|
-
controls_string = "#{@form['controls'] || params[:table].gsub(';','_')}_control"
|
|
707
|
-
controls = "#{controls_string.classify}".constantize rescue nil
|
|
708
|
-
end
|
|
709
|
-
extend controls if controls
|
|
660
|
+
# Permissions can be also defined on form
|
|
661
|
+
#TODO So far only can_view is used. Think about if using other permissions has sense
|
|
662
|
+
can_view = @form.dig('permissions','can_view')
|
|
663
|
+
if can_view.nil? or dc_user_has_role(can_view)
|
|
664
|
+
extend_with_control_module
|
|
710
665
|
else
|
|
711
666
|
render(action: 'error', locals: { error: t('drgcms.not_authorized')} )
|
|
712
667
|
end
|
|
@@ -728,7 +683,7 @@ end
|
|
|
728
683
|
########################################################################
|
|
729
684
|
# Creates new empty record for new and create action.
|
|
730
685
|
########################################################################
|
|
731
|
-
def create_new_empty_record(initial_data=nil) #:nodoc:
|
|
686
|
+
def create_new_empty_record(initial_data = nil) #:nodoc:
|
|
732
687
|
if @tables.size == 1
|
|
733
688
|
@record = @tables.first[0].new(initial_data)
|
|
734
689
|
else
|
|
@@ -745,9 +700,9 @@ def update_standards(record = @record)
|
|
|
745
700
|
record.updated_by = session[:user_id] if record.respond_to?('updated_by')
|
|
746
701
|
if record.new_record?
|
|
747
702
|
record.created_by = session[:user_id] if record.respond_to?('created_by')
|
|
748
|
-
# set this only initialy. Allow to be set to nil on updates.
|
|
749
|
-
# and will be directly visible only to admins
|
|
750
|
-
record.dc_site_id = dc_get_site.
|
|
703
|
+
# set this only initialy. Allow to be set to nil on updates. Document can then belong to all sites
|
|
704
|
+
# and will be directly visible only to admins
|
|
705
|
+
record.dc_site_id = dc_get_site.id if record.respond_to?('dc_site_id') && record.dc_site_id.nil?
|
|
751
706
|
end
|
|
752
707
|
end
|
|
753
708
|
|
|
@@ -759,17 +714,15 @@ end
|
|
|
759
714
|
# [changes] Current document changed fields.
|
|
760
715
|
########################################################################
|
|
761
716
|
def save_journal(operation, changes = {})
|
|
762
|
-
# return unless session[:save_journal]
|
|
763
717
|
if operation == :delete
|
|
764
718
|
@record.attributes.each {|k,v| changes[k] = v}
|
|
765
|
-
# elsif operation == :new
|
|
766
|
-
# changes = {}
|
|
767
719
|
end
|
|
768
|
-
|
|
769
|
-
if (operation != :update)
|
|
770
|
-
# determine site_id
|
|
720
|
+
|
|
721
|
+
if (operation != :update) || changes.size > 0
|
|
722
|
+
# determine site_id
|
|
771
723
|
site_id = @record.site_id if @record.respond_to?('site_id')
|
|
772
|
-
site_id = dc_get_site._id if site_id.nil?
|
|
724
|
+
site_id = dc_get_site._id if site_id.nil? && dc_get_site
|
|
725
|
+
|
|
773
726
|
DcJournal.create(site_id: site_id,
|
|
774
727
|
operation: operation,
|
|
775
728
|
user_id: session[:user_id],
|
|
@@ -787,22 +740,23 @@ end
|
|
|
787
740
|
# Returns callback method name or nil if not defined.
|
|
788
741
|
########################################################################
|
|
789
742
|
def callback_method(key) #:nodoc:
|
|
790
|
-
data_key = key.gsub('_','-') #
|
|
791
|
-
|
|
743
|
+
data_key = key.gsub('_','-') # convert _ to -
|
|
744
|
+
callback = case
|
|
792
745
|
when params['data'] && params['data'][data_key] then params['data'][data_key]
|
|
793
|
-
#
|
|
746
|
+
# dc_ + key method is present then call it automatically
|
|
747
|
+
when @form['form'][key] then @form['form'][key]
|
|
794
748
|
when respond_to?('dc_' + key) then 'dc_' + key
|
|
795
749
|
when params[data_key] then params[data_key]
|
|
796
750
|
else nil
|
|
797
751
|
end
|
|
798
|
-
|
|
752
|
+
|
|
799
753
|
ret = case
|
|
800
|
-
when
|
|
801
|
-
when
|
|
802
|
-
when
|
|
803
|
-
params[:return_to] =
|
|
754
|
+
when callback.nil? then callback # otherwise there will be errors in next lines
|
|
755
|
+
when callback.match('eval ') then callback.sub('eval ','')
|
|
756
|
+
when callback.match('return_to ')
|
|
757
|
+
params[:return_to] = callback.sub('return_to ','')
|
|
804
758
|
return nil
|
|
805
|
-
else
|
|
759
|
+
else callback
|
|
806
760
|
end
|
|
807
761
|
ret
|
|
808
762
|
end
|
|
@@ -841,16 +795,16 @@ end
|
|
|
841
795
|
|
|
842
796
|
########################################################################
|
|
843
797
|
# Since tabs have been introduced on form it is a little more complicated
|
|
844
|
-
# to
|
|
798
|
+
# to collect all edit fields on form. This method does it. Subroutine of save_data.
|
|
845
799
|
########################################################################
|
|
846
|
-
def fields_on_form
|
|
800
|
+
def fields_on_form #:nodoc:
|
|
847
801
|
form_fields = []
|
|
848
802
|
if @form['form']['fields']
|
|
849
|
-
# read only field elements (key is Integer)
|
|
850
|
-
@form['form']['fields'].each {|key,options| form_fields << options if key.class == Integer }
|
|
803
|
+
# read only field elements (key is Integer)
|
|
804
|
+
@form['form']['fields'].each { |key, options| form_fields << options if key.class == Integer }
|
|
851
805
|
else
|
|
852
806
|
@form['form']['tabs'].keys.each do |tab|
|
|
853
|
-
@form['form']['tabs'][tab].each {|key,options| form_fields << options if key.class == Integer }
|
|
807
|
+
@form['form']['tabs'][tab].each { |key, options| form_fields << options if key.class == Integer }
|
|
854
808
|
end
|
|
855
809
|
end
|
|
856
810
|
form_fields
|
|
@@ -863,36 +817,262 @@ end
|
|
|
863
817
|
def save_data
|
|
864
818
|
form_fields = fields_on_form()
|
|
865
819
|
return true if form_fields.size == 0
|
|
866
|
-
|
|
820
|
+
|
|
867
821
|
form_fields.each do |v|
|
|
868
822
|
session[:form_processing] = v['name'] # for debuging
|
|
869
|
-
next if v['type'].nil? or
|
|
823
|
+
next if v['type'].nil? or v['name'].nil? or
|
|
870
824
|
v['type'].match('embedded') or # don't wipe embedded types
|
|
871
825
|
(params[:edit_only] and params[:edit_only] != v['name']) or # otherwise other fields would be wiped
|
|
872
826
|
v['readonly'] or # fields with readonly option don't return value and would be wiped
|
|
873
|
-
!@record.respond_to?(v['name']) # there
|
|
827
|
+
!@record.respond_to?(v['name']) # there are temporary fields on the form
|
|
874
828
|
# good to know! How to get type of field @record.fields[v['name']].type
|
|
875
829
|
# return value from form field definition
|
|
876
830
|
value = DrgcmsFormFields.const_get(v['type'].camelize).get_data(params, v['name'])
|
|
877
831
|
@record.send("#{v['name']}=", value)
|
|
878
832
|
end
|
|
879
|
-
#
|
|
880
|
-
operation = @record.new_record? ? :new : :update
|
|
881
|
-
# controls callback method
|
|
833
|
+
# before_save callback
|
|
882
834
|
if (m = callback_method('before_save') )
|
|
883
835
|
ret = call_callback_method(m)
|
|
884
|
-
#
|
|
836
|
+
# don't save if callback returns false
|
|
885
837
|
return false if ret.class == FalseClass
|
|
886
838
|
end
|
|
887
|
-
|
|
839
|
+
|
|
840
|
+
# save data
|
|
888
841
|
changes = @record.changes
|
|
889
842
|
update_standards() if changes.size > 0 # update only if there has been some changes
|
|
890
843
|
if (saved = @record.save)
|
|
844
|
+
operation = @record.new_record? ? :new : :update
|
|
891
845
|
save_journal(operation, changes)
|
|
892
|
-
# callback
|
|
893
|
-
if (m = callback_method('after_save') ) then call_callback_method(m)
|
|
846
|
+
# after_save callback
|
|
847
|
+
if (m = callback_method('after_save') ) then call_callback_method(m) end
|
|
894
848
|
end
|
|
895
849
|
saved
|
|
896
850
|
end
|
|
851
|
+
|
|
852
|
+
########################################################################
|
|
853
|
+
# Will return comma separated data (field names) as array of symbols. For usage
|
|
854
|
+
# in select_fields and deny_fields
|
|
855
|
+
########################################################################
|
|
856
|
+
def separated_to_symbols(data)
|
|
857
|
+
data.chomp.split(',').map { |e| e.strip.downcase.to_sym }
|
|
858
|
+
end
|
|
897
859
|
|
|
860
|
+
########################################################################
|
|
861
|
+
# Will process only (select_fields) and without (deny_fields) option
|
|
862
|
+
########################################################################
|
|
863
|
+
def process_select_and_deny_fields
|
|
864
|
+
only = @form['result_set']['select_fields'] || @form['result_set']['only']
|
|
865
|
+
@records = @records.only( separated_to_symbols(only) ) if only
|
|
866
|
+
|
|
867
|
+
without = @form['result_set']['deny_fields'] || @form['result_set']['without']
|
|
868
|
+
@records = @records.without( separated_to_symbols(without) ) if without
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
########################################################################
|
|
872
|
+
# Will check and set sorting options for current result set. Subroutine of index method.
|
|
873
|
+
########################################################################
|
|
874
|
+
def check_sort_options() #:nodoc:
|
|
875
|
+
table_name = @tables.first[1]
|
|
876
|
+
old_sort = session[table_name][:sort].to_s
|
|
877
|
+
sort, direction = old_sort.split(' ')
|
|
878
|
+
|
|
879
|
+
if params['sort']
|
|
880
|
+
# reverse sort if same selected
|
|
881
|
+
if params['sort'] == sort
|
|
882
|
+
direction = (direction == '1') ? '-1' : '1'
|
|
883
|
+
end
|
|
884
|
+
direction ||= '1'
|
|
885
|
+
sort = params[:sort]
|
|
886
|
+
session[table_name][:sort] = "#{params['sort']} #{direction}"
|
|
887
|
+
session[table_name][:page] = 1
|
|
888
|
+
end
|
|
889
|
+
@records.sort( sort => direction.to_i ) if session[table_name][:sort] && @records.class == Mongoid::Criteria
|
|
890
|
+
params['sort'] = nil # otherwise there is problem with other links
|
|
891
|
+
end
|
|
892
|
+
|
|
893
|
+
########################################################################
|
|
894
|
+
# Set aditional filter options when filter is defined by filter method in control object.
|
|
895
|
+
########################################################################
|
|
896
|
+
def user_filter_options(model) #:nodoc:
|
|
897
|
+
table_name = @tables.first[1]
|
|
898
|
+
if session[table_name]
|
|
899
|
+
DcFilter.get_filter(session[table_name][:filter]) || model
|
|
900
|
+
else
|
|
901
|
+
model
|
|
902
|
+
end
|
|
903
|
+
end
|
|
904
|
+
|
|
905
|
+
########################################################################
|
|
906
|
+
# Return current sort options for model (table)
|
|
907
|
+
########################################################################
|
|
908
|
+
def user_sort_options(model) #:nodoc:
|
|
909
|
+
table_name = (model.class == String ? model : model.to_s).underscore
|
|
910
|
+
return nil unless session[table_name][:sort]
|
|
911
|
+
|
|
912
|
+
field, direction = session[table_name][:sort].split(' ')
|
|
913
|
+
{ field.to_sym => direction.to_i }
|
|
914
|
+
end
|
|
915
|
+
|
|
916
|
+
########################################################################
|
|
917
|
+
# Will set session[table_name][:filter] and save last filter settings to session.
|
|
918
|
+
# subroutine of check_filter_options.
|
|
919
|
+
########################################################################
|
|
920
|
+
def set_session_filter(table_name)
|
|
921
|
+
# models that can not be filtered (for now)
|
|
922
|
+
return if %w(dc_temp dc_memory).include?(params[:table])
|
|
923
|
+
# clear filter
|
|
924
|
+
if params[:filter] == 'off'
|
|
925
|
+
session[table_name][:filter] = nil
|
|
926
|
+
return
|
|
927
|
+
end
|
|
928
|
+
# field_name should exist on set filter condition
|
|
929
|
+
return if params[:filter_oper] && params[:filter_field].blank?
|
|
930
|
+
|
|
931
|
+
filter_value = if params[:filter_value].nil?
|
|
932
|
+
#NIL indicates that no filtering is needed
|
|
933
|
+
'#NIL'
|
|
934
|
+
else
|
|
935
|
+
if params[:filter_value].class == String and params[:filter_value][0] == '@'
|
|
936
|
+
# Internal value. Remove leading @ and evaluate expression
|
|
937
|
+
expression = DcInternals.get(params[:filter_value])
|
|
938
|
+
eval(expression) rescue nil
|
|
939
|
+
else
|
|
940
|
+
# No filter when empty
|
|
941
|
+
params[:filter_value] == '' ? '#NIL' : params[:filter_value]
|
|
942
|
+
end
|
|
943
|
+
end
|
|
944
|
+
# if filter field parameter is omitted then just set filter value
|
|
945
|
+
session[table_name][:filter] =
|
|
946
|
+
if params[:filter_field].nil?
|
|
947
|
+
saved = YAML.load(session[table_name][:filter])
|
|
948
|
+
saved['value'] = filter_value
|
|
949
|
+
saved.to_yaml
|
|
950
|
+
else
|
|
951
|
+
# as field defined. Split name and alternative input field
|
|
952
|
+
field = if params[:filter_field].match(' as ')
|
|
953
|
+
params[:filter_input] = params[:filter_field].split(' as ').last.strip
|
|
954
|
+
params[:filter_field].split(' as ').first.strip
|
|
955
|
+
else
|
|
956
|
+
params[:filter_field]
|
|
957
|
+
end
|
|
958
|
+
|
|
959
|
+
{'field' => field,
|
|
960
|
+
'operation' => params[:filter_oper],
|
|
961
|
+
'value' => filter_value,
|
|
962
|
+
'input' => params[:filter_input],
|
|
963
|
+
'table' => table_name }.to_yaml
|
|
964
|
+
end
|
|
965
|
+
# must be. Otherwise kaminari includes parames on paging links
|
|
966
|
+
params[:filter] = nil
|
|
967
|
+
params[:filter_id] = nil
|
|
968
|
+
params[:filter_oper] = nil
|
|
969
|
+
params[:filter_input] = nil
|
|
970
|
+
params[:filter_field] = nil
|
|
971
|
+
end
|
|
972
|
+
|
|
973
|
+
########################################################################
|
|
974
|
+
# Will check and set current filter options for result set. Subroutine of index method.
|
|
975
|
+
########################################################################
|
|
976
|
+
def check_filter_options() #:nodoc:
|
|
977
|
+
table_name = @tables.first[1]
|
|
978
|
+
model = @tables.first[0]
|
|
979
|
+
session[table_name] ||= {}
|
|
980
|
+
# page is set
|
|
981
|
+
session[table_name][:page] = params[:page] if params[:page]
|
|
982
|
+
# new filter is applied
|
|
983
|
+
if params[:filter]
|
|
984
|
+
set_session_filter(table_name)
|
|
985
|
+
session[table_name][:page] = 1
|
|
986
|
+
end
|
|
987
|
+
# if data model has field dc_site_id ensure that only documents which belong to the site are selected.
|
|
988
|
+
site_id = dc_get_site._id if dc_get_site
|
|
989
|
+
|
|
990
|
+
# don't filter site if no dc_site_id field or user is ADMIN
|
|
991
|
+
site_id = nil if !model.method_defined?('dc_site_id') or dc_user_can(DcPermission::CAN_ADMIN)
|
|
992
|
+
site_id = nil if session[table_name][:filter].to_s.match('dc_site_id')
|
|
993
|
+
|
|
994
|
+
if @records = DcFilter.get_filter(session[table_name][:filter])
|
|
995
|
+
@records = @records.and(dc_site_id: site_id) if site_id
|
|
996
|
+
else
|
|
997
|
+
@records = site_id ? model.where(dc_site_id: site_id) : model
|
|
998
|
+
end
|
|
999
|
+
process_select_and_deny_fields
|
|
1000
|
+
# pagination if required
|
|
1001
|
+
per_page = (@form['result_set']['per_page'] || 30).to_i
|
|
1002
|
+
@records = @records.page(session[table_name][:page]).per(per_page) if per_page > 0
|
|
1003
|
+
end
|
|
1004
|
+
|
|
1005
|
+
########################################################################
|
|
1006
|
+
# Process index action for normal collections.
|
|
1007
|
+
########################################################################
|
|
1008
|
+
def process_collections #:nodoc
|
|
1009
|
+
# If result_set is not defined on form, then it will fail. :return_to should know where to go
|
|
1010
|
+
if @form['result_set'].nil?
|
|
1011
|
+
process_return_to(params[:return_to] || 'reload')
|
|
1012
|
+
return true
|
|
1013
|
+
end
|
|
1014
|
+
# for now enable only filtering of top level documents
|
|
1015
|
+
if @tables.size == 1
|
|
1016
|
+
check_filter_options()
|
|
1017
|
+
check_sort_options()
|
|
1018
|
+
end
|
|
1019
|
+
# result set is defined by filter method in control object
|
|
1020
|
+
form_filter = @form['result_set']['filter']
|
|
1021
|
+
if form_filter
|
|
1022
|
+
if respond_to?(form_filter)
|
|
1023
|
+
@records = send(form_filter)
|
|
1024
|
+
# something went wrong. flash[] should have explanation.
|
|
1025
|
+
if @records.class == FalseClass
|
|
1026
|
+
@records = []
|
|
1027
|
+
render(action: :index)
|
|
1028
|
+
return true
|
|
1029
|
+
end
|
|
1030
|
+
process_select_and_deny_fields
|
|
1031
|
+
# pagination but only if not already set
|
|
1032
|
+
unless (@form['table'] == 'dc_memory' or @records.options[:limit])
|
|
1033
|
+
per_page = (@form['result_set']['per_page'] || 30).to_i
|
|
1034
|
+
@records = @records.page(params[:page]).per(per_page) if per_page > 0
|
|
1035
|
+
end
|
|
1036
|
+
elsif form_filter != 'dc_filter'
|
|
1037
|
+
Rails.logger.error "Error: result_set:filter: #{@form['result_set']['filter']} not found in controls!"
|
|
1038
|
+
end
|
|
1039
|
+
else
|
|
1040
|
+
if @tables.size > 1
|
|
1041
|
+
rec = @tables.first[0].find(@ids.first) # top most document.id
|
|
1042
|
+
1.upto(@tables.size - 2) { |i| rec = rec.send(@tables[i][1].pluralize).find(@ids[i]) } # find embedded childrens by ids
|
|
1043
|
+
# TO DO. When field name is different then pluralized class name. Not working yet.
|
|
1044
|
+
embedded_field_name = @tables.last[0] ? @tables.last[1].pluralize : @tables.last[1]
|
|
1045
|
+
@records = rec.send(embedded_field_name) # current embedded set
|
|
1046
|
+
# sort by order if order field is present in model
|
|
1047
|
+
if @tables.last[1].classify.constantize.respond_to?(:order)
|
|
1048
|
+
@records = @records.order_by('order asc')
|
|
1049
|
+
end
|
|
1050
|
+
end
|
|
1051
|
+
end
|
|
1052
|
+
false
|
|
1053
|
+
end
|
|
1054
|
+
|
|
1055
|
+
########################################################################
|
|
1056
|
+
# Process index action for in memory data.
|
|
1057
|
+
########################################################################
|
|
1058
|
+
def process_in_memory #:nodoc
|
|
1059
|
+
@records = []
|
|
1060
|
+
# result set is defined by filter method in control object
|
|
1061
|
+
if (method = @form['result_set']['filter'])
|
|
1062
|
+
send(method) if respond_to?(method)
|
|
1063
|
+
end
|
|
1064
|
+
# result set is defined by class method
|
|
1065
|
+
if (klass_method = @form['result_set']['filter_method'])
|
|
1066
|
+
_klass, method = klass_method.split('.')
|
|
1067
|
+
klass = _klass.classify.constantize
|
|
1068
|
+
@records = klass.send(method) if klass.respond_to?(method)
|
|
1069
|
+
end
|
|
1070
|
+
# ensure that record has id field
|
|
1071
|
+
if @records.size > 0
|
|
1072
|
+
raise "Exception: id field must be set in dc_memory record!" unless @records.first.id
|
|
1073
|
+
end
|
|
1074
|
+
false
|
|
1075
|
+
end
|
|
1076
|
+
|
|
1077
|
+
|
|
898
1078
|
end
|