parlement 0.8 → 0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. data/CHANGES +22 -0
  2. data/Rakefile +2 -2
  3. data/app/controllers/account_controller.rb +20 -7
  4. data/app/controllers/application.rb +17 -4
  5. data/app/controllers/elt_controller.rb +1 -10
  6. data/app/controllers/person_controller.rb +1 -1
  7. data/app/helpers/elt_helper.rb +14 -0
  8. data/app/models/elt.rb +2 -0
  9. data/app/models/mail.rb +6 -5
  10. data/app/models/person.rb +5 -0
  11. data/app/views/account/_login.rhtml +52 -48
  12. data/app/views/account/_show.rhtml +13 -12
  13. data/app/views/elt/_choice.rhtml +11 -2
  14. data/app/views/elt/_elt.rhtml +38 -50
  15. data/app/views/elt/new.rhtml +8 -8
  16. data/app/views/elt/show.rhtml +21 -12
  17. data/app/views/layouts/top.rhtml +1 -0
  18. data/app/views/person/_listElts.rhtml +47 -26
  19. data/app/views/person/show.rhtml +8 -18
  20. data/config/environment.rb +6 -3
  21. data/db/ROOT/fr.txt +34 -31
  22. data/db/ROOT/parlement/test.txt +6 -4
  23. data/db/development_structure.sql +18 -20
  24. data/public/engine_files/login_engine/stylesheets/login_engine.css +81 -0
  25. data/public/images/ParlementLogo_fr.png +0 -0
  26. data/public/images/comments.gif +0 -0
  27. data/public/images/vote_minus.png +0 -0
  28. data/public/images/vote_plus.png +0 -0
  29. data/public/images/vote_plus_minus.svg +79 -0
  30. data/public/images/write.png +0 -0
  31. data/public/images/write.svg +70 -0
  32. data/public/javascripts/mybehaviour.js +3 -4
  33. data/public/stylesheets/default.css +449 -0
  34. data/public/stylesheets/live_tree.css +62 -0
  35. data/public/stylesheets/scaffold.css +74 -0
  36. data/script/about +3 -0
  37. data/script/benchmarker +19 -0
  38. data/script/breakpointer +3 -0
  39. data/script/console +3 -0
  40. data/script/create_db +7 -0
  41. data/script/destroy +3 -0
  42. data/script/generate +3 -0
  43. data/script/plugin +3 -0
  44. data/script/profiler +34 -0
  45. data/script/runner +3 -0
  46. data/script/server +3 -0
  47. data/test/unit/elt_test.rb +11 -0
  48. data/test/unit/mail_test.rb +29 -0
  49. metadata +27 -40
  50. data/test/fixtures/attachments.yml +0 -13
  51. data/test/fixtures/choices.yml +0 -13
  52. data/test/fixtures/elts.yml +0 -36
  53. data/test/fixtures/img.png +0 -0
  54. data/test/fixtures/mail/avatar +0 -249
  55. data/test/fixtures/mail/mail_ruby +0 -39
  56. data/test/fixtures/mail/mail_rubyChild +0 -30
  57. data/test/fixtures/mail/mail_rubyChild2 +0 -30
  58. data/test/fixtures/mail/mail_rubyWithAttachment +0 -7932
  59. data/test/fixtures/mail/mail_rubyWithSubject +0 -27
  60. data/test/fixtures/mails.yml +0 -13
  61. data/test/fixtures/people.yml +0 -68
  62. data/test/fixtures/subscribers.yml +0 -14
  63. data/test/fixtures/users.yml +0 -41
  64. data/test/functional/account_controller_test.rb +0 -317
  65. data/test/functional/elt_controller_test.rb +0 -87
  66. data/test/functional/person_controller_test.rb +0 -18
  67. data/test/functional/subscriber_controller_test.rb +0 -128
  68. data/test/mocks/test/time.rb +0 -17
  69. data/test/mocks/test/user_notify.rb +0 -16
  70. data/test/test_helper.rb +0 -72
data/CHANGES CHANGED
@@ -1,5 +1,27 @@
1
1
  - parlement changelog
2
2
 
