motiro 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License
15
15
  along with this program; if not, write to the Free Software
16
16
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
17
  --------------------------------------------------------------------------------
18
- Motiro version 0.6.3 - March 2007
18
+ Motiro version 0.6.4 - April 2007
19
19
 
20
20
  Please refer to your preferred language README. Every text file below this
21
21
  directory is UTF-8 encoded. Please make sure to set up your reader accordingly.
@@ -15,11 +15,11 @@
15
15
  # along with this program; if not, write to the Free Software
16
16
  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
17
 
18
- class WikiController < EditionController
18
+ class WikiController < ApplicationController
19
19
 
20
20
  layout :choose_layout
21
21
 
22
- before_filter :login_required, :except => [:show, :last]
22
+ before_filter :login_required, :except => [:show, :last, :history]
23
23
  before_filter :fetch_page, :drop_crumbs
24
24
  before_filter :check_edit_access, :only => [:edit, :save]
25
25
 
@@ -75,15 +75,30 @@ class WikiController < EditionController
75
75
  render(:action => 'edit', :layout => 'application')
76
76
  end
77
77
 
78
- def do_save
79
- params[:page].delete(:original_author_id)
80
- params[:page].delete(:editors) unless current_user.can_change_editors?(@page)
78
+ def save
79
+ if params['btnSave']
80
+ really_save
81
+ else
82
+ redirect_to :controller => 'root', :action => 'index'
83
+ end
84
+ end
85
+
86
+ def show
87
+ if params[:revision]
88
+ @page = @page.revisions[params[:revision].to_i]
89
+ @page_revision_id = @page.id
90
+ end
91
+ end
92
+
93
+ def access_denied
94
+ redirect_to :controller => 'wiki', :action => 'show',
95
+ :page_name => params[:page_name]
96
+ end
97
+
98
+ private
81
99
 
82
- @page.original_author ||= current_user
83
- @page.last_editor = current_user
84
- @page.modified_at = Time.now
85
- @page.attributes = params[:page]
86
- @page.save
100
+ def really_save
101
+ @page.revise(current_user, Time.now, params[:page])
87
102
 
88
103
  if 'MainPage' == @page.name
89
104
  redirect_to :controller => 'root', :action => 'index'
@@ -91,8 +106,6 @@ class WikiController < EditionController
91
106
  redirect_to :action => 'show', :page_name => @page.name
92
107
  end
93
108
  end
94
-
95
- private
96
109
 
97
110
  def find_page(name, type)
98
111
  @real_page_provider.find_by_name(name) ||
data/app/core/version.rb CHANGED
@@ -1 +1 @@
1
- MOTIRO_VERSION = '0.6.3'
1
+ MOTIRO_VERSION = '0.6.4'
@@ -20,8 +20,6 @@ class DefaultPageProvider
20
20
  def find_by_name_and_type(name, type)
21
21
  class_name = type || 'Page'
22
22
  page = class_name.constantize.new(:name => name)
23
- page.text = WIKI_NOT_FOUND_TEXT
24
- page.text = CONGRATS_TEXT if 'MainPage' == name
25
23
  return page
26
24
  end
27
25
 
data/app/models/page.rb CHANGED
@@ -19,13 +19,35 @@ PLACE_HOLDER_TITLE = 'Insert page title here'
19
19
 
20
20
  class Page < ActiveRecord::Base
21
21
 
22
- belongs_to :last_editor, :class_name => 'User',
23
- :foreign_key => 'last_editor_id'
24
- belongs_to :original_author, :class_name => 'User',
25
- :foreign_key => 'original_author_id'
22
+ has_many :revisions, :order => 'modified_at DESC, id DESC'
23
+
24
+ def original_author
25
+ oldest(:last_editor)
26
+ end
27
+
28
+ %w{modified_at last_editor}.each do |attr|
29
+ define_method attr do
30
+ most_recent(attr)
31
+ end
32
+ end
33
+
34
+ def title
35
+ result = most_recent(:title)
36
+ return title_from_name || PLACE_HOLDER_TITLE.t if result.nil? || result.empty?
37
+ return result
38
+ end
39
+
40
+ def editors
41
+ most_recent(:editors) || ''
42
+ end
43
+
44
+ def text
45
+ most_recent(:text) ||
46
+ ('MainPage' == self.name ? CONGRATS_TEXT : WIKI_NOT_FOUND_TEXT)
47
+ end
26
48
 
27
49
  def after_initialize
28
- default('', :editors, :text, :name, :title)
50
+ default('', :name)
29
51
  default('common', :kind)
30
52
  end
31
53
 
@@ -38,7 +60,7 @@ class Page < ActiveRecord::Base
38
60
 
39
61
  def before_save
40
62
  if title == PLACE_HOLDER_TITLE.t
41
- write_attribute(:title, title_from_kind)
63
+ revisions.first.title = title_from_kind
42
64
  end
43
65
 
44
66
  write_attribute(:name, self.name)
@@ -51,29 +73,45 @@ class Page < ActiveRecord::Base
51
73
  return result
52
74
  end
53
75
 
54
- def title; title_before_type_cast; end
55
- def title_before_type_cast
56
- result = read_attribute(:title)
57
- return title_from_name || PLACE_HOLDER_TITLE.t if result.nil? || result.empty?
58
- return result
59
- end
60
-
61
- def use_parser(parser)
62
- @parser = parser
63
- end
64
-
65
76
  def is_open_to_all?
66
77
  0 == editors.strip.size
67
78
  end
68
79
 
80
+ def revise(author, time, attrs)
81
+ #TODO ugly! ugly! ugly!
82
+ if !attrs[:happens_at] && attrs['happens_at(1i)'] && attrs['happens_at(2i)'] && attrs['happens_at(3i)']
83
+ attrs[:happens_at] =
84
+ Date.new(attrs['happens_at(1i)'].to_i, attrs['happens_at(2i)'].to_i,
85
+ attrs['happens_at(3i)'].to_i)
86
+ end
87
+ unless revisions.size == 0 || original_author
88
+ revisions.last.last_editor = author
89
+ revisions.last.save
90
+ end
91
+ rev = Revision.new(:last_editor => author, :modified_at => time)
92
+ rev.editors = if author.can_change_editors?(self)
93
+ attrs[:editors]
94
+ else
95
+ revisions.first.editors
96
+ end
97
+ self.kind = attrs[:kind] if attrs[:kind]
98
+ self.happens_at = attrs[:happens_at] if attrs[:happens_at]
99
+ rev.kind, rev.happens_at = self.kind, self.happens_at
100
+ rev.title, rev.text = attrs[:title], attrs[:text]
101
+ self.revisions.unshift(rev)
102
+
103
+ save
104
+ self
105
+ end
106
+
69
107
  private
70
108
 
71
109
  def name_from_title
72
- sequence(drop_non_alpha(clean(title)).downcase.gsub(/ /, '_').camelize, 'name')
110
+ sequence(Page, drop_non_alpha(clean(title)).downcase.gsub(/ /, '_').camelize, 'name')
73
111
  end
74
112
 
75
113
  def title_from_kind
76
- sequence(kind.capitalize + ' page ', 'title')
114
+ sequence(Revision, kind.capitalize + ' page ', 'title')
77
115
  end
78
116
 
79
117
  def title_from_name
@@ -82,24 +120,24 @@ private
82
120
  name && name.underscore.gsub(/_/, ' ').capitalize
83
121
  end
84
122
 
85
- def sequence(target, attr)
123
+ def sequence(finder, target, attr)
86
124
  result = target.strip
87
125
  suffix = 2
88
- while self.class.find(:first, :conditions => "#{attr} = '#{result}'")
126
+ while finder.find(:first, :conditions => "#{attr} = '#{result}'")
89
127
  result = target + suffix.to_s
90
128
  suffix += 1
91
129
  end
92
130
  return result
93
131
  end
94
132
 
