mirror of
https://github.com/TracksApp/tracks.git
synced 2026-01-30 20:55:17 +01:00
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:
parent
bc978622e7
commit
1d29f43785
21 changed files with 270 additions and 2 deletions
50
tracks/app/controllers/note_controller.rb
Normal file
50
tracks/app/controllers/note_controller.rb
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
2
tracks/app/helpers/note_helper.rb
Normal file
2
tracks/app/helpers/note_helper.rb
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
module NoteHelper
|
||||
end
|
||||
13
tracks/app/models/note.rb
Normal file
13
tracks/app/models/note.rb
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
6
tracks/app/views/note/_note_edit_form.rhtml
Normal file
6
tracks/app/views/note/_note_edit_form.rhtml
Normal 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 %>
|
||||
33
tracks/app/views/note/_notes.rhtml
Normal file
33
tracks/app/views/note/_notes.rhtml
Normal 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}\'?" ) + " "%><%= 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" ) %> |
|
||||
Created: <%= format_date(note.created_at) %>
|
||||
<% if note.updated_at? -%>
|
||||
| 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 -%>
|
||||
6
tracks/app/views/note/_notes_summary.rhtml
Normal file
6
tracks/app/views/note/_notes_summary.rhtml
Normal 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" ) %>
|
||||
<%= textilize(truncate(note.body, 50, "...")) %>
|
||||
</div>
|
||||
<% note = nil -%>
|
||||
7
tracks/app/views/note/index.rhtml
Normal file
7
tracks/app/views/note/index.rhtml
Normal 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>
|
||||
5
tracks/app/views/note/show.rhtml
Normal file
5
tracks/app/views/note/show.rhtml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<div id="display_box_projects">
|
||||
<div class="contexts" id="note-<%= @note.id %>-wrapper">
|
||||
<%= render_partial "notes", @note %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
@ -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'
|
||||
) ;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
5
tracks/test/fixtures/notes.yml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||
first_notes:
|
||||
id: 1
|
||||
another_notes:
|
||||
id: 2
|
||||
18
tracks/test/functional/note_controller_test.rb
Normal file
18
tracks/test/functional/note_controller_test.rb
Normal 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
|
||||
14
tracks/test/unit/notes_test.rb
Normal file
14
tracks/test/unit/notes_test.rb
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue