hobo 0.7.3 → 0.7.4
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/hobo +1 -1
- data/hobo_files/plugin/CHANGES.txt +302 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +2 -9
- data/hobo_files/plugin/generators/hobo_model/templates/model.rb +1 -1
- data/hobo_files/plugin/generators/hobo_model_resource/hobo_model_resource_generator.rb +0 -2
- data/hobo_files/plugin/generators/hobo_rapid/templates/hobo-rapid.js +76 -46
- data/hobo_files/plugin/generators/hobo_rapid/templates/lowpro.js +25 -18
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/clean/public/stylesheets/application.css +29 -11
- data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +2 -2
- data/hobo_files/plugin/init.rb +0 -1
- data/hobo_files/plugin/lib/active_record/has_many_association.rb +3 -0
- data/hobo_files/plugin/lib/hobo.rb +12 -8
- data/hobo_files/plugin/lib/hobo/bundle.rb +1 -1
- data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +1 -1
- data/hobo_files/plugin/lib/hobo/dryml/parser/attribute.rb +41 -0
- data/hobo_files/plugin/lib/hobo/dryml/parser/base_parser.rb +253 -0
- data/hobo_files/plugin/lib/hobo/dryml/parser/document.rb +26 -0
- data/hobo_files/plugin/lib/hobo/dryml/parser/element.rb +27 -0
- data/hobo_files/plugin/lib/hobo/dryml/parser/elements.rb +45 -0
- data/hobo_files/plugin/lib/hobo/dryml/parser/source.rb +58 -0
- data/hobo_files/plugin/lib/hobo/dryml/parser/text.rb +13 -0
- data/hobo_files/plugin/lib/hobo/dryml/parser/tree_parser.rb +67 -0
- data/hobo_files/plugin/lib/hobo/dryml/scoped_variables.rb +10 -5
- data/hobo_files/plugin/lib/hobo/dryml/template.rb +48 -27
- data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +28 -13
- data/hobo_files/plugin/lib/hobo/hobo_helper.rb +3 -1
- data/hobo_files/plugin/lib/hobo/model.rb +70 -10
- data/hobo_files/plugin/lib/hobo/model_controller.rb +49 -34
- data/hobo_files/plugin/lib/hobo/model_router.rb +10 -2
- data/hobo_files/plugin/lib/hobo/rapid_helper.rb +1 -0
- data/hobo_files/plugin/lib/hobo/scopes.rb +15 -0
- data/hobo_files/plugin/lib/hobo/scopes/apply_scopes.rb +23 -0
- data/hobo_files/plugin/lib/hobo/scopes/association_proxy_extensions.rb +4 -2
- data/hobo_files/plugin/lib/hobo/scopes/automatic_scopes.rb +34 -7
- data/hobo_files/plugin/lib/hobo/scopes/defined_scope_proxy_extender.rb +3 -1
- data/hobo_files/plugin/lib/hobo/scopes/scoped_proxy.rb +1 -5
- data/hobo_files/plugin/taglibs/rapid.dryml +33 -24
- data/hobo_files/plugin/taglibs/rapid_editing.dryml +6 -5
- data/hobo_files/plugin/taglibs/rapid_forms.dryml +37 -31
- data/hobo_files/plugin/taglibs/rapid_generics.dryml +68 -27
- data/hobo_files/plugin/taglibs/rapid_navigation.dryml +5 -8
- data/hobo_files/plugin/taglibs/rapid_pages.dryml +71 -47
- data/hobo_files/plugin/taglibs/rapid_plus.dryml +4 -5
- data/hobo_files/plugin/taglibs/rapid_support.dryml +11 -4
- metadata +23 -6
- data/hobo_files/plugin/lib/rexml.rb +0 -443
@@ -8,6 +8,8 @@ module Hobo
|
|
8
8
|
|
9
9
|
include AutomaticScopes
|
10
10
|
|
11
|
+
include ApplyScopes
|
12
|
+
|
11
13
|
def method_missing(name, *args, &block)
|
12
14
|
if (scope = named_scope(name))
|
13
15
|
association_proxy_for_scope(name, scope, args)
|
@@ -69,7 +71,7 @@ module Hobo
|
|
69
71
|
options[:order] = scope[:order] if scope[:order]
|
70
72
|
options[:include] = scope[:include] if scope[:include]
|
71
73
|
|
72
|
-
r = ScopeReflection.new(:has_many, name, options, proxy_owner.class, proxy_reflection.
|
74
|
+
r = ScopeReflection.new(:has_many, name, options, proxy_owner.class, proxy_reflection.association_name)
|
73
75
|
|
74
76
|
@reflections ||= {}
|
75
77
|
@reflections[name] = r
|
@@ -4,7 +4,7 @@ module Hobo
|
|
4
4
|
|
5
5
|
class ScopedProxy
|
6
6
|
|
7
|
-
|
7
|
+
include ApplyScopes
|
8
8
|
|
9
9
|
def initialize(klass, scope)
|
10
10
|
@klass = klass
|
@@ -22,10 +22,6 @@ module Hobo
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def all
|
26
|
-
self.find(:all)
|
27
|
-
end
|
28
|
-
|
29
25
|
def first
|
30
26
|
self.find(:first)
|
31
27
|
end
|
@@ -31,18 +31,20 @@
|
|
31
31
|
|
32
32
|
<def tag="nil-view"><%= scope.nil_view || "(Not Available)" %></def>
|
33
33
|
|
34
|
-
<def tag="ul">
|
34
|
+
<def tag="ul" attrs="empty">
|
35
35
|
<% if all_parameters.li? # don't use dryml if, because it will mess up <ul/><else> %>
|
36
|
-
<
|
36
|
+
<if test="&empty || all_parameters[:head] || all_parameters[:foot] || !this.empty?">
|
37
37
|
<% element "ul", attributes do %>
|
38
|
+
<do param="head"/>
|
38
39
|
<repeat>
|
39
40
|
<li param if="&can_view?" class="#{scope.even_odd} #{this_type.name.underscore.dasherize}"
|
40
41
|
merge-attrs="&{'hobo-model-id' => dom_id(this)} if this.respond_to?(:typed_id)">
|
41
42
|
<do param="default"><a/></do>
|
42
43
|
</li>
|
43
44
|
</repeat>
|
45
|
+
<do param="foot"/>
|
44
46
|
<% end %>
|
45
|
-
</
|
47
|
+
</if>
|
46
48
|
<% else %>
|
47
49
|
<%= element("ul", attributes, all_parameters.default) %>
|
48
50
|
<% end %>
|
@@ -162,6 +164,16 @@
|
|
162
164
|
name = name.downcase if lowercase
|
163
165
|
name
|
164
166
|
%></def>
|
167
|
+
|
168
|
+
|
169
|
+
<def tag="name-for-collection" attrs="singular, lowercase"><%=
|
170
|
+
name = (attr = this.try.origin_attribute and attr.to_s) || type_name(:plural => true)
|
171
|
+
name = name.titleize
|
172
|
+
name = name.singularize if singular
|
173
|
+
name = name.downcase if lowercase
|
174
|
+
name
|
175
|
+
%></def>
|
176
|
+
|
165
177
|
|
166
178
|
|
167
179
|
<def tag="a" attrs="action, to, params, query-params, href, format, subsite"><%=
|
@@ -194,6 +206,7 @@
|
|
194
206
|
|
195
207
|
add_classes!(attributes, "new-#{new_class_name.underscore}-link")
|
196
208
|
content = "New #{new_class_name.titleize}" if content.blank?
|
209
|
+
Hobo::Dryml.last_if = true
|
197
210
|
element(:a, attributes.update(:href => href), content)
|
198
211
|
else
|
199
212
|
Hobo::Dryml.last_if = false
|
@@ -209,7 +222,8 @@
|
|
209
222
|
# This target is registered with ModelRouter as not linkable
|
210
223
|
content
|
211
224
|
else
|
212
|
-
|
225
|
+
css_class = target.try.origin_attribute || target.class.name.underscore
|
226
|
+
add_classes!(attributes, "#{css_class}-link")
|
213
227
|
|
214
228
|
href.sub!(/\?|$/, ".#{format}\\0") unless format.blank?
|
215
229
|
|
@@ -227,18 +241,18 @@
|
|
227
241
|
|
228
242
|
res = if this.nil? && if_blank.nil?
|
229
243
|
this_type.is_a?(Class) && this_type <= String ? "" : nil_view
|
230
|
-
elsif refl = this_field_reflection
|
231
|
-
|
232
|
-
belongs_to_view(attributes)
|
233
|
-
elsif refl.macro == :has_many
|
234
|
-
has_many_view(attributes)
|
235
|
-
end
|
244
|
+
elsif (refl = this_field_reflection) && refl.macro == :has_many
|
245
|
+
has_many_view(attributes)
|
236
246
|
else
|
237
247
|
|
238
248
|
view_tag = find_polymorphic_tag("view")
|
239
249
|
|
240
250
|
if view_tag == "view" # i.e. it didn't find a type specific tag
|
241
|
-
|
251
|
+
if this.respond_to?(:to_html)
|
252
|
+
this.to_html
|
253
|
+
else
|
254
|
+
raise HoboError, "Cannot view: #{this.inspect} (field is #{this_field}, type is #{this.class})"
|
255
|
+
end
|
242
256
|
else
|
243
257
|
attrs = add_classes(attributes, "view", type_and_field)
|
244
258
|
id = dom_id
|
@@ -282,20 +296,12 @@
|
|
282
296
|
|
283
297
|
<def tag="view" for="Numeric" attrs="format"><%= format ? format % this : this.to_s %></def>
|
284
298
|
|
285
|
-
<def tag="view" for="Hobo::Text"><%= h(this).gsub("\n", "<br/>") %></def>
|
286
|
-
|
287
|
-
<def tag="view" for="html"><%= this %></def>
|
288
|
-
|
289
|
-
<def tag="view" for="markdown"><%= this.to_html %></def>
|
290
|
-
|
291
|
-
<def tag="view" for="textile"><%= this.to_html %></def>
|
292
|
-
|
293
|
-
<def tag="view" for="password">[password withheld]</def>
|
294
|
-
|
295
299
|
<def tag="view" for="string"><%= h(this).gsub("\n", "<br/>") %></def>
|
296
300
|
|
297
301
|
<def tag="view" for="boolean"><%= this ? 'Yes' : 'No' %></def>
|
298
302
|
|
303
|
+
<def tag="view" for="ActiveRecord::Base"><a/></def>
|
304
|
+
|
299
305
|
|
300
306
|
<def tag="count" attrs="label, prefix, if-any, lowercase"><%=
|
301
307
|
raise Exception.new("asked for count of a string") if this.is_a?(String)
|
@@ -304,9 +310,11 @@
|
|
304
310
|
|
305
311
|
label ||= if this.is_a?(Class)
|
306
312
|
this.name
|
313
|
+
elsif (attr = this.try.origin_attribute)
|
314
|
+
attr.to_s.singularize
|
307
315
|
else
|
308
|
-
|
309
|
-
end.
|
316
|
+
this.member_class.name
|
317
|
+
end.titleize
|
310
318
|
|
311
319
|
label = label.downcase if lowercase
|
312
320
|
|
@@ -378,7 +386,7 @@ in the future - use at your own risk. -->
|
|
378
386
|
</def>
|
379
387
|
|
380
388
|
|
381
|
-
<def tag="you" attrs="have, are, do, titleize"><if test="&this == current_user"><%= "#{titleize ? 'Y' : 'y'}ou
|
389
|
+
<def tag="you" attrs="have, are, do, titleize"><if test="&this == current_user"><%= "#{titleize ? 'Y' : 'y'}ou#{' have' if have}#{' are' if are}#{' do' if do_}" %></if><else><do param="default"><name/><%= "#{' has' if have}#{' is' if are}#{' does' if do_}" %></do></else></def>
|
382
390
|
|
383
391
|
<def tag="You"><you merge titleize/></def>
|
384
392
|
|
@@ -417,6 +425,7 @@ in the future - use at your own risk. -->
|
|
417
425
|
|
418
426
|
|
419
427
|
<def tag="filter-menu" attrs="param-name, options, no-filter">
|
428
|
+
<% no_filter ||= "All" %>
|
420
429
|
<form action="&request.request_uri" method="get" class="filter-menu">
|
421
430
|
<hidden-field name="filter-parameter" value="¶m_name"/>
|
422
431
|
<select-menu name="¶m_name" options="&options" selected="¶ms[param_name.gsub('-', '_')]" first-option="&no_filter" merge-params/>
|
@@ -43,7 +43,7 @@
|
|
43
43
|
|
44
44
|
<def tag="editor" for="big_integer"><%= in_place_editor "in_place_textfield_bhv", attributes %></def>
|
45
45
|
|
46
|
-
<def tag="editor" for="
|
46
|
+
<def tag="editor" for="HoboFields::EnumString">
|
47
47
|
<string-select-editor values="&this_type.values" merge/>
|
48
48
|
</def>
|
49
49
|
|
@@ -67,13 +67,14 @@
|
|
67
67
|
</def>
|
68
68
|
|
69
69
|
|
70
|
-
<def tag="belongs-to-menu-editor"><%
|
70
|
+
<def tag="belongs-to-menu-editor" attrs="sort"><%
|
71
71
|
raise HoboError.new("Not allowed to edit") unless can_edit?
|
72
72
|
link_id = "#{dom_id}_editor" %>
|
73
|
-
<span id="#{link_id}" part="rapid-belongs-to-edit">
|
73
|
+
<span id="#{link_id}" part="rapid-belongs-to-edit" part-locals="sort">
|
74
74
|
<% select_options = this_field_reflection.klass.find(:all).select {|x| can_view?(x)}.map {|x|
|
75
75
|
[ name(:with => x, :no_wrapper => true), x.id ]
|
76
76
|
}
|
77
|
+
select_options = select_options.sort if sort
|
77
78
|
select_options.insert(0, ["(No #{this_type.name.to_s.titleize})", ""]) if this.nil?
|
78
79
|
link_id = "#{dom_id}_editor"
|
79
80
|
f = ajax_updater(object_url(this_parent),
|
@@ -84,8 +85,8 @@
|
|
84
85
|
} })
|
85
86
|
%>
|
86
87
|
<select onchange="#{f}">
|
87
|
-
<%= options_for_select(select_options
|
88
|
-
</select> <a if="&this">View</a>
|
88
|
+
<%= options_for_select(select_options, this ? this.id : "") %>
|
89
|
+
</select> <a if="&this && linkable?">View</a>
|
89
90
|
</span>
|
90
91
|
</def>
|
91
92
|
|
@@ -58,7 +58,7 @@
|
|
58
58
|
|
59
59
|
hiddens = hidden_fields(:fields => hidden_fields, :skip => field_names) if new_record
|
60
60
|
|
61
|
-
auth_token = if request_forgery_protection_token.nil?
|
61
|
+
auth_token = if method.nil? || method == 'get' || request_forgery_protection_token.nil?
|
62
62
|
''
|
63
63
|
else
|
64
64
|
element(:input, :type => "hidden",
|
@@ -107,10 +107,10 @@
|
|
107
107
|
attrs = add_classes(attributes, type_id, type_and_field)
|
108
108
|
the_input = if (refl = this_field_reflection)
|
109
109
|
if refl.macro == :belongs_to
|
110
|
-
|
110
|
+
select_one(attrs)
|
111
111
|
elsif refl.macro == :has_many
|
112
112
|
if refl.options[:through]
|
113
|
-
|
113
|
+
select_many(attrs)
|
114
114
|
else
|
115
115
|
has_many_input(attrs)
|
116
116
|
end
|
@@ -145,13 +145,21 @@
|
|
145
145
|
<%= text_area_tag(name, this, add_classes(attributes, :tiny_mce)) %>
|
146
146
|
</def>
|
147
147
|
|
148
|
+
<def tag="input" for="markdown" attrs="name">
|
149
|
+
<%= text_area_tag(name, this, attributes) %>
|
150
|
+
</def>
|
151
|
+
|
152
|
+
<def tag="input" for="textile" attrs="name">
|
153
|
+
<%= text_area_tag(name, this, attributes) %>
|
154
|
+
</def>
|
155
|
+
|
148
156
|
<def tag="input" for="date" attrs="order">
|
149
157
|
<% order = order.nil? ? [:year, :month, :day] : comma_split(order).*.to_sym -%>
|
150
158
|
<%= select_date(this || Time.now, attributes.merge(:prefix => param_name_for_this, :order => order)) %>
|
151
159
|
</def>
|
152
160
|
|
153
161
|
<def tag="input" for="datetime" attrs="order">
|
154
|
-
<% order = order.nil? ? [:year, :month, :day
|
162
|
+
<% order = order.nil? ? [:year, :month, :day ] : comma_split(order).*.to_sym -%>
|
155
163
|
<%= select_datetime(this || Time.now, attributes.merge(:prefix => param_name_for_this, :order => order)) %>
|
156
164
|
</def>
|
157
165
|
|
@@ -179,16 +187,8 @@
|
|
179
187
|
</select>
|
180
188
|
</def>
|
181
189
|
|
182
|
-
<def tag="input" for="percentage" attrs="name">
|
183
|
-
<%= text_field_tag(name, this, attributes.merge(:size => '3', :maxlength => '3')) %>%
|
184
|
-
</def>
|
185
|
-
|
186
190
|
|
187
|
-
|
188
|
-
<%= belongs_to_menu_input(attributes) %>
|
189
|
-
</def>
|
190
|
-
|
191
|
-
<!--- Buttons --->
|
191
|
+
<!-- Buttons -->
|
192
192
|
|
193
193
|
<def tag="remote-method-button" attrs="method, update, label"><%=
|
194
194
|
ajax_attributes, html_attributes = attributes.partition_hash(Hobo::RapidHelper::AJAX_ATTRS)
|
@@ -219,7 +219,7 @@
|
|
219
219
|
|
220
220
|
|
221
221
|
<def tag="delete-button" attrs="label, update, in-place, image, confirm, fade, subsite"><%=
|
222
|
-
in_place = false if in_place.nil? && this == @this
|
222
|
+
in_place = false if in_place.nil? && this == @this && !request.xhr?
|
223
223
|
url = object_url(this, :method => :delete, :subsite => subsite)
|
224
224
|
if (Hobo::Dryml.last_if = url && can_delete?)
|
225
225
|
attributes = attributes.merge(if image
|
@@ -240,6 +240,7 @@
|
|
240
240
|
button_to(label, url, attributes)
|
241
241
|
else
|
242
242
|
fade = true if fade.nil?
|
243
|
+
scope.collection_contains_delete_button = true if fade
|
243
244
|
attributes[:value] = label
|
244
245
|
attributes[:onclick] = "Hobo.removeButton(this, '#{url}', #{js_updates(update)}, {fade:#{fade}, confirm: #{confirm.inspect}})"
|
245
246
|
element(:input, attributes)
|
@@ -277,16 +278,17 @@
|
|
277
278
|
%></def>
|
278
279
|
|
279
280
|
|
280
|
-
<def tag="
|
281
|
+
<def tag="select-one" attrs="include-none, blank-message, options, sort"><%
|
281
282
|
raise HoboError.new("Not allowed to edit") unless can_edit?
|
282
283
|
|
283
284
|
blank_message ||= "(No #{this_type.name.to_s.titleize})"
|
284
285
|
conditions = ActiveRecord::Associations::BelongsToAssociation.new(this, this_field_reflection).conditions
|
285
|
-
options ||= this_field_reflection.klass.
|
286
|
+
options ||= this_field_reflection.klass.all(:conditions => conditions).select {|x| can_view?(x)}
|
286
287
|
#Todo: switch to autocompleter for id_name when too many records, and id_name supported
|
287
288
|
select_options = options.map { |x|
|
288
289
|
[ name(:with => x, :no_wrapper => true), x.id ]
|
289
|
-
}
|
290
|
+
}
|
291
|
+
select_options = select_options.sort if sort
|
290
292
|
select_options.insert(0, [blank_message, ""]) if include_none || (this.nil? && include_none != false)
|
291
293
|
attributes = add_classes(attributes, "input", "belongs_to", type_and_field)
|
292
294
|
%>
|
@@ -335,29 +337,33 @@
|
|
335
337
|
</def>
|
336
338
|
|
337
339
|
|
338
|
-
<def tag="
|
340
|
+
<def tag="select-many" attrs="options, targets, remove-label, prompt">
|
339
341
|
<%
|
340
|
-
|
342
|
+
prompt ||= "Add a #{this_field.titleize.singularize}"
|
343
|
+
options ||= this.member_class.all
|
341
344
|
values = this
|
342
345
|
%>
|
343
|
-
<div class="input
|
346
|
+
<div class="input select-many" merge-attrs>
|
344
347
|
<div style="display:none" class="item-proto">
|
345
|
-
<div class="item">
|
348
|
+
<div class="item" param="proto-item">
|
346
349
|
<span></span>
|
347
|
-
<input type="hidden" name="#{param_name_for_this}[]" />
|
348
|
-
<input type="button" class="remove-item" value="#{remove_label || 'Remove'}"/>
|
350
|
+
<input type="hidden" name="#{param_name_for_this}[]" param="proto-hidden"/>
|
351
|
+
<input type="button" class="remove-item" value="#{remove_label || 'Remove'}" param="proto-remove-button"/>
|
349
352
|
</div>
|
350
353
|
</div>
|
351
354
|
<div class="items">
|
352
|
-
<
|
353
|
-
|
354
|
-
<
|
355
|
-
|
356
|
-
|
355
|
+
<set param-name="¶m_name_for_this"/>
|
356
|
+
<repeat>
|
357
|
+
<div class="item" param="item">
|
358
|
+
<span><%= this %></span>
|
359
|
+
<input type="hidden" name="#{param_name}[]" value="#{this}" param="hidden"/>
|
360
|
+
<input type="button" class="remove-item" value="#{remove_label || 'Remove'}" param="remove-button"/>
|
361
|
+
</div>
|
362
|
+
</repeat>
|
357
363
|
</div>
|
358
364
|
<select>
|
359
|
-
<option value=""
|
360
|
-
<option repeat="&
|
365
|
+
<option value=""><prompt/></option>
|
366
|
+
<option repeat="&options.sort_by {|x| name(:no_wrapper => true, :with => x).downcase}"
|
361
367
|
merge-attrs="&{:style => 'display:none'} if this.in?(values)"><name/></option>
|
362
368
|
</select>
|
363
369
|
</div>
|
@@ -377,6 +383,6 @@
|
|
377
383
|
<def tag="select-menu" attrs="options, selected, first-option, first-value">
|
378
384
|
<select merge-attrs param="default">
|
379
385
|
<option value="#{first_value}" unless="&first_option.nil?"><first-option/></option>
|
380
|
-
<do param="options"
|
386
|
+
<do param="options"><% options_for_select(options.*.to_s, selected) %></do>
|
381
387
|
</select>
|
382
388
|
</def>
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<def tag="creation-details">
|
2
|
-
<
|
3
|
-
<view field="&this.class.creator_attribute" class="creator" if="&this.class.creator_attribute" />
|
4
|
-
<view:created_at class="created-at" if="&this.respond_to?(:created_at)"/>
|
5
|
-
</
|
2
|
+
<div class="creation-details">
|
3
|
+
<view field="&this.class.creator_attribute" class="creator" if="&this.class.creator_attribute" param="by"/>
|
4
|
+
<view:created_at class="created-at" if="&this.respond_to?(:created_at)" param="at"/>
|
5
|
+
</div>
|
6
6
|
</def>
|
7
7
|
|
8
8
|
<def tag="primary-content">
|
@@ -17,9 +17,15 @@
|
|
17
17
|
|
18
18
|
<def tag="base-card">
|
19
19
|
<if test="&can_view?">
|
20
|
-
<
|
21
|
-
|
22
|
-
|
20
|
+
<set has-heading="&this.class.name_attribute || all_parameters[:heading]"/>
|
21
|
+
<set has-link="&has_heading && linkable?"/>
|
22
|
+
<div class="card #{has_link ? 'linkable' : 'content'} #{'with-owner' if this.class.creator_attribute} #{type_name :dasherize => true}"
|
23
|
+
merge-attrs>
|
24
|
+
<a action="edit" class="edit" if="&!has_link && linkable?(:edit)" param="edit-link">Edit</a>
|
25
|
+
<delete-button label="X" unless="&linkable?(:edit)" param/>
|
26
|
+
|
27
|
+
<h3 param="heading" if="&has_heading"><a><name/></a></h3>
|
28
|
+
<div class="content" param="content" unless="&has_link">
|
23
29
|
<primary-content/>
|
24
30
|
</div>
|
25
31
|
<creation-details param/>
|
@@ -29,7 +35,6 @@
|
|
29
35
|
<span class="dependents"><count field="&primary_collection"/></span>
|
30
36
|
</if>
|
31
37
|
</do>
|
32
|
-
<delete-button label="X" unless="&linkable?(this, :edit)" param/>
|
33
38
|
</div>
|
34
39
|
</if>
|
35
40
|
</def>
|
@@ -47,28 +52,64 @@
|
|
47
52
|
</def>
|
48
53
|
|
49
54
|
<def tag="collection">
|
50
|
-
|
51
|
-
|
52
|
-
<
|
55
|
+
<set-scoped collection-contains-delete-button="&false">
|
56
|
+
<%= poly = call_polymorphic_tag('collection', attributes, parameters) %>
|
57
|
+
<base-collection if="&poly.nil?" merge/>
|
58
|
+
<p class="empty-collection-message"
|
59
|
+
if="&this.empty? || scope.collection_contains_delete_button"
|
60
|
+
style="#{'display:none' if !this.empty?}"
|
61
|
+
param="empty-message">
|
62
|
+
There are no <name-for-collection lowercase/>
|
63
|
+
</p>
|
64
|
+
</set-scoped>
|
65
|
+
</def>
|
66
|
+
|
67
|
+
|
68
|
+
<def tag="base-collection" attrs="sortable, sortable-options"><%
|
69
|
+
sortable = (sortable != false and
|
70
|
+
first = this.first and
|
71
|
+
first.respond_to?(:position_column) and
|
72
|
+
reorder_url = object_url(this.member_class, :reorder, :method => :post) and
|
73
|
+
can_edit?(first, first.position_column))
|
74
|
+
if sortable
|
75
|
+
singular_name = first.class.name.underscore
|
76
|
+
attributes[:id] ||= "#{singular_name}_ordering"
|
77
|
+
end
|
78
|
+
%>
|
79
|
+
<ul class="collection #{this.origin_attribute.to_s.gsub('_', '-')}" merge-attrs>
|
80
|
+
<li: id="&%(#{singular_name}_#{this.id}) if sortable" param>
|
81
|
+
<div class="ordering-handle" param="handle" if="&sortable">↑<br/>↓</div>
|
82
|
+
<card param/>
|
83
|
+
</li:>
|
53
84
|
</ul>
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
85
|
+
<%= if sortable && Hobo::Dryml.last_if
|
86
|
+
opts = { :url => reorder_url,
|
87
|
+
:constraint => :vertical,
|
88
|
+
:overlap => :vertical,
|
89
|
+
:scroll => :window,
|
90
|
+
:handle => 'ordering-handle',
|
91
|
+
:complete => [visual_effect(:highlight, attributes[:id])]
|
92
|
+
}
|
93
|
+
opts.reverse_merge!(sortable_options) if sortable_options
|
94
|
+
sortable_element attributes[:id], opts
|
95
|
+
end
|
96
|
+
%>
|
64
97
|
</def>
|
65
98
|
|
99
|
+
|
66
100
|
<def tag="collection-preview" attrs="limit">
|
67
101
|
<% limit ||= 6 %>
|
68
|
-
<
|
69
|
-
<
|
70
|
-
<
|
71
|
-
<
|
72
|
-
|
73
|
-
|
102
|
+
<do with="&this.is_a?(Class) ? this.limit(limit).all : this.limit(limit)">
|
103
|
+
<set collection-name="&(this.try.origin_attribute || this.member_class.name.pluralize).to_s"/>
|
104
|
+
<div class="collection-preview" merge-attrs>
|
105
|
+
<h2>
|
106
|
+
<do param="heading"><collection-name.titleize/></do>
|
107
|
+
<span param="show-all-link" if="&this.any? && linkable?">(<a>show all</a>)</span>
|
108
|
+
</h2>
|
109
|
+
<collection merge-params>
|
110
|
+
<card: class="small"/>
|
111
|
+
</collection>
|
112
|
+
</div>
|
113
|
+
</do>
|
74
114
|
</def>
|
115
|
+
|