Commit ce8eba89135c901fd4f04f1b2385bdbd23f48766
Exists in
master
and in
4 other branches
Merge branch 'wiki'
Conflicts: app/views/layouts/_project_menu.html.haml
Showing
22 changed files
with
294 additions
and
17 deletions
Show diff stats
app/assets/stylesheets/main.scss
app/assets/stylesheets/projects.css.scss
... | ... | @@ -0,0 +1,68 @@ |
1 | +class WikisController < ApplicationController | |
2 | + before_filter :project | |
3 | + before_filter :add_project_abilities | |
4 | + before_filter :authorize_read_wiki! | |
5 | + before_filter :authorize_write_wiki!, :except => [:show, :destroy] | |
6 | + before_filter :authorize_admin_wiki!, :only => :destroy | |
7 | + layout "project" | |
8 | + | |
9 | + def show | |
10 | + if params[:old_page_id] | |
11 | + @wiki = @project.wikis.find(params[:old_page_id]) | |
12 | + else | |
13 | + @wiki = @project.wikis.where(:slug => params[:id]).order("created_at").last | |
14 | + end | |
15 | + respond_to do |format| | |
16 | + if @wiki | |
17 | + format.html | |
18 | + else | |
19 | + @wiki = @project.wikis.new(:slug => params[:id]) | |
20 | + format.html { render "edit" } | |
21 | + end | |
22 | + end | |
23 | + end | |
24 | + | |
25 | + def edit | |
26 | + @wiki = @project.wikis.where(:slug => params[:id]).order("created_at").last | |
27 | + @wiki = Wiki.regenerate_from @wiki | |
28 | + end | |
29 | + | |
30 | + def create | |
31 | + @wiki = @project.wikis.new(params[:wiki]) | |
32 | + @wiki.user = current_user | |
33 | + | |
34 | + respond_to do |format| | |
35 | + if @wiki.save | |
36 | + format.html { redirect_to [@project, @wiki], notice: 'Wiki was successfully updated.' } | |
37 | + else | |
38 | + format.html { render action: "edit" } | |
39 | + end | |
40 | + end | |
41 | + end | |
42 | + | |
43 | + def history | |
44 | + @wikis = @project.wikis.where(:slug => params[:id]).order("created_at") | |
45 | + end | |
46 | + | |
47 | + def destroy | |
48 | + @wikis = @project.wikis.where(:slug => params[:id]).delete_all | |
49 | + | |
50 | + respond_to do |format| | |
51 | + format.html { redirect_to project_wiki_path(@project, :index), notice: "Page was successfully deleted" } | |
52 | + end | |
53 | + end | |
54 | + | |
55 | + protected | |
56 | + | |
57 | + def authorize_read_wiki! | |
58 | + can?(current_user, :read_wiki, @project) | |
59 | + end | |
60 | + | |
61 | + def authorize_write_wiki! | |
62 | + can?(current_user, :write_wiki, @project) | |
63 | + end | |
64 | + | |
65 | + def authorize_admin_wiki! | |
66 | + can?(current_user, :admin_wiki, @project) | |
67 | + end | |
68 | +end | ... | ... |
app/models/ability.rb
... | ... | @@ -5,6 +5,7 @@ class Ability |
5 | 5 | when "Issue" then issue_abilities(object, subject) |
6 | 6 | when "Note" then note_abilities(object, subject) |
7 | 7 | when "Snippet" then snippet_abilities(object, subject) |
8 | + when "Wiki" then wiki_abilities(object, subject) | |
8 | 9 | else [] |
9 | 10 | end |
10 | 11 | end |
... | ... | @@ -14,35 +15,40 @@ class Ability |
14 | 15 | |
15 | 16 | rules << [ |
16 | 17 | :read_project, |
18 | + :read_wiki, | |
17 | 19 | :read_issue, |
18 | 20 | :read_snippet, |
19 | 21 | :read_team_member, |
20 | 22 | :read_merge_request, |
21 | - :read_note | |
22 | - ] if project.allow_read_for?(user) | |
23 | - | |
24 | - rules << [ | |
23 | + :read_note, | |
25 | 24 | :write_project, |
26 | 25 | :write_issue, |
27 | 26 | :write_snippet, |
28 | 27 | :write_merge_request, |
29 | 28 | :write_note |
30 | - ] if project.allow_write_for?(user) | |
29 | + ] if project.guest_access_for?(user) | |
30 | + | |
31 | + rules << [ | |
32 | + :download_code, | |
33 | + ] if project.report_access_for?(user) | |
34 | + | |
35 | + rules << [ | |
36 | + :write_wiki | |
37 | + ] if project.dev_access_for?(user) | |
31 | 38 | |
32 | 39 | rules << [ |
33 | 40 | :modify_issue, |
34 | 41 | :modify_snippet, |
42 | + :modify_wiki, | |
35 | 43 | :admin_project, |
36 | 44 | :admin_issue, |
37 | 45 | :admin_snippet, |
38 | 46 | :admin_team_member, |
39 | 47 | :admin_merge_request, |
40 | - :admin_note | |
41 | - ] if project.allow_admin_for?(user) | |
48 | + :admin_note, | |
49 | + :admin_wiki | |
50 | + ] if project.master_access_for?(user) | |
42 | 51 | |
43 | - rules << [ | |
44 | - :download_code, | |
45 | - ] if project.allow_pull_for?(user) | |
46 | 52 | |
47 | 53 | rules.flatten |
48 | 54 | end | ... | ... |
app/models/project.rb
... | ... | @@ -12,6 +12,7 @@ class Project < ActiveRecord::Base |
12 | 12 | has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key" |
13 | 13 | has_many :web_hooks, :dependent => :destroy |
14 | 14 | has_many :protected_branches, :dependent => :destroy |
15 | + has_many :wikis, :dependent => :destroy | |
15 | 16 | |
16 | 17 | acts_as_taggable |
17 | 18 | |
... | ... | @@ -232,16 +233,20 @@ class Project < ActiveRecord::Base |
232 | 233 | !users_projects.where(:user_id => user.id).empty? |
233 | 234 | end |
234 | 235 | |
235 | - def allow_write_for?(user) | |
236 | + def guest_access_for?(user) | |
236 | 237 | !users_projects.where(:user_id => user.id).empty? |
237 | 238 | end |
238 | 239 | |
239 | - def allow_admin_for?(user) | |
240 | - !users_projects.where(:user_id => user.id, :project_access => [UsersProject::MASTER]).empty? || owner_id == user.id | |
240 | + def report_access_for?(user) | |
241 | + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty? | |
241 | 242 | end |
242 | 243 | |
243 | - def allow_pull_for?(user) | |
244 | - !users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty? | |
244 | + def dev_access_for?(user) | |
245 | + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::DEVELOPER, UsersProject::MASTER]).empty? | |
246 | + end | |
247 | + | |
248 | + def master_access_for?(user) | |
249 | + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::MASTER]).empty? || owner_id == user.id | |
245 | 250 | end |
246 | 251 | |
247 | 252 | def root_ref | ... | ... |
... | ... | @@ -0,0 +1,33 @@ |
1 | +class Wiki < ActiveRecord::Base | |
2 | + belongs_to :project | |
3 | + belongs_to :user | |
4 | + | |
5 | + validates :content, :title, :user_id, :presence => true | |
6 | + validates :title, :length => 1..250 | |
7 | + | |
8 | + before_update :set_slug | |
9 | + | |
10 | + | |
11 | + def to_param | |
12 | + slug | |
13 | + end | |
14 | + | |
15 | + protected | |
16 | + | |
17 | + def set_slug | |
18 | + self.slug = self.title.parameterize | |
19 | + end | |
20 | + | |
21 | + class << self | |
22 | + def regenerate_from wiki | |
23 | + regenerated_field = [:slug, :content, :title] | |
24 | + | |
25 | + new_wiki = Wiki.new | |
26 | + regenerated_field.each do |field| | |
27 | + new_wiki.send("#{field}=", wiki.send(field)) | |
28 | + end | |
29 | + new_wiki | |
30 | + end | |
31 | + | |
32 | + end | |
33 | +end | ... | ... |
app/views/layouts/_project_menu.html.haml
... | ... | @@ -12,7 +12,6 @@ |
12 | 12 | = link_to project_issues_filter_path(@project), :class => (controller.controller_name == "issues") ? "current" : nil do |
13 | 13 | Issues |
14 | 14 | %span.count= @project.issues.opened.count |
15 | - | |
16 | 15 | - if @project.merge_requests_enabled |
17 | 16 | = link_to project_merge_requests_path(@project), :class => (controller.controller_name == "merge_requests") ? "current" : nil do |
18 | 17 | Merge Requests |
... | ... | @@ -21,3 +20,7 @@ |
21 | 20 | - if @project.wall_enabled |
22 | 21 | = link_to wall_project_path(@project), :class => current_page?(:controller => "projects", :action => "wall", :id => @project) ? "current" : nil do |
23 | 22 | Wall |
23 | + | |
24 | + - if @project.wiki_enabled | |
25 | + = link_to project_wiki_path(@project, :index), :class => (controller.controller_name == "wikis") ? "current" : nil do | |
26 | + Wiki | ... | ... |
app/views/projects/_form.html.haml
... | ... | @@ -0,0 +1,18 @@ |
1 | += form_for [@project, @wiki] do |f| | |
2 | + -if @wiki.errors.any? | |
3 | + #error_explanation | |
4 | + %h2= "#{pluralize(@wiki.errors.count, "error")} prohibited this wiki from being saved:" | |
5 | + %ul | |
6 | + - @wiki.errors.full_messages.each do |msg| | |
7 | + %li= msg | |
8 | + | |
9 | + .clearfix | |
10 | + = f.label :title | |
11 | + .input= f.text_field :title, :class => :xxlarge | |
12 | + = f.hidden_field :slug | |
13 | + .clearfix | |
14 | + = f.label :content | |
15 | + .input= f.text_area :content, :class => :xxlarge | |
16 | + .actions | |
17 | + = f.submit 'Save', :class => "primary btn" | |
18 | + = link_to "Cancel", project_wiki_path(@project, :index), :class => "btn" | ... | ... |
... | ... | @@ -0,0 +1,19 @@ |
1 | +%h2 Versions | |
2 | +%table | |
3 | + %thead | |
4 | + %tr | |
5 | + %th # | |
6 | + %th last edit | |
7 | + %th created by | |
8 | + %tbody | |
9 | + - @wikis.each_with_index do |wiki_page, i| | |
10 | + %tr | |
11 | + %td= i + 1 | |
12 | + %td | |
13 | + = link_to wiki_page.created_at.to_s(:short), project_wiki_path(@project, wiki_page, :old_page_id => wiki_page.id) | |
14 | + ( | |
15 | + = time_ago_in_words(wiki_page.created_at) | |
16 | + ago | |
17 | + ) | |
18 | + %td= wiki_page.user.name | |
19 | + | ... | ... |
... | ... | @@ -0,0 +1,15 @@ |
1 | +%h3 | |
2 | + = @wiki.title | |
3 | + = link_to edit_project_wiki_path(@project, @wiki), :class => "right btn small" do | |
4 | + Edit | |
5 | + - if can? current_user, :write_wiki, @project | |
6 | + = link_to history_project_wiki_path(@project, @wiki), :class => "right btn small" do | |
7 | + History | |
8 | +%hr | |
9 | + | |
10 | += markdown_to_html @wiki.content | |
11 | + | |
12 | +%p.time Last edited by #{@wiki.user.name}, in #{time_ago_in_words @wiki.created_at} | |
13 | +- if can? current_user, :write_wiki, @project | |
14 | + = link_to project_wiki_path(@project, @wiki), :confirm => "Are you sure you want to delete this page?", :method => :delete do | |
15 | + Delete this page | ... | ... |
config/routes.rb
1 | 1 | Gitlab::Application.routes.draw do |
2 | 2 | |
3 | + | |
3 | 4 | # Optionally, enable Resque here |
4 | 5 | require 'resque/server' |
5 | 6 | mount Resque::Server.new, at: '/info/resque' |
... | ... | @@ -55,6 +56,12 @@ Gitlab::Application.routes.draw do |
55 | 56 | get "files" |
56 | 57 | end |
57 | 58 | |
59 | + resources :wikis, :only => [:show, :edit, :destroy, :create] do | |
60 | + member do | |
61 | + get "history" | |
62 | + end | |
63 | + end | |
64 | + | |
58 | 65 | resource :repository do |
59 | 66 | member do |
60 | 67 | get "branches" | ... | ... |
db/migrate/20120219140810_add_wiki_enabled_to_project.rb
0 → 100644
db/schema.rb
... | ... | @@ -11,7 +11,7 @@ |
11 | 11 | # |
12 | 12 | # It's strongly recommended to check this file into your version control system. |
13 | 13 | |
14 | -ActiveRecord::Schema.define(:version => 20120216085842) do | |
14 | +ActiveRecord::Schema.define(:version => 20120219193300) do | |
15 | 15 | |
16 | 16 | create_table "issues", :force => true do |t| |
17 | 17 | t.string "title" |
... | ... | @@ -80,6 +80,7 @@ ActiveRecord::Schema.define(:version => 20120216085842) do |
80 | 80 | t.boolean "issues_enabled", :default => true, :null => false |
81 | 81 | t.boolean "wall_enabled", :default => true, :null => false |
82 | 82 | t.boolean "merge_requests_enabled", :default => true, :null => false |
83 | + t.boolean "wiki_enabled", :default => true, :null => false | |
83 | 84 | end |
84 | 85 | |
85 | 86 | create_table "protected_branches", :force => true do |t| |
... | ... | @@ -158,4 +159,14 @@ ActiveRecord::Schema.define(:version => 20120216085842) do |
158 | 159 | t.datetime "updated_at" |
159 | 160 | end |
160 | 161 | |
162 | + create_table "wikis", :force => true do |t| | |
163 | + t.string "title" | |
164 | + t.text "content" | |
165 | + t.integer "project_id" | |
166 | + t.datetime "created_at", :null => false | |
167 | + t.datetime "updated_at", :null => false | |
168 | + t.string "slug" | |
169 | + t.integer "user_id" | |
170 | + end | |
171 | + | |
161 | 172 | end | ... | ... |
spec/factories.rb
... | ... | @@ -0,0 +1,35 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe "Wiki" do | |
4 | + let(:project) { Factory :project } | |
5 | + | |
6 | + before do | |
7 | + login_as :user | |
8 | + project.add_access(@user, :read, :write) | |
9 | + end | |
10 | + | |
11 | + describe "Add pages" do | |
12 | + before do | |
13 | + visit project_wiki_path(project, :index) | |
14 | + end | |
15 | + | |
16 | + it "should see form" do | |
17 | + page.should have_content("Editing page") | |
18 | + end | |
19 | + | |
20 | + it "should see added page" do | |
21 | + fill_in "Title", :with => 'Test title' | |
22 | + fill_in "Content", :with => '[link test](test)' | |
23 | + click_on "Save" | |
24 | + | |
25 | + page.should have_content("Test title") | |
26 | + page.should have_content("link test") | |
27 | + | |
28 | + click_link "link test" | |
29 | + | |
30 | + page.should have_content("Editing page") | |
31 | + end | |
32 | + | |
33 | + end | |
34 | + | |
35 | +end | ... | ... |