hobo_rapid 1.4.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/README.markdown +5 -0
  2. data/VERSION +1 -0
  3. data/app/controllers/dev_controller.rb +25 -0
  4. data/app/helpers/hobo_rapid_helper.rb +197 -0
  5. data/hobo_rapid.gemspec +26 -0
  6. data/lib/hobo_rapid/railtie.rb +6 -0
  7. data/lib/hobo_rapid.rb +13 -0
  8. data/taglibs/buttons/buttons.dryml +1 -0
  9. data/taglibs/buttons/create_button.dryml +40 -0
  10. data/taglibs/buttons/delete-button.dryml +75 -0
  11. data/taglibs/buttons/remote_method_button.dryml +34 -0
  12. data/taglibs/buttons/transition_button.dryml +71 -0
  13. data/taglibs/buttons/transition_link.dryml +22 -0
  14. data/taglibs/buttons/update_button.dryml +29 -0
  15. data/taglibs/cache/cache.dryml +1 -0
  16. data/taglibs/cache/nested_cache.dryml +332 -0
  17. data/taglibs/cards/card.dryml +7 -0
  18. data/taglibs/cards/cards.dryml +1 -0
  19. data/taglibs/cards/search_card.dryml +4 -0
  20. data/taglibs/editors/click_editor.dryml +60 -0
  21. data/taglibs/editors/editors.dryml +27 -0
  22. data/taglibs/editors/live_editor.dryml +37 -0
  23. data/taglibs/forms/error_messages.dryml +21 -0
  24. data/taglibs/forms/form.dryml +101 -0
  25. data/taglibs/forms/formlet.dryml +48 -0
  26. data/taglibs/forms/forms.dryml +5 -0
  27. data/taglibs/forms/submit.dryml +14 -0
  28. data/taglibs/hobo_rapid.dryml +14 -0
  29. data/taglibs/html/a.dryml +156 -0
  30. data/taglibs/html/aside.dryml +5 -0
  31. data/taglibs/html/doctype.dryml +39 -0
  32. data/taglibs/html/empty_tag.dryml +23 -0
  33. data/taglibs/html/footer.dryml +5 -0
  34. data/taglibs/html/header.dryml +5 -0
  35. data/taglibs/html/html.dryml +18 -0
  36. data/taglibs/html/if_ie.dryml +11 -0
  37. data/taglibs/html/image.dryml +11 -0
  38. data/taglibs/html/javascript.dryml +12 -0
  39. data/taglibs/html/section.dryml +12 -0
  40. data/taglibs/html/section_group.dryml +11 -0
  41. data/taglibs/html/stylesheet.dryml +5 -0
  42. data/taglibs/html/table.dryml +174 -0
  43. data/taglibs/i18n/ht.dryml +48 -0
  44. data/taglibs/i18n/human_attribute_name +18 -0
  45. data/taglibs/i18n/human_collection_name.dryml +69 -0
  46. data/taglibs/i18n/i18n.dryml +1 -0
  47. data/taglibs/i18n/model_name_human.dryml +16 -0
  48. data/taglibs/i18n/t.dryml +12 -0
  49. data/taglibs/inputs/after_submit.dryml +32 -0
  50. data/taglibs/inputs/check_many.dryml +25 -0
  51. data/taglibs/inputs/collection_input.dryml +10 -0
  52. data/taglibs/inputs/hidden_field.dryml +48 -0
  53. data/taglibs/inputs/hot_input.dryml +50 -0
  54. data/taglibs/inputs/input.dryml +76 -0
  55. data/taglibs/inputs/input_all.dryml +14 -0
  56. data/taglibs/inputs/input_for.dryml +38 -0
  57. data/taglibs/inputs/input_for_date.dryml +86 -0
  58. data/taglibs/inputs/input_for_enum_string.dryml +26 -0
  59. data/taglibs/inputs/input_many.dryml +131 -0
  60. data/taglibs/inputs/inputs.dryml +1 -0
  61. data/taglibs/inputs/name_one.dryml +74 -0
  62. data/taglibs/inputs/or_cancel.dryml +8 -0
  63. data/taglibs/inputs/select_input.dryml +13 -0
  64. data/taglibs/inputs/select_many.dryml +58 -0
  65. data/taglibs/inputs/select_menu.dryml +23 -0
  66. data/taglibs/inputs/select_one.dryml +46 -0
  67. data/taglibs/inputs/sortable_input_many.dryml +31 -0
  68. data/taglibs/inputs/sti_type_input.dryml +6 -0
  69. data/taglibs/lists/collection.dryml +26 -0
  70. data/taglibs/lists/empty_collection_message.dryml +13 -0
  71. data/taglibs/lists/feckless_fieldset.dryml +94 -0
  72. data/taglibs/lists/field_list.dryml +21 -0
  73. data/taglibs/lists/field_list_v1.dryml +64 -0
  74. data/taglibs/lists/labelled_item_list.dryml +11 -0
  75. data/taglibs/lists/lists.dryml +2 -0
  76. data/taglibs/lists/with_fields.dryml +98 -0
  77. data/taglibs/pages/account.dryml +30 -0
  78. data/taglibs/pages/account_disabled.dryml +19 -0
  79. data/taglibs/pages/flash_message.dryml +23 -0
  80. data/taglibs/pages/forgot_password.dryml +62 -0
  81. data/taglibs/pages/login.dryml +57 -0
  82. data/taglibs/pages/not_found_page.dryml +18 -0
  83. data/taglibs/pages/page_nav.dryml +17 -0
  84. data/taglibs/pages/pages.dryml +12 -0
  85. data/taglibs/pages/permission_denied_page.dryml +24 -0
  86. data/taglibs/plus/collection_preview.dryml +23 -0
  87. data/taglibs/plus/filter_menu.dryml +103 -0
  88. data/taglibs/plus/gravatar.dryml +12 -0
  89. data/taglibs/plus/live_search.dryml +40 -0
  90. data/taglibs/plus/plus.dryml +1 -0
  91. data/taglibs/plus/sortable_collection.dryml +36 -0
  92. data/taglibs/plus/table_plus.dryml +63 -0
  93. data/taglibs/views/a_or_an.dryml +10 -0
  94. data/taglibs/views/collection_name.dryml +28 -0
  95. data/taglibs/views/comma_list.dryml +2 -0
  96. data/taglibs/views/count.dryml +99 -0
  97. data/taglibs/views/links_for_collection.dryml +2 -0
  98. data/taglibs/views/name.dryml +30 -0
  99. data/taglibs/views/nil_view.dryml +10 -0
  100. data/taglibs/views/record_flags.dryml +5 -0
  101. data/taglibs/views/type_name.dryml +24 -0
  102. data/taglibs/views/view.dryml +79 -0
  103. data/taglibs/views/view_for.dryml +42 -0
  104. data/taglibs/views/views.dryml +1 -0
  105. data/taglibs/views/you.dryml +150 -0
  106. data/vendor/assets/javascripts/hobo_rapid.js +1 -0
  107. data/vendor/assets/stylesheets/feckless-fieldset.css +40 -0
  108. data/vendor/assets/stylesheets/hobo-rapid.css +94 -0
  109. data/vendor/assets/stylesheets/hobo_rapid.css +1 -0
  110. metadata +174 -0
