diff --git a/tracks/app/controllers/note_controller.rb b/tracks/app/controllers/note_controller.rb
new file mode 100644
index 00000000..0656ebd9
--- /dev/null
+++ b/tracks/app/controllers/note_controller.rb
@@ -0,0 +1,50 @@
+class NoteController < ApplicationController
+
+ layout "standard"
+
+ def index
+ @all_notes = Note.list_all
+ @page_title = "TRACKS::All notes"
+ end
+
+ def show
+ @note = Note.find(@params[:id])
+ @page_title = "TRACKS::Note " + @note.id.to_s
+ end
+
+ # Add a new note to this project
+ #
+ def add_note
+
+ note = Note.new
+ note.attributes = @params["new_note"]
+
+ if note.save
+ render_partial 'notes_summary', note
+ else
+ render_text ""
+ end
+ end
+
+ def destroy_note
+ note = Note.find_by_id(@params[:id])
+ if note.destroy
+ render_text ""
+ else
+ flash["warning"] = "Couldn't delete note \"#{note.id.to_s}\""
+ render_text ""
+ end
+ end
+
+ def update_note
+ note = Note.find_by_id(@params[:id])
+ note.attributes = @params["note"]
+ if note.save
+ render_partial 'notes', note
+ else
+ flash["warning"] = "Couldn't update note \"#{note.id.to_s}\""
+ render_text ""
+ end
+ end
+
+end
diff --git a/tracks/app/controllers/project_controller.rb b/tracks/app/controllers/project_controller.rb
index 6eb168c2..21eccdd5 100644
--- a/tracks/app/controllers/project_controller.rb
+++ b/tracks/app/controllers/project_controller.rb
@@ -141,6 +141,7 @@ class ProjectController < ApplicationController
render_partial 'show_items', item
end
+
# Methods for changing the sort order of the projects in the list
#
def move_up
diff --git a/tracks/app/helpers/note_helper.rb b/tracks/app/helpers/note_helper.rb
new file mode 100644
index 00000000..d27337d4
--- /dev/null
+++ b/tracks/app/helpers/note_helper.rb
@@ -0,0 +1,2 @@
+module NoteHelper
+end
diff --git a/tracks/app/models/note.rb b/tracks/app/models/note.rb
new file mode 100644
index 00000000..115ae51b
--- /dev/null
+++ b/tracks/app/models/note.rb
@@ -0,0 +1,13 @@
+class Note < ActiveRecord::Base
+
+ belongs_to :project
+
+ def self.list_all
+ find(:all, :order => "created_at DESC")
+ end
+
+ def self.list_of(project_id)
+ find(:all, :conditions => [ "project_id = ?" , project_id ])
+ end
+
+end
diff --git a/tracks/app/models/project.rb b/tracks/app/models/project.rb
index 5b68d4ff..a3b4d55f 100644
--- a/tracks/app/models/project.rb
+++ b/tracks/app/models/project.rb
@@ -1,6 +1,7 @@
class Project < ActiveRecord::Base
has_many :todo, :dependent => true
+ has_many :note
acts_as_list
# Project name must not be empty
diff --git a/tracks/app/views/layouts/standard.rhtml b/tracks/app/views/layouts/standard.rhtml
index 0175a569..0edb603f 100644
--- a/tracks/app/views/layouts/standard.rhtml
+++ b/tracks/app/views/layouts/standard.rhtml
@@ -28,6 +28,7 @@
<%= link_to( "Contexts", {:controller => "context", :action => "list"}, {:accesskey=>"c", :title=>"Contexts AccessKey: Alt+C"} ) %>
<%= link_to( "Projects", {:controller => "project", :action => "list"}, {:accesskey=>"p", :title=>"Projects AccessKey: Alt+P"} ) %>
<%= link_to( "Completed", {:controller => "todo", :action => "completed"}, {:accesskey=>"d", :title=>"Completed AccessKey: Alt+D"} ) %>
+ <%= link_to( "Notes", {:controller => "note", :action => "index"}, :title => "Show all notes" ) %>
Show
Hide
<%= link_to("RSS ", {:controller => "feed", :action => "na_feed", :name => "#{@session['user']['login']}", :token => "#{@session['user']['word']}"}, :title => "Subscribe to an RSS feed of your next actions" ) %>
diff --git a/tracks/app/views/note/_note_edit_form.rhtml b/tracks/app/views/note/_note_edit_form.rhtml
new file mode 100644
index 00000000..49ae4deb
--- /dev/null
+++ b/tracks/app/views/note/_note_edit_form.rhtml
@@ -0,0 +1,6 @@
+<% @note = note_edit_form %>
+<%= hidden_field( "note", "project_id" ) %>
+<%= text_area( "note", "body", "cols" => 70, "rows" => 15, "tabindex" => 1 ) %>
+
+
+<% @note = nil %>
\ No newline at end of file
diff --git a/tracks/app/views/note/_notes.rhtml b/tracks/app/views/note/_notes.rhtml
new file mode 100644
index 00000000..4fb0b5a0
--- /dev/null
+++ b/tracks/app/views/note/_notes.rhtml
@@ -0,0 +1,33 @@
+<% note = notes -%>
+
+
<%= link_to("Note #{note.id.to_s}", {:action => "show", :id => note.id}, :title => "Show note #{note.id.to_s}" ) %>
+
+
+ <%= textilize(note.body) %>
+
+
+
+
+
+ <%= form_remote_tag :url => { :action => 'update_note', :id => note.id },
+ :html => { :id => "form-note-#{note.id}", :class => "inline-form" },
+ :update => "note-#{note.id}-container",
+ :complete => "new Effect.appear('note-#{note.id}-container');" %>
+ <%= render_partial "note_edit_form", note %>
+ <%= end_form_tag %>
+
+
+
+<% note = nil -%>
\ No newline at end of file
diff --git a/tracks/app/views/note/_notes_summary.rhtml b/tracks/app/views/note/_notes_summary.rhtml
new file mode 100644
index 00000000..50ad67a2
--- /dev/null
+++ b/tracks/app/views/note/_notes_summary.rhtml
@@ -0,0 +1,6 @@
+<% note = notes_summary -%>
+
+<%= link_to(image_tag("blank"), {:controller => "note", :action => "show", :id => note.id}, :title => "Show note", :class => "show_notes" ) %>
+<%= textilize(truncate(note.body, 50, "...")) %>
+
+<% note = nil -%>
\ No newline at end of file
diff --git a/tracks/app/views/note/index.rhtml b/tracks/app/views/note/index.rhtml
new file mode 100644
index 00000000..9638074c
--- /dev/null
+++ b/tracks/app/views/note/index.rhtml
@@ -0,0 +1,7 @@
+
+ <% for notes in @all_notes -%>
+
+ <%= render_partial "notes", notes %>
+
+ <% end -%>
+
\ No newline at end of file
diff --git a/tracks/app/views/note/show.rhtml b/tracks/app/views/note/show.rhtml
new file mode 100644
index 00000000..5a350a1a
--- /dev/null
+++ b/tracks/app/views/note/show.rhtml
@@ -0,0 +1,5 @@
+
+
+ <%= render_partial "notes", @note %>
+
+
\ No newline at end of file
diff --git a/tracks/app/views/project/show.rhtml b/tracks/app/views/project/show.rhtml
index cf7b22b0..2afad4a3 100644
--- a/tracks/app/views/project/show.rhtml
+++ b/tracks/app/views/project/show.rhtml
@@ -33,6 +33,35 @@
+
+<% @notes = Note.list_of(@project.id) -%>
+
+
+
+
Notes
+ <% for note in @notes -%>
+ <%= render_partial "note/notes_summary", note %>
+ <% end -%>
+
+
+
+
+<%= link_to_function( "Add a note",
+ "Element.toggle('new-note'); Form.focusFirstElement('form-new-note');") %>
+
+
+<%= form_remote_tag :url => { :controller => "note", :action => "add_note" },
+ :update => "notes",
+ :position => "bottom",
+ :complete => "new Effect.Highlight('notes');",
+ :html => {:id=>'form-new-note', :class => 'inline-form'} %>
+<%= hidden_field( "new_note", "project_id", "value" => "#{@project.id}" ) %>
+<%= text_area( "new_note", "body", "cols" => 50, "rows" => 3, "tabindex" => 1 ) %>
+
+
+<%= end_form_tag %>
+
+
diff --git a/tracks/config/routes.rb b/tracks/config/routes.rb
index cbee3442..8a52cb7d 100644
--- a/tracks/config/routes.rb
+++ b/tracks/config/routes.rb
@@ -37,6 +37,12 @@ ActionController::Routing::Routes.draw do |map|
map.connect 'project/:name', :controller => 'project', :action => 'show'
map.connect 'project/:id', :controller => 'project', :action => 'show'
+ # Notes Routes
+ map.connect 'note/add_note', :controller => 'note', :action => 'add_note'
+ map.connect 'note/update_note/:id', :controller => 'note', :action => 'update_note', :id => 'id'
+ map.connect 'note/:id', :controller => 'note', :action => 'show', :id => 'id'
+ map.connect 'notes', :controller => 'note', :action => 'index'
+
# Feed Routes
map.connect 'feed/:action/:name/:user', :controller => 'feed'
diff --git a/tracks/db/tracks_1.0.3_mysql.sql b/tracks/db/tracks_1.0.3_mysql.sql
index b2fa2f86..02696ea6 100644
--- a/tracks/db/tracks_1.0.3_mysql.sql
+++ b/tracks/db/tracks_1.0.3_mysql.sql
@@ -64,4 +64,17 @@ CREATE TABLE `users` (
) TYPE=MyISAM;
+-- Dump of table notes
+-- ------------------------------------------------------------
+
+CREATE TABLE `notes` (
+ `id` int(11) NOT NULL auto_increment,
+ `project_id` int(11) NOT NULL default '0',
+ `body` text,
+ `created_at` datetime NOT NULL default '0000-00-00 00:00:00',
+ `updated_at` datetime default '0000-00-00 00:00:00',
+ PRIMARY KEY (`id`)
+) TYPE=MyISAM;
+
+
diff --git a/tracks/db/tracks_1.0.3_postgres.sql b/tracks/db/tracks_1.0.3_postgres.sql
index 8b0560d5..c610810e 100644
--- a/tracks/db/tracks_1.0.3_postgres.sql
+++ b/tracks/db/tracks_1.0.3_postgres.sql
@@ -53,4 +53,16 @@ create table users (
);
-- Set the sequence to the proper value
-select setval('users_id_seq', (select max(id) from users));
\ No newline at end of file
+select setval('users_id_seq', (select max(id) from users));
+
+create table notes (
+ id serial not null,
+ project_id int not null default 0,
+ body text,
+ created_at timestamp default null,
+ updated_at timestamp default null,
+ primary key (id)
+);
+
+-- Set the sequence to the proper value
+select setval('notes_id_seq', (select max(id) from notes));
\ No newline at end of file
diff --git a/tracks/db/tracks_1.0.3_sqlite.sql b/tracks/db/tracks_1.0.3_sqlite.sql
index b613ced1..c75d23d9 100644
--- a/tracks/db/tracks_1.0.3_sqlite.sql
+++ b/tracks/db/tracks_1.0.3_sqlite.sql
@@ -52,3 +52,15 @@ CREATE TABLE 'users' (
'word' varchar(255) default NULL,
'is_admin' tinyint(4) NOT NULL default '0'
) ;
+
+-- Dump of table notes
+-- ------------------------------------------------------------
+
+CREATE TABLE 'notes' (
+ 'id' INTEGER PRIMARY KEY,
+ 'project_id' int(11) NOT NULL default '0',
+ 'body' text,
+ 'created_at' datetime NOT NULL default '0000-00-00 00:00:00',
+ 'updated_at' datetime default '0000-00-00 00:00:00'
+) ;
+
diff --git a/tracks/doc/CHANGELOG b/tracks/doc/CHANGELOG
index f09af8e2..7c38b49e 100644
--- a/tracks/doc/CHANGELOG
+++ b/tracks/doc/CHANGELOG
@@ -13,6 +13,12 @@ Trac (for bug reports and feature requests): http://dev.rousette.org.uk/report/6
Wiki (deprecated - please use Trac): http://www.rousette.org.uk/projects/wiki/
+== Version 1.04
+
+1. Tidied up the interface a bit, fixing mistakes in the wording.
+2. The number of actions reported is now correctly pluralized depending on the number of actions (e.g. 1 action, 2 actions).
+3. Added a Note model and notes database table. Notes have their own interface (/notes lists them all, and /note/1 shows note id 1), but they are displayed on the /project/show/[name] page. For now, notes belong to a particular project, and are added from the /project/show/[name] pages. You can delete and edit notes either from the /notes page or from the /note/[id] page. Notes use Textile/Markdown formatting.
+
== Version 1.03
13. All the adding, updating, deleting and marking actions done is performed using Ajax, so happens without needing to refresh the page.
diff --git a/tracks/public/stylesheets/standard.css b/tracks/public/stylesheets/standard.css
index 2fefbf20..64cecd38 100644
--- a/tracks/public/stylesheets/standard.css
+++ b/tracks/public/stylesheets/standard.css
@@ -156,7 +156,6 @@ a.refresh, a.refresh:link, a.refresh:active {color: #57A620;}
margin-top: 20px;
width: 313px;
padding: 0px 15px 0px 15px;
- /* border: 1px solid #999; */
}
#input_box h2 {
@@ -227,6 +226,35 @@ div.big-box, div.big-box a, div.big-box a:hover {
list-style-type: decimal;
margin-left: 5px;
}
+
+/* The notes for the project */
+
+div.note_wrapper {
+ margin: 3px;
+ padding: 2px;
+ }
+
+div.note_wrapper p {
+ display: inline;
+ }
+
+div.note_footer {
+ border-top: 1px solid #999;
+ padding-top: 3px;
+ font-style: italic;
+ font-size: 0.9em;
+ color: #666;
+ }
+
+div.note_footer a, div.note_footer a:hover {
+ border-top: none;
+ padding-top: 0px;
+ vertical-align: middle;
+ background-color: transparent;
+ }
+
+a.footer_link {color: #cc3334; font-style: normal;}
+a.footer_link:hover {color: #fff; background-color: #cc3334 !important;}
/* The alert box notifications */
.confirmation {
diff --git a/tracks/test/fixtures/notes.yml b/tracks/test/fixtures/notes.yml
new file mode 100644
index 00000000..cce14437
--- /dev/null
+++ b/tracks/test/fixtures/notes.yml
@@ -0,0 +1,5 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+first_notes:
+ id: 1
+another_notes:
+ id: 2
diff --git a/tracks/test/functional/note_controller_test.rb b/tracks/test/functional/note_controller_test.rb
new file mode 100644
index 00000000..7a398cdf
--- /dev/null
+++ b/tracks/test/functional/note_controller_test.rb
@@ -0,0 +1,18 @@
+require File.dirname(__FILE__) + '/../test_helper'
+require 'note_controller'
+
+# Re-raise errors caught by the controller.
+class NoteController; def rescue_action(e) raise e end; end
+
+class NoteControllerTest < Test::Unit::TestCase
+ def setup
+ @controller = NoteController.new
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ end
+
+ # Replace this with your real tests.
+ def test_truth
+ assert true
+ end
+end
diff --git a/tracks/test/unit/notes_test.rb b/tracks/test/unit/notes_test.rb
new file mode 100644
index 00000000..cc9bc619
--- /dev/null
+++ b/tracks/test/unit/notes_test.rb
@@ -0,0 +1,14 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class NotesTest < Test::Unit::TestCase
+ fixtures :notes
+
+ def setup
+ @notes = Notes.find(1)
+ end
+
+ # Replace this with your real tests.
+ def test_truth
+ assert_kind_of Notes, @notes
+ end
+end