Commit ef2bf1520489a23ff64224c3e102a03b46243dbf

Authored by Dmitriy Zaporozhets
1 parent 7b5799a9

1.0.2

@@ -19,6 +19,7 @@ gem "albino", :git => "git://github.com/gitlabhq/albino.git" @@ -19,6 +19,7 @@ gem "albino", :git => "git://github.com/gitlabhq/albino.git"
19 gem "kaminari" 19 gem "kaminari"
20 gem "thin" 20 gem "thin"
21 gem "git" 21 gem "git"
  22 +gem "acts_as_list"
22 23
23 group :assets do 24 group :assets do
24 gem 'sass-rails', " ~> 3.1.0" 25 gem 'sass-rails', " ~> 3.1.0"
@@ -61,6 +61,7 @@ GEM @@ -61,6 +61,7 @@ GEM
61 activesupport (= 3.1.0) 61 activesupport (= 3.1.0)
62 activesupport (3.1.0) 62 activesupport (3.1.0)
63 multi_json (~> 1.0) 63 multi_json (~> 1.0)
  64 + acts_as_list (0.1.4)
64 addressable (2.2.6) 65 addressable (2.2.6)
65 ansi (1.3.0) 66 ansi (1.3.0)
66 archive-tar-minitar (0.5.2) 67 archive-tar-minitar (0.5.2)
@@ -240,6 +241,7 @@ PLATFORMS @@ -240,6 +241,7 @@ PLATFORMS
240 ruby 241 ruby
241 242
242 DEPENDENCIES 243 DEPENDENCIES
  244 + acts_as_list
243 albino! 245 albino!
244 annotate! 246 annotate!
245 autotest 247 autotest
app/assets/images/move.png 0 → 100644

260 Bytes

app/assets/javascripts/dashboard.js.coffee
@@ -1,3 +0,0 @@ @@ -1,3 +0,0 @@
1 -# Place all the behaviors and hooks related to the matching controller here.  
2 -# All this logic will automatically be available in application.js.  
3 -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/  
app/assets/javascripts/issues.js.coffee
@@ -1,3 +0,0 @@ @@ -1,3 +0,0 @@
1 -# Place all the behaviors and hooks related to the matching controller here.  
2 -# All this logic will automatically be available in application.js.  
3 -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/  
app/assets/javascripts/profile.js.coffee
@@ -1,3 +0,0 @@ @@ -1,3 +0,0 @@
1 -# Place all the behaviors and hooks related to the matching controller here.  
2 -# All this logic will automatically be available in application.js.  
3 -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/  
app/assets/javascripts/projects.js
@@ -34,6 +34,7 @@ $(document).ready(function(){ @@ -34,6 +34,7 @@ $(document).ready(function(){
34 e.preventDefault(); 34 e.preventDefault();
35 } 35 }
36 }); 36 });
  37 +
37 }); 38 });
38 39
39 function focusSearch() { 40 function focusSearch() {
app/assets/stylesheets/projects.css.scss
@@ -539,3 +539,13 @@ tbody tr:nth-child(2n) td, tbody tr.even td { @@ -539,3 +539,13 @@ tbody tr:nth-child(2n) td, tbody tr.even td {
539 float:left; 539 float:left;
540 } 540 }
541 } 541 }
  542 +
  543 +.handle:hover{
  544 + cursor: move;
  545 +}
  546 +
  547 +.handle{
  548 + width: 12px;
  549 + height: 12px;
  550 + padding: 10px;
  551 +}
app/controllers/application_controller.rb
@@ -61,4 +61,8 @@ class ApplicationController < ActionController::Base @@ -61,4 +61,8 @@ class ApplicationController < ActionController::Base
61 def render_404 61 def render_404
62 render :file => File.join(Rails.root, "public", "404"), :layout => false, :status => "404" 62 render :file => File.join(Rails.root, "public", "404"), :layout => false, :status => "404"
63 end 63 end
  64 +
  65 + def require_non_empty_project
  66 + redirect_to @project unless @project.repo_exists?
  67 + end
64 end 68 end
app/controllers/commits_controller.rb
@@ -6,6 +6,7 @@ class CommitsController < ApplicationController @@ -6,6 +6,7 @@ class CommitsController < ApplicationController
6 # Authorize 6 # Authorize
7 before_filter :add_project_abilities 7 before_filter :add_project_abilities
8 before_filter :authorize_read_project! 8 before_filter :authorize_read_project!
  9 + before_filter :require_non_empty_project
