radiant-reader-extension 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/.gitignore +2 -0
  2. data/README.md +89 -0
  3. data/Rakefile +140 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/admin/messages_controller.rb +20 -0
  6. data/app/controllers/admin/reader_settings_controller.rb +92 -0
  7. data/app/controllers/admin/readers_controller.rb +28 -0
  8. data/app/controllers/password_resets_controller.rb +64 -0
  9. data/app/controllers/reader_action_controller.rb +84 -0
  10. data/app/controllers/reader_activations_controller.rb +60 -0
  11. data/app/controllers/reader_sessions_controller.rb +56 -0
  12. data/app/controllers/readers_controller.rb +131 -0
  13. data/app/helpers/admin/reader_settings_helper.rb +36 -0
  14. data/app/models/message.rb +108 -0
  15. data/app/models/message_function.rb +37 -0
  16. data/app/models/message_reader.rb +13 -0
  17. data/app/models/reader.rb +146 -0
  18. data/app/models/reader_notifier.rb +34 -0
  19. data/app/models/reader_session.rb +3 -0
  20. data/app/views/admin/messages/_form.html.haml +29 -0
  21. data/app/views/admin/messages/_help.html.haml +41 -0
  22. data/app/views/admin/messages/_message_description.html.haml +3 -0
  23. data/app/views/admin/messages/edit.html.haml +16 -0
  24. data/app/views/admin/messages/new.html.haml +16 -0
  25. data/app/views/admin/reader_settings/_setting.html.haml +24 -0
  26. data/app/views/admin/reader_settings/edit.html.haml +10 -0
  27. data/app/views/admin/reader_settings/index.html.haml +35 -0
  28. data/app/views/admin/reader_settings/show.html.haml +1 -0
  29. data/app/views/admin/readers/_avatar.html.haml +3 -0
  30. data/app/views/admin/readers/_form.html.haml +50 -0
  31. data/app/views/admin/readers/_list_head.html.haml +9 -0
  32. data/app/views/admin/readers/_listed.html.haml +22 -0
  33. data/app/views/admin/readers/_password_fields.html.haml +18 -0
  34. data/app/views/admin/readers/edit.html.haml +8 -0
  35. data/app/views/admin/readers/index.html.haml +17 -0
  36. data/app/views/admin/readers/new.html.haml +7 -0
  37. data/app/views/admin/readers/remove.html.haml +18 -0
  38. data/app/views/admin/sites/_choose_reader_layout.html.haml +7 -0
  39. data/app/views/password_resets/create.html.haml +13 -0
  40. data/app/views/password_resets/edit.html.haml +71 -0
  41. data/app/views/password_resets/new.html.haml +31 -0
  42. data/app/views/reader_activations/_activation_required.html.haml +34 -0
  43. data/app/views/reader_activations/_on_activation.html.haml +4 -0
  44. data/app/views/reader_activations/show.html.haml +41 -0
  45. data/app/views/reader_notifier/message.html.haml +1 -0
  46. data/app/views/reader_sessions/_login_form.html.haml +59 -0
  47. data/app/views/reader_sessions/new.html.haml +38 -0
  48. data/app/views/readers/_contributions.html.haml +2 -0
  49. data/app/views/readers/_controls.html.haml +25 -0
  50. data/app/views/readers/_extra_controls.html.haml +0 -0
  51. data/app/views/readers/_flasher.html.haml +6 -0
  52. data/app/views/readers/_form.html.haml +73 -0
  53. data/app/views/readers/create.html.haml +28 -0
  54. data/app/views/readers/edit.html.haml +47 -0
  55. data/app/views/readers/index.html.haml +16 -0
  56. data/app/views/readers/login.html.haml +15 -0
  57. data/app/views/readers/new.html.haml +41 -0
  58. data/app/views/readers/permission_denied.html.haml +23 -0
  59. data/app/views/readers/show.html.haml +35 -0
  60. data/app/views/wrappers/_field_errors.html.haml +5 -0
  61. data/config/routes.rb +22 -0
  62. data/config/settings.rb +9 -0
  63. data/db/migrate/001_create_readers.rb +31 -0
  64. data/db/migrate/002_extend_sites.rb +17 -0
  65. data/db/migrate/003_reader_honorifics.rb +12 -0
  66. data/db/migrate/004_user_readers.rb +11 -0
  67. data/db/migrate/005_last_login.rb +15 -0
  68. data/db/migrate/007_adapt_for_authlogic.rb +27 -0
  69. data/db/migrate/20090921125653_reader_messages.rb +27 -0
  70. data/db/migrate/20090924164413_functional_messages.rb +9 -0
  71. data/db/migrate/20090925081225_standard_messages.rb +106 -0
  72. data/db/migrate/20091006102438_message_visibility.rb +9 -0
  73. data/db/migrate/20091010083503_registration_config.rb +10 -0
  74. data/db/migrate/20091019124021_message_functions.rb +9 -0
  75. data/db/migrate/20091020133533_forenames.rb +9 -0
  76. data/db/migrate/20091020135152_contacts.rb +23 -0
  77. data/db/migrate/20091111090819_ensure_functional_messages_visible.rb +9 -0
  78. data/db/migrate/20091119092936_messages_have_layout.rb +9 -0
  79. data/db/migrate/20100922152338_lock_versions.rb +9 -0
  80. data/db/migrate/20100927095703_default_settings.rb +14 -0
  81. data/db/migrate/20101004074945_unlock_version.rb +9 -0
  82. data/lib/config_extensions.rb +5 -0
  83. data/lib/controller_extensions.rb +77 -0
  84. data/lib/reader_admin_ui.rb +64 -0
  85. data/lib/reader_helper.rb +36 -0
  86. data/lib/reader_site.rb +10 -0
  87. data/lib/reader_tags.rb +297 -0
  88. data/lib/rfc822.rb +29 -0
  89. data/lib/tasks/reader_extension_tasks.rake +28 -0
  90. data/pkg/radiant-reader-extension-0.9.0.gem +0 -0
  91. data/public/images/admin/chk_off.png +0 -0
  92. data/public/images/admin/chk_on.png +0 -0
  93. data/public/images/admin/new-message.png +0 -0
  94. data/public/images/admin/new-reader.png +0 -0
  95. data/public/javascripts/admin/messages.js +13 -0
  96. data/public/stylesheets/sass/admin/reader.sass +95 -0
  97. data/radiant-reader-extension.gemspec +184 -0
  98. data/reader_extension.rb +55 -0
  99. data/spec/controllers/admin/messages_controller_spec.rb +38 -0
  100. data/spec/controllers/admin/readers_controller_spec.rb +14 -0
  101. data/spec/controllers/password_resets_controller_spec.rb +140 -0
  102. data/spec/controllers/reader_activations_controller_spec.rb +45 -0
  103. data/spec/controllers/readers_controller_spec.rb +193 -0
  104. data/spec/datasets/messages_dataset.rb +49 -0
  105. data/spec/datasets/reader_layouts_dataset.rb +26 -0
  106. data/spec/datasets/reader_sites_dataset.rb +10 -0
  107. data/spec/datasets/readers_dataset.rb +51 -0
  108. data/spec/lib/reader_admin_ui_spec.rb +35 -0
  109. data/spec/lib/reader_site_spec.rb +18 -0
  110. data/spec/matchers/reader_login_system_matcher.rb +35 -0
  111. data/spec/models/message_spec.rb +109 -0
  112. data/spec/models/reader_notifier_spec.rb +34 -0
  113. data/spec/models/reader_spec.rb +155 -0
  114. data/spec/spec.opts +5 -0
  115. data/spec/spec_helper.rb +48 -0
  116. metadata +267 -0
