wagn 1.12.10 → 1.12.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Gemfile +14 -12
- data/VERSION +1 -1
- data/app/assets/javascripts/wagn.js.coffee +25 -22
- data/app/assets/javascripts/wagn_mod.js.coffee +0 -44
- data/app/controllers/card_controller.rb +0 -1
- data/app/controllers/wagn_controller.rb +1 -2
- data/config/routes.rb +0 -1
- data/features/hello_wagn.feature +7 -5
- data/lib/card/exceptions.rb +7 -2
- data/lib/card/format.rb +8 -3
- data/lib/card/query/card_spec.rb +2 -1
- data/lib/card/set.rb +1 -0
- data/lib/wagn/all.rb +4 -4
- data/mods/core/formats/html_format.rb +296 -284
- data/mods/core/formats/text_format.rb +5 -2
- data/mods/core/sets/all/phases.rb +13 -0
- data/mods/standard/formats/css_format.rb +4 -1
- data/mods/standard/formats/csv_format.rb +4 -1
- data/mods/standard/formats/js_format.rb +6 -0
- data/mods/standard/formats/json_format.rb +4 -1
- data/mods/standard/formats/kml_format.rb +4 -1
- data/mods/standard/formats/rss_format.rb +7 -4
- data/mods/standard/formats/xml_format.rb +4 -1
- data/mods/standard/lib/stylesheets/functional.scss +2 -1
- data/mods/standard/sets/all/account.rb +1 -1
- data/mods/standard/sets/all/all_css.rb +5 -1
- data/mods/standard/sets/all/json.rb +17 -21
- data/mods/standard/sets/all/rich_html.rb +4 -3
- data/mods/standard/sets/self/head.rb +6 -0
- data/mods/standard/sets/type/cardtype.rb +1 -1
- data/mods/standard/sets/type/pointer.rb +23 -11
- data/mods/standard/sets/type/scss.rb +1 -0
- data/mods/standard/sets/type/search_type.rb +0 -2
- data/mods/standard/sets/type/user.rb +1 -2
- data/public/assets/application-7cda003cf1291a165b1eac69ea3027aa.js +107 -0
- data/public/assets/application-7cda003cf1291a165b1eac69ea3027aa.js.gz +0 -0
- data/public/assets/application.js +42 -38
- data/public/assets/application.js.gz +0 -0
- data/public/assets/html5shiv-printshiv-ad36fc7219f4aeaa275f9a7fe2383413.js.gz +0 -0
- data/public/assets/html5shiv-printshiv.js.gz +0 -0
- data/public/assets/jquery.min-8b58c0fbf303b938d8e749262f7e50dd.map +1 -0
- data/public/assets/jquery.min.map +1 -0
- data/public/assets/manifest.yml +4 -2
- data/public/assets/tinymce-22b5a139d9ff7df7643afae9ce205508.js.gz +0 -0
- data/public/assets/tinymce.js.gz +0 -0
- data/spec/lib/card/query_spec.rb +3 -2
- data/spec/mods/standard/sets/all/all_css_spec.rb +1 -1
- data/spec/mods/standard/sets/type/pointer_spec.rb +2 -2
- data/wagn.gemspec +5 -4
- metadata +10 -80
- data/public/assets/application-af2bc486eb3db1c02c4dcd0e23ca25fc.js +0 -103
- data/public/assets/application-af2bc486eb3db1c02c4dcd0e23ca25fc.js.gz +0 -0
- data/public/assets2bpacked/jstree/README.txt +0 -10
- data/public/assets2bpacked/jstree/_demo/_dump.sql +0 -20
- data/public/assets2bpacked/jstree/_demo/_inc/__mysql_errors.log +0 -0
- data/public/assets2bpacked/jstree/_demo/_inc/class._database.php +0 -146
- data/public/assets2bpacked/jstree/_demo/_inc/class._database_i.php +0 -152
- data/public/assets2bpacked/jstree/_demo/_inc/class.tree.php +0 -602
- data/public/assets2bpacked/jstree/_demo/_install.txt +0 -6
- data/public/assets2bpacked/jstree/_demo/config.php +0 -14
- data/public/assets2bpacked/jstree/_demo/file.png +0 -0
- data/public/assets2bpacked/jstree/_demo/folder.png +0 -0
- data/public/assets2bpacked/jstree/_demo/index.html +0 -461
- data/public/assets2bpacked/jstree/_demo/root.png +0 -0
- data/public/assets2bpacked/jstree/_demo/server.php +0 -69
- data/public/assets2bpacked/jstree/_docs/!style.css +0 -48
- data/public/assets2bpacked/jstree/_docs/_drive.png +0 -0
- data/public/assets2bpacked/jstree/_docs/_html_data.html +0 -2
- data/public/assets2bpacked/jstree/_docs/_json_data.json +0 -4
- data/public/assets2bpacked/jstree/_docs/_search_data.json +0 -6
- data/public/assets2bpacked/jstree/_docs/_search_result.json +0 -1
- data/public/assets2bpacked/jstree/_docs/_xml_flat.xml +0 -12
- data/public/assets2bpacked/jstree/_docs/_xml_nest.xml +0 -18
- data/public/assets2bpacked/jstree/_docs/checkbox.html +0 -171
- data/public/assets2bpacked/jstree/_docs/contextmenu.html +0 -121
- data/public/assets2bpacked/jstree/_docs/cookies.html +0 -97
- data/public/assets2bpacked/jstree/_docs/core.html +0 -689
- data/public/assets2bpacked/jstree/_docs/crrm.html +0 -316
- data/public/assets2bpacked/jstree/_docs/dnd.html +0 -199
- data/public/assets2bpacked/jstree/_docs/hotkeys.html +0 -82
- data/public/assets2bpacked/jstree/_docs/html_data.html +0 -175
- data/public/assets2bpacked/jstree/_docs/index.html +0 -86
- data/public/assets2bpacked/jstree/_docs/json_data.html +0 -249
- data/public/assets2bpacked/jstree/_docs/languages.html +0 -152
- data/public/assets2bpacked/jstree/_docs/logo.png +0 -0
- data/public/assets2bpacked/jstree/_docs/search.html +0 -153
- data/public/assets2bpacked/jstree/_docs/sort.html +0 -85
- data/public/assets2bpacked/jstree/_docs/syntax/!script.js +0 -2232
- data/public/assets2bpacked/jstree/_docs/syntax/!style.css +0 -511
- data/public/assets2bpacked/jstree/_docs/syntax/clipboard.swf +0 -0
- data/public/assets2bpacked/jstree/_docs/syntax/help.png +0 -0
- data/public/assets2bpacked/jstree/_docs/syntax/magnifier.png +0 -0
- data/public/assets2bpacked/jstree/_docs/syntax/page_white_code.png +0 -0
- data/public/assets2bpacked/jstree/_docs/syntax/page_white_copy.png +0 -0
- data/public/assets2bpacked/jstree/_docs/syntax/printer.png +0 -0
- data/public/assets2bpacked/jstree/_docs/syntax/wrapping.png +0 -0
- data/public/assets2bpacked/jstree/_docs/themeroller.html +0 -107
- data/public/assets2bpacked/jstree/_docs/themes.html +0 -127
- data/public/assets2bpacked/jstree/_docs/types.html +0 -178
- data/public/assets2bpacked/jstree/_docs/ui.html +0 -197
- data/public/assets2bpacked/jstree/_docs/unique.html +0 -85
- data/public/assets2bpacked/jstree/_docs/xml_data.html +0 -218
- data/public/assets2bpacked/jstree/_lib/jquery.cookie.js +0 -96
- data/public/assets2bpacked/jstree/_lib/jquery.hotkeys.js +0 -99
- data/public/assets2bpacked/jstree/_lib/jquery.js +0 -5
- data/public/assets2bpacked/jstree/jquery.jstree.js +0 -4564
- data/public/assets2bpacked/jstree/themes/apple/bg.jpg +0 -0
- data/public/assets2bpacked/jstree/themes/apple/d.png +0 -0
- data/public/assets2bpacked/jstree/themes/apple/dot_for_ie.gif +0 -0
- data/public/assets2bpacked/jstree/themes/apple/style.css +0 -61
- data/public/assets2bpacked/jstree/themes/apple/throbber.gif +0 -0
- data/public/assets2bpacked/jstree/themes/classic/d.gif +0 -0
- data/public/assets2bpacked/jstree/themes/classic/d.png +0 -0
- data/public/assets2bpacked/jstree/themes/classic/dot_for_ie.gif +0 -0
- data/public/assets2bpacked/jstree/themes/classic/style.css +0 -77
- data/public/assets2bpacked/jstree/themes/classic/throbber.gif +0 -0
- data/public/assets2bpacked/jstree/themes/default-rtl/d.gif +0 -0
- data/public/assets2bpacked/jstree/themes/default-rtl/d.png +0 -0
- data/public/assets2bpacked/jstree/themes/default-rtl/dots.gif +0 -0
- data/public/assets2bpacked/jstree/themes/default-rtl/style.css +0 -84
- data/public/assets2bpacked/jstree/themes/default-rtl/throbber.gif +0 -0
- data/public/assets2bpacked/jstree/themes/default/d.gif +0 -0
- data/public/assets2bpacked/jstree/themes/default/d.png +0 -0
- data/public/assets2bpacked/jstree/themes/default/style.css +0 -74
- data/public/assets2bpacked/jstree/themes/default/throbber.gif +0 -0
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OTNmYzI3MDdkNzE0ZmIwODFjZDgzZGJkZDQwMDFhMGM4MjBmZTUwYQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YTJkYzkwODU2NDViYTZiNzNhZTc4Y2U5YmEwZWZhY2M3MTk2MThhNg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZWRiZDc5MzgwOTc5ZGY5ZDllOWRiNzM0N2QxNjhiNDQ3ZjVkNmQ2NWI5NWZh
|
10
|
+
MGZhMjNkMzEwNjU5NWVjZWIwN2EyNDczOTI3MTE3YTg0MGExYzlkOTE4Yzdl
|
11
|
+
ZDE2NjY1MjA0YTEwMDNkOTNiYjVkZDRhYjg4ZmI4ZTkxODRkNDg=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OTQ4OGZmYjYyZTFiZDg3MTJkZGNjN2VkMDU1MTBkNjZmNDY5OWU4ZWM0OTIz
|
14
|
+
YjEzMGQxOGI4MzM4NmQxOTI0NDcxM2Y1NzIzOTk2ODhkOTE2NzUzZTJiMGQ0
|
15
|
+
ZGQ0NzE1MWM1YTM3ZTMwMzU2MTFjNWZkZTQyZjNhYjljMmQ2Mzg=
|
data/Gemfile
CHANGED
@@ -5,32 +5,32 @@ gemspec
|
|
5
5
|
|
6
6
|
gem 'wagn', :path=>File.expand_path( '../', __FILE__ )
|
7
7
|
|
8
|
-
gem 'wagn-dev', :path=>File.expand_path( '../../wagn-dev', __FILE__ )
|
9
|
-
|
10
|
-
group :mysql do
|
11
|
-
gem "mysql2", "~> 0.3"
|
12
|
-
end
|
8
|
+
gem 'wagn-dev', :path=>File.expand_path( '../../wagn-dev', __FILE__ ), :group=>:development
|
9
|
+
gem "mysql2", "~> 0.3"
|
13
10
|
|
14
11
|
|
15
12
|
|
16
|
-
group :profile do
|
17
|
-
gem 'ruby-prof', '~>0.12.1' # profiling
|
18
|
-
#gem 'test-unit' #was causing errors after cucumber runs.
|
19
|
-
end
|
20
13
|
|
21
|
-
group :
|
22
|
-
|
14
|
+
group :assets do
|
23
15
|
gem 'sass-rails', "~> 3.1" # pretty code; compiles to CSS
|
24
16
|
gem 'coffee-rails', "~> 3.1" # pretty code; compiles to JS
|
25
17
|
gem 'uglifier' # makes pretty code ugly again. compresses js/css for fast loading
|
26
18
|
|
27
|
-
gem 'jquery-rails', '~> 2.
|
19
|
+
gem 'jquery-rails', '~> 2.3' # main js framework, along with rails-specific unobtrusive lib
|
28
20
|
gem "jquerymobile-rails", "~> 0.2"
|
29
21
|
|
30
22
|
gem 'tinymce-rails', '~> 3.4' # wysiwyg editor
|
31
23
|
|
32
24
|
# execjs is necessary for developing coffeescript. mac users have execjs built-in; don't need this one
|
33
25
|
gem 'therubyrhino', :platform=>:ruby # :ruby is MRI rubies, so if you use a mac ruby ...
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
group :test do
|
31
|
+
|
32
|
+
# execjs is necessary for developing coffeescript. mac users have execjs built-in; don't need this one
|
33
|
+
gem 'therubyrhino', :platform=>:ruby # :ruby is MRI rubies, so if you use a mac ruby ...
|
34
34
|
|
35
35
|
gem 'rails-dev-tweaks', '~> 0.6' # dramatic speeds up asset loading, among other tweaks
|
36
36
|
gem 'rspec-rails', "~> 2.6" # behavior-driven-development suite
|
@@ -59,6 +59,8 @@ group :test do
|
|
59
59
|
gem 'win32-process', '~> 0.6', :platforms => ['mingw', 'mswin']
|
60
60
|
end
|
61
61
|
|
62
|
+
gem 'ruby-prof', '~>0.12.1', :group=>:profile # profiling
|
63
|
+
|
62
64
|
group :debug do
|
63
65
|
case RUBY_VERSION
|
64
66
|
when /^1\.9\.3-p0/
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.12.
|
1
|
+
1.12.11
|
@@ -41,6 +41,28 @@ jQuery.fn.extend {
|
|
41
41
|
s.replaceWith v
|
42
42
|
v
|
43
43
|
|
44
|
+
slotSuccess: (data) ->
|
45
|
+
if data.redirect
|
46
|
+
window.location=data.redirect
|
47
|
+
else
|
48
|
+
notice = @attr('notify-success')
|
49
|
+
newslot = @setSlotContent data
|
50
|
+
|
51
|
+
if newslot.jquery # sometimes response is plaintext
|
52
|
+
wagn.initializeEditors newslot
|
53
|
+
if notice?
|
54
|
+
newslot.notify notice
|
55
|
+
|
56
|
+
slotError: (status, result) ->
|
57
|
+
if status == 403 #permission denied
|
58
|
+
@setSlotContent result
|
59
|
+
else
|
60
|
+
@notify result
|
61
|
+
if status == 409 #edit conflict
|
62
|
+
@slot().find('.current_revision_id').val @slot().find('.new-current-revision-id').text()
|
63
|
+
else if status == 449
|
64
|
+
@slot().find('.recaptcha-box').loadCaptcha()
|
65
|
+
|
44
66
|
notify: (message) ->
|
45
67
|
slot = @slot()
|
46
68
|
notice = slot.find '.card-notice'
|
@@ -112,28 +134,10 @@ $(window).ready ->
|
|
112
134
|
# dislike the timeout, but without this forms with multiple TinyMCE editors were failing to load properly
|
113
135
|
|
114
136
|
$('body').on 'ajax:success', '.slotter', (event, data, c, d) ->
|
115
|
-
|
116
|
-
window.location=data.redirect
|
117
|
-
else
|
118
|
-
notice = $(this).attr('notify-success')
|
119
|
-
newslot = $(this).setSlotContent data
|
120
|
-
|
121
|
-
if newslot.jquery # sometimes response is plaintext
|
122
|
-
wagn.initializeEditors newslot
|
123
|
-
if notice?
|
124
|
-
newslot.notify notice
|
137
|
+
$(this).slotSuccess data
|
125
138
|
|
126
139
|
$('body').on 'ajax:error', '.slotter', (event, xhr) ->
|
127
|
-
|
128
|
-
if xhr.status == 403 #permission denied
|
129
|
-
$(this).setSlotContent result
|
130
|
-
else
|
131
|
-
$(this).notify result
|
132
|
-
s = $(this).slot()
|
133
|
-
if xhr.status == 409 #edit conflict
|
134
|
-
s.find('.current_revision_id').val s.find('.new-current-revision-id').text()
|
135
|
-
else if xhr.status == 449
|
136
|
-
s.find('.recaptcha-box').loadCaptcha()
|
140
|
+
$(this).slotError xhr.status, xhr.responseText
|
137
141
|
|
138
142
|
$('body').on 'click', 'button.slotter', (event)->
|
139
143
|
return false if !$.rails.allowAction $(this)
|
@@ -141,10 +145,9 @@ $(window).ready ->
|
|
141
145
|
|
142
146
|
$('body').on 'ajax:beforeSend', '.slotter', (event, xhr, opt)->
|
143
147
|
return if opt.skip_before_send
|
144
|
-
|
148
|
+
|
145
149
|
unless opt.url.match /home_view/ #avoiding duplication. could be better test?
|
146
150
|
opt.url = wagn.prepUrl opt.url, $(this).slot()
|
147
|
-
|
148
151
|
|
149
152
|
if $(this).is('form')
|
150
153
|
if wagn.recaptchaKey and $(this).attr('recaptcha')=='on' and !($(this).find('.recaptcha-box')[0])
|
@@ -9,7 +9,6 @@ $.extend wagn,
|
|
9
9
|
'.pointer-list-ul' : -> pointerContent @find('input' ).map( -> $(this).val() )
|
10
10
|
'.pointer-checkbox-list' : -> pointerContent @find('input:checked').map( -> $(this).val() )
|
11
11
|
'.perm-editor' : -> permissionsContent this # must happen after pointer-list-ul, I think
|
12
|
-
'.wikirate-topic-tree' : -> pointerContent @find('.jstree-clicked').map( -> $.trim( $(this).text() ) )
|
13
12
|
}
|
14
13
|
|
15
14
|
editorInitFunctionMap: {
|
@@ -19,14 +18,6 @@ $.extend wagn,
|
|
19
18
|
'.pointer-list-editor' : -> @sortable(); wagn.initPointerList @find('input')
|
20
19
|
'.file-upload' : -> @fileupload( add: wagn.chooseFile )#, forceIframeTransport: true )
|
21
20
|
'.etherpad-textarea' : -> $(this).closest('form').find('.edit-submit-button').attr('class', 'etherpad-submit-button')
|
22
|
-
'.wikirate-topic-tree' : -> $(this).jstree
|
23
|
-
plugins: ["themes","html_data","ui","crrm"],
|
24
|
-
ui:
|
25
|
-
select_multiple_modifier: 'on'
|
26
|
-
initially_select: $(this).closest('.editor').find('.initial-content').text().split '|'
|
27
|
-
selected_parent_close: false
|
28
|
-
themes: icons: false
|
29
|
-
|
30
21
|
}
|
31
22
|
|
32
23
|
initPointerList: (input)->
|
@@ -284,41 +275,6 @@ $(window).ready ->
|
|
284
275
|
$(firstShade).trigger 'click'
|
285
276
|
|
286
277
|
|
287
|
-
#wikirate mod
|
288
|
-
$('body').on 'mouseenter', '#wikirate-nav > a', ->
|
289
|
-
ul = $(this).find 'ul'
|
290
|
-
if ul[0]
|
291
|
-
ul.css 'display', 'inline-block'
|
292
|
-
else
|
293
|
-
link = $(this)
|
294
|
-
$.ajax link.attr('href'), {
|
295
|
-
data : { view: 'navdrop', layout: 'none', index: $('#wikirate-nav > a').index(link) },
|
296
|
-
# type : 'POST',
|
297
|
-
success: (data) ->
|
298
|
-
#alert 'success!'
|
299
|
-
wagn.d = data
|
300
|
-
link.prepend $(data).menu()
|
301
|
-
}
|
302
|
-
|
303
|
-
$('body').on 'mouseleave', '#wikirate-nav ul', ->
|
304
|
-
$(this).hide()
|
305
|
-
|
306
|
-
# $('body').on 'change', '.TYPE-claim .card-editor fieldset.RIGHT-source_type', ->
|
307
|
-
# f = $(this).closest 'form'
|
308
|
-
# val = $(this).find('input:checked').val()
|
309
|
-
#
|
310
|
-
# new_field = f.find 'fieldset.RIGHT-source_link'
|
311
|
-
# existing_field = f.find 'fieldset.RIGHT-source'
|
312
|
-
#
|
313
|
-
# if val == 'existing'
|
314
|
-
# existing_field.show()
|
315
|
-
# new_field.hide()
|
316
|
-
# else
|
317
|
-
# existing_field.hide()
|
318
|
-
# new_field.show()
|
319
|
-
#
|
320
|
-
# $('.TYPE-claim .card-editor fieldset.RIGHT-source_type').trigger 'change'
|
321
|
-
|
322
278
|
# following not in use??
|
323
279
|
|
324
280
|
$('body').on 'change', '.go-to-selected select', ->
|
@@ -69,7 +69,6 @@ class WagnController < ActionController::Base
|
|
69
69
|
|
70
70
|
target = case target
|
71
71
|
when '*previous' ; previous_location #could do as *previous
|
72
|
-
when '_self ' ; card #could do as _self
|
73
72
|
when /^(http|\/)/ ; target
|
74
73
|
when /^TEXT:\s*(.+)/ ; $1
|
75
74
|
else ; Card.fetch target.to_name.to_absolute(card.cardname), :new=>{}
|
@@ -103,7 +102,7 @@ class WagnController < ActionController::Base
|
|
103
102
|
|
104
103
|
def show view = nil, status = 200
|
105
104
|
format = request.parameters[:format]
|
106
|
-
format = :file if params[:explicit_file] or !
|
105
|
+
format = :file if params[:explicit_file] or !Card::Format.registered.member? format #unknown format
|
107
106
|
|
108
107
|
opts = ( params[:slot] || {} ).deep_symbolize_keys
|
109
108
|
opts[:view] = view || params[:view]
|
data/config/routes.rb
CHANGED
data/features/hello_wagn.feature
CHANGED
@@ -14,11 +14,13 @@ Feature: Reading and Creating a card
|
|
14
14
|
Then I should see "Home"
|
15
15
|
And I should see "Joe User"
|
16
16
|
And I should see "Sign out"
|
17
|
-
|
18
|
-
|
19
|
-
Then In the main card header I should see a link with class "ui-icon-circle-triangle-
|
20
|
-
Then In the main card header I click "
|
21
|
-
Then In the main card header I should see a link with class "ui-icon-circle-triangle-
|
17
|
+
|
18
|
+
# all of the following assume the toggle shows up on the main card by default, which it no longer does
|
19
|
+
# Then In the main card header I should see a link with class "ui-icon-circle-triangle-s"
|
20
|
+
# Then In the main card header I click "close Home"
|
21
|
+
# Then In the main card header I should see a link with class "ui-icon-circle-triangle-e"
|
22
|
+
# Then In the main card header I click "open Home"
|
23
|
+
# Then In the main card header I should see a link with class "ui-icon-circle-triangle-s"
|
22
24
|
|
23
25
|
Scenario: Create a Card
|
24
26
|
Given I log in as Joe User
|
data/lib/card/exceptions.rb
CHANGED
@@ -14,9 +14,14 @@ module Card::Exceptions
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
class Abort < Exception
|
18
|
+
attr_reader :status
|
19
|
+
def initialize status=:failure, msg=''
|
20
|
+
@status = status
|
21
|
+
super msg
|
22
|
+
end
|
18
23
|
# def backtrace
|
19
24
|
# ["\n( card action gently canceled )\n"]
|
20
25
|
# end
|
21
|
-
|
26
|
+
end
|
22
27
|
end
|
data/lib/card/format.rb
CHANGED
@@ -8,15 +8,20 @@ class Card
|
|
8
8
|
INCLUSION_MODES = { :closed=>:closed, :closed_content=>:closed, :edit=>:edit,
|
9
9
|
:layout=>:layout, :new=>:edit, :normal=>:normal, :template=>:template } #should be set in views
|
10
10
|
|
11
|
-
cattr_accessor :ajax_call, :perms, :denial_views, :subset_views, :error_codes, :view_tags, :aliases
|
11
|
+
cattr_accessor :ajax_call, :perms, :denial_views, :subset_views, :error_codes, :view_tags, :aliases, :registered
|
12
12
|
[ :perms, :denial_views, :subset_views, :error_codes, :view_tags, :aliases ].each { |acc| self.send "#{acc}=", {} }
|
13
13
|
@@max_char_count = 200 #should come from Wagn.config
|
14
14
|
@@max_depth = 20 # ditto
|
15
|
-
|
15
|
+
|
16
16
|
attr_reader :card, :root, :parent, :vars
|
17
17
|
attr_accessor :form, :error_status, :inclusion_opts
|
18
18
|
|
19
19
|
class << self
|
20
|
+
@@registered = []
|
21
|
+
|
22
|
+
def register format
|
23
|
+
@@registered << format.to_s
|
24
|
+
end
|
20
25
|
|
21
26
|
def get_format format
|
22
27
|
fkey = @@aliases[ format ] || format
|
@@ -493,7 +498,7 @@ class Card
|
|
493
498
|
content = params[cardname.to_s.gsub(/\+/,'_')]
|
494
499
|
|
495
500
|
# CLEANME This is a hack to get it so plus cards re-populate on failed signups
|
496
|
-
if p = params['cards'] and card_params = p[cardname.
|
501
|
+
if p = params['cards'] and card_params = p[cardname.to_s]
|
497
502
|
content = card_params['content']
|
498
503
|
end
|
499
504
|
content if content.present? # why is this necessary? - efm
|
data/lib/card/query/card_spec.rb
CHANGED
data/lib/card/set.rb
CHANGED
data/lib/wagn/all.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'rails/all'
|
2
2
|
|
3
3
|
if Rails.env.development?
|
4
|
-
|
4
|
+
if $LOAD_PATH.find { |path| File.exists? "#{path}/wagn/dev.rb" }
|
5
5
|
require 'wagn/dev'
|
6
|
-
|
7
|
-
|
6
|
+
else
|
7
|
+
puts "WARNING: the gem wagn-dev is strongly recommended when running wagn in development mode but is not found"
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -20,6 +20,6 @@ require 'paperclip'
|
|
20
20
|
# require 'xmlscan'
|
21
21
|
# require 'rubyzip'
|
22
22
|
require 'coderay'
|
23
|
-
require 'sass'
|
23
|
+
#require 'sass'
|
24
24
|
|
25
25
|
require 'wagn/application'
|
@@ -2,363 +2,375 @@
|
|
2
2
|
|
3
3
|
require_dependency 'card/diff'
|
4
4
|
|
5
|
-
class Card
|
6
|
-
|
5
|
+
class Card
|
6
|
+
Format.register :html
|
7
|
+
class HtmlFormat < Format
|
8
|
+
include Diff
|
7
9
|
|
8
|
-
|
10
|
+
attr_accessor :options_need_save, :start_time, :skip_autosave
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
# builtin layouts allow for rescue / testing
|
13
|
+
LAYOUTS = Wagn::Loader.load_layouts.merge 'none' => '{{_main}}'
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
INCLUSION_DEFAULTS = {
|
16
|
+
:layout => { :view => :core },
|
17
|
+
:normal => { :view => :content }
|
18
|
+
}
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
def get_inclusion_defaults
|
21
|
+
INCLUSION_DEFAULTS[@mode] || {}
|
22
|
+
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
def default_item_view
|
25
|
+
:closed
|
26
|
+
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def view_for_unknown view, args
|
29
|
+
case
|
30
|
+
when focal? && ok?( :create ) ; :new
|
31
|
+
when commentable?( view, args ) ; view
|
32
|
+
else super
|
33
|
+
end
|
31
34
|
end
|
32
|
-
end
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
def commentable? view, args
|
37
|
+
self.class.tagged view, :comment and
|
38
|
+
show_view? :comment_box, args, :hide and #developer or wagneer has overridden default
|
39
|
+
ok? :comment
|
40
|
+
end
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
def get_layout_content(args)
|
43
|
+
Account.as_bot do
|
44
|
+
case
|
45
|
+
when (params[:layout] || args[:layout]) ; layout_from_name args
|
46
|
+
when card ; layout_from_card
|
47
|
+
else ; LAYOUTS['default']
|
48
|
+
end
|
46
49
|
end
|
47
50
|
end
|
48
|
-
end
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
def layout_from_name args
|
53
|
+
lname = (params[:layout] || args[:layout]).to_s
|
54
|
+
lcard = Card.fetch(lname, :skip_virtual=>true, :skip_modules=>true)
|
55
|
+
case
|
56
|
+
when lcard && lcard.ok?(:read) ; lcard.content
|
57
|
+
when hardcoded_layout = LAYOUTS[lname] ; hardcoded_layout
|
58
|
+
else ; "<h1>Unknown layout: #{lname}</h1>Built-in Layouts: #{LAYOUTS.keys.join(', ')}"
|
59
|
+
end
|
57
60
|
end
|
58
|
-
end
|
59
61
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
62
|
+
def layout_from_card
|
63
|
+
return unless rule_card = (card.rule_card(:layout) or Card.default_rule_card(:layout))
|
64
|
+
#return unless rule_card.is_a?(Card::Set::Type::Pointer) and # type check throwing lots of warnings under cucumber: rule_card.type_id == Card::PointerID and
|
65
|
+
return unless rule_card.type_id == Card::PointerID and
|
66
|
+
layout_name=rule_card.item_names.first and
|
67
|
+
!layout_name.nil? and
|
68
|
+
lo_card = Card.fetch( layout_name, :skip_virtual => true, :skip_modules=>true ) and
|
69
|
+
lo_card.ok?(:read)
|
70
|
+
lo_card.content
|
71
|
+
end
|
70
72
|
|
71
|
-
|
72
|
-
|
73
|
-
|
73
|
+
def slot_options args
|
74
|
+
@@slot_option_keys ||= Card::Chunk::Include.options.reject { |k| k == :view }.unshift :home_view
|
75
|
+
options_hash = {}
|
74
76
|
|
75
|
-
|
76
|
-
|
77
|
-
|
77
|
+
if @context_names.present?
|
78
|
+
options_hash['name_context'] = @context_names.map( &:key ) * ','
|
79
|
+
end
|
78
80
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
81
|
+
@@slot_option_keys.inject(options_hash) do |hash, opt|
|
82
|
+
hash[opt] = args[opt] if args[opt].present?
|
83
|
+
hash
|
84
|
+
end
|
83
85
|
|
84
|
-
|
85
|
-
|
86
|
+
JSON( options_hash )
|
87
|
+
end
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
89
|
+
def wrap args = {}
|
90
|
+
classes = [
|
91
|
+
( 'card-slot' unless args[:no_slot] ),
|
92
|
+
"#{ @current_view }-view",
|
93
|
+
( args[:slot_class] if args[:slot_class] ),
|
94
|
+
( "STRUCTURE-#{args[:structure].to_name.key}" if args[:structure]),
|
95
|
+
card.safe_set_keys
|
96
|
+
].compact
|
95
97
|
|
96
|
-
|
97
|
-
|
98
|
+
div = %{<div id="#{card.cardname.url_key}" data-card-id="#{card.id}" data-card-name="#{h card.name}" style="#{h args[:style]}" class="#{classes*' '}" } +
|
99
|
+
%{data-slot='#{html_escape_except_quotes slot_options( args )}'>#{ output yield }</div>}
|
98
100
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
101
|
+
if params[:debug] == 'slot' && !tagged( @current_view, :no_wrap_comments )
|
102
|
+
name = h card.name
|
103
|
+
space = ' ' * @depth
|
104
|
+
%{<!--\n\n#{ space }BEGIN SLOT: #{ name }\n\n-->#{ div }<!--\n\n#{space}END SLOT: #{ name }\n\n-->}
|
105
|
+
else
|
106
|
+
div
|
107
|
+
end
|
105
108
|
end
|
106
|
-
end
|
107
109
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
110
|
+
def wrap_body args={}
|
111
|
+
css_classes = [ 'card-body' ]
|
112
|
+
css_classes << args[:body_class] if args[:body_class]
|
113
|
+
css_classes += [ 'card-content', card.safe_set_keys ] if args[:content]
|
114
|
+
content_tag :div, :class=>css_classes.compact*' ' do
|
115
|
+
yield args
|
116
|
+
end
|
114
117
|
end
|
115
|
-
end
|
116
118
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
119
|
+
def frame args={}
|
120
|
+
wrap args.merge(:slot_class=>'card-frame') do
|
121
|
+
%{
|
122
|
+
#{ _render_header args }
|
123
|
+
#{ %{ <div class="card-subheader">#{ args[:subheader] }</div> } if args[:subheader] }
|
124
|
+
#{ _optional_render :help, args, :hide }
|
125
|
+
#{ wrap_body args do output( yield args ) end }
|
126
|
+
}
|
127
|
+
end
|
125
128
|
end
|
126
|
-
end
|
127
129
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
130
|
+
def frame_and_form action, args={}, form_opts={}
|
131
|
+
form_opts[:hidden] = args.delete(:hidden)
|
132
|
+
frame args do
|
133
|
+
card_form action, form_opts do
|
134
|
+
output( yield args )
|
135
|
+
end
|
133
136
|
end
|
134
137
|
end
|
135
|
-
end
|
136
138
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
139
|
+
def output content
|
140
|
+
case content
|
141
|
+
when String; content
|
142
|
+
when Array ; content.compact.join "\n"
|
143
|
+
end
|
144
|
+
end
|
143
145
|
|
144
146
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
147
|
+
def wrap_main(content)
|
148
|
+
return content if params[:layout]=='none'
|
149
|
+
%{#{
|
150
|
+
if flash[:notice]
|
151
|
+
%{<div class="flash-notice">#{ flash[:notice] }</div>}
|
152
|
+
end
|
153
|
+
}<div id="main">#{content}</div>}
|
150
154
|
end
|
151
|
-
}<div id="main">#{content}</div>}
|
152
|
-
end
|
153
155
|
|
154
156
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
157
|
+
def html_escape_except_quotes s
|
158
|
+
# to be used inside single quotes (makes for readable json attributes)
|
159
|
+
s.to_s.gsub(/&/, "&").gsub(/\'/, "'").gsub(/>/, ">").gsub(/</, "<")
|
160
|
+
end
|
159
161
|
|
160
162
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
process_content( inc ).strip
|
166
|
-
end.join
|
167
|
-
# raw _render_core(args)
|
168
|
-
else
|
169
|
-
# single-card edit mode
|
170
|
-
field = content_field form, args
|
163
|
+
def edit_slot args={}
|
164
|
+
#note: @mode should already be :edit here...
|
165
|
+
if args[:structure] || card.structure
|
166
|
+
# multi-card editing
|
171
167
|
|
172
|
-
|
173
|
-
|
174
|
-
|
168
|
+
if args[:core_edit] #need better name!
|
169
|
+
_render_core args
|
170
|
+
else
|
171
|
+
process_relative_tags args
|
172
|
+
end
|
173
|
+
|
175
174
|
else
|
176
|
-
|
175
|
+
# single-card edit mode
|
176
|
+
field = content_field form, args
|
177
|
+
|
178
|
+
if [ args[:optional_type_fieldset], args[:optional_name_fieldset] ].member? :show
|
179
|
+
# display content field in fieldset for consistency with other fields
|
180
|
+
fieldset '', field, :editor=>:content
|
181
|
+
else
|
182
|
+
editor_wrap( :content ) { field }
|
183
|
+
end
|
177
184
|
end
|
178
185
|
end
|
179
|
-
|
186
|
+
|
187
|
+
def process_relative_tags args
|
188
|
+
_render_raw(args).scan( /\{\{\s*\+[^\}]*\}\}/ ).map do |inc| #fixme - wrong place for regexp!
|
189
|
+
process_content( inc ).strip
|
190
|
+
end.join
|
191
|
+
end
|
180
192
|
|
181
193
|
|
182
194
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
195
|
+
#### -------------------- additional helpers ---------------- ###
|
196
|
+
|
197
|
+
def rendering_error exception, view
|
198
|
+
%{
|
199
|
+
<span class="render-error">
|
200
|
+
error rendering
|
201
|
+
#{
|
202
|
+
if Account.always_ok?
|
203
|
+
%{
|
204
|
+
#{ link_to_page error_cardname, nil, :class=>'render-error-link' }
|
205
|
+
<div class="render-error-message errors-view" style="display:none">
|
206
|
+
<h3>Error message (visible to admin only)</h3>
|
207
|
+
<p><strong>#{ exception.message }</strong></p>
|
208
|
+
<div>
|
209
|
+
#{exception.backtrace * "<br>\n"}
|
210
|
+
</div>
|
198
211
|
</div>
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
end
|
212
|
+
}
|
213
|
+
else
|
214
|
+
error_cardname
|
215
|
+
end
|
216
|
+
}
|
217
|
+
(#{view} view)
|
218
|
+
</span>
|
219
|
+
}
|
220
|
+
end
|
209
221
|
|
210
|
-
|
211
|
-
|
212
|
-
|
222
|
+
def unknown_view view
|
223
|
+
"<strong>unknown view: <em>#{view}</em></strong>"
|
224
|
+
end
|
213
225
|
|
214
|
-
|
215
|
-
|
216
|
-
end
|
217
|
-
|
218
|
-
def final_link href, opts={}
|
219
|
-
text = opts[:text] || href
|
220
|
-
%{<a class="#{opts[:class]}" href="#{href}">#{text}</a>}
|
221
|
-
end
|
222
|
-
|
223
|
-
def link_to_view text, view, opts={}
|
224
|
-
path_opts = view==:home ? {} : { :view=>view }
|
225
|
-
if p = opts.delete( :path_opts )
|
226
|
-
path_opts.merge! p
|
226
|
+
def unsupported_view view
|
227
|
+
"<strong>view <em>#{view}</em> not supported for <em>#{error_cardname}</em></strong>"
|
227
228
|
end
|
228
|
-
opts[:remote] = true
|
229
|
-
opts[:rel] = 'nofollow'
|
230
|
-
link_to text, path( path_opts ), opts
|
231
|
-
end
|
232
229
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
:autocomplete=>'off'
|
238
|
-
}.merge(options))
|
239
|
-
end
|
230
|
+
def final_link href, opts={}
|
231
|
+
text = opts[:text] || href
|
232
|
+
%{<a class="#{opts[:class]}" href="#{href}">#{text}</a>}
|
233
|
+
end
|
240
234
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
# current type should be an option on existing cards, regardless of create perms
|
246
|
-
typelist = (typelist << card.type_name).sort
|
247
|
-
end
|
248
|
-
Card[ card ? card.type_id : Card.default_type_id ].name
|
235
|
+
def link_to_view text, view, opts={}
|
236
|
+
path_opts = view==:home ? {} : { :view=>view }
|
237
|
+
if p = opts.delete( :path_opts )
|
238
|
+
path_opts.merge! p
|
249
239
|
end
|
240
|
+
opts[:remote] = true
|
241
|
+
opts[:rel] = 'nofollow'
|
242
|
+
link_to text, path( path_opts ), opts
|
243
|
+
end
|
250
244
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
@nested = options[:nested]
|
258
|
-
revision_tracking = if card && !card.new_card? && !options[:skip_rev_id]
|
259
|
-
form.hidden_field :current_revision_id, :class=>'current_revision_id'
|
245
|
+
def name_field form=nil, options={}
|
246
|
+
form ||= self.form
|
247
|
+
form.text_field( :name, {
|
248
|
+
:value=>card.name, #needed because otherwise gets wrong value if there are updates
|
249
|
+
:autocomplete=>'off'
|
250
|
+
}.merge(options))
|
260
251
|
end
|
261
|
-
%{
|
262
|
-
#{ revision_tracking }
|
263
|
-
#{ _render_editor options }
|
264
|
-
}
|
265
|
-
end
|
266
252
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
253
|
+
def type_field args={}
|
254
|
+
typelist = Account.createable_types
|
255
|
+
current_type = unless args.delete :no_current_type
|
256
|
+
unless card.new_card? || typelist.include?( card.type_name )
|
257
|
+
# current type should be an option on existing cards, regardless of create perms
|
258
|
+
typelist = (typelist << card.type_name).sort
|
259
|
+
end
|
260
|
+
Card[ card ? card.type_id : Card.default_type_id ].name
|
261
|
+
end
|
274
262
|
|
275
|
-
|
276
|
-
|
277
|
-
|
263
|
+
options = options_from_collection_for_select typelist, :to_s, :to_s, current_type
|
264
|
+
template.select_tag 'card[type]', options, args
|
265
|
+
end
|
278
266
|
|
279
|
-
|
280
|
-
hidden_args = opts.delete :hidden
|
281
|
-
form_for card, card_form_opts(action, opts) do |form|
|
267
|
+
def content_field form, options={}
|
282
268
|
@form = form
|
269
|
+
@nested = options[:nested]
|
270
|
+
revision_tracking = if card && !card.new_card? && !options[:skip_rev_id]
|
271
|
+
form.hidden_field :current_revision_id, :class=>'current_revision_id'
|
272
|
+
end
|
283
273
|
%{
|
284
|
-
#{
|
285
|
-
#{
|
274
|
+
#{ revision_tracking }
|
275
|
+
#{ _render_editor options }
|
286
276
|
}
|
287
277
|
end
|
288
|
-
end
|
289
278
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
279
|
+
def form_for_multi
|
280
|
+
block = Proc.new {}
|
281
|
+
builder = ActionView::Base.default_form_builder
|
282
|
+
card.name = card.name.gsub(/^#{Regexp.escape(root.card.name)}\+/, '+') if root.card.new_card? ##FIXME -- need to match other relative inclusions.
|
283
|
+
|
284
|
+
builder.new("card[cards][#{card.relative_name}]", card, template, {}, block)
|
285
|
+
end
|
286
|
+
|
287
|
+
def form
|
288
|
+
@form ||= form_for_multi
|
289
|
+
end
|
290
|
+
|
291
|
+
def card_form action, opts={}
|
292
|
+
hidden_args = opts.delete :hidden
|
293
|
+
form_for card, card_form_opts(action, opts) do |form|
|
294
|
+
@form = form
|
295
|
+
%{
|
296
|
+
#{ hidden_tags hidden_args if hidden_args }
|
297
|
+
#{ yield form }
|
298
|
+
}
|
296
299
|
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def card_form_opts action, html={}
|
303
|
+
url, action = case action
|
304
|
+
when Symbol ; [ path(:action=>action) , action ]
|
305
|
+
when Hash ; [ path(action) , action[:action] ]
|
306
|
+
when String ; [ wagn_path(action) , nil ] #deprecated
|
307
|
+
else ; raise Wagn::Error, "unsupported card_form action class: #{action.class}"
|
308
|
+
end
|
297
309
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
310
|
+
klasses = Array.wrap( html[:class] )
|
311
|
+
klasses << 'card-form slotter'
|
312
|
+
klasses << 'autosave' if action == :update
|
313
|
+
html[:class] = klasses.join ' '
|
302
314
|
|
303
|
-
|
304
|
-
|
315
|
+
html[:recaptcha] ||= 'on' if Wagn::Env[:recaptcha_on] && Card.toggle( card.rule(:captcha) )
|
316
|
+
html.delete :recaptcha if html[:recaptcha] == :off
|
305
317
|
|
306
|
-
|
307
|
-
|
318
|
+
{ :url=>url, :remote=>true, :html=>html }
|
319
|
+
end
|
308
320
|
|
309
|
-
|
310
|
-
|
311
|
-
|
321
|
+
def editor_wrap type=nil
|
322
|
+
content_tag( :div, :class=>"editor#{ " #{type}-editor" if type }" ) { yield }
|
323
|
+
end
|
312
324
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
325
|
+
def fieldset title, content, opts={}
|
326
|
+
if attribs = opts[:attribs]
|
327
|
+
attrib_string = attribs.keys.map do |key|
|
328
|
+
%{#{key}="#{attribs[key]}"}
|
329
|
+
end * ' '
|
330
|
+
end
|
331
|
+
help_text = case opts[:help]
|
332
|
+
when String ; _render_help :help_text=> opts[:help]
|
333
|
+
when true ; _render_help
|
334
|
+
else ; nil
|
335
|
+
end
|
336
|
+
%{
|
337
|
+
<fieldset #{ attrib_string }>
|
338
|
+
<legend>
|
339
|
+
<h2>#{ title }</h2>
|
340
|
+
#{ help_text }
|
341
|
+
</legend>
|
342
|
+
#{ editor_wrap( opts[:editor] ) { content } }
|
343
|
+
</fieldset>
|
344
|
+
}
|
345
|
+
end
|
334
346
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
347
|
+
def hidden_tags hash, base=nil
|
348
|
+
# convert hash into a collection of hidden tags
|
349
|
+
result = ''
|
350
|
+
hash ||= {}
|
351
|
+
hash.each do |key, val|
|
352
|
+
result += if Hash === val
|
353
|
+
hidden_tags val, key
|
354
|
+
else
|
355
|
+
name = base ? "#{base}[#{key}]" : key
|
356
|
+
hidden_field_tag name, val
|
357
|
+
end
|
345
358
|
end
|
359
|
+
result
|
346
360
|
end
|
347
|
-
result
|
348
|
-
end
|
349
361
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
362
|
+
def main?
|
363
|
+
if ajax_call?
|
364
|
+
@depth == 0 && params[:is_main]
|
365
|
+
else
|
366
|
+
@depth == 1 && @mainline
|
367
|
+
end
|
355
368
|
end
|
356
|
-
end
|
357
369
|
|
358
|
-
|
370
|
+
private
|
359
371
|
|
360
|
-
|
361
|
-
|
372
|
+
def fancy_title title=nil
|
373
|
+
raw %{<span class="card-title">#{ showname(title).to_name.parts.join %{<span class="joint">+</span>} }</span>}
|
374
|
+
end
|
362
375
|
end
|
363
|
-
|
364
376
|
end
|