9 10
10 def index 11 def index
11 load_refs # load @branch, @tag & @ref 12 load_refs # load @branch, @tag & @ref
app/controllers/issues_controller.rb
@@ -5,7 +5,7 @@ class IssuesController < ApplicationController @@ -5,7 +5,7 @@ class IssuesController < ApplicationController
5 # Authorize 5 # Authorize
6 before_filter :add_project_abilities 6 before_filter :add_project_abilities
7 before_filter :authorize_read_issue! 7 before_filter :authorize_read_issue!
8 - before_filter :authorize_write_issue!, :only => [:new, :create, :close, :edit, :update] 8 + before_filter :authorize_write_issue!, :only => [:new, :create, :close, :edit, :update, :sort]
9 before_filter :authorize_admin_issue!, :only => [:destroy] 9 before_filter :authorize_admin_issue!, :only => [:destroy]
10 10
11 respond_to :js 11 respond_to :js
@@ -69,4 +69,14 @@ class IssuesController < ApplicationController @@ -69,4 +69,14 @@ class IssuesController < ApplicationController
69 format.js { render :nothing => true } 69 format.js { render :nothing => true }
70 end 70 end
71 end 71 end
  72 +
  73 + def sort
  74 + @issues = @project.issues.where(:id => params['issue'])
  75 + @issues.each do |issue|
  76 + issue.position = params['issue'].index(issue.id.to_s) + 1
  77 + issue.save
  78 + end
  79 +
  80 + render :nothing => true
  81 + end
72 end 82 end
app/controllers/projects_controller.rb
@@ -6,6 +6,8 @@ class ProjectsController < ApplicationController @@ -6,6 +6,8 @@ class ProjectsController < ApplicationController
6 before_filter :authorize_read_project!, :except => [:index, :new, :create] 6 before_filter :authorize_read_project!, :except => [:index, :new, :create]
7 before_filter :authorize_admin_project!, :only => [:edit, :update, :destroy] 7 before_filter :authorize_admin_project!, :only => [:edit, :update, :destroy]
8 8
  9 + before_filter :require_non_empty_project, :only => [:blob, :tree]
  10 +
9 def index 11 def index
10 @projects = current_user.projects.all 12 @projects = current_user.projects.all
11 end 13 end
@@ -48,7 +50,7 @@ class ProjectsController < ApplicationController @@ -48,7 +50,7 @@ class ProjectsController < ApplicationController
48 def update 50 def update
49 respond_to do |format| 51 respond_to do |format|
50 if project.update_attributes(params[:project]) 52 if project.update_attributes(params[:project])
51 - format.html { redirect_to project, notice: 'Project was successfully updated.' } 53 + format.html { redirect_to project, :notice => 'Project was successfully updated.' }
52 format.js 54 format.js
53 else 55 else
54 format.html { render action: "edit" } 56 format.html { render action: "edit" }
app/models/issue.rb
@@ -21,6 +21,8 @@ class Issue < ActiveRecord::Base @@ -21,6 +21,8 @@ class Issue < ActiveRecord::Base
21 scope :opened, where(:closed => false) 21 scope :opened, where(:closed => false)
22 scope :closed, where(:closed => true) 22 scope :closed, where(:closed => true)
23 scope :assigned, lambda { |u| where(:assignee_id => u.id)} 23 scope :assigned, lambda { |u| where(:assignee_id => u.id)}
  24 +
  25 + acts_as_list
24 end 26 end
25 # == Schema Information 27 # == Schema Information
26 # 28 #
app/models/project.rb
@@ -3,7 +3,7 @@ require "grit" @@ -3,7 +3,7 @@ require "grit"
3 class Project < ActiveRecord::Base 3 class Project < ActiveRecord::Base
4 belongs_to :owner, :class_name => "User" 4 belongs_to :owner, :class_name => "User"
5 5
6 - has_many :issues, :dependent => :destroy 6 + has_many :issues, :dependent => :destroy, :order => "position"
7 has_many :users_projects, :dependent => :destroy 7 has_many :users_projects, :dependent => :destroy
8 has_many :users, :through => :users_projects 8 has_many :users, :through => :users_projects
9 has_many :notes, :dependent => :destroy 9 has_many :notes, :dependent => :destroy
@@ -16,6 +16,8 @@ class Project &lt; ActiveRecord::Base @@ -16,6 +16,8 @@ class Project &lt; ActiveRecord::Base
16 validates :path, 16 validates :path,
17 :uniqueness => true, 17 :uniqueness => true,
18 :presence => true, 18 :presence => true,
  19 + :format => { :with => /^[a-zA-Z0-9_\-]*$/,
  20 + :message => "only letters, digits & '_' '-' allowed" },