95
- def renderer
96
- @renderer ||= WikiRenderer.new
133
+ def most_recent(attr)
134
+ revisions.first && revisions.first.send(attr)
97
135
  end
98
136
 
99
- def my_parser
100
- @parser ||= WikiParser.new
137
+ def oldest(attr)
138
+ revisions.last && revisions.last.send(attr)
101
139
  end
102
-
140
+
103
141
  private
104
142
 
105
143
  def clean(text)
@@ -0,0 +1,27 @@
1
+ # Motiro - A project tracking tool
2
+ # Copyright (C) 2006-2007 Thiago Arrais
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
+
18
+ class Revision < ActiveRecord::Base
19
+ belongs_to :page
20
+ belongs_to :last_editor, :class_name => 'User', :foreign_key => 'last_editor_id'
21
+
22
+ #Delegate methods to parent page
23
+ %w{name original_author}.each do |method|
24
+ define_method(method) { page.send(method) }
25
+ end
26
+
27
+ end
@@ -56,6 +56,7 @@ function tooglePasswordConfirmation(show) {
56
56
  var action = show ? '#{url_for :controller => 'account', :action => 'signup'}' : '#{url_for :controller => 'account', :action => 'login'}' ;
57
57
 
58
58
  document.getElementById("user_password_confirmation").disabled = !show;
59
+ document.getElementById("authentication_errors").style.display = state;
59
60
  document.forms[0].action = action;
60
61
 
61
62
  elem.style.display = state;
@@ -23,4 +23,7 @@
23
23
  :action => 'edit',
24
24
  :page_name => @page.name } )%>
25
25
  <% end %>
26
+ |
27
+ <%= link_to('Page history'.t, :controller => 'wiki', :action => 'history',
28
+ :page_name => @page.name) -%>
26
29
  </div>
@@ -0,0 +1,28 @@
1
+ <% pagetext('Page history for %s' / @page.title) do %>
2
+ <table class="oldernews">
3
+ <thead>
4
+ <tr>
5
+ <th class="date"><%= 'Date'.t -%></th>
6
+ <th class="relative"/>
7
+ <th><%= 'Author'.t -%></th>
8
+ <th><%= 'Title'.t -%></th>
9
+ </tr>
10
+ </thead>
11
+ <tbody>
12
+ <% i = 0 %>
13
+ <% @page.revisions.each do |rev| %>
14
+ <tr class="<%= i % 2 == 0 ? 'odd' : 'even' -%>">
15
+ <td class="date"><%= rev.modified_at-%></td>
16
+ <td class="relative"><%= rev.modified_at.relative_to_now %></td>
17
+ <td><%= rev.last_editor.login %></td>
18
+ <td><%= content_tag :a, rev.title,
19
+ :href => server_url_for(:controller => 'wiki',
20
+ :action => 'show',
21
+ :page_name => @page.name,
22
+ :revision => i) -%></td>
23
+ </tr>
24
+ <% i += 1 %>
25
+ <% end %>
26
+ </tbody>
27
+ </table>
28
+ <% end %>
@@ -1,7 +1,7 @@
1
1
  <% pagetext(@page.title) do %>
2
2
  <% cache(:controller=> 'wiki', :action => 'show',
3
- :page => @page.name, :locale_suffix => @locale) do
4
- %>
3
+ :page => @page.name, :locale_suffix => @locale,
4
+ :revision => @page_revision_id) do %>
5
5
  <%= render :partial => 'properties_show' %>
6
6
  <%= @renderer.render_html(@page.text) %>
7
7
  <% end %>