@@ -0,0 +1,10 @@
1
+ module ReaderSite
2
+
3
+ def self.included(base)
4
+ base.class_eval do
5
+ belongs_to :reader_layout, :class_name => 'Layout'
6
+ has_many :readers
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,297 @@
1
+ module ReaderTags
2
+ include Radiant::Taggable
3
+
4
+ class TagError < StandardError; end
5
+
6
+
7
+ # I can see this causing problems: will change soon
8
+
9
+ desc %{
10
+ The root 'site' tag is not meant to be called directly.
11
+ All it does is to prepare the way for eg.
12
+ <pre><code><r:site:url /></code></pre>
13
+ }
14
+ tag 'site' do |tag|
15
+ raise TagError, "r:site currently only works in email" unless @mailer_vars
16
+ raise TagError, "no site" unless tag.locals.site = @mailer_vars[:@site]
17
+ tag.expand
18
+ end
19
+ tag 'site:name' do |tag|
20
+ if defined?(Site) && tag.locals.site.is_a?(Site)
21
+ tag.locals.site.name
22
+ else
23
+ tag.locals.site[:name]
24
+ end
25
+ end
26
+ tag 'site:url' do |tag|
27
+ if defined?(Site) && tag.locals.site.is_a?(Site)
28
+ tag.locals.site.base_domain
29
+ else
30
+ tag.locals.site[:url]
31
+ end
32
+ end
33
+ tag 'site:login_url' do |tag|
34
+ reader_login_url(:host => @mailer_vars[:@host])
35
+ end
36
+
37
+ desc %{
38
+ The root 'recipient' tag is not meant to be called directly.
39
+ All it does is summon a reader object so that its fields can be displayed with eg.
40
+ <pre><code><r:recipient:name /></code></pre>
41
+ }
42
+ tag 'recipient' do |tag|
43
+ raise TagError, "r:recipient only works in email" unless @mailer_vars
44
+ raise TagError, "no recipient" unless tag.locals.recipient = @mailer_vars[:@reader]
45
+ tag.expand
46
+ end
47
+
48
+ [:name, :forename, :email, :description, :login].each do |field|
49
+ desc %{
50
+ Only for use in email messages. Displays the #{field} field of the reader currently being emailed.
51
+ <pre><code><r:recipient:#{field} /></code></pre>
52
+ }
53
+ tag "recipient:#{field}" do |tag|
54
+ tag.locals.recipient.send(field)
55
+ end
56
+ end
57
+
58
+ desc %{
59
+ Only for use in email messages. Displays the password of the reader currently being emailed, if we still have it.
60
+
61
+ (After the first successful login we forget the cleartext version of their password, so you only want to use this
62
+ tag in welcome and activation messages.)
63
+
64
+ <pre><code><r:recipient:url /></code></pre>
65
+ }
66
+ tag "recipient:password" do |tag|
67
+ tag.locals.recipient.clear_password || "<encrypted>"
68
+ end
69
+
70
+ desc %{
71
+ Only for use in email messages. Displays the me-page url of the reader currently being emailed.
72
+ <pre><code><r:recipient:url /></code></pre>
73
+ }
74
+ tag "recipient:url" do |tag|
75
+ reader_url(tag.locals.recipient, :host => @mailer_vars[:@host])
76
+ end
77
+
78
+ desc %{
79
+ Only for use in email messages. Displays the preferences url of the reader currently being emailed.
80
+ <pre><code><r:recipient:url /></code></pre>
81
+ }
82
+ tag "recipient:edit_url" do |tag|
83
+ edit_reader_url(tag.locals.recipient, :host => @mailer_vars[:@host])
84
+ end
85
+
86
+ desc %{
87
+ Only for use in email messages. Displays the address that will activate the current reader account.
88
+ <pre><code><r:recipient:activation_url /></code></pre>
89
+ }
90
+ tag "recipient:activation_url" do |tag|
91
+ activate_me_url(tag.locals.recipient, :activation_code => tag.locals.recipient.perishable_token, :host => @mailer_vars[:@host])
92
+ end
93
+
94
+ desc %{
95
+ Only for use in email messages. Displays the address that will bring up a new-password form for the current reader account.
96
+ <pre><code><r:recipient:repassword_url /></code></pre>
97
+ }
98
+ tag "recipient:repassword_url" do |tag|
99
+ repassword_url(tag.locals.recipient, :confirmation_code => tag.locals.recipient.perishable_token, :host => @mailer_vars[:@host])
100
+ end
101
+
102
+ desc %{
103
+ The root 'sender' tag is not meant to be called directly.
104
+ All it does is summon a sender object so that its fields can be displayed with eg.
105
+ <pre><code><r:sender:name /></code></pre>
106
+ }
107
+ tag 'sender' do |tag|
108
+ raise TagError, "r:sender only works in email" unless @mailer_vars
109
+ raise TagError, "no sender" unless tag.locals.sender = @mailer_vars[:@sender]
110
+ tag.expand
111
+ end
112
+
113
+ [:name, :email].each do |field|
114
+ desc %{
115
+ Only for use in email messages. Displays the #{field} field of the user sending the current message.
116
+ <pre><code><r:sender:#{field} /></code></pre>
117
+ }
118
+ tag "sender:#{field}" do |tag|
119
+ tag.locals.sender.send(field)
120
+ end
121
+ end
122
+
123
+ # and for referring to messages on pages
124
+ # at the moment this only works inside r:reader:messages:each or r:group:messages:each,
125
+ # both of which are defined in reader_group
126
+ # but soon there will be a conditional r:messages:each tag here too
127
+
128
+ desc %{
129
+ The root 'message' tag is not meant to be called directly.
130
+ All it does is summon a message object so that its fields can be displayed with eg.
131
+ <pre><code><r:message:subject /></code></pre>
132
+ }
133
+ tag 'message' do |tag|
134
+ raise TagError, "no message!" unless tag.locals.message
135
+ tag.expand
136
+ end
137
+
138
+ desc %{
139
+ Displays the message subject.
140
+
141
+ <pre><code><r:message:subject /></code></pre>
142
+ }
143
+ tag "message:subject" do |tag|
144
+ tag.locals.message.subject
145
+ end
146
+
147
+ desc %{
148
+ Displays the formatted message body.
149
+
150
+ <pre><code><r:message:body /></code></pre>
151
+ }
152
+ tag "message:body" do |tag|
153
+ tag.locals.message.filtered_body
154
+ end
155
+
156
+ desc %{
157
+ Returns the url of the show-message page.
158
+
159
+ <pre><code><r:message:url /></code></pre>
160
+ }
161
+ tag "message:url" do |tag|
162
+ message_path(tag.locals.message)
163
+ end
164
+
165
+ desc %{
166
+ Displays a link to the show-message page.
167
+
168
+ <pre><code><r:message:link /></code></pre>
169
+ }
170
+ tag "message:link" do |tag|
171
+ options = tag.attr.dup
172
+ attributes = options.inject('') { |s, (k, v)| s << %{#{k.downcase}="#{v}" } }.strip
173
+ attributes = " #{attributes}" unless attributes.empty?
174
+ text = tag.double? ? tag.expand : tag.render('message:subject')
175
+ %{<a href="#{tag.render('message:url')}"#{attributes}>#{text}</a>}
176
+ end
177
+
178
+
179
+
180
+ desc %{
181
+ The root 'reader' tag is not meant to be called directly.
182
+ All it does is summon a reader object so that its fields can be displayed with eg.
183
+ <pre><code><r:reader:name /></code></pre>
184
+
185
+ This will only work on an access-protected page and should never be used on a cached page, because everyone will see it.
186
+ }
187
+ tag 'reader' do |tag|
188
+ tag.expand if !tag.locals.page.cache? && tag.locals.reader = Reader.current
189
+ end
190
+
191
+ [:name, :forename, :email, :description, :login].each do |field|
192
+ desc %{
193
+ Displays the #{field} field of the current reader.
194
+ <pre><code><r:reader:#{field} /></code></pre>
195
+ }
196
+ tag "reader:#{field}" do |tag|
197
+ tag.locals.reader.send(field)
198
+ end
199
+ end
200
+
201
+ desc %{
202
+ Expands if the current reader has been sent any messages.
203
+
204
+ <pre><code><r:reader:if_messages>...</r:reader:if_messages /></code></pre>
205
+ }
206
+ tag "reader:if_messages" do |tag|
207
+ tag.expand if tag.locals.reader.messages.any?
208
+ end
209
+
210
+ desc %{
211
+ Expands if the current reader has not been sent any messages.
212
+
213
+ <pre><code><r:reader:unless_messages>...</r:reader:unless_messages /></code></pre>
214
+ }
215
+ tag "reader:unless_messages" do |tag|
216
+ tag.expand unless tag.locals.reader.messages.any?
217
+ end
218
+
219
+ desc %{
220
+ Loops through the messages that belong to this reader (whether they have been sent or not, so at the moment this may include drafts).
221
+
222
+ <pre><code><r:reader:messages:each>...</r:reader:messages:each /></code></pre>
223
+ }
224
+ tag "reader:messages" do |tag|
225
+ tag.locals.messages = tag.locals.reader.messages
226
+ tag.expand if tag.locals.messages.any?
227
+ end
228
+ tag "reader:messages:each" do |tag|
229
+ result = []
230
+ tag.locals.messages.each do |message|
231
+ tag.locals.message = message
232
+ result << tag.expand
233
+ end
234
+ result
235
+ end
236
+
237
+ desc %{
238
+ Displays the standard reader_welcome block, but only if a reader is present. For a block that shows an invitation to non-logged-in
239
+ people, use @r:reader_welcome@
240
+
241
+ <pre><code><r:reader:controls /></code></pre>
242
+ }
243
+ tag "reader:controls" do |tag|
244
+ tag.render('reader_welcome')
245
+ end
246
+
247
+ desc %{
248
+ Displays the standard block of reader controls: greeting, links to preferences, etc.
249
+ If there is no reader, this will show a 'login or register' invitation, provided the reader.allow_registration? config entry is true.
250
+ If you don't want that, use @r:reader:controls@ instead: the reader: prefix means it will only show when a reader is present.
251
+
252
+ If this tag appears on a cached page, we return an empty @<div class="remote_controls">@ into which you can drop whatever you like.
253
+
254
+ <pre><code><r:reader_welcome /></code></pre>
255
+ }
256
+ tag "reader_welcome" do |tag|
257
+ if tag.locals.page.cache?
258
+ %{<div class="remote_controls"></div>}
259
+ else
260
+ if tag.locals.reader = Reader.current
261
+ welcome = %{<span class="greeting">Hello #{tag.render('reader:name')}.</span> }
262
+ links = []
263
+ if tag.locals.reader.activated?
264
+ links << %{<a href="#{edit_reader_path(tag.locals.reader)}">Preferences</a>}
265
+ links << %{<a href="#{reader_path(tag.locals.reader)}">Your page</a>}
266
+ links << %{<a href="/admin">Admin</a>} if tag.locals.reader.is_user?
267
+ links << %{<a href="#{reader_logout_path}">Log out</a>}
268
+ else
269
+ welcome << "Please check your email and activate your account."
270
+ end
271
+ %{<div class="controls"><p>} + welcome + links.join(%{<span class="separator"> | </span>}) + %{</p></div>}
272
+ elsif Radiant::Config['reader.allow_registration?']
273
+ %{<div class="controls"><p><span class="greeting">Welcome!</span> To take part, please <a href="#{reader_login_path}">log in</a> or <a href="#{reader_register_path}">register</a>.</p></div>}
274
+ end
275
+ end
276
+ end
277
+
278
+ desc %{
279
+ Expands only if there is a reader and we are on an uncached page.
280
+
281
+ <pre><code><r:if_reader><div id="controls"><r:reader:controls /></r:if_reader></code></pre>
282
+ }
283
+ tag "if_reader" do |tag|
284
+ tag.expand if !tag.locals.page.cache? && tag.locals.reader = Reader.current
285
+ end
286
+
287
+ desc %{
288
+ Expands only if there is no reader or we are not on an uncached page.
289
+
290
+ <pre><code><r:unless_reader>Please log in</r:unless_reader></code></pre>
291
+ }
292
+ tag "unless_reader" do |tag|
293
+ tag.expand unless Reader.current && !tag.locals.page.cache?
294
+ end
295
+
296
+
297
+ end
data/lib/rfc822.rb ADDED
@@ -0,0 +1,29 @@
1
+ # RFC822 Email Address Regex
2
+ # --------------------------
3
+ #
4
+ # Originally written by Cal Henderson
5
+ # c.f. http://iamcal.com/publish/articles/php/parsing_email/
6
+ #
7
+ # Translated to Ruby by Tim Fletcher, with changes suggested by Dan Kubb.
8
+ #
9
+ # Licensed under a Creative Commons Attribution-ShareAlike 2.5 License
10
+ # http://creativecommons.org/licenses/by-sa/2.5/
11
+ #
12
+ module RFC822
13
+ RFC822_valid = begin
14
+ qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'
15
+ dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'
16
+ atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-' +
17
+ '\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+'
18
+ quoted_pair = '\\x5c[\\x00-\\x7f]'
19
+ domain_literal = "\\x5b(?:#{dtext}|#{quoted_pair})*\\x5d"
20
+ quoted_string = "\\x22(?:#{qtext}|#{quoted_pair})*\\x22"
21
+ domain_ref = atom
22
+ sub_domain = "(?:#{domain_ref}|#{domain_literal})"
23
+ word = "(?:#{atom}|#{quoted_string})"
24
+ domain = "#{sub_domain}(?:\\x2e#{sub_domain})*"
25
+ local_part = "#{word}(?:\\x2e#{word})*"
26
+ addr_spec = "#{local_part}\\x40#{domain}"
27
+ pattern = /\A#{addr_spec}\z/
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ namespace :radiant do
2
+ namespace :extensions do
3
+ namespace :reader do
4
+
5
+ desc "Runs the migration of the Reader extension"
6
+ task :migrate => :environment do
7
+ require 'radiant/extension_migrator'
8
+ if ENV["VERSION"]
9
+ ReaderExtension.migrator.migrate(ENV["VERSION"].to_i)
10
+ else
11
+ ReaderExtension.migrator.migrate
12
+ end
13
+ end
14
+
15
+ desc "Copies public assets of the Reader to the instance public/ directory."
16
+ task :update => :environment do
17
+ is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
18
+ puts "Copying assets from ReaderExtension"
19
+ Dir[ReaderExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
20
+ path = file.sub(ReaderExtension.root, '')
21
+ directory = File.dirname(path)
22
+ mkdir_p RAILS_ROOT + directory
23
+ cp file, RAILS_ROOT + path
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,13 @@
1
+ document.observe('dom:loaded', function() {
2
+ $$('.delivery_chooser').each(function (rb) { rb.observe('click', toggle_readerlist); });
3
+ if (delivery_selection() != 'selection') Effect.Fade('select_readers');
4
+ });
5
+
6
+ var toggle_readerlist = function() {
7
+ fx = (delivery_selection() == 'selection') ? Effect.Appear : Effect.Fade;
8
+ fx('select_readers', { duration: 0.5 });
9
+ };
10
+
11
+ var delivery_selection = function () {
12
+ return $$('input:checked[type="radio"][name="delivery"]').pluck('value');
13
+ };
@@ -0,0 +1,95 @@
1
+ @import compass
2
+
3
+ #content
4
+ form
5
+ p
6
+ span.filter
7
+ float: right
8
+ width: 400px
9
+ text-align: right
10
+ label
11
+ display: inline
12
+ div.body
13
+ padding: 12px 20px 20px
14
+ background: image_url('admin/vertical_tan_gradient.png') top left repeat-x #f5f1e2
15
+ +box-shadow(rgba(0,0,0,0.15), 2px, 2px, 3px)
16
+ p
17
+ margin-top: 0
18
+ label
19
+ color: #333
20
+ text-shadow: none
21
+ textarea
22
+ border: 1px solid #ccc
23
+
24
+ ul.help
25
+ list-style: square
26
+ padding-left: 40px
27
+ color: #ccc
28
+ font-size: 85%
29
+ code
30
+ color: white
31
+ font-size: 115%
32
+
33
+ #reader_settings
34
+ label
35
+ padding-left: 25px
36
+
37
+ #message_settings
38
+ label
39
+ margin-right: 50px
40
+
41
+ .box
42
+ span.inplace
43
+ a
44
+ color: black
45
+ &:hover
46
+ color: #06c
47
+ text-decoration: underline
48
+ form
49
+ display: inline
50
+ padding-left: 25px
51
+ background:
52
+ image: none
53
+ repeat: no-repeat
54
+ position: left center
55
+ &.waiting
56
+ background-image: url(/images/admin/spinner.gif)
57
+ a
58
+ color: #666
59
+ form
60
+ opacity: 0.2
61
+ span.checkbox
62
+ label
63
+ width: auto
64
+ margin: 0
65
+ label
66
+ padding-left: 25px
67
+ background:
68
+ image: none
69
+ repeat: no-repeat
70
+ position: left center
71
+ cursor: pointer
72
+ &.true
73
+ label
74
+ color: #393
75
+ background-image: url(/images/admin/chk_on.png)
76
+ &.false
77
+ label
78
+ color: #666
79
+ background-image: url(/images/admin/chk_off.png)
80
+ &.waiting
81
+ label
82
+ color: #999
83
+ background-image: url(/images/admin/spinner.gif)
84
+ input
85
+ position: absolute
86
+ left: -999px
87
+ a
88
+ text-decoration: none
89
+ a.create
90
+ color: #393
91
+ span.notes
92
+ display: block
93
+ margin-left: 25px
94
+ font-size: 85%
95
+ color: #555