3
+ == Version 0.9
4
+
5
+ Improved look, particularly the voting and writing part. Long posts and lists
6
+ now truncated. Permanent login. Positioned elements. Search form (though
7
+ google).
8
+
9
+ * now asking to choose a pseudo
10
+ * focus now on the login box
11
+ * anonymous mails can also be received
12
+ * correcting personal page
13
+ * choices now on the right bottom side of elements
14
+ * elements can now be positioned
15
+ * new elements are directly placed under their parent
16
+ * long posts and lists only display their n first paragraphs or items
17
+ * google search form
18
+ * position text is hidden
19
+ * the >> link now more closely associated associated to the choices
20
+ * images for vote and write
21
+ * anonymous users now have a hidden subscription link
22
+ * login is permanent over browser sessions
23
+ * some font encoding corrections in mails
24
+
3
25
  == Version 0.8
4
26
 
5
27
  Users can now filter elements according to an acceptation's threshold
data/Rakefile CHANGED
@@ -35,8 +35,8 @@ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
35
35
  PKG_FILES = FileList[
36
36
  '[A-Z]*', 'app/**/*', 'components/**/*', 'config/**/*', 'db/**/*',
37
37
  'lib/**/*', 'public/*.*', 'public/dynamic/*', 'public/images/*',
38
- 'public/engine_files/*', 'public/javascripts/*', 'script/stylesheets/*',
39
- 'test/**/*', 'vendor/**/*'
38
+ 'public/engine_files/*', 'public/engine_files/**/*', 'public/javascripts/*',
39
+ 'public/stylesheets/*', 'script/*', 'script/**/*' 'test/**/*', 'vendor/**/*'
40
40
  ].exclude(/\b(svn|tmp|attachment)\b|~$/)
41
41
 
42
42
  spec = Gem::Specification.new do |s|
@@ -7,14 +7,16 @@ class AccountController < UserController
7
7
 
8
8
  def login
9
9
  # Cleaning up
10
- session[:person] = session[:user] = nil
10
+ session[:person] = @person = session[:user] = @user = nil
11
+ cookies.delete :person_name
12
+ cookies.delete :salted_password
11
13
 
12
14
  login = @params[:person][:name]
13
15
  email = @params[:person][:email]
14
16
  password = @params[:user][:password]
15
17
 
16
18
  @person = Person.find_by_name(login)
17
- @user = User.find_by_login(login) if @person
19
+ @user = @person.user if @person
18
20
 
19
21
  # First we eventually create a new pseudo
20
22
  if not @person
@@ -112,14 +114,23 @@ class AccountController < UserController
112
114
  end
113
115
  end
114
116
 
115
- render :partial => 'show', :locals => {
116
- :divId => params[:divId], :choices => getAllVotes }
117
- end
117
+ # Record cookies for re authentication
118
+ if session[:person]
119
+ cookies[:person_name] = session[:person].name
120
+ cookies[:salted_password] = @user.salted_password if @user
121
+ end
118
122
 
123
+ render :partial => 'show',
124
+ :locals => { :divId => params[:divId], :choices => getAllVotes },
125
+ :status => (session[:person] ? 200 : 403)
126
+ end
119
127
 
120
128
  def logout
121
- session[:person] = @person = nil
122
- session[:user] = @user = nil
129
+ # Cleaning up
130
+ session[:person] = @person = session[:user] = @user = nil
131
+ cookies.delete :person_name
132
+ cookies.delete :salted_password
133
+
123
134
  render :partial => 'show', :locals => {
124
135
  :divId => params[:divId], :choices => getAllVotes }
125
136
  end
@@ -148,6 +159,8 @@ class AccountController < UserController
148
159
  end
149
160
 
150
161
  def setAvatar
162
+ return render(:text => "Not logged in", :status => 403) \
163
+ unless session[:person]
151
164
  logger.info "Setting up an avatar for person #{session[:person].name}"
152
165
 
153
166
  @elt = Elt.find_by_id 'people'
@@ -8,21 +8,34 @@ class ApplicationController < ActionController::Base
8
8
  model :user
9
9
 
10
10
  before_filter :set_charset
11
+ before_filter :set_login_from_cookie
11
12
  after_filter :fix_unicode_for_safari
12
13
  after_filter OutputCompressionFilter
13
14
 
14
15
  # automatically and transparently fixes utf-8 bug
15
16
  # with Safari when using xmlhttp
16
- def fix_unicode_for_safari
17
- if @headers["Content-Type"] == "text/html; charset=utf-8" and
17
+ def fix_unicode_for_safari
18
+ if @headers["Content-Type"] == "text/html; charset=utf-8" and
18
19
  @request.env['HTTP_USER_AGENT'].to_s.include? 'AppleWebKit' then