@@ -0,0 +1,19 @@
1
+ class CreateRevisions < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :revisions do |t|
5
+ t.column 'page_id', :integer
6
+ t.column 'text', :text
7
+ t.column 'editors', :text
8
+ t.column 'kind', :text
9
+ t.column 'title', :text
10
+ t.column 'created_at', :timestamp
11
+ t.column 'revisor_id', :integer
12
+ end
13
+ end
14
+
15
+ def self.down
16
+ drop_table :revisions
17
+ end
18
+
19
+ end
@@ -0,0 +1,13 @@
1
+ class RevisionMimicsPage < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ rename_column :revisions, :revisor_id, :last_editor_id
5
+ rename_column :revisions, :created_at, :modified_at
6
+ end
7
+
8
+ def self.down
9
+ rename_column :revisions, :last_editor_id, :revisor_id
10
+ rename_column :revisions, :modified_at, :created_at
11
+ end
12
+
13
+ end
@@ -0,0 +1,25 @@
1
+ class DropRedundantPageColumns < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ execute("INSERT INTO revisions (page_id, text, editors, kind, title, " +
5
+ "modified_at, last_editor_id) " +
6
+ "SELECT id, text, editors, kind, title, " +
7
+ "'2006-02-01 00:00:00', original_author_id " +
8
+ "FROM pages")
9
+ execute("INSERT INTO revisions (page_id, text, editors, kind, title, " +
10
+ "modified_at, last_editor_id) " +
11
+ "SELECT id, text, editors, kind, title, " +
12
+ "modified_at, last_editor_id " +
13
+ "FROM pages")
14
+ remove_column :pages, :text
15
+ remove_column :pages, :editors
16
+ remove_column :pages, :title
17
+ remove_column :pages, :last_editor_id
18
+ remove_column :pages, :original_author_id
19
+ end
20
+
21
+ def self.down
22
+ raise IrreversibleMigration
23
+ end
24
+
25
+ end
@@ -0,0 +1,13 @@
1
+ class MoveEventDateToRevision < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ add_column :revisions, :happens_at, :date
5
+ execute("UPDATE revisions " +
6
+ "SET happens_at = (select happens_at from pages p where p.id = page_id)")
7
+ end
8
+
9
+ def self.down
10
+ remove_column :revisions, :happens_at
11
+ end
12
+
13
+ end
Binary file
data/db/schema_version CHANGED
@@ -1 +1 @@
1
- 15
1
+ 19
@@ -71,6 +71,8 @@
71
71
  'Who should be able to edit this page?' => 'Quem pode editar esta página?',
72
72
  '(Usernames separated by spaces. Blank for everyone)' => '(Nomes de usuário separados por espaços. Em branco para todos.)',
73
73
 
74
- # Older headlines page
75
- 'Author' => 'Autor'
74
+ # Older headlines and history pages
75
+ 'Author' => 'Autor',
76
+ 'Page history for %s' => 'Histórico da página %s',
77
+ 'Page history' => 'Histórico da página'
76
78
  }
@@ -66,7 +66,7 @@ class WikiAcceptanceTest < AcceptanceTestCase
66
66
  log_as(:bob)
67
67
 
68
68
  click "//a[text() = 'Edit']"
69
- wait_for_page_to_load(1500)
69
+ wait_for_page_to_load(2000)
70
70
 
71
71
  type 'txaEditor', "= This title does not show =\n\n" +
72
72
  "Neither does this text"
@@ -87,7 +87,7 @@ class WikiAcceptanceTest < AcceptanceTestCase
87
87
  type 'txaEditor', 'Original Text'
88
88
  type 'txtAuthorized', 'bob eric'
89
89
  click 'btnSave'
90
- wait_for_page_to_load(1500)
90
+ wait_for_page_to_load(2000)
91
91
 
92
92
  log_out
93
93
  log_as(:john)
@@ -106,7 +106,7 @@ class WikiAcceptanceTest < AcceptanceTestCase
106
106
 
107
107
  type 'txtAuthorized', 'bob eric john'
108
108
  click 'btnSave'
109
- wait_for_page_to_load(1500)
109
+ wait_for_page_to_load(2000)
110
110
 
111
111
  log_out
112
112
  log_as(:john)
@@ -134,7 +134,7 @@ class WikiAcceptanceTest < AcceptanceTestCase
134
134
 
135
135
  type 'txaEditor', 'New edited text for Nobody\'s Page'