19 :length => { :within => 0..255 } 21 :length => { :within => 0..255 }
20 22
21 validates :description, 23 validates :description,
@@ -24,14 +26,15 @@ class Project &lt; ActiveRecord::Base @@ -24,14 +26,15 @@ class Project &lt; ActiveRecord::Base
24 validates :code, 26 validates :code,
25 :presence => true, 27 :presence => true,
26 :uniqueness => true, 28 :uniqueness => true,
27 - :length => { :within => 3..12 } 29 + :format => { :with => /^[a-zA-Z0-9_\-]*$/,
  30 + :message => "only letters, digits & '_' '-' allowed" },
  31 + :length => { :within => 3..16 }
28 32
29 validates :owner, 33 validates :owner,
30 :presence => true 34 :presence => true
31 35
32 validate :check_limit 36 validate :check_limit
33 37
34 - before_save :format_code  
35 after_destroy :destroy_gitosis_project 38 after_destroy :destroy_gitosis_project
36 after_save :update_gitosis_project 39 after_save :update_gitosis_project
37 40
@@ -47,10 +50,6 @@ class Project &lt; ActiveRecord::Base @@ -47,10 +50,6 @@ class Project &lt; ActiveRecord::Base
47 notes.where(:noteable_type => ["", nil]) 50 notes.where(:noteable_type => ["", nil])
48 end 51 end
49 52
50 - def format_code  
51 - read_attribute(:code).downcase.strip.gsub(' ', '')  
52 - end  
53 -  
54 def update_gitosis_project 53 def update_gitosis_project
55 Gitosis.new.configure do |c| 54 Gitosis.new.configure do |c|
56 c.update_project(path, gitosis_writers) 55 c.update_project(path, gitosis_writers)
app/views/issues/_show.html.haml
1 %tr{ :id => dom_id(issue), :class => "issue", :url => project_issue_path(@project, issue) } 1 %tr{ :id => dom_id(issue), :class => "issue", :url => project_issue_path(@project, issue) }
2 %td 2 %td
  3 + = image_tag "move.png" , :class => [:handle, :left]
3 = image_tag gravatar_icon(issue.assignee.email), :class => "left", :width => 40, :style => "padding:0 5px;" 4 = image_tag gravatar_icon(issue.assignee.email), :class => "left", :width => 40, :style => "padding:0 5px;"
4 = truncate issue.assignee.name, :lenght => 20 5 = truncate issue.assignee.name, :lenght => 20
5 %td ##{issue.id} 6 %td ##{issue.id}
app/views/issues/index.html.haml
@@ -22,3 +22,29 @@ @@ -22,3 +22,29 @@
22 :javascript 22 :javascript
23 $('.delete-issue').live('ajax:success', function() { 23 $('.delete-issue').live('ajax:success', function() {
24 $(this).closest('tr').fadeOut(); }); 24 $(this).closest('tr').fadeOut(); });
  25 +
  26 + function setSortable(){
  27 + $('#issues-table>tbody').sortable({
  28 + axis: 'y',
  29 + dropOnEmpty: false,
  30 + handle: '.handle',
  31 + cursor: 'crosshair',
  32 + items: 'tr',
  33 + opacity: 0.4,
  34 + scroll: true,
  35 + update: function(){
  36 + $.ajax({
  37 + type: 'post',
  38 + data: $('#issues-table>tbody').sortable('serialize'),
  39 + dataType: 'script',
  40 + complete: function(request){
  41 + $('#issues-table>tbody').effect('highlight');
  42 + },
  43 + url: "#{sort_project_issues_path(@project)}"})
  44 + }
  45 + });
  46 + }
  47 +
  48 + $(function(){
  49 + setSortable();
  50 + });
app/views/issues/index.js.haml
1 :plain 1 :plain
2 $('#issues-table-holder').html("#{escape_javascript(render('issues'))}"); 2 $('#issues-table-holder').html("#{escape_javascript(render('issues'))}");
  3 + setSortable();