19
20
  @response.body = @response.body.gsub(/([^\x00-\xa0])/u) { |s| "&#x%x;" % $1.unpack('U')[0] }
20
- end
21
- end
21
+ end
22
+ end
22
23
 
23
24
  def set_charset
24
25
  #@headers["Content-Type"] = "text/html; charset=iso-8859-15"
25
26
  @headers["Content-Type"] = "text/html; charset=utf-8"
26
27
  end
28
+
29
+ def set_login_from_cookie
30
+ unless session[:person]
31
+ if (person = Person.find_by_name(cookies[:person_name])) and \
32
+ ((!person.user and !cookies[:salted_password]) \
33
+ or (person.user \
34
+ and person.user.salted_password == cookies[:salted_password]))
35
+ session[:person] = person
36
+ session[:user] = person.user
37
+ end
38
+ end
39
+ end
27
40
  end
28
41
 
@@ -15,13 +15,8 @@ class EltController < ApplicationController
15
15
  @elt = Elt.find(params[:id])
16
16
  @title = @elt.subject
17
17
  @title += " (parlement)" if !@title.downcase.include? "parlement"
18
- if request.env['REQUEST_URI'].match '.dyndns'
19
- headers["Status"] = "301 Moved Permanently"
20
- redirect_to request.env['REQUEST_URI'].gsub(/.dyndns/, '')
21
- end
22
18
  render :layout => 'top'
23
19
 
24
- # TODO
25
20
  rescue ActiveRecord::RecordNotFound => e
26
21
  flash[:error] = "Element '#{params[:id]}' does not exist"
27
22
  headers["Status"] = "301 Moved Permanently"
@@ -67,10 +62,6 @@ class EltController < ApplicationController
67
62
  end
68
63
  end
69
64
 
70
- def preview
71
- render :inline => format(params[:elt][:body])
72
- end
73
-
74
65
  def create
75
66
  @elt = Elt.new(params[:elt])
76
67
  @elt.person = @session[:person]
@@ -82,7 +73,7 @@ class EltController < ApplicationController
82
73
  headers["Status"] = "404 Post considered as spam"
83
74
  render :controller => 'elt', :action => 'new', :status => 404
84
75
  elsif params[:submit] == "preview" or (@elt.publish and @elt.parent.add_child(@elt)) then
85
- headers["Status"] = "201 Created"
76
+ #headers["Status"] = "201 Created"
86
77
  render :partial => '/elt/elt', :locals => { :elt => @elt, :eltTop => false }
87
78
  else
88
79
  flash[:notice] = 'Error'
@@ -15,7 +15,7 @@ class PersonController < ApplicationController
15
15
  end
16
16
 
17
17
  def list
18
- @person = Person.find(params[:id]) if @person == nil
18
+ @person = Person.find(params[:id]) unless @person
19
19
  render :partial => '/person/listElts', :locals => { :person => @person }
20
20
  end
21
21
  end
@@ -11,6 +11,7 @@ module EltHelper
11
11
  # 1. numbered list
12
12
  # chat log lines become list elements
13
13
  # short lines to which are added a break
14
+ # positions have a special treatment in the view
14
15
  text = auto_link data \
15
16
  .gsub(/^\b(.*:)$(\n)^>\s/, '\\1<br/>\\2\\2> ') \
16
17
  .gsub(/^Yahoo! Groups Links$(\n{2}^<*.*$\s.*$)*/, '') \
@@ -20,8 +21,19 @@ module EltHelper
20
21
  .gsub(/^\d+[\.-]\s+/, '# ') \
21
22
  .gsub(/^(\d\d:\d\d\s)/, '* \\1') \
22
23
  .gsub(/^\b(.{2,50})$(\n)\b/, '\\1<br/>\\2') \
24
+ .gsub(/\n*^\b(position:\s*(\d*(\.\d+)?))\s*$\n*/, ' <span class="position">\1</span>') \
23
25
  if data != nil
24
26
 
