drg_cms 0.6.1.11 → 0.7.0.2
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/CHANGELOG.md +260 -0
- data/MIT-LICENSE +1 -1
- data/README.md +9 -5
- data/app/assets/javascripts/drg_cms/drg_cms.js +35 -19
- data/app/assets/javascripts/drg_cms_application.js +0 -2
- data/app/assets/javascripts/drg_cms_cms.js +2 -3
- data/app/assets/stylesheets/drg_cms/jstree.css +32 -27
- data/app/assets/stylesheets/drg_cms/select-multiple.css +4 -2
- data/app/controllers/dc_application_controller.rb +3 -2
- data/app/controllers/dc_common_controller.rb +7 -7
- data/app/controls/dc_category_control.rb +61 -0
- data/app/forms/cms_menu.yml +3 -2
- data/app/forms/dc_category.yml +17 -8
- data/app/forms/dc_category_as_tree.yml +31 -0
- data/app/forms/help/dc_category_as_tree.en +4 -0
- data/app/forms/help/dc_category_as_tree.sl +5 -0
- data/app/helpers/cms_edit_helper.rb +2 -2
- data/app/helpers/dc_application_helper.rb +31 -49
- data/app/helpers/dc_category_helper.rb +129 -0
- data/app/models/dc_category.rb +50 -24
- data/app/models/drgcms_form_fields/date_picker.rb +10 -12
- data/app/models/drgcms_form_fields/datetime_picker.rb +10 -11
- data/app/models/drgcms_form_fields/drgcms_field.rb +46 -4
- data/app/models/drgcms_form_fields/tree_select.rb +20 -19
- data/app/views/layouts/content.html.erb +1 -1
- data/config/locales/drgcms_en.yml +2 -0
- data/config/locales/drgcms_sl.yml +2 -0
- data/drg_cms.gemspec +2 -2
- data/lib/drg_cms/version.rb +1 -1
- data/lib/tasks/dc_cleanup.rake +20 -42
- metadata +12 -7
- data/History.log +0 -109
@@ -116,7 +116,7 @@ def toggle_edit_mode
|
|
116
116
|
end
|
117
117
|
url << (url.match(/\?/) ? '&' : '?')
|
118
118
|
url << "return_to_ypos=#{ypos}"
|
119
|
-
redirect_to
|
119
|
+
redirect_to(url, allow_other_host: true)
|
120
120
|
end
|
121
121
|
|
122
122
|
####################################################################
|
@@ -128,15 +128,15 @@ def process_login
|
|
128
128
|
|
129
129
|
unless params[:record][:password].blank? #password must not be empty
|
130
130
|
user = DcUser.find_by(username: params[:record][:username], active: true)
|
131
|
-
if user
|
131
|
+
if user && user.authenticate(params[:record][:password])
|
132
132
|
fill_login_data(user, params[:record][:remember_me].to_i == 1)
|
133
|
-
return redirect_to
|
133
|
+
return redirect_to(params[:return_to] || '/', allow_other_host: true)
|
134
134
|
else
|
135
135
|
clear_login_data # on the safe side
|
136
136
|
end
|
137
137
|
end
|
138
138
|
flash[:error] = t('drgcms.invalid_username')
|
139
|
-
redirect_to
|
139
|
+
redirect_to(params[:return_to] || '/', allow_other_host: true)
|
140
140
|
end
|
141
141
|
|
142
142
|
####################################################################
|
@@ -144,7 +144,7 @@ end
|
|
144
144
|
####################################################################
|
145
145
|
def logout
|
146
146
|
clear_login_data
|
147
|
-
redirect_to
|
147
|
+
redirect_to(params[:return_to] || '/', allow_other_host: true)
|
148
148
|
end
|
149
149
|
|
150
150
|
####################################################################
|
@@ -156,14 +156,14 @@ def login
|
|
156
156
|
user = DcUser.find(cookies.signed[:remember_me])
|
157
157
|
if user and user.active
|
158
158
|
fill_login_data(user, true)
|
159
|
-
return
|
159
|
+
return(redirect_to params[:return_to], allow_other_host: true)
|
160
160
|
else
|
161
161
|
clear_login_data # on the safe side
|
162
162
|
end
|
163
163
|
end
|
164
164
|
# Display login
|
165
165
|
route = params[:route] || 'poll'
|
166
|
-
redirect_to
|
166
|
+
redirect_to("/#{route}?poll_id=login&return_to=#{params[:return_to]}", allow_other_host: true)
|
167
167
|
end
|
168
168
|
|
169
169
|
####################################################################
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2014+ Damjan Rems
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
######################################################################
|
25
|
+
# DrgcmsControls for DcPage model.
|
26
|
+
######################################################################
|
27
|
+
module DcCategoryControl
|
28
|
+
|
29
|
+
######################################################################
|
30
|
+
# Called when new empty record is created
|
31
|
+
######################################################################
|
32
|
+
def dc_new_record
|
33
|
+
if params[:selected]
|
34
|
+
|
35
|
+
end
|
36
|
+
if params[:from_menu]
|
37
|
+
# find menu and submenu. Menu class is defined in Site.
|
38
|
+
menu_a = params[:id].split(';')
|
39
|
+
menu = dc_get_site.menu_klass.find(menu_a.shift)
|
40
|
+
menu_items_method = "#{dc_get_site.menu_class}_items".underscore
|
41
|
+
menu_i = menu.send(menu_items_method).find(menu_a.shift)
|
42
|
+
while menu_a.size > 0 do menu_i = menu_i.send(menu_items_method).find(menu_a.shift) end
|
43
|
+
# Fill values for form
|
44
|
+
@record.subject = menu_i.caption
|
45
|
+
@record.dc_site_id = menu.dc_site_id
|
46
|
+
@record.menu_id = params[:id]
|
47
|
+
# set update_menu on save parameter
|
48
|
+
params['p__update_menu'] = '1'
|
49
|
+
else
|
50
|
+
@record.design_id = params[:design_id] if params[:design_id]
|
51
|
+
return unless params[:page_id]
|
52
|
+
# inherit some values from currently active page
|
53
|
+
if page = DcPage.find(params[:page_id])
|
54
|
+
@record.design_id = page.design_id
|
55
|
+
@record.menu = page.menu
|
56
|
+
@record.dc_site_id = page.dc_site_id
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
data/app/forms/cms_menu.yml
CHANGED
@@ -62,12 +62,13 @@ menu:
|
|
62
62
|
controller: cmsedit
|
63
63
|
icon: more_horiz-o
|
64
64
|
table: dc_simple_menu
|
65
|
-
90:
|
65
|
+
90:
|
66
66
|
caption: helpers.label.dc_category.tabletitle
|
67
67
|
controller: cmsedit
|
68
68
|
icon: list
|
69
69
|
table: dc_category
|
70
|
-
|
70
|
+
|
71
|
+
100:
|
71
72
|
caption: helpers.label.dc_poll.tabletitle
|
72
73
|
controller: cmsedit
|
73
74
|
icon: poll-o
|
data/app/forms/dc_category.yml
CHANGED
@@ -3,8 +3,17 @@
|
|
3
3
|
table: dc_category
|
4
4
|
|
5
5
|
index:
|
6
|
-
filter: name, description,
|
7
|
-
actions:
|
6
|
+
filter: name, description, dc_site_id, parent
|
7
|
+
actions:
|
8
|
+
1: new
|
9
|
+
2: filter
|
10
|
+
10:
|
11
|
+
type: link
|
12
|
+
icon: account_tree-o
|
13
|
+
caption: drgcms.category_as_tree
|
14
|
+
table: dc_category
|
15
|
+
form_name: dc_category_as_tree
|
16
|
+
# controller: cmsedit
|
8
17
|
|
9
18
|
result_set:
|
10
19
|
actions:
|
@@ -36,13 +45,11 @@ form:
|
|
36
45
|
10:
|
37
46
|
name: name
|
38
47
|
type: text_field
|
39
|
-
|
40
|
-
size: 30
|
48
|
+
size: 30
|
41
49
|
20:
|
42
50
|
name: description
|
43
51
|
type: text_field
|
44
|
-
|
45
|
-
size: 100
|
52
|
+
size: 100
|
46
53
|
30:
|
47
54
|
name: ctype
|
48
55
|
type: select
|
@@ -51,8 +58,7 @@ form:
|
|
51
58
|
40:
|
52
59
|
name: order
|
53
60
|
type: text_field
|
54
|
-
|
55
|
-
size: 5
|
61
|
+
size: 5
|
56
62
|
50:
|
57
63
|
name: dc_site_id
|
58
64
|
type: select
|
@@ -65,4 +71,7 @@ form:
|
|
65
71
|
eval: DcCategory.values_for_parent
|
66
72
|
html:
|
67
73
|
include_blank: true
|
74
|
+
70:
|
75
|
+
name: active
|
76
|
+
type: check_box
|
68
77
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
## YAML Template for page
|
2
|
+
---
|
3
|
+
extend: dc_category
|
4
|
+
|
5
|
+
index:
|
6
|
+
actions:
|
7
|
+
10: /
|
8
|
+
|
9
|
+
result_set:
|
10
|
+
type: method
|
11
|
+
eval: categories_as_tree
|
12
|
+
|
13
|
+
form:
|
14
|
+
actions:
|
15
|
+
standard: /
|
16
|
+
1:
|
17
|
+
type: link
|
18
|
+
caption: drgcms.back
|
19
|
+
icon: arrow-back
|
20
|
+
form_name: dc_category_as_tree
|
21
|
+
table: dc_category
|
22
|
+
params:
|
23
|
+
ids:
|
24
|
+
object: params
|
25
|
+
method: ids
|
26
|
+
|
27
|
+
10:
|
28
|
+
type: submit
|
29
|
+
caption: 'drgcms.save&back'
|
30
|
+
form_name: dc_category_as_tree
|
31
|
+
table: dc_category
|
@@ -0,0 +1,5 @@
|
|
1
|
+
---
|
2
|
+
index: "<p>Urejanje kategorij v drevesnem pogledu. Poiščite vašo kategorijo
|
3
|
+
in kliknite desni gumb na miški za menu.</p>\r\n"
|
4
|
+
form: "<p>Urejanje kategorij v drevesnem pogledu. Poiščite vašo kategorijo
|
5
|
+
in kliknite desni gumb na miški za menu.</p>\r\n"
|
@@ -137,7 +137,7 @@ def dc_actions_for_form(position)
|
|
137
137
|
actions.delete('standard')
|
138
138
|
actions = actions.to_a.sort { |x, y| x[0] <=> y[0] }
|
139
139
|
# Add spinner to the beginning
|
140
|
-
html = %
|
140
|
+
html = %(<span class="dc-spinner">#{mi_icon('settings-o spin')}</span><ul class="dc-menu #{position}">)
|
141
141
|
|
142
142
|
actions.each do |key, options|
|
143
143
|
session[:form_processing] = "form:actions: #{key} #{options}"
|
@@ -211,7 +211,7 @@ def dc_actions_for_form(position)
|
|
211
211
|
dc_submit_tag(caption, icon, { data: parameters, title: options['title'] }) +
|
212
212
|
'</li>'
|
213
213
|
else
|
214
|
-
%(<li><div class="dc-link-no">#{
|
214
|
+
%(<li><div class="dc-link-no">#{mi_icon(icon)} #{caption}</div></li>)
|
215
215
|
end
|
216
216
|
|
217
217
|
# delete with some sugar added
|
@@ -314,50 +314,22 @@ def dc_new_title
|
|
314
314
|
end
|
315
315
|
end
|
316
316
|
|
317
|
-
####################################################################
|
318
|
-
# Formats label and html input code for display on edit form.
|
319
|
-
#
|
320
|
-
# Parameters:
|
321
|
-
# [input_html] String. HTML code for data input field.
|
322
|
-
# [label] String. Input field label.
|
323
|
-
####################################################################
|
324
|
-
def dc_label_for(input_html, label)
|
325
|
-
c =<<eot
|
326
|
-
<tr>
|
327
|
-
<td class="dc-edit-label">#{label}</td>
|
328
|
-
<td class="dc-edit-field">#{input_html}</td>
|
329
|
-
</tr>
|
330
|
-
eot
|
331
|
-
c.html_safe
|
332
|
-
end
|
333
|
-
|
334
317
|
############################################################################
|
335
318
|
# Similar to rails submit_tag, but also takes care of link icon, translation, ...
|
336
319
|
############################################################################
|
337
|
-
def dc_submit_tag(caption, icon, parms, rest={})
|
338
|
-
|
339
|
-
|
340
|
-
icon_image = if icon.match(/\./)
|
341
|
-
image_tag(icon)
|
342
|
-
elsif icon.match('<i')
|
343
|
-
icon
|
344
|
-
else
|
345
|
-
fa_icon(icon)
|
346
|
-
end
|
347
|
-
end
|
348
|
-
html = icon_image || ''
|
349
|
-
#html << submit_tag(t(caption, caption), parms)
|
350
|
-
%Q[<button type="submit" class="dc-submit" name="commit" value="#{t(caption, caption)}">#{icon_image} #{t(caption, caption)}</button>].html_safe
|
320
|
+
def dc_submit_tag(caption, icon, parms, rest = {})
|
321
|
+
icon_image = dc_icon_for_link(icon, nil)
|
322
|
+
%(<button type="submit" class="dc-submit" name="commit" value="#{t(caption, caption)}">#{icon_image} #{t(caption, caption)}</button>).html_safe
|
351
323
|
end
|
352
324
|
|
353
325
|
############################################################################
|
354
326
|
# Returns icon code if icon is specified
|
355
327
|
############################################################################
|
356
|
-
def dc_icon_for_link(icon)
|
328
|
+
def dc_icon_for_link(icon, clas = 'dc-link-img')
|
357
329
|
return '' if icon.blank?
|
358
330
|
|
359
331
|
if icon.match(/\./)
|
360
|
-
_origin.image_tag(icon, class:
|
332
|
+
_origin.image_tag(icon, class: clas)
|
361
333
|
elsif icon.match('<i')
|
362
334
|
icon
|
363
335
|
else
|
@@ -619,7 +591,7 @@ def dc_page_edit_menu(opts = @opts)
|
|
619
591
|
opts[:editparams] ||= {}
|
620
592
|
dc_link_menu_tag(title) do |html|
|
621
593
|
opts[:editparams].merge!( controller: 'cmsedit', action: 'edit', 'icon' => 'edit-o' )
|
622
|
-
opts[:editparams].merge!( :id => page.id, :
|
594
|
+
opts[:editparams].merge!( :id => page.id, :table => _origin.site.page_class.underscore, form_name: opts[:form_name], edit_only: 'body' )
|
623
595
|
html << dc_link_for_edit1( opts[:editparams], t('drgcms.edit_content') )
|
624
596
|
|
625
597
|
opts[:editparams].merge!( edit_only: nil, 'icon' => 'edit-o' )
|
@@ -867,7 +839,7 @@ end
|
|
867
839
|
#
|
868
840
|
# Parameters:
|
869
841
|
# [ctrl] Controller object or object which holds methods to access session object. For example @parent
|
870
|
-
#
|
842
|
+
# when called from renderer.
|
871
843
|
# [policy_id] Document or documents policy_id field value required to view data. Method will automatically
|
872
844
|
# check if parameter send has policy_id field defined and use value of that field.
|
873
845
|
#
|
@@ -882,9 +854,11 @@ end
|
|
882
854
|
# False and message from policy that is blocking view if access is not allowed.
|
883
855
|
############################################################################
|
884
856
|
def dc_user_can_view(ctrl, policy_id)
|
885
|
-
|
857
|
+
@can_view_cache ||= {}
|
858
|
+
policy_id = policy_id.policy_id if policy_id&.respond_to?(:policy_id)
|
886
859
|
# Eventualy object without policy_id will be checked. This is to prevent error
|
887
860
|
policy_id = nil unless policy_id.class == BSON::ObjectId
|
861
|
+
return @can_view_cache[policy_id] if @can_view_cache[policy_id]
|
888
862
|
|
889
863
|
site = ctrl.site
|
890
864
|
policies = if site.inherit_policy.blank?
|
@@ -894,7 +868,7 @@ def dc_user_can_view(ctrl, policy_id)
|
|
894
868
|
end
|
895
869
|
# permission defined by default policy
|
896
870
|
default_policy = Mongoid::QueryCache.cache { policies.find_by(is_default: true) }
|
897
|
-
return false, 'Default access policy not found for the site!' unless default_policy
|
871
|
+
return cache_add(policy_id, false, 'Default access policy not found for the site!') unless default_policy
|
898
872
|
|
899
873
|
permissions = {}
|
900
874
|
default_policy.dc_policy_rules.to_a.each { |v| permissions[v.dc_policy_role_id] = v.permission }
|
@@ -902,28 +876,29 @@ def dc_user_can_view(ctrl, policy_id)
|
|
902
876
|
part_policy = nil
|
903
877
|
if policy_id
|
904
878
|
part_policy = Mongoid::QueryCache.cache { policies.find(policy_id) }
|
905
|
-
return false, 'Access policy not found for part!' unless part_policy
|
879
|
+
return cache_add(policy_id, false, 'Access policy not found for part!') unless part_policy
|
880
|
+
|
906
881
|
part_policy.dc_policy_rules.to_a.each { |v| permissions[v.dc_policy_role_id] = v.permission }
|
907
882
|
end
|
908
883
|
# apply guest role if no roles defined
|
909
884
|
if ctrl.session[:user_roles].nil?
|
910
885
|
role = Mongoid::QueryCache.cache { DcPolicyRole.find_by(system_name: 'guest', active: true) }
|
911
|
-
return false, 'System guest role not defined!' unless role
|
886
|
+
return cache_add(policy_id, false, 'System guest role not defined!') unless role
|
887
|
+
|
912
888
|
ctrl.session[:user_roles] = [role.id]
|
913
889
|
end
|
914
890
|
# Check if user has any role that allows him to view part
|
915
|
-
can_view
|
916
|
-
|
917
|
-
next unless permissions[role] # role not yet defined. Will die in next line.
|
918
|
-
if permissions[role] > 0
|
919
|
-
can_view = true
|
920
|
-
break
|
921
|
-
end
|
891
|
+
can_view = ctrl.session[:user_roles].reduce(false) do |result, role|
|
892
|
+
break true if permissions[role] && permissions[role] > 0
|
922
893
|
end
|
923
|
-
|
924
|
-
|
894
|
+
|
895
|
+
msg = ''
|
896
|
+
unless can_view
|
897
|
+
msg = part_policy ? t(part_policy.message, part_policy.message) : t(default_policy.message, default_policy.message)
|
898
|
+
# message may have variable content
|
899
|
+
msg = _origin.render(inline: msg, layout: nil) if msg.match('<%=')
|
925
900
|
end
|
926
|
-
|
901
|
+
cache_add(policy_id, can_view, msg)
|
927
902
|
end
|
928
903
|
|
929
904
|
####################################################################
|
@@ -1234,5 +1209,12 @@ def dc_img_alt(file_name, text=nil)
|
|
1234
1209
|
name[0,name.index('.')].downcase rescue name
|
1235
1210
|
end
|
1236
1211
|
|
1212
|
+
private
|
1213
|
+
|
1214
|
+
# will cache dc_user_can_view response
|
1215
|
+
def cache_add(id, can_view, msg)
|
1216
|
+
@can_view_cache[id] = [can_view, msg]
|
1217
|
+
end
|
1218
|
+
|
1237
1219
|
|
1238
1220
|
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2012+ Damjan Rems
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
|
25
|
+
####################################################################
|
26
|
+
# Helper for editing categories as tree view.
|
27
|
+
####################################################################
|
28
|
+
module DcCategoryHelper
|
29
|
+
|
30
|
+
####################################################################
|
31
|
+
#
|
32
|
+
####################################################################
|
33
|
+
def categories_as_tree
|
34
|
+
html = '<div id="catagories-as-tree"><ul><li data-id="nil"><span class="mi-o mi-home"></span>'
|
35
|
+
data = DcCategory.where(parent: nil).order_by(order: 1).to_a
|
36
|
+
html_for_category_tree(html, data)
|
37
|
+
(html << '</li></ul></div>' << js_for_category_tree).html_safe
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
####################################################################
|
43
|
+
#
|
44
|
+
####################################################################
|
45
|
+
def html_for_category_tree(html, data)
|
46
|
+
html << '<ul>'
|
47
|
+
data.each do |category|
|
48
|
+
icon = category.active ? 'check_box' : 'check_box_outline_blank'
|
49
|
+
html << %(<li id="#{category.id}" data-parent="#{category.parent}"><span class="mi-o mi-#{icon} mi-18"></span>#{category.name}\n)
|
50
|
+
children = DcCategory.where(parent: category.id).order_by(order: 1).to_a
|
51
|
+
|
52
|
+
html_for_category_tree(html, children) if children.size > 0
|
53
|
+
html << '</li>'
|
54
|
+
end
|
55
|
+
html << '</ul>'
|
56
|
+
end
|
57
|
+
|
58
|
+
####################################################################
|
59
|
+
#
|
60
|
+
####################################################################
|
61
|
+
def js_for_category_tree
|
62
|
+
%(<script>
|
63
|
+
$(function() {
|
64
|
+
$("#catagories-as-tree").jstree( {
|
65
|
+
core: { themes: { icons: false },
|
66
|
+
multiple: false
|
67
|
+
},
|
68
|
+
plugins: ["types", "contextmenu"],
|
69
|
+
contextmenu: {
|
70
|
+
items: function ($node) {
|
71
|
+
return {
|
72
|
+
edit: {
|
73
|
+
label: "<span class='dc-result-submenu'>#{t('drgcms.edit')}</span>",
|
74
|
+
icon: "mi-o mi-edit",
|
75
|
+
action: function (obj) {
|
76
|
+
let id = $('#catagories-as-tree').jstree('get_selected', true)[0].id;
|
77
|
+
let params = "&ids=" + id;
|
78
|
+
location.href = "/cmsedit/" + id + "/edit?t=dc_category&f=dc_category_as_tree" + params;
|
79
|
+
}
|
80
|
+
},
|
81
|
+
|
82
|
+
new_child: {
|
83
|
+
label: "<span class='dc-result-submenu'>#{t('drgcms.new')}</span>",
|
84
|
+
icon: "mi-o mi-plus",
|
85
|
+
action: function (obj) {
|
86
|
+
let id = $('#catagories-as-tree').jstree('get_selected', true)[0].id;
|
87
|
+
let params = "&ids=" + id + "&p_parent=" + id;
|
88
|
+
location.href = "/cmsedit/new?t=dc_category&f=dc_category_as_tree" + params
|
89
|
+
}
|
90
|
+
},
|
91
|
+
|
92
|
+
delete: {
|
93
|
+
label: "<span class='dc-result-submenu'>#{t('drgcms.delete')}</span>",
|
94
|
+
icon: "mi-o mi-delete",
|
95
|
+
action: function (obj) {
|
96
|
+
if (confirmation_is_cancled("#{t('drgcms.confirm_delete')}") === true) return false;
|
97
|
+
|
98
|
+
let id = $('#catagories-as-tree').jstree('get_selected', true)[0].id;
|
99
|
+
let id_return = $('#catagories-as-tree').jstree('get_selected', true)[0].data["parent"];
|
100
|
+
|
101
|
+
$.ajax({
|
102
|
+
url: "/cmsedit/" + id + "?t=dc_category",
|
103
|
+
type: 'DELETE',
|
104
|
+
success: function(data) {
|
105
|
+
let error = data.match("#{I18n.t('drgcms.category_has_subs')}");
|
106
|
+
if (error !== null) {
|
107
|
+
alert(error[0]);
|
108
|
+
params = "?t=dc_category&f=dc_category_as_tree&ids=" + id;
|
109
|
+
location.href = "/cmsedit" + params;
|
110
|
+
return true;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
});
|
114
|
+
|
115
|
+
let params = "?t=dc_category&f=dc_category_as_tree&ids=" + id_return;
|
116
|
+
location.href = "/cmsedit" + params;
|
117
|
+
}
|
118
|
+
},
|
119
|
+
}
|
120
|
+
},
|
121
|
+
},
|
122
|
+
});
|
123
|
+
$("#catagories-as-tree").jstree(true).select_node("#{params[:ids]}");
|
124
|
+
});
|
125
|
+
|
126
|
+
</script>)
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
data/app/models/dc_category.rb
CHANGED
@@ -42,32 +42,60 @@
|
|
42
42
|
# is most useful for grouping news, blog entries ...
|
43
43
|
#####################################################################
|
44
44
|
class DcCategory
|
45
|
-
|
46
|
-
|
45
|
+
include Mongoid::Document
|
46
|
+
include Mongoid::Timestamps
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
48
|
+
field :name, type: String
|
49
|
+
field :description, type: String
|
50
|
+
field :ctype, type: Integer, default: 1
|
51
|
+
field :parent, type: BSON::ObjectId
|
52
|
+
field :active, type: Boolean, default: true
|
53
|
+
field :order, type: Integer, default: 0
|
54
|
+
field :created_by, type: BSON::ObjectId
|
55
|
+
field :updated_by, type: BSON::ObjectId
|
56
|
+
field :dc_site_id, type: BSON::ObjectId
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
index name: 1
|
59
|
+
index ctype: 1
|
60
|
+
index site_id: 1
|
61
|
+
|
62
|
+
validates :name, presence: true
|
63
|
+
|
64
|
+
before_destroy :can_destroy?
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
#########################################################################
|
69
|
+
# Can't delete if category document has children documents
|
70
|
+
#########################################################################
|
71
|
+
def can_destroy?
|
72
|
+
if DcCategory.where(parent: id).count > 0
|
73
|
+
errors.add(:base, I18n.t('drgcms.category_has_subs'))
|
74
|
+
throw :abort
|
75
|
+
end
|
76
|
+
end
|
63
77
|
|
64
78
|
#########################################################################
|
65
|
-
# Returns all values
|
79
|
+
# Returns all values for use as parent select field.
|
66
80
|
#########################################################################
|
67
|
-
def self.values_for_parent(site_id=nil) #:nodoc:
|
81
|
+
def self.values_for_parent(site_id = nil) #:nodoc:
|
68
82
|
qry = where(active: true)
|
69
83
|
qry = qry.and(dc_site_id: site_id.id) if site_id
|
70
|
-
|
84
|
+
parents = {} # cache parent names to minimize database usage
|
85
|
+
qry.inject([]) do |r, v|
|
86
|
+
if parents[v.parent].nil?
|
87
|
+
name = ''
|
88
|
+
parent = v.parent
|
89
|
+
until parent.nil?
|
90
|
+
doc = find(parent)
|
91
|
+
name = doc.name + ' / ' + name
|
92
|
+
parent = doc.parent
|
93
|
+
end
|
94
|
+
parents[v.parent] = name
|
95
|
+
end
|
96
|
+
name = v.parent ? parents[v.parent] + v.name : v.name
|
97
|
+
r << [name, v._id]
|
98
|
+
end.sort { |a, b| a.first <=> b.first }
|
71
99
|
end
|
72
100
|
|
73
101
|
#########################################################################
|
@@ -80,8 +108,8 @@ def self.choices4_ctype(site_id=nil)
|
|
80
108
|
DcBigTable.choices4('dc_category_type', site_id)
|
81
109
|
else
|
82
110
|
opts = I18n.t('helpers.label.dc_category.choices4_ctype')
|
83
|
-
# not defined
|
84
|
-
|
111
|
+
return [] if opts.blank? # not defined
|
112
|
+
|
85
113
|
opts.split(',').inject([]) {|result, e| result << e.split(':')}
|
86
114
|
end
|
87
115
|
end
|
@@ -89,13 +117,11 @@ end
|
|
89
117
|
#########################################################################
|
90
118
|
# Returns choices for all categories, prepared for tree_select input field
|
91
119
|
#########################################################################
|
92
|
-
def self.choices4_categories(site_id=nil)
|
120
|
+
def self.choices4_categories(site_id = nil)
|
93
121
|
qry = where(active: true)
|
94
|
-
#
|
95
122
|
ar = [nil]
|
96
123
|
ar << site_id.id if site_id
|
97
124
|
qry = qry.in(dc_site_id: ar)
|
98
|
-
#
|
99
125
|
qry.inject([]) { |result, category| result << [category.name, category.id, category.parent, category.order] }
|
100
126
|
end
|
101
127
|
|
@@ -66,30 +66,28 @@ class DatePicker < DrgcmsField
|
|
66
66
|
###########################################################################
|
67
67
|
def render
|
68
68
|
value = @record.try(@yaml['name']) ? I18n.localize(@record[@yaml['name']].to_date) : nil
|
69
|
-
#return ro_standard( @parent.dc_format_value(value)) if @readonly
|
70
|
-
|
71
|
-
@yaml['options'] ||= {}
|
72
69
|
set_initial_value
|
73
70
|
@yaml['html']['size'] ||= @yaml['size'] || 10
|
74
71
|
@yaml['html']['value'] ||= value
|
75
72
|
@yaml['html']['autocomplete'] ||= 'off'
|
76
73
|
@yaml['html']['class'] = @yaml['html']['class'].to_s + ' date-picker'
|
77
74
|
|
78
|
-
@yaml['options']
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
75
|
+
options = options_to_hash(@yaml['options'])
|
76
|
+
options['lang'] ||= I18n.locale.to_s
|
77
|
+
options['format'] ||= t('datetimepicker.formats.date')
|
78
|
+
options['timepicker'] = false
|
79
|
+
options['scrollMonth'] ||= false
|
80
|
+
options['scrollInput'] ||= false
|
83
81
|
|
84
82
|
record = record_text_for(@yaml['name'])
|
85
83
|
@html << @parent.text_field(record, @yaml['name'], @yaml['html'])
|
86
|
-
@js << %
|
84
|
+
@js << %(
|
87
85
|
$(document).ready(function() {
|
88
|
-
$("##{record}_#{@yaml['name']}").datetimepicker(
|
89
|
-
#{hash_to_options(
|
86
|
+
$("##{record}_#{@yaml['name']}").datetimepicker({
|
87
|
+
#{hash_to_options(options)}
|
90
88
|
});
|
91
89
|
});
|
92
|
-
|
90
|
+
) unless @readonly
|
93
91
|
|
94
92
|
self
|
95
93
|
end
|