app/views/layouts/_head_panel.html.erb
@@ -10,12 +10,13 @@ @@ -10,12 +10,13 @@
10 </div> 10 </div>
11 <div class="right"> 11 <div class="right">
12 <%= link_to truncate(@project.name, :length => 20), project_path(@project), :class => "current button" if @project && !@project.new_record? %> 12 <%= link_to truncate(@project.name, :length => 20), project_path(@project), :class => "current button" if @project && !@project.new_record? %>
13 - <%= link_to 'Home', root_path, :class => current_page?(root_url) ? "current button" : "button" %>  
14 <%= link_to 'Projects', projects_path, :class => current_page?(projects_path) ? "current button" : "button" %> 13 <%= link_to 'Projects', projects_path, :class => current_page?(projects_path) ? "current button" : "button" %>
15 - <%= link_to 'Profile', profile_path, :class => (controller.controller_name == "keys") ? "current button" : "button" %>  
16 <%= link_to('Admin', admin_root_path, :class => admin_namespace? ? "current button" : "button" ) if current_user.is_admin? %> 14 <%= link_to('Admin', admin_root_path, :class => admin_namespace? ? "current button" : "button" ) if current_user.is_admin? %>
17 - <%#= link_to 'Profile', edit_user_registration_path, :class => "button" %>  
18 - <%= link_to 'Logout', destroy_user_session_path, :class => "button", :method => :delete %> 15 + <%= link_to profile_path, :class => ((controller.controller_name == "keys" || controller.controller_name == "profile") ? "current button" : "button") do %>
  16 + <%= image_tag gravatar_icon(current_user.email) %>
  17 + <%= current_user.name.split(" ").first %>
  18 + <% end %>
  19 + <%= link_to 'Logout', destroy_user_session_path, :style => "border-left: 1px solid #666;", :class => "button", :method => :delete %>
19 </div> 20 </div>
20 </div> 21 </div>
21 </div> 22 </div>
app/views/notify/note_commit_email.html.haml
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 %td{:align => "left", :style => "padding: 20px 0 0;"} 5 %td{:align => "left", :style => "padding: 20px 0 0;"}
6 %h2{:style => "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "} 6 %h2{:style => "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "}
7 New comment for commmit 7 New comment for commmit
8 - = link_to truncate(@commit.id.to_s, :length => 16), project_commit_url(@project, :id => @commit.id) 8 + = link_to truncate(@commit.id.to_s, :length => 16), project_commit_url(@project, :id => @commit.id, :anchor => "note_#{@note.id}")
9 %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} 9 %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"}
10 %tr 10 %tr
11 %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} 11 %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"}
app/views/notify/note_issue_email.html.haml
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 %td{:align => "left", :style => "padding: 20px 0 0;"} 5 %td{:align => "left", :style => "padding: 20px 0 0;"}
6 %h2{:style => "color:#646464 !important; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "} 6 %h2{:style => "color:#646464 !important; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "}
7 New comment - 7 New comment -
8 - = link_to project_issue_url(@project, @issue) do 8 + = link_to project_issue_url(@project, @issue, :anchor => "note_#{@note.id}") do
9 = "Issue ##{@issue.id.to_s}" 9 = "Issue ##{@issue.id.to_s}"
10 = truncate(@issue.title, :length => 35) 10 = truncate(@issue.title, :length => 35)
11 %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} 11 %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"}
app/views/notify/note_wall_email.html.haml
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 %td{:align => "left", :style => "padding: 20px 0 0;"} 5 %td{:align => "left", :style => "padding: 20px 0 0;"}
6 %h2{:style => "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "} 6 %h2{:style => "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "}
7 New message on 7 New message on
8 - = link_to "Project Wall", wall_project_url(@project) 8 + = link_to "Project Wall", wall_project_url(@project, :anchor => "note_#{@note.id}")
9 %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} 9 %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"}
10 %tr 10 %tr
11 %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} 11 %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"}
app/views/projects/index.html.haml
1 -%div{:class => "tile", :style => view_mode_style("tile")}  
2 - = render "tile"  
3 -%div{:class => "list", :style => view_mode_style("list")}  
4 - = render "list" 1 +- unless @projects.empty?
  2 + %div{:class => "tile", :style => view_mode_style("tile")}
  3 + = render "tile"
  4 + %div{:class => "list", :style => view_mode_style("list")}
  5 + = render "list"
  6 +- else
  7 + %center.prepend-top
  8 + %h2
  9 + %cite Nothing here