136
136
  click 'btnSave'
137
- wait_for_page_to_load(1500)
137
+ wait_for_page_to_load(2000)
138
138
 
139
139
  log_out
140
140
  log_as(:john)
@@ -1,98 +1,58 @@
1
1
  main_page:
2
2
  id: 1
3
3
  name: MainPage
4
- original_author_id: 1000001
5
- editors: ""
6
- text: = Motiro =
7
-
8
- This is project motiro
9
4
 
10
5
  johns_page:
11
6
  id: 2
12
- original_author_id: 1000004
13
7
  name: John_s
14
- editors: john
15
- text: This is John's page
16
8
 
17
9
  bob_and_erics_page:
18
10
  id: 3
19
11
  name: Bob_and_Eric_s
20
- original_author_id: 1000001 #bob
21
- editors: bob eric
22
- text: This is Bob and Eric's page
23
12
 
24
13
  nobodys_page:
25
14
  id: 4
26
15
  name: Unclaimed
27
- original_author_id:
28
- editors: ""
29
- text: This page was created before the wiki access control was in place
30
16
 
31
17
  test_page:
32
18
  id: 5
33
19
  name: TestPage
34
20
  kind: common
35
- original_author_id: 1000001
36
- editors: ""
37
- title:
38
- text: This is the page text
39
21
 
40
22
  non_matching_title_page:
41
23
  id: 6
42
- name: NonMatchingTitlePage
43
24
  kind: common
44
- original_author_id: 1000001
45
- editors: ""
46
- title: The title does not match the name
47
- text: This is the page text
25
+ name: NonMatchingTitlePage
48
26
 
49
27
  list_last_modified_features_page:
50
28
  id: 7
51
- name: ListLastModifiedFeatures
52
29
  kind: feature
53
- original_author_id: 1000001
30
+ name: ListLastModifiedFeatures
54
31
  modified_at: 2033-12-27 16:47:00
55
- last_editor_id: 1000001
56
- editors: ""
57
- title: List last modified features
58
- text: Motiro should list the last modified feature suggestion pages on the
59
- main page
60
32
 
61
33
  provide_rss_feed_for_last_modified_pages_page:
62
34
  id: 8
63
- name: ProvideRSSFeedForLastModifiedPages
64
35
  kind: feature
65
- original_author_id: 1000001
36
+ name: ProvideRSSFeedForLastModifiedPages
66
37
  modified_at: 2033-12-27 12:33:48
67
- last_editor_id: 1000004
68
- editors: ""
69
- title: Provide RSS feed for last modified pages
70
- text: There could be an RSS feed for the last modified pages
71
-
38
+
72
39
  events_are_just_special_pages_too_page:
73
40
  id: 9
74
- name: EventsAreJustSpecialWikiPagesToo
75
41
  kind: feature
76
- original_author_id: 1000001
42
+ name: EventsAreJustSpecialWikiPagesToo
77
43
  modified_at: 2033-12-25 18:43:31
78
- last_editor_id: 1000005
79
- editors: ""
80
- title: Events are just special wiki pages too
81
- text: Event descriptions can be treated just like other regular wiki pages,
82
- in the same way that feature suggestion pages are
83
-
44
+
84
45
  release_event:
85
46
  id: 10
47
+ kind: event
86
48
  name: FourteenthRelease
87
49
  kind: event
88
50
  type: Event
89
- original_author_id: 1000004 #john
90
- modified_at: 2007-01-18 13:28:47
91
- last_editor_id: 1000004 #john
92
- editors: ""
93
51
  happens_at: 2007-01-24
94
- title: Fourteenth release
95
- text: The 0.6.1 release will be a bug fixing one and will introduce editable
96
- event pages. This is included as part of the everything is a wiki page
97
- motto.
98
-
52
+ modified_at: 2007-01-18 13:28:47
53
+
54
+ changed_page:
55
+ id: 11
56
+ name: ChangedPage
57
+ kind: common
58
+ modified_at: 2007-01-22 13:21:26