diff options
-rw-r--r-- | app/controllers/comment_controller.rb | 54 | ||||
-rw-r--r-- | app/helpers/link_to_helper.rb | 5 | ||||
-rw-r--r-- | app/models/comment.rb (renamed from app/models/comments.rb) | 6 | ||||
-rw-r--r-- | app/models/info_request.rb | 25 | ||||
-rw-r--r-- | app/models/info_request_event.rb | 45 | ||||
-rw-r--r-- | app/views/admin/timeline.rhtml | 2 | ||||
-rw-r--r-- | app/views/admin_request/show.rhtml | 24 | ||||
-rw-r--r-- | app/views/comment/_comment_form.rhtml | 11 | ||||
-rw-r--r-- | app/views/comment/new.rhtml | 7 | ||||
-rw-r--r-- | app/views/comment/preview.rhtml | 24 | ||||
-rw-r--r-- | app/views/general/search.rhtml | 2 | ||||
-rw-r--r-- | app/views/request/_correspondence.rhtml | 12 | ||||
-rw-r--r-- | app/views/request/_request_listing_via_event.rhtml | 4 | ||||
-rw-r--r-- | app/views/request/show.rhtml | 6 | ||||
-rw-r--r-- | app/views/track_mailer/event_digest.rhtml | 5 | ||||
-rw-r--r-- | config/routes.rb | 6 | ||||
-rw-r--r-- | db/migrate/062_add_comments.rb | 32 | ||||
-rw-r--r-- | db/schema.rb | 1 | ||||
-rw-r--r-- | public/stylesheets/main.css | 12 | ||||
-rw-r--r-- | todo.txt | 34 |
20 files changed, 261 insertions, 56 deletions
diff --git a/app/controllers/comment_controller.rb b/app/controllers/comment_controller.rb new file mode 100644 index 000000000..d852ffe17 --- /dev/null +++ b/app/controllers/comment_controller.rb @@ -0,0 +1,54 @@ +# app/controllers/comment_controller.rb: +# Show annotations upon a request or other object. +# +# Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved. +# Email: francis@mysociety.org; WWW: http://www.mysociety.org/ +# +# $Id: comment_controller.rb,v 1.1 2008-08-13 01:39:41 francis Exp $ + +class CommentController < ApplicationController + + def new + if params[:type] == 'request' + @info_request = InfoRequest.find_by_url_title(params[:url_title]) + @comment = Comment.new(params[:comment].merge({ + :comment_type => 'request', + :user => @user + })) + + else + raise "Unknown type " + params[:type] + end + + # XXX this check should theoretically be a validation rule in the model + #@existing_comment = Comment.find_by_existing_comment(params[:info_request][:title], params[:info_request][:public_body_id], params[:outgoing_message][:body]) + + # See if values were valid or not + if !@comment.valid? || params[:reedit] + render :action => 'new' + return + end + + # Show preview page, if it is a preview + if params[:preview].to_i == 1 + render :action => 'preview' + return + end + + if authenticated?( + :web => "To post your annotation", + :email => "Then your annotation to " + @info_request.title + " will be posted.", + :email_subject => "Confirm your annotation to " + @info_request.title + ) + @info_request.add_comment(params[:comment][:body], authenticated_user) + # This automatically saves dependent objects in the same transaction + @info_request.save! + flash[:notice] = "Thank you for making an annotation!" + redirect_to request_url(@info_request) + else + # do nothing - as "authenticated?" has done the redirect to signin page for us + end + end + +end + diff --git a/app/helpers/link_to_helper.rb b/app/helpers/link_to_helper.rb index b255885cb..96e489e26 100644 --- a/app/helpers/link_to_helper.rb +++ b/app/helpers/link_to_helper.rb @@ -5,7 +5,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: link_to_helper.rb,v 1.35 2008-08-07 00:24:51 francis Exp $ +# $Id: link_to_helper.rb,v 1.36 2008-08-13 01:39:41 francis Exp $ module LinkToHelper @@ -35,6 +35,9 @@ module LinkToHelper def outgoing_message_url(outgoing_message) return request_url(outgoing_message.info_request)+"#outgoing-"+outgoing_message.id.to_s end + def comment_url(comment) + return request_url(comment.info_request)+"#comment-"+comment.id.to_s + end # Public bodies def public_body_url(public_body) diff --git a/app/models/comments.rb b/app/models/comment.rb index 00e58df55..c82bb64ce 100644 --- a/app/models/comments.rb +++ b/app/models/comment.rb @@ -19,11 +19,11 @@ # Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: comments.rb,v 1.1 2008-08-09 15:19:01 francis Exp $ +# $Id: comment.rb,v 1.1 2008-08-13 01:39:41 francis Exp $ -class Comments < ActiveRecord::Base +class Comment < ActiveRecord::Base belongs_to :user - validates_presence_of :user + #validates_presence_of :user # breaks during construction of new ones :( validates_inclusion_of :comment_type, :in => [ 'request' ] belongs_to :info_request diff --git a/app/models/info_request.rb b/app/models/info_request.rb index da82f8ab4..78b9655d0 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -23,7 +23,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: info_request.rb,v 1.126 2008-08-09 15:19:01 francis Exp $ +# $Id: info_request.rb,v 1.127 2008-08-13 01:39:41 francis Exp $ require 'digest/sha1' require File.join(File.dirname(__FILE__),'../../vendor/plugins/acts_as_xapian/lib/acts_as_xapian') @@ -43,6 +43,7 @@ class InfoRequest < ActiveRecord::Base has_many :info_request_events, :order => 'created_at' has_many :user_info_request_sent_alerts has_many :track_things, :order => 'created_at desc' + has_many :comments, :order => 'created_at' # user described state (also update in info_request_event, admin_request/edit.rhtml) validates_inclusion_of :described_state, :in => [ @@ -259,6 +260,22 @@ public RequestMailer.deliver_new_response(self, incoming_message) end + # An annotation (comment) is made + def add_comment(body, user) + comment = Comment.new + + ActiveRecord::Base.transaction do + comment.body = body + comment.user = user + comment.comment_type = 'request' + comment.info_request = self + comment.save! + + self.log_event("comment", { :comment_id => comment.id }) + self.save! + end + end + # The "holding pen" is a special request which stores incoming emails whose # destination request is unknown. def InfoRequest.holding_pen_request @@ -275,8 +292,8 @@ public om = OutgoingMessage.new({ :status => 'ready', :message_type => 'initial_request', - :body => 'This is the holding pen request. It shows responses that were sent to invalid addresses, and need moving to the correct request by an adminstrator.', - :last_sent_at => Time.now() + :body => 'this is the holding pen request. it shows responses that were sent to invalid addresses, and need moving to the correct request by an adminstrator.', + :last_sent_at => time.now() }) ir.outgoing_messages << om om.info_request = ir @@ -287,7 +304,7 @@ public return ir end - # Change status, including for last event for later historical purposes + # change status, including for last event for later historical purposes def set_described_state(new_state) ActiveRecord::Base.transaction do self.awaiting_description = false diff --git a/app/models/info_request_event.rb b/app/models/info_request_event.rb index 4eff38554..eb1cb98d8 100644 --- a/app/models/info_request_event.rb +++ b/app/models/info_request_event.rb @@ -20,7 +20,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: info_request_event.rb,v 1.50 2008-08-09 15:19:01 francis Exp $ +# $Id: info_request_event.rb,v 1.51 2008-08-13 01:39:41 francis Exp $ class InfoRequestEvent < ActiveRecord::Base belongs_to :info_request @@ -28,6 +28,7 @@ class InfoRequestEvent < ActiveRecord::Base belongs_to :outgoing_message belongs_to :incoming_message + belongs_to :comment has_many :user_info_request_sent_alerts has_many :track_things_sent_emails @@ -41,7 +42,8 @@ class InfoRequestEvent < ActiveRecord::Base 'edit_outgoing', # outgoing message edited in admin interface 'destroy_incoming', # deleted an incoming message 'manual', # you did something in the db by hand - 'response' + 'response', + 'comment' ] # user described state (also update in info_request) @@ -69,7 +71,7 @@ class InfoRequestEvent < ActiveRecord::Base [ :variety, 'V', "variety" ] ], :if => :indexed_by_search, - :eager_load => [ :incoming_message, :outgoing_message, { :info_request => [ :user, :public_body ] } ] + :eager_load => [ :incoming_message, :outgoing_message, :comment, { :info_request => [ :user, :public_body ] } ] def requested_by self.info_request.user.url_name @@ -99,6 +101,8 @@ class InfoRequestEvent < ActiveRecord::Base text = text + self.outgoing_message.body_without_salutation + "\n\n" elsif self.event_type == 'response' text = text + self.incoming_message.get_text_for_indexing + "\n\n" + elsif self.event_type == 'comment' + text = text + self.comment.body + "\n\n" else # nothing end @@ -111,7 +115,7 @@ class InfoRequestEvent < ActiveRecord::Base return '' end def indexed_by_search - if ['sent', 'followup_sent', 'response'].include?(self.event_type) + if ['sent', 'followup_sent', 'response', 'comment'].include?(self.event_type) if info_request.prominence == 'backpage' return false end @@ -134,42 +138,15 @@ class InfoRequestEvent < ActiveRecord::Base if not params[:outgoing_message_id].nil? self.outgoing_message_id = params[:outgoing_message_id] end + if not params[:comment_id].nil? + self.comment_id = params[:comment_id] + end self.params_yaml = params.to_yaml end def params YAML.load(self.params_yaml) end - # Find related incoming message - # XXX search for the find below and call this function more instead - # XXX deprecated, remove it - def incoming_message_via_params - if not ['response'].include?(self.event_type) - return nil - end - - if not self.params[:incoming_message_id] - raise "internal error, no incoming message id for response event" - end - - return IncomingMessage.find(self.params[:incoming_message_id].to_i) - end - - # Find related outgoing message - # XXX search for the find below and call this function more instead - # XXX deprecated, remove it - def outgoing_message_via_params - if not [ 'edit_outgoing', 'sent', 'resent', 'followup_sent' ].include?(self.event_type) - return nil - end - - if not self.params[:outgoing_message_id] - raise "internal error, no outgoing message id for event type which expected one" - end - - return OutgoingMessage.find(self.params[:outgoing_message_id].to_i) - end - # Display version of status def display_status if incoming_message.nil? diff --git a/app/views/admin/timeline.rhtml b/app/views/admin/timeline.rhtml index d7680b994..f24d0be4b 100644 --- a/app/views/admin/timeline.rhtml +++ b/app/views/admin/timeline.rhtml @@ -62,6 +62,8 @@ had the request resent to <%=h event.params[:email]%> at <%=h event.info_request.public_body.name %>. <% elsif event.event_type == 'followup_sent' %> had a follow up message sent to <%=h event.info_request.public_body.name %>. + <% elsif event.event_type == 'comment' %> + had an annotation posted by <%=h event.comment.user.name %>. <% else %> had '<%=event.event_type%>' done to it, parameters <%=h event.params_yaml%>. <% end %> diff --git a/app/views/admin_request/show.rhtml b/app/views/admin_request/show.rhtml index 91b0646a4..d5356dd10 100644 --- a/app/views/admin_request/show.rhtml +++ b/app/views/admin_request/show.rhtml @@ -109,3 +109,27 @@ <% end %> </table> +<h2>Comments</h2> + +<table> + <tr> + <th>Id</th> + <th>Posted by</th> + <% for column in Comment.content_columns %> + <th><%= column.human_name %></th> + <% end %> + <!--<th>Actions</th>--> + </tr> + +<% for comment in @info_request.comments.find(:all, :order => 'created_at') %> + <tr class="<%= cycle('odd', 'even') %>"> + <td><%=h comment.id %></td> + <td><%= user_admin_link(comment.user) %></td> + <% for column in Comment.content_columns.map { |c| c.name } %> + <td><%=h comment.send(column) %></td> + <% end %> + </tr> +<% end %> +</table> + + diff --git a/app/views/comment/_comment_form.rhtml b/app/views/comment/_comment_form.rhtml index d1ce0a61a..9b2f251cb 100644 --- a/app/views/comment/_comment_form.rhtml +++ b/app/views/comment/_comment_form.rhtml @@ -1,6 +1,10 @@ -<% form_for(:comment, @comment) do |o| %> +<% form_for(:comment, @comment, :url => { :controller => "comment", :action => "new", :type => "request" }, :html => { :id => 'comment_form' } ) do |f| %> <p> - <%= o.text_area :body, :rows => 10, :cols => 55 %> + <%= f.text_area :body, :rows => 10, :cols => 55 %> + </p> + + <p> + <script type="text/javascript">document.write('<input name="doSpell" type="button" value="Check spelling" onClick="openSpellChecker(document.getElementById(\'comment_form\').body);"/> (optional)')</script> </p> <p> @@ -9,7 +13,8 @@ <p> <%= hidden_field_tag 'submitted_comment', 1 %> - <%= submit_tag "Add public annotation" %> + <%= hidden_field_tag 'preview', 1 %> + <%= submit_tag "Preview your annotation" %> </p> <% end %> diff --git a/app/views/comment/new.rhtml b/app/views/comment/new.rhtml new file mode 100644 index 000000000..22e260c1b --- /dev/null +++ b/app/views/comment/new.rhtml @@ -0,0 +1,7 @@ +<% @title = "Make an annotation on '" + h(@info_request.title) + "'" %> + +<%= foi_error_messages_for :comment %> + +<h1>Add an annotation</h1> + +<%= render :partial => 'comment/comment_form', :locals => { } %> diff --git a/app/views/comment/preview.rhtml b/app/views/comment/preview.rhtml new file mode 100644 index 000000000..39f99e889 --- /dev/null +++ b/app/views/comment/preview.rhtml @@ -0,0 +1,24 @@ +<% @title = "Preview new annotation on '" + h(@info_request.title) + "'" %> + +<% form_for(:comment, @comment, :html => { :id => 'preview_form' }, :url => { :controller => "comment", :action => "new", :type => "request" } ) do |f| %> + + <h1>Now preview your annotation</h1> + + <p class="comment_in_request"> + <%= @comment.get_body_for_html_display %> + <%= f.hidden_field(:body) %> + </p> + + <p> + Your name and annotation will appear in <strong>search engines</strong>. + + <p> + <%= hidden_field_tag(:submitted_comment, 1) %> + <%= hidden_field_tag(:preview, 0 ) %> + <%= submit_tag "Re-edit this annotation", :name => 'reedit' %> + <%= submit_tag "Post annotation", :name => 'submit' %> + </p> + +<% end %> + + diff --git a/app/views/general/search.rhtml b/app/views/general/search.rhtml index 01a52fe99..6ecebcdf1 100644 --- a/app/views/general/search.rhtml +++ b/app/views/general/search.rhtml @@ -89,7 +89,7 @@ <li>Enter words that you want to find separated by spaces, e.g. <strong>climbing lane</strong></li> <li>Use OR (in capital letters) where you don't mind which word, e.g. <strong>commons OR lords</strong> <li>Use quotes when you want to find an exact phrase, e.g. <strong>"Liverpool City Council"</strong> - <li><strong>variety:</strong> with value sent, followup_sent, response, authority or user to select type of thing to search for. + <li><strong>variety:</strong> with value sent, followup_sent, response, comment, authority or user to select type of thing to search for. <li>Type <strong>status:</strong> to select based on the status or historical status of the request, see table below. <li><strong>requested_from:home_office</strong> to restrict to requests from the <%= link_to "Home Office", show_public_body_url(:url_name => 'home_office') %>, typing the name as in the URL. <li><strong>requested_by:julian_todd</strong> to restrict to requests made by <%= link_to "Julian Todd", show_user_url(:url_name => 'julian_todd') %>, typing the name as in the URL. diff --git a/app/views/request/_correspondence.rhtml b/app/views/request/_correspondence.rhtml index c15d34b6f..cb58756bf 100644 --- a/app/views/request/_correspondence.rhtml +++ b/app/views/request/_correspondence.rhtml @@ -68,6 +68,18 @@ elsif info_request_event.event_type == 'sent' || info_request_event.event_type = to <%= public_body_link(@info_request.public_body) %> again<% if @info_request.get_previous_email_sent_to(info_request_event) != info_request_event.params[:email] %>, using a new contact address<% end %>. </p> </div> +<% elsif info_request_event.event_type == 'comment' + comment = info_request_event.comment +%> + <div class="comment_in_request" id="comment-<%=comment.id.to_s%>"> + <p class=""> + On <%= simple_date(info_request_event.created_at) %>, + <%= user_link(comment.user) %> added an annotation: + </p> + <p> + "<%= comment.get_body_for_html_display %>" + </p> + </div> <% end diff --git a/app/views/request/_request_listing_via_event.rhtml b/app/views/request/_request_listing_via_event.rhtml index fae19bcfa..fd30a5dc9 100644 --- a/app/views/request/_request_listing_via_event.rhtml +++ b/app/views/request/_request_listing_via_event.rhtml @@ -8,6 +8,8 @@ end %> <%= link_to highlight_words(info_request.title, @highlight_words), incoming_message_url(event.incoming_message) %> <% elsif not event.outgoing_message.nil? and event.event_type == 'followup_sent' %> <%= link_to highlight_words(info_request.title, @highlight_words), outgoing_message_url(event.outgoing_message) %> + <% elsif not event.comment.nil? %> + <%= link_to highlight_words(info_request.title, @highlight_words), comment_url(event.comment) %> <% else %> <%= link_to highlight_words(info_request.title, @highlight_words), request_url(info_request) %> <% end %> @@ -36,6 +38,8 @@ end %> <% end %> by <%= public_body_link(info_request.public_body) %> to <%= user_link(info_request.user) %> + <% elsif event.event_type == 'comment' %> + Annotation by <%= user_link(event.comment.user) %> <% else %> <% raise "unknown event type indexed " + event.event_type %> <% end %> diff --git a/app/views/request/show.rhtml b/app/views/request/show.rhtml index e5ac5b008..e10550022 100644 --- a/app/views/request/show.rhtml +++ b/app/views/request/show.rhtml @@ -99,7 +99,6 @@ <% end %> <!-- - <div id="comment_form"> <h2>Add an annotation</h2> @@ -125,7 +124,7 @@ <% if [ 'successful', 'partially_successful' ].include?(@info_request.described_state) %> <li> <strong>Summarise</strong> the content of any information returned. </li> <li> Say how you've <strong>used the information</strong>, with links if possible. </li> - <li> <strong>Thank</strong> the local authority or <%=h @info_request.user.name %>. </li> + <li> <strong>Thank</strong> the public authority or <%=h @info_request.user.name %>. </li> <% end %> <% if [ 'partially_successful' ].include?(@info_request.described_state) %> <li> Suggest how the requester can find the <strong>rest of the information</strong>. </li> @@ -148,7 +147,8 @@ </ul> <%= render :partial => 'comment/comment_form', :locals => { } %> - </div> --> + </div> + --> </div> diff --git a/app/views/track_mailer/event_digest.rhtml b/app/views/track_mailer/event_digest.rhtml index 83ce6d516..a6b4a2729 100644 --- a/app/views/track_mailer/event_digest.rhtml +++ b/app/views/track_mailer/event_digest.rhtml @@ -24,8 +24,11 @@ main_text += event.info_request.user.name + " sent a follow up message to " + event.info_request.public_body.name elsif event.event_type == 'sent' # this is unlikely to happen in real life, but happens in the test code - url = main_url(request_url(event.info_request))+"#outgoing-"+event.outgoing_message.id.to_s + url = main_url(outgoing_message_url(event.outgoing_message)) main_text += event.info_request.user.name + " sent a request to " + event.info_request.public_body.name + elsif event.event_type == 'comment' + url = main_url(comment_url(event.comment)) + main_text += event.comment.user.name + " added an annotation" else raise "unknown type in event_digest " + event.event_type end diff --git a/config/routes.rb b/config/routes.rb index 6d26afeea..6580e0e62 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,7 +4,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: routes.rb,v 1.66 2008-07-18 22:22:59 francis Exp $ +# $Id: routes.rb,v 1.67 2008-08-13 01:39:43 francis Exp $ ActionController::Routing::Routes.draw do |map| @@ -61,6 +61,10 @@ ActionController::Routing::Routes.draw do |map| body.show_public_body "/body/:url_name", :action => 'show' end + map.with_options :controller => 'comment' do |comment| + comment.new_comment "/annotate/request/:url_title", :action => 'new', :type => 'request' + end + map.with_options :controller => 'track' do |track| # /track/ is for setting up an email alert for the item # /feed/ is a direct RSS feed of the item diff --git a/db/migrate/062_add_comments.rb b/db/migrate/062_add_comments.rb new file mode 100644 index 000000000..d523dd808 --- /dev/null +++ b/db/migrate/062_add_comments.rb @@ -0,0 +1,32 @@ +class AddComments < ActiveRecord::Migration + def self.up + create_table :comments do |t| + t.column :user_id, :integer, :null => false + t.column :comment_type, :string, :null => false, :default => "internal_error" + + t.column :info_request_id, :integer + + t.column :body, :text, :null => false + t.column :visible, :boolean, :default => true, :null => false + + t.column :created_at, :datetime, :null => false + t.column :updated_at, :datetime, :null => false + end + + if ActiveRecord::Base.connection.adapter_name == "PostgreSQL" + execute "ALTER TABLE comments ADD CONSTRAINT fk_comments_user FOREIGN KEY (user_id) REFERENCES users(id)" + + execute "ALTER TABLE comments ADD CONSTRAINT fk_comments_info_request FOREIGN KEY (info_request_id) REFERENCES info_requests(id)" + end + + add_column :info_request_events, :comment_id, :integer + if ActiveRecord::Base.connection.adapter_name == "PostgreSQL" + execute "ALTER TABLE info_request_events ADD CONSTRAINT fk_info_request_events_comment_id FOREIGN KEY (comment_id) REFERENCES comments(id)" + end + end + + def self.down + drop_table :comments + remove_column :info_request_events, :comment_id + end +end diff --git a/db/schema.rb b/db/schema.rb index b53ac9e8e..3511724da 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -48,6 +48,7 @@ ActiveRecord::Schema.define(:version => 62) do t.datetime "last_described_at" t.integer "incoming_message_id" t.integer "outgoing_message_id" + t.integer "comment_id" end create_table "info_requests", :force => true do |t| diff --git a/public/stylesheets/main.css b/public/stylesheets/main.css index 71a3f0b98..4c37c8754 100644 --- a/public/stylesheets/main.css +++ b/public/stylesheets/main.css @@ -638,6 +638,15 @@ div.correspondence h2 .event_actions { text-align: right} +div.comment_in_request +{ + width: 37em; + float: left; + padding: 0em 0em 0em 0em; + margin: 0 0 0 0; + overflow: auto; +} + /* id starts with... */ div[id|="outgoing"] { } div[id|="outgoing"] p { font-size: 0.95em;} @@ -645,6 +654,9 @@ div[id|="outgoing"] { } div[id|="incoming"] { background-color: #E7E7E7; font-family: Times New Roman, Times, serif; } div[id|="incoming"] p { font-size: 1.08em;} +div[id|="comment"] { } + div[id|="comment"] p { font-size: 1.00em;} + .correspondence_text { margin: 0 1.2em 0 0.8em; } /*.event_bubble { margin: 3em 0 0 0; font-size: 0.9em;}*/ @@ -6,22 +6,46 @@ Site move: Next ==== +Compress the emails in the database + Green box when you are classifying request is a bit too big / prominent Solicit people to tell us requests are misclassified? Search for user.name, esp. ./contact_mailer/user_message.rhtml +Sort list of email subscriptions by type, and probably alphabetically / +chronologically, and compress them a bit more somehow in vertical space. + +"Then you will be emailed whenever 'Martin Stabe' requests something or gets a +response" doesn't word wrap in confirmation email, and no full stop. + +Reply links should probably link to form rather than message +http://www.whatdotheyknow.com/request/4/response/866#show_response_followup + +Email subjects badly escaped +Subject: Confirm you want to be emailed about requests to 'HM Revenue & Customs' + Comments interleaved with body - - Allow anyone logged in to add a comment to any request. - - Add an event too - - Index it all in Xapian + grep -rin followup_sent . + - Add it to the spec fixtures - Add basic tests - - Make sure it works in email alerts - - Email people when comments on their own request + + - Test email alerts for comments - Email people subscribed to people about new comments that they make ... and likewise to requests, public bodies + - Email people when comments on their own request + - Email people when responses to their own comment, or warn them they need to sign up + + - Flag bad comments + - Delete comments from admin interface + + - Test spell checker + - Don't allow double posting + - Check CSS class/id names used in all comment HTML + - Think about the "nonsense" text a lot more + http://www.whatdotheyknow.com/request/communications_about_whatdotheyk Mask all emails from binary attachments |