motiro 0.6.3 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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