data/README.markdown ADDED
@@ -0,0 +1,5 @@
1
+ RAPID is the standard Hobo tag library.
2
+
3
+ #### Note
4
+
5
+ Many of the tags require a javascript plugin such as hobo_jquery to function.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.4.0.pre2
@@ -0,0 +1,25 @@
1
+ class DevController < ActionController::Base
2
+
3
+ hobo_controller
4
+
5
+ before_filter :developer_modes_only
6
+
7
+ def set_current_user
8
+ model = params[:model] || Hobo::Model::UserBase.default_user_model
9
+ self.current_user = if params[:login]
10
+ model.where(model.login_attribute => params[:login]).first
11
+ else
12
+ model.find(params[:id])
13
+ end
14
+ redirect_to(request.env["HTTP_REFERER"] ? :back : home_page)
15
+ end
16
+
17
+ private
18
+
19
+ def developer_modes_only
20
+ # Belt and braces. In addition to this check, the routes only get
21
+ # defined when developer_features is true
22
+ render :text => "Permission Denied", :status => 403 unless Rails.application.config.hobo.developer_features
23
+ end
24
+
25
+ end
@@ -0,0 +1,197 @@
1
+ module HoboRapidHelper
2
+ AJAX_CALLBACKS = [ :success, :failure, :complete, :before ]
3
+
4
+ AJAX_UPDATE_ATTRS = [ :update, :updates, :ajax ]
5
+
6
+ AJAX_EFFECT_ATTRS = [ :hide, :show ]
7
+
8
+ AJAX_SPINNER_ATTRS = [:spinner_next_to, :spinner_options, :spinner_at, :no_spinner, :message]
9
+
10
+ AJAX_PUSHSTATE_ATTRS = [:push_state, :new_title]
11
+
12
+ AJAX_ATTRS = AJAX_CALLBACKS + AJAX_UPDATE_ATTRS + AJAX_EFFECT_ATTRS + AJAX_SPINNER_ATTRS + AJAX_PUSHSTATE_ATTRS
13
+ [:params, :errors_ok,
14
+ :reset_form, :refocus_form ]
15
+
16
+ def app_name(add_subsite=true)
17
+ an = Rails.application.config.hobo.app_name
18
+ if add_subsite && subsite
19
+ subsite_name = t 'hobo.admin.subsite_name', :default => subsite.titleize
20
+ an = an + " - #{subsite_name}"
21
+ end
22
+ an
23
+ end
24
+
25
+ def comma_split(x)
26
+ case x
27
+ when nil
28
+ []
29
+ when String
30
+ x.strip.split(/\s*,\s*/)
31
+ else
32
+ x.compact.map{|e| comma_split(e)}.flatten
33
+ end
34
+ end
35
+
36
+ def a_or_an(word)
37
+ if word =~ /^[aeiouh]/
38
+ "an #{word}"
39
+ else
40
+ "a #{word}"
41
+ end
42
+ end
43
+
44
+
45
+ def no_break(s)
46
+ s = new_context { yield } if block_given?
47
+ s.gsub(' ', '&nbsp;')
48
+ end
49
+
50
+ # returns the number of items in the collection. See LH #889
51
+ def collection_count
52
+ this.try.to_int || this.try.total_entries || (this.try.loaded? && this.try.length) || this.try.count || this.try.length
53
+ end
54
+
55
+ def through_collection_names(object=this)
56
+ object.class.reflections.values.select do |refl|
57
+ refl.macro == :has_many && refl.options[:through]
58
+ end.map {|x| x.options[:through]}
59
+ end
60
+
61
+
62
+ def non_through_collections(object=this)
63
+ names = object.class.reflections.values.select do |refl|
64
+ refl.macro == :has_many
65
+ end.*.name
66
+
67
+ names - through_collection_names
68
+ end
69
+
70
+ def standard_fields(model, include_timestamps=false)
71
+ fields = model.attr_order.*.to_s & model.content_columns.*.name
72
+ fields -= %w{created_at updated_at created_on updated_on deleted_at} unless include_timestamps
73
+ fields.reject! { |f| model.never_show? f }
74
+ fields
75
+ end
76
+
77
+ def current_time
78
+ Time.zone ? Time.zone.now : Time.now
79
+ end
80
+
81
+ # provides the meat for hidden-fields for-query-string and anybody
82
+ # else who wants a list of relevant parameters. options: :skip, :only
83
+ def query_parameters_filtered(options = {})
84
+ query_params = (request.query_parameters | request.request_parameters)
85
+ if options[:only]
86
+ query_params = query_params & options[:only]
87
+ else
88
+ query_params = query_params - [:render, :render_options, :"_", :page_path, :authenticity_token]
89
+ if form_field_path
90
+ query_params = query_params - [form_field_path[0]]
91
+ end
92
+ end
93
+ query_params = query_params - options[:skip] if options[:skip]
94
+ query_params
95
+ end
96
+
97
+ # this function provides the meat for the form and formlet tags. It
98
+ # returns a tuple of:
99
+ # body: html body
100
+ # html_attrs: class, id, etc.
101
+ # ajax_attrs: update, spinner-next-to, etc
102
+ # form_attrs: action, method, enctype
103
+ def form_helper(attributes, parameters)
104
+ attrs, other_attrs = attributes.partition_hash([:hidden_fields, :action, :method, :web_method, :lifecycle, :owner, :multipart])
105
+ ajax_attrs, html_attrs = other_attrs.partition_hash(HoboRapidHelper::AJAX_ATTRS)
106
+ form_attrs = {}
107
+
108
+ if html_attrs[:confirm]
109
+ if ajax_attrs.blank?
110
+ html_attrs["data-confirm"] = html_attrs.delete(:confirm) # rely on rails_ujs
111
+ else
112
+ ajax_attrs[:confirm] = html_attrs.delete(:confirm)
113
+ end
114
+ end
115
+
116
+ form_attrs[:enctype] = html_attrs[:enctype] if html_attrs[:enctype]
117
+ form_attrs[:enctype] ||= "multipart/form-data" if attrs[:multipart]
118
+
119
+ new_record = self.this.try.new_record?
120
+
121
+ method = if attrs[:method].nil?
122
+ (attrs[:action] || attrs[:web_method] || new_record) ? "post" : "put"
123
+ else
124
+ attrs[:method].downcase
125
+ end
126
+
127
+ form_attrs[:action] = attrs[:action] ||
128
+ begin
129
+ target = if attrs[:owner]
130
+ collection_name = this.class.reverse_reflection(attrs[:owner]).name
131
+ this.send(attrs[:owner]).send(collection_name)
132
+ else
133
+ this
134
+ end
135
+ attrs[:action] = attrs[:web_method] || attrs[:lifecycle]
136
+ object_url(target, attrs[:action], :method => method)
137
+ end
138
+
139
+ if attrs[:action].nil? && (form_attrs[:action].nil? ||
140
+ (attrs[:lifecycle].nil? && new_record && !this.creatable_by?(current_user)) ||
141
+ (attrs[:lifecycle].nil? && !new_record && !can_edit?))
142
+ Dryml.last_if = false
143
+ logger.info("unable to render form")
144
+ return nil
145
+ else
146
+ if method == "put" || method == "delete"
147
+ # browsers don't support put -- use post and add the Rails _method hack
148
+ http_method_hidden = hidden_field_tag("_method", method.upcase)
149
+ form_attrs[:method] = "post"
150
+ else
151
+ http_method_hidden = ""
152
+ form_attrs[:method] = method
153
+ end
154
+
155
+ hiddens = ""
156
+ body = with_form_context do
157
+ # It is important to evaluate parameters.default first, in order to populate scope.form_field_names
158
+ b = parameters.default
159
+ hiddens = self.hidden_fields(:fields => attrs[:hidden_fields]) if new_record
160
+ b
161
+ end
162
+
163
+ auth_token = if method.nil? || method == 'get' || !protect_against_forgery?
164
+ ''
165
+ else
166
+ element(:input, {:type => "hidden",
167
+ :name => request_forgery_protection_token.to_s,
168
+ :value => form_authenticity_token}, nil, true, true)
169
+ end
170
+
171
+ unless method == "get"
172
+ page_path = if (request.post? || request.put? || request.delete?) && params[:page_path]
173
+ params[:page_path]
174
+ else
175
+ request.fullpath
176
+ end
177
+ page_path_hidden = hidden_field_tag("page_path", page_path)
178
+ end
179
+
180
+ hiddens_div = element(:div, {:class => "hidden-fields"}, [http_method_hidden, page_path_hidden, auth_token, hiddens].safe_join)
181
+
182
+ body = [hiddens_div, body].safe_join
183
+
184
+ if attrs[:action].nil? # don't add automatic css classes if the action was specified
185
+ if attrs[:web_method]
186
+ add_classes!(html_attrs, "#{type_id.dasherize}-#{web_method}-form")
187
+ else
188
+ add_classes!(html_attrs, "#{'new ' if new_record}#{type_id.dasherize}")
189
+ end
190
+ end
191
+
192
+ Dryml.last_if = true
193
+ [body, html_attrs, ajax_attrs, form_attrs]
194
+ end
195
+ end
196
+
197
+ end
@@ -0,0 +1,26 @@
1
+ name = File.basename( __FILE__, '.gemspec' )
2
+ version = File.read(File.expand_path('../VERSION', __FILE__)).strip
3
+ require 'date'
4
+
5
+ Gem::Specification.new do |s|
6
+
7
+ s.authors = ['Tom Locke, Bryan Larsen']
8
+ s.email = 'tom@tomlocke.com'
9
+ s.homepage = 'http://hobocentral.net'
10
+ s.rubyforge_project = 'hobo'
11
+ s.summary = 'The RAPID tag library for Hobo'
12
+ s.description = 'The RAPID tag library for Hobo'
13
+
14
+ s.add_runtime_dependency('hobo', ["= #{version}"])
15
+
16
+ s.files = `git ls-files -x #{name}/* -z`.split("\0")
17
+
18
+ s.name = name
19
+ s.version = version
20
+ s.date = Date.today.to_s
21
+
22
+ s.required_rubygems_version = ">= 1.3.6"
23
+ s.rdoc_options = ["--charset=UTF-8"]
24
+ s.require_paths = ["lib", "vendor"]
25
+
26
+ end
@@ -0,0 +1,6 @@
1
+ require 'hobo_rapid'
2
+ require 'rails'
3
+ module HoboRapid
4
+ class Railtie < Rails::Railtie
5
+ end
6
+ end
data/lib/hobo_rapid.rb ADDED
@@ -0,0 +1,13 @@
1
+ module HoboRapid
2
+
3
+ VERSION = File.read(File.expand_path('../../VERSION', __FILE__)).strip
4
+ @@root = Pathname.new File.expand_path('../..', __FILE__)
5
+ def self.root; @@root; end
6
+
7
+ EDIT_LINK_BASE = "https://github.com/tablatom/hobo_tree_table/edit/master/hobo_rapid"
8
+
9
+ require 'hobo_rapid/railtie' if defined?(Rails)
10
+
11
+ class Engine < ::Rails::Engine
12
+ end
13
+ end
@@ -0,0 +1 @@
1
+ <!-- Buttons that do stuff. -->
@@ -0,0 +1,40 @@
1
+ <!-- Provides an ajax create button that will send a RESTful "POST" to the server to create a new resource.
2
+
3
+ All of the standard ajax attributes are supported (see the main taglib documention for Rapid Forms).
4
+
5
+ ### Attributes
6
+
7
+ - model: The class to instantiate, pass either the class name or the class object.
8
+
9
+ -->
10
+ <def tag="create-button" attrs="model, update, label, fields, message"><%=
11
+ raise Hobo::Error.new("no update specified") unless update
12
+
13
+ fields ||= {}
14
+ class_or_assoc = if model
15
+ model.is_a?(String) ? model.constantize : model
16
+ elsif Hobo.simple_has_many_association?(this)
17
+ id_method = this_field_reflection.options[:primary_key] || this_field_reflection.klass.primary_key
18
+ fields[this_field_reflection.foreign_key] = this.proxy_owner.send(id_method)
19
+ this
20
+ else
21
+ raise Hobo::Error.new("invalid context for <create-button>")
22
+ end
23
+ new = class_or_assoc.new(fields)
24
+ new.set_creator(current_user)
25
+ if can_create?(new)
26
+ label ||= ht("#{new.class.to_s.underscore}.actions.new", :default=>"New #{new.class.model_name.human}")
27
+ class_name = new.class.name.underscore
28
+ params ||= params || {}
29
+ params = params.merge(class_name => fields) unless fields.blank?
30
+
31
+ ajax_attributes, html_attributes = attributes.partition_hash(HoboRapidHelper::AJAX_ATTRS)
32
+
33
+ ajax_attributes.reverse_merge!(:message => message, :params => params)
34
+ func = ajax_updater(object_url(new.class, :method => :post), update, ajax_attributes)
35
+ html_attributes.reverse_merge!(:type =>'button', :onclick => func, :value => label)
36
+
37
+ element :input, add_classes(html_attributes,
38
+ "button create-button create-#{class_name}-button"), nil, true, true
39
+ end
40
+ %></def>
@@ -0,0 +1,75 @@
1
+ <!-- Provides either an ajax or non-ajax delete button to send a
2
+ RESTful "DELETE". The context should be a record for which you to
3
+ want provide a delete button.
4
+
5
+ There are three possible types of `delete-button` created.
6
+
7
+ ### Non-Ajax
8
+
9
+ No Ajax is used if
10
+
11
+ - the `update`, `updates` and `ajax` attributes are not set AND EITHER
12
+ - `in-place` is explicitly set false OR
13
+ - the context for the delete is the same as the top-level context for the page. In other words, if you're trying to delete the entire page.
14
+
15
+ ### Standard form Ajax
16
+
17
+ If you set the `update`, `updates` or `ajax` attributes, standard form/part AJAX is used. It's assumed that the part you're specifying includes the item to be deleted so that it will be removed from the page by the update.
18
+
19
+ ### "Magic" Ajax
20
+
21
+ If:
22
+
23
+ - the `update`, `updates` and `ajax` attributes are not set AND EITHER
24
+ - `in-place` is explicitly set true OR
25
+ - the context for the delete is not the same as the top-level context for the page. In other words, if you're not trying to delete the entire page.
26
+
27
+ then `delete-button` performs an Ajax delete and then attempts to fix up the page. It does this by removing all items on the page that have their hobo-rapid-context set to the item being deleted. If said deletion results in an empty list, it shows the `.empty-collection-message`. This procedure should work with `<collection>`, `<table>` and their children (`<sortable-collection>`, `<table-plus>`, etc.).
28
+
29
+ ### Attributes
30
+
31
+ All the standard ajax attributes *except the callbacks* are supported (see the main taglib documention for Rapid Forms).
32
+
33
+ - label: The label for the button. Default: "Remove". (Alternately, use the hobo.actions.remove translation to customize)
34
+
35
+ - in-place: see above
36
+
37
+ - image: URL of an image for the button.
38
+
39
+ - fade: Perform the fade effect (true/false)? Default: true
40
+
41
+ - confirm: has a default value of "Are you sure?" or hobo.messages.confirm translated. You must explicitly set this to false if you don't want a confirm message.
42
+
43
+ -->
44
+ <def tag="delete-button" attrs="label, in-place, image, confirm, fade, subsite"><%
45
+ url = object_url(this, :method => :delete, :subsite => subsite)
46
+ if url && can_delete?
47
+ in_place = !(this == @this && request.method.downcase == "get") if in_place.nil?
48
+ update_attrs, attributes = attributes.partition_hash(HoboRapidHelper::AJAX_UPDATE_ATTRS)
49
+ ajax_attrs, attributes = attributes.partition_hash(HoboRapidHelper::AJAX_ATTRS)
50
+ attributes[src] = "#{base_url}/images/#{image}" if image
51
+ label ||= t("hobo.actions.remove", :default=>"Remove")
52
+ confirm = t("hobo.messages.confirm", :default=>"Are you sure?") if confirm.nil?
53
+ ajax_attrs[:confirm] = confirm if confirm
54
+
55
+ add_classes!(attributes,
56
+ image ? "image-button" : "button",
57
+ "delete-button delete-#{this.class.name.underscore.dasherize}-button")
58
+
59
+ if in_place && update_attrs.blank?
60
+ data_rapid = data_rapid(:delete_button)
61
+ ajax_attrs[:update] ||= "" # force form ajax
62
+ elsif !update_attrs.blank?
63
+ ajax_attrs.merge!(update_attrs)
64
+ data_rapid = nil
65
+ else
66
+ data_rapid = nil
67
+ end
68
+ end
69
+ %>
70
+ <if test="&url && can_delete?">
71
+ <form method="delete" action="&url" class="button_to" merge-attrs="&ajax_attrs" data-rapid="&data_rapid" data-rapid-context="&typed_id">
72
+ <input type="submit" value="&label" merge/>
73
+ </form>
74
+ </if>
75
+ </def>
@@ -0,0 +1,34 @@
1
+ <!-- Provides either an ajax or non-ajax button to invoke a "remote method" or "web method" declared in the controller.
2
+ Web Methods provide support for the RPC model of client-server interaction, in contrast to the REST model. The
3
+ preference in Rails is to use REST as much as possible, but we are pragmatists, and sometimes you just to need a remote
4
+ procedure call.
5
+
6
+ The URL that the call is POSTed to is the `object_url` of `this`, plus the method name
7
+
8
+ `<remote-method-button>` supports all of the standard ajax attributes (see the main taglib documention for Rapid
9
+ Forms). If any ajax attributes are given, the button becomes an ajax button, if not, Rails' `button_to` is used, which behaves similarly to a standard link.
10
+
11
+ ### Attributes
12
+
13
+ - method: the name of the web-method to call
14
+
15
+ - label: the label on the button
16
+
17
+ -->
18
+ <def tag="remote-method-button" attrs="method, update, label, confirm, url"><%=
19
+ ajax_attributes, html_attributes = attributes.partition_hash(HoboRapidHelper::AJAX_ATTRS)
20
+
21
+ url ||= object_url(this, method.to_s.gsub('-', '_'), :method => :post)
22
+ raise ArgumentError, "no such web method '#{method}' on #{this.typed_id}" unless url
23
+
24
+ add_classes!(html_attributes, "button remote-method-button #{method}-button")
25
+ label ||= method.titleize
26
+ if update || !ajax_attributes.empty?
27
+ ajax_attributes[:message] ||= label
28
+ func = ajax_updater(url, update, ajax_attributes.merge(:confirm => confirm))
29
+ html_attributes.update(:onclick => "var e = this; " + func, :type =>'button', :value => label)
30
+ element(:input, html_attributes, nil, true, true)
31
+ else
32
+ button_to(label, url, html_attributes.merge(:confirm => confirm))
33
+ end
34
+ %></def>
@@ -0,0 +1,71 @@
1
+ <!-- A push-button to invoke a lifecycle transition either as a page-reload or as an ajax call.
2
+
3
+ ### Attributes
4
+
5
+ - `transition` - the name of the transition to invoke. Required
6
+ - `update` - one or more DOM IDs of ajax parts to update after the transition
7
+ - `label` - the label on the button. Defaults to the name of the transition
8
+
9
+ All of the [standard ajax attributes](/api_taglibs/rapid_forms) are also supported.
10
+
11
+ ### Warning
12
+
13
+ Transitions with parameters are implemented using a form. HTML does not allow forms to be nested, so a transitions with parameters should not be placed inside of a form.
14
+
15
+ ### Invalid transitions
16
+
17
+ If the transition could not be found, the user does not have permissions for the transition or the object is not in the correct state for the transition, the transition-button displays nothing. You can use an `<else>` to display an appropriate message.
18
+
19
+ <transition-button transition="mogrify"/><else>Cannot mogrify</else>
20
+
21
+ -->
22
+ <def tag="transition-button" attrs="transition, update, label"><%=
23
+ if transition.is_a?(String)
24
+ transition = this.lifecycle.find_transition(transition, current_user)
25
+ end
26
+ if transition.nil?
27
+ Dryml.last_if = false
28
+ return ""
29
+ end
30
+ transition_name = transition.name
31
+ has_params = !transition.options[:params].blank?
32
+ ajax_attributes, html_attributes = attributes.partition_hash(HoboRapidHelper::AJAX_ATTRS)
33
+
34
+ html_attributes[:method] ||= has_params ? :get : :put
35
+ add_classes!(html_attributes, "transition-button #{transition_name}-button")
36
+ label = t("activerecord.attributes.#{this.class.to_s.underscore}.lifecycle.transitions.#{transition_name}", :default => (label || transition_name.to_s.titleize))
37
+ title = t("activerecord.attribute_help.#{this.class.to_s.underscore}.lifecycle.transitions.#{transition_name}")
38
+ html_attributes.update(:title => title) unless title.empty?
39
+ url = object_url(this, transition_name, :method => html_attributes[:method])
40
+
41
+ if (update || !ajax_attributes.empty?) && !has_params
42
+ ajax_attributes[:message] ||= label
43
+ ajax_attributes[:method] = html_attributes[:method]
44
+ func = ajax_updater(url, update, ajax_attributes)
45
+ html_attributes.update(:onclick => "var e = this; " + func, :type =>'button', :value => label)
46
+ element(:input, html_attributes, nil, true, true)
47
+ else
48
+ button_to(label, url, html_attributes)
49
+ end
50
+ %>
51
+ </def>
52
+
53
+ <!-- Renders a div containing transition buttons for every transition available to the current user.
54
+
55
+ For example, you could use this on a `Friendship` card: the person invited to have friendship would automatically see 'Accept' and 'Decline' buttons, while the person initiating the invite would see 'Retract'.
56
+
57
+ This tag behaves similarly to repeat: an else tag may be used to handle the case of no buttons:
58
+
59
+ <transition-buttons/><else>Sorry, no buttons to press.</else>
60
+ -->
61
+ <def tag="transition-buttons">
62
+ <% ajax_attrs, html_attrs = attributes.partition_hash(HoboRapidHelper::AJAX_ATTRS) %>
63
+ <div merge-attrs="&html_attrs" class="transitions">
64
+ <% transitions = this.lifecycle.publishable_transitions_for(current_user) %>
65
+ <if test="&transitions">
66
+ <% transitions.each do |t| %>
67
+ <transition-button merge-attrs="&ajax_attrs" transition="&t"/>
68
+ <% end %>
69
+ </if>
70
+ </div>
71
+ </def>
@@ -0,0 +1,22 @@
1
+ <!-- Displays a link to a lifecycle transition page if the transition is valid. If the transition is valid, this is equivalent to:
2
+
3
+ <a action="&transition" ...
4
+
5
+ If the transition is invalid, you may use the `<else>` tag to display an appropriate message:
6
+
7
+ <transition-link transition="mogrify">Mogrify</transition-link>
8
+ <else>Cannot mogrify</else>
9
+
10
+ ### Attributes
11
+
12
+ All attributes and parameters for the `<a>` tag are also valid.
13
+
14
+ - `transition` - the name of the transition to invoke. Required
15
+ -->
16
+ <def tag="transition-link" attrs="transition"><%
17
+ trans = this.lifecycle.find_transition(transition, current_user) %>
18
+ <if test="&trans">
19
+ <a action="&transition" merge/>
20
+ </if>
21
+ </def>
22
+
@@ -0,0 +1,29 @@
1
+ <!-- Provides an ajax button to send a RESTful update or "PUT" to the server. i.e. to udate one or more fields of a
2
+ record.
3
+
4
+ Note that unlike simliar tags, `<update-button>` does not support both ajax and non-ajax modes at this time. It only
5
+ does ajax.
6
+
7
+ `<update-button>` supports all of the standard ajax attributes (see the main taglib documention for Rapid Forms).
8
+
9
+ ### Attributes
10
+
11
+ - label: The label on the button.
12
+
13
+ - fields: A hash with new field values pairs to update the resource with. The items in the hash will be converted to
14
+ HTTP parameters.
15
+
16
+ - params: Another hash with additional HTTP parameters to include in the ajax request
17
+
18
+ -->
19
+ <def tag="update-button" attrs="label, update, fields, params"><%=
20
+ raise Hobo::Error.new("no update specified") unless update
21
+
22
+ ajax_attributes, html_attributes = attributes.partition_hash(HoboRapidHelper::AJAX_ATTRS)
23
+ params = (params || {}).merge(this.class.name.underscore => fields)
24
+ ajax_attributes.reverse_merge!(:message => label, :params => params, :method => :put)
25
+ func = ajax_updater(object_url(this), update, ajax_attributes)
26
+ html_attributes.reverse_merge!(:type =>'button', :onclick => func, :value => label)
27
+
28
+ element :input, add_classes(html_attributes, "button update-button update-#{this.class.name.underscore}-button"), nil, true, true %>
29
+ </def>
@@ -0,0 +1 @@
1
+ <!-- Tags for caching -->