27
+ # Only show the n first paragraphs
28
+ text.gsub!(/((?:(\n)(?:^.+$\n)*){#{NB_PARAGRAPH_TO_DISPLAY}})((?:.|\n)*)/,
29
+ '\1\2<a class="readMore" href="#" onclick="Element.hide(this); Element.removeClassName(this.parentNode.nextSibling, \'tooLarge\'); return false;">Read more...</a>\2<div class="tooLarge">\2\3\2</div>') \
30
+ if data and text.strip =~ /((?:(\n)(?:^.+$\n)*){#{NB_PARAGRAPH_TO_DISPLAY+2}})/
31
+
32
+ # Only show the n*2 first list items
33
+ text.gsub!(/((?:^\*\s+.+$\n){#{NB_PARAGRAPH_TO_DISPLAY*2}})((?:.|\n)*)(\n)/,
34
+ '\1\3\3* <a class="readMore" href="#" onclick="Element.hide(this.parentNode.parentNode); Element.removeClassName(this.parentNode.parentNode.nextSibling.nextSibling, \'tooLarge\'); return false;">Read more...</a>\3\3<div class="tooLarge">\3\3\2</div>') \
35
+ if data and text.strip =~ /(?:(?:^\*\s+.+$\n){#{NB_PARAGRAPH_TO_DISPLAY*2+2}})/
36
+
25
37
  #hard_breaks = true
26
38
  textiled = text.blank? ? "" : RedCloth.new(text)
27
39
  begin
@@ -35,6 +47,8 @@ module EltHelper
35
47
  # Remove any leading and finishing <p> </p> as they are not required
36
48
  if textiled[0..2] == "<p>" then textiled = textiled[3..-1] end
37
49
  if textiled[-4..-1] == "</p>" then textiled = textiled[0..-5] end
50
+ # Here to push away the choice span
51
+ textiled += " "+"&#160;"*22
38
52
  end
39
53
 
40
54
  textiled
data/app/models/elt.rb CHANGED
@@ -56,6 +56,8 @@ class Elt < ActiveRecord::Base
56
56
 
57
57
  build_mail(:elt => self) unless mail
58
58
  mail.publish
59
+
60
+ self.position = Regexp.last_match(1) if body =~ /^\s*position:\s*(\d+(\.\d+)?)(\s|$)/
59
61
  save!
60
62
 
61
63
  parent.vote Regexp.last_match(1), person if body =~ /^\s*(-1|0|\+1)(\s|$)/
data/app/models/mail.rb CHANGED
@@ -98,7 +98,8 @@ class Mail < ActiveRecord::Base
98
98
  || Person.find_by_name(unquote(mail.friendly_from)) \
99
99
  || elt.build_person(:id => unquote(mail.friendly_from).gsub(/\s/, '_'),
100
100
  :name => unquote(mail.friendly_from),
101
- :email => mail.from.first)
101
+ :email => mail.from.first) \
102
+ if not mail.from.first.match(/#{ANONYMOUS_POSTER}@#{ActionMailer::Base.server_settings[:domain]}/)
102
103
 
103
104
  self.mail_parents = mail.references
104
105
  self.message = mail.message_id
@@ -183,9 +184,9 @@ class Mail < ActiveRecord::Base
183
184
 
184
185
  private
185
186
 
186
- # This is to make sure we only have utf-8, no iso-8859
187
+ # This is to make sure we only have text, no iso-8859 or utf-8 encoding
187
188
  def unquote(text)
188
- text.gsub(/\=\?.*?\?\=/) { |m| TMail::Unquoter.unquote_and_convert_to m, 'utf-8' }
189
+ text.gsub(/\=\?(.*)\?(Q|q)\?.*?\?\=/) { |m| TMail::Unquoter.unquote_and_convert_to m, Regexp.last_match(1) }
189
190
  end
190
191
 
191
192
  # Get and store the attachments
@@ -210,9 +211,9 @@ class Mail < ActiveRecord::Base
210
211
  # Here to correct a null character which can occur in some mails
211
212
  # It looks like ==0 or ^@ !!!
212
213
  # Otherwise the elt can not be saved in the db :(
213
- elt.body += Iconv.new(charset, 'utf-8').iconv(attachment.body).gsub(/\0/, '')
214
+ elt.body += Iconv.new(charset, 'iso-8859-1').iconv(attachment.body).gsub(/\0/, '')
214
215
  else
215
- elt.body += Iconv.new(charset, 'utf-8').iconv(attachment.body)
216
+ elt.body += Iconv.new(charset, 'iso-8859-1').iconv(attachment.body)
216
217
  end
217
218
  else
218
219
  # Here too have to remove any eventual null character!
data/app/models/person.rb CHANGED
@@ -14,5 +14,10 @@ class Person < ActiveRecord::Base
14
14
  has_and_belongs_to_many :subscribed_elts,
15
15
  :class_name => "Elt",
16
16
  :join_table => "subscribers"
17
+
18
+ # Convenience method, because User is as it was from the salted login plugin
19
+ def user
20
+ return User.find_by_login(name)
21
+ end
17
22
  end
18
23
 
@@ -7,55 +7,59 @@
7
7
  <%= hidden_field 'elt', 'id' if @elt %>
8
8
  <input type="hidden" id="divId" name="divId" value="<%= divId %>"/>
9
9
 
10
- <div class="login">
11
- <label for="person_name">Pseudo:
12
- <%= text_field "person", "name", :size => 10 %>
10
+ <div class="login">Please, choose a pseudo</div>
11
+
12
+ <label for="person_name">Pseudo:
13
+ <%= text_field "person", "name", :size => 10 %>
14
+ <script type="text/javascript">Form.focusFirstElement(document.forms[0]);</script>
15
+ </label>
16
+
17
+ <%= link_to_function('<span class="icon">&gt;&gt;</span>',
18
+ "Element.toggle(this);" \
19
+ +visual_effect(:Grow, 'user_password_'+divId.to_s) \
20
+ +"Form.focusFirstElement(document.forms[0])") %>
21
+
22
+ <span style="display: none;" id="user_password_<%= divId %>">
23
+ <br/>
24
+ <label for="user_password">Password:
25
+ <%= password_field "user", "password", :size => 10 %>
13
26
  </label>
14
27
 
15
- <%= link_to_function('+',
16
- "Element.show(this);"+visual_effect(:Grow, 'user_password_'+divId.to_s),
17
- :class => "subscribeLink") %>
18
-
19
- <span style="display: none;" id="user_password_<%= divId %>">
20
- <br/>
21
- <label for="user_password">Password:
22
- <%= password_field "user", "password", :size => 10 %>
23
- </label>
24
-
25
- <%= link_to_function('email? &gt;',
26
- "Element.toggle(this);"+visual_effect(:Grow, 'person_email_'+divId.to_s),
27
- :class => "subscribeLink") %>
28
- </span>
29
-
30
- <span style="display: none;" id="person_email_<%= divId %>">
31
- <br/>
32
- <label for="person_email">Email (or check key):</label>
33
- <%= text_field "person", "email", :size => 20 %>
34
- </span>
35
-
36
- <%= submit_tag 'Ok' %>
37
-
38
- <%= render :partial => '/help',
39
- :locals => { :divId => 'login'+divId.to_s, :content => '
40
- <p>You can propose an element with</p>
41
- <ul>
42
- <li>no pseudo</li>
43
- <li>an unprotected pseudo</li>
44
- <li>a password protected pseudo (click on "+")</li>
45
- <li>a password protected and email verified pseudo</li>
46
- </ul>
47
- <p>
48
- The last method is the only secure way to protect a nickname on
49
- <strong>this</strong> server.
50
- </p>
51
- <p>
52
- If a nick is not protected and verified, anybody else can protect it for
53
- themselves if they at least supply a password <em>and</em> an email.
54
- </p>
55
- <p>
56
- A login must contain [3..40] characters, a password [5..40].
57
- </p>
58
- ' } %>
59
- </div>
28
+ <%= link_to_function('<span class="icon">&gt;&gt;</span>',
29
+ "Element.toggle(this);" \
30
+ +visual_effect(:Grow, 'person_email_'+divId.to_s) \
31
+ +"Form.focusFirstElement(document.forms[0])") %>
32
+ </span>
33
+
34
+ <span style="display: none;" id="person_email_<%= divId %>">
35
+ <br/>
36
+ <label for="person_email">Email (or check key):</label>
37
+ <%= text_field "person", "email", :size => 20 %>
38
+ </span>
39
+
40
+ <%= submit_tag 'OK' %>
41
+
42
+ <%= render :partial => '/help',
43
+ :locals => { :divId => 'login'+divId.to_s, :content => '
44
+ <p>You can participate with:</p>
45
+ <ul>
46
+ <li>no pseudo</li>
47
+ <li>an unprotected pseudo</li>
48
+ <li>a password protected pseudo (click on "<span class="icon">&gt;&gt;</span>")</li>
49
+ <li>a password protected and email verified pseudo</li>
50
+ </ul>
51
+ <p>
52
+ The last method is the only secure way to protect a nickname on
53
+ <strong>this</strong> server.
54
+ </p>
55
+ <p>
56
+ If a pseudo is not protected <strong>and</strong> verified, anybody
57
+ else can protect it for themselves if they at least supply a password
58
+ <em>and</em> an email.
59
+ </p>
60
+ <p>
61
+ A login must contain [3..40] characters, a password [5..40].
62
+ </p>
63
+ ' } %>
60
64
  <%= end_form_tag %>
61
65
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  <% if choices ||= false %>
9
9
  <!-- Here are updated all choices, watch out, javascript! -->
10
- <div class="choicesToUpdate" title="choicesToUpdate">
10
+ <span class="choicesToUpdate" title="choicesToUpdate">
11
11
  <%= choices.size %>
12
12
  <script language="JavaScript">
13
13
  var choices_to_update = {
@@ -15,7 +15,7 @@
15
15
  };
16
16
  updateChoices(choices_to_update);
17
17
  </script>
18
- </div>
18
+ </span>
19
19
  <% end %>
20
20
 
21
21
  <% if @person = session[:person] %>
@@ -28,32 +28,33 @@
28
28
  { :href => url_for(:controller => 'account', :action => 'logout') }) %>
29
29
  </span>
30
30
 
31
- <% if session[:person].name and session[:person].name != '' %>
32
- <span class="author">
33
- &lt;<%= link_to session[:person].name,
34
- :controller => 'person',
35
- :action => 'show',
36
- :id => session[:person] %>&gt;
37
- </span>
38
- <% end %>
31
+ <span class="author">
32
+ &lt;<%= link_to session[:person].name,
33
+ :controller => 'person',
34
+ :action => 'show',
35
+ :id => session[:person] %>&gt;
36
+ </span>
39
37
 
40
38
  <div>
41
39
  <%= image_tag (@person.image ? @person.image : "/javascripts/blank.gif"),
42
- :id => "person_avatar", :class => "avatar" %>
40
+ :id => "person_avatar", :class => "avatar" %>
43
41
  </div>
44
42
 
45
43
  <%= form_tag( { :controller => "account", :action => "setAvatar"},
46
44
  :multipart => true, :target => "avatar", :class => "setAvatar") %>
47
45
  <label>
48
46
  Avatar:
49
- <%= file_field "person", "image", :onchange => "submit()" %>
47
+ <%= file_field "person", "image", :onchange => "submit()", :size => "18" %>
50
48
  </label>
51
49
  <%= submit_tag 'Ok' %>
52
50
  <%= end_form_tag %>
53
51
 
54
52
  <iframe id="avatar" name="avatar" style="display: none"></iframe>
53
+
54
+ <script language="JavaScript">Element.show($('subscription'));</script>
55
55
  <% else %>
56
56
 
57
57
  <%= render :partial => '/account/login', :locals => { :divId => divId } %>
58
+ <script language="JavaScript">Element.hide($('subscription'));</script>
58
59
  <% end %>
59
60
 
@@ -5,7 +5,7 @@ result = elt.result
5
5
 
6
6
  <label class="con <%= choice and choice.value == -1 ? "selected" : "" %>"
7
7
  title="-1" for="choice_<%= elt.id %>_con">
8
- V
8
+ <%= image_tag 'vote_minus' %>
9
9
  <%= radio_button_tag "choice[value]", "-1",
10
10
  (choice and choice.value == -1),
11
11
  :id => "choice_#{elt.id}_con",
@@ -22,7 +22,7 @@ result = elt.result
22
22
 
23
23
  <label class="pro <%= choice and choice.value == 1 ? "selected" : "" %>"
24
24
  title="+1" for="choice_<%= elt.id %>_pro">
25
- Λ
25
+ <%= image_tag 'vote_plus' %>
26
26
  <%= radio_button_tag "choice[value]", "+1",
27
27
  (choice and choice.value == +1),
28
28
  :id => "choice_#{elt.id}_pro",
@@ -31,3 +31,12 @@ result = elt.result
31
31
 
32
32
  <%= submit_tag 'Vote!' %>
33
33
 
34
+ <span class="eltQuickAdd" id="eltQuickAdd_<%= elt.id %>" title="<%= elt.created_on %>">
35
+ <%= link_to_remote(image_tag('write'),
36
+ { :update => 'eltNew_'+elt.id.to_s,
37
+ :url => { :controller => 'elt', :action => 'new', :id => elt },
38
+ :loaded => visual_effect(:BlindDown, 'eltNew_'+elt.id.to_s)+
39
+ visual_effect(:BlindDown, 'eltSubsClose_'+elt.id.to_s) },
40
+ { :href => url_for(:controller => 'elt', :action => 'new', :id => @elt)}) %>
41
+ </span>
42
+