Added Notes. These are added to a particular project, and displayed in summary form on /project/[name]. You can see all notes on /notes, and individual notes on /note/[id]. The latter two pages allow you to delete and edit the notes. The note body uses Textile/Markdown format.

git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@110 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
bsag 2005-06-18 13:46:03 +00:00
parent bc978622e7
commit 1d29f43785
21 changed files with 270 additions and 2 deletions

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
module NoteHelper
end

13
tracks/app/models/note.rb Normal file
View file

@ -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

View file

@ -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

View file

@ -28,6 +28,7 @@
<li><%= link_to( "Contexts", {:controller => "context", :action => "list"}, {:accesskey=>"c", :title=>"Contexts AccessKey: Alt+C"} ) %></li>
<li><%= link_to( "Projects", {:controller => "project", :action => "list"}, {:accesskey=>"p", :title=>"Projects AccessKey: Alt+P"} ) %></li>
<li><%= link_to( "Completed", {:controller => "todo", :action => "completed"}, {:accesskey=>"d", :title=>"Completed AccessKey: Alt+D"} ) %></li>
<li><%= link_to( "Notes", {:controller => "note", :action => "index"}, :title => "Show all notes" ) %></li>
<li><a href="javascript:toggleAll('notes','block')" accesskey="S" title="Show all notes AccessKey: Alt+S">Show</a></li>
<li><a href="javascript:toggleAll('notes','none')" accesskey="H" title="Show all notes AccessKey: Alt+H">Hide</a></li>
<li><%= link_to("<span class=\"feed\">RSS</span>", {:controller => "feed", :action => "na_feed", :name => "#{@session['user']['login']}", :token => "#{@session['user']['word']}"}, :title => "Subscribe to an RSS feed of your next actions" ) %></li>

View file

@ -0,0 +1,6 @@
<% @note = note_edit_form %>
<%= hidden_field( "note", "project_id" ) %>
<%= text_area( "note", "body", "cols" => 70, "rows" => 15, "tabindex" => 1 ) %>
<br /><br />
<input type="submit" value="Update" tabindex="2" />
<% @note = nil %>

View file

@ -0,0 +1,33 @@
<% note = notes -%>
<div id="note-<%= note.id.to_s %>-container">
<h2><%= link_to("Note #{note.id.to_s}", {:action => "show", :id => note.id}, :title => "Show note #{note.id.to_s}" ) %></h2>
<div id="note-<%= note.id.to_s %>">
<%= textilize(note.body) %>
<div class="note_footer">
<%= link_to_remote( image_tag("blank", :title =>"Delete this note", :class=>"delete_item"),
:update => "note-#{note.id}",
:loading => "new Effect2.Fade('note-#{note.id}-container', true)",
:complete => "Element.remove('note-#{note.id}-wrapper');",
:url => { :action => "destroy_note", :id => note.id }, :confirm => "Are you sure that you want to delete the note \'#{note.id.to_s}\'?" ) + "&nbsp;"%><%= link_to_function(image_tag( "blank", :title => "Edit item", :class=>"edit_item"),
"Element.toggle('note-#{note.id}','note-#{note.id}-edit-form'); new Effect.Appear('note-#{note.id}-edit-form'); Form.focusFirstElement('form-note-#{note.id}');" ) + " | " %>
<%= link_to("In: " + note.project.name, {:controller => "project", :action => "show", :name => urlize(note.project.name)}, :class=>"footer_link" ) %>&nbsp;|&nbsp;
Created: <%= format_date(note.created_at) %>
<% if note.updated_at? -%>
&nbsp;|&nbsp;Modified: <%= format_date(note.updated_at) %>
<% end -%>
</div>
</div><!-- [end.note.id] -->
<div id="note-<%= note.id %>-edit-form" class="edit-form" style="display:none;">
<%= 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 %>
</div><!-- [end:action-item.id-edit-form] -->
</div><!-- [end.note-note.id-container] -->
<% note = nil -%>

View file

@ -0,0 +1,6 @@
<% note = notes_summary -%>
<div class="note_wrapper">
<%= link_to(image_tag("blank"), {:controller => "note", :action => "show", :id => note.id}, :title => "Show note", :class => "show_notes" ) %>&nbsp;
<%= textilize(truncate(note.body, 50, "...")) %>
</div>
<% note = nil -%>

View file

@ -0,0 +1,7 @@
<div id="display_box_projects">
<% for notes in @all_notes -%>
<div class="contexts" id="note-<%= notes.id %>-wrapper">
<%= render_partial "notes", notes %>
</div>
<% end -%>
</div>

View file

@ -0,0 +1,5 @@
<div id="display_box_projects">
<div class="contexts" id="note-<%= @note.id %>-wrapper">
<%= render_partial "notes", @note %>
</div>
</div>

View file

@ -33,6 +33,35 @@
</div>
</div><!-- [end:contexts] -->
<!-- begin div.contexts -->
<% @notes = Note.list_of(@project.id) -%>
<div class="contexts">
<div id="notes">
<h2>Notes</h2>
<% for note in @notes -%>
<%= render_partial "note/notes_summary", note %>
<% end -%>
</div>
</div>
<!-- end div.contexts -->
<%= link_to_function( "Add a note",
"Element.toggle('new-note'); Form.focusFirstElement('form-new-note');") %>
<div id="new-note" style="display:none;">
<%= 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 ) %>
<br /><br />
<input type="submit" value="Add note" tabindex="2" />
<%= end_form_tag %>
</div>
</div><!-- [end:display_box] -->
<div id="input_box">

View file

@ -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'

View file

@ -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;

View file

@ -53,4 +53,16 @@ create table users (
);
-- Set the sequence to the proper value
select setval('users_id_seq', (select max(id) from users));
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));

View file

@ -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'
) ;

View file

@ -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.

View file

@ -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 {

5
tracks/test/fixtures/notes.yml vendored Normal file
View file

@ -0,0 +1,5 @@
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
first_notes:
id: 1
another_notes:
id: 2

View file

@ -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

View file

@ -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