config/initializers/rails_footnotes.rb
1 -if defined?(Footnotes) && Rails.env.development?  
2 - Footnotes.run! # first of all 1 +#if defined?(Footnotes) && Rails.env.development?
  2 + #Footnotes.run! # first of all
3 3
4 # ... other init code 4 # ... other init code
5 -end 5 +#end
config/routes.rb
@@ -32,7 +32,7 @@ Gitlab::Application.routes.draw do @@ -32,7 +32,7 @@ Gitlab::Application.routes.draw do
32 get "tree/:commit_id/:path" => "projects#tree", 32 get "tree/:commit_id/:path" => "projects#tree",
33 :as => :tree_file, 33 :as => :tree_file,
34 :constraints => { 34 :constraints => {
35 - :id => /[a-zA-Z0-9]+/, 35 + :id => /[a-zA-Z0-9_\-]+/,
36 :commit_id => /[a-zA-Z0-9]+/, 36 :commit_id => /[a-zA-Z0-9]+/,
37 :path => /.*/ 37 :path => /.*/
38 } 38 }
@@ -40,7 +40,11 @@ Gitlab::Application.routes.draw do @@ -40,7 +40,11 @@ Gitlab::Application.routes.draw do
40 end 40 end
41 resources :commits 41 resources :commits
42 resources :team_members 42 resources :team_members
43 - resources :issues 43 + resources :issues do
  44 + collection do
  45 + post :sort
  46 + end
  47 + end
44 resources :notes, :only => [:create, :destroy] 48 resources :notes, :only => [:create, :destroy]
45 end 49 end
46 root :to => "projects#index" 50 root :to => "projects#index"
db/migrate/20111015154310_add_position_to_issues.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class AddPositionToIssues < ActiveRecord::Migration
  2 + def change
  3 + add_column :issues, :position, :integer, :default => 0
  4 + end
  5 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20111009111204) do 14 +ActiveRecord::Schema.define(:version => 20111015154310) do
15 15
16 create_table "issues", :force => true do |t| 16 create_table "issues", :force => true do |t|
17 t.string "title" 17 t.string "title"
@@ -22,6 +22,7 @@ ActiveRecord::Schema.define(:version =&gt; 20111009111204) do @@ -22,6 +22,7 @@ ActiveRecord::Schema.define(:version =&gt; 20111009111204) do
22 t.datetime "created_at" 22 t.datetime "created_at"
23 t.datetime "updated_at" 23 t.datetime "updated_at"
24 t.boolean "closed", :default => false, :null => false 24 t.boolean "closed", :default => false, :null => false
  25 + t.integer "position", :default => 0
25 end 26 end
26 27
27 create_table "keys", :force => true do |t| 28 create_table "keys", :force => true do |t|
spec/requests/admin/admin_projects_spec.rb
@@ -88,7 +88,7 @@ describe &quot;Admin::Projects&quot; do @@ -88,7 +88,7 @@ describe &quot;Admin::Projects&quot; do
88 visit new_admin_project_path 88 visit new_admin_project_path
89 fill_in 'Name', :with => 'NewProject' 89 fill_in 'Name', :with => 'NewProject'
90 fill_in 'Code', :with => 'NPR' 90 fill_in 'Code', :with => 'NPR'
91 - fill_in 'Path', :with => '/tmp/legit_test/legit' 91 + fill_in 'Path', :with => 'legit_1'
92 expect { click_button "Save" }.to change { Project.count }.by(1) 92 expect { click_button "Save" }.to change { Project.count }.by(1)
93 @project = Project.last 93 @project = Project.last
94 end 94 end
spec/requests/projects_spec.rb
@@ -39,7 +39,7 @@ describe &quot;Projects&quot; do @@ -39,7 +39,7 @@ describe &quot;Projects&quot; do
39 visit new_project_path 39 visit new_project_path
40 fill_in 'Name', :with => 'NewProject' 40 fill_in 'Name', :with => 'NewProject'
41 fill_in 'Code', :with => 'NPR' 41 fill_in 'Code', :with => 'NPR'
42 - fill_in 'Path', :with => '/tmp/legit_test/legit' 42 + fill_in 'Path', :with => 'newproject'
43 expect { click_button "Create Project" }.to change { Project.count }.by(1) 43 expect { click_button "Create Project" }.to change { Project.count }.by(1)
44 @project = Project.last 44 @project = Project.last
45 end 45 end