saucy 0.4.10 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,26 @@
1
+ 0.5.0
2
+
3
+ Added the ability to archive projects. Archived projects are not included in
4
+ an accounts `projects_count`.
5
+
6
+ To upgrade to this version add the following column to the projects table:
7
+
8
+ add_column :projects, :archived, :default => false, :null => false
9
+
10
+ This version adds a list of archived projects to the projects index of an
11
+ account. An introduced headers to these two lists. Archived projects have
12
+ a "View Project" link, which is how the user can view an archived project.
13
+ You will probably want to style this list, headers, and link.
14
+
15
+ It also adds an Archive link on the project's edit page. You will probably
16
+ want to style this link.
17
+
18
+ It is up to your application to provide any additional logic about what
19
+ limitations are present for archived projects (for example, not being able to
20
+ create new comments on them).
21
+
22
+ 0.4.10
23
+
24
+ A user following an invite link who is already signed in and whose email
25
+ address matches the one in the invite automatically accepts the invite when
26
+ following the link.
@@ -0,0 +1,27 @@
1
+ class ArchivesController < ApplicationController
2
+ before_filter :authenticate
3
+ before_filter :authorize_admin
4
+ before_filter :ensure_account_within_projects_limit
5
+
6
+ def create
7
+ @project = current_project
8
+ @project.archived = true
9
+ @project.save
10
+ flash[:success] = "Project has been archived"
11
+ redirect_to account_projects_url(current_project.account)
12
+ end
13
+
14
+ def destroy
15
+ @project = current_project
16
+ @project.archived = false
17
+ @project.save
18
+ flash[:success] = "Project unarchived"
19
+ redirect_to account_projects_url(current_project.account)
20
+ end
21
+
22
+ private
23
+
24
+ def ensure_account_within_projects_limit
25
+ ensure_account_within_limit("projects")
26
+ end
27
+ end
@@ -3,6 +3,15 @@
3
3
  <% end -%>
4
4
 
5
5
  <div class="actions">
6
+ <% if !@project.archived? -%>
7
+ <%= link_to account_project_archive_path(@project.account, @project), :method => 'post', :confirm => 'Are you sure you want to archive this project?', :class => 'action' do %>
8
+ <span class="archive_item">Archive this project</span>
9
+ <% end -%>
10
+ <% else -%>
11
+ <%= link_to account_project_archive_path(@project.account, @project), :method => 'delete', :class => 'action' do %>
12
+ <span class="unarchive_item">Unarchive this project</span>
13
+ <% end -%>
14
+ <% end -%>
6
15
  <%= link_to project_path(@project), :method => 'delete', :confirm => 'Are you sure you want to delete this project and all associated content?', :class => 'action' do %>
7
16
  <span class="delete_item">Remove this project</span>
8
17
  <% end -%>
@@ -4,12 +4,25 @@
4
4
 
5
5
  <%= render :partial => 'accounts/subnav' %>
6
6
 
7
- <ul class="projects">
8
- <% @projects.each do |project| -%>
7
+ <h3>Active Projects</h3>
8
+ <ul class="projects active">
9
+ <% @active_projects.each do |project| -%>
9
10
  <%= content_tag_for :li, project do -%>
10
- <%= link_to h(project.name), edit_project_path(project) %>
11
+ <%= link_to h(project.name), edit_project_path(project), :class => "edit" %>
11
12
  <% end -%>
12
13
  <% end -%>
13
14
  </ul>
14
15
 
15
16
  <%= link_to 'New Project', new_account_project_path(current_account), :class => "button" %>
17
+
18
+ <% if @archived_projects.any? -%>
19
+ <h3>Archived Projects</h3>
20
+ <ul class="projects archived">
21
+ <% @archived_projects.each do |project| -%>
22
+ <%= content_tag_for :li, project do -%>
23
+ <%= link_to h(project.name), edit_project_path(project), :class => "edit" %>
24
+ <%= link_to "View Project", project_path(project), :class => "view" %>
25
+ <% end -%>
26
+ <% end -%>
27
+ </ul>
28
+ <% end -%>
data/config/routes.rb CHANGED
@@ -6,7 +6,9 @@ Rails.application.routes.draw do
6
6
  through :accounts do
7
7
  resource :billing
8
8
  resource :plan
9
- resources :projects
9
+ resources :projects do
10
+ resource :archive, :only => [:create, :destroy]
11
+ end
10
12
  resources :memberships, :only => [:index, :edit, :update, :destroy]
11
13
  resources :invitations, :only => [:show, :update, :new, :create]
12
14
  end
@@ -34,17 +34,53 @@ Feature: Manage Projects
34
34
  And I press "Update"
35
35
  Then I should see "Name Change"
36
36
 
37
+ Scenario: Archive a project
38
+ Given the following project exists:
39
+ | account | name |
40
+ | name: Test | Project 1 |
41
+ When I go to the projects page for the "Test" account
42
+ And I follow "Project 1" within "ul.projects"
43
+ And I follow "Archive this project"
44
+ And I should see "Project 1" within "ul.projects.archived"
45
+
46
+ Scenario: Unarchive a project
47
+ Given the following project exists:
48
+ | account | name | archived |
49
+ | name: Test | Project 1 | true |
50
+ When I go to the projects page for the "Test" account
51
+ And I follow "Project 1" within "ul.projects.archived"
52
+ And I follow "Unarchive this project"
53
+ And I should see "Project 1" within "ul.projects.active"
54
+
55
+ Scenario: Unarchive a project when at the account limit
56
+ Given the following limit exists for the "Test" account:
57
+ | name | value |
58
+ | projects | 1 |
59
+ And the following projects exist:
60
+ | account | name | archived |
61
+ | name: Test | Project 1 | false |
62
+ | name: Test | Project 2 | true |
63
+ When I go to the projects page for the "Test" account
64
+ And I follow "Project 2"
65
+ And I follow "Unarchive this project"
66
+ Then I should see "at your limit"
67
+ When I go to the projects page for the "Test" account
68
+ And I should see "Project 1" within "ul.projects.active"
69
+ And I should see "Project 2" within "ul.projects.archived"
70
+
37
71
  Scenario: View all projects
38
72
  Given the following projects exist:
39
- | account | name |
40
- | name: Test | Project 1 |
41
- | name: Test | Project 2 |
42
- | name: Other | Project 3 |
43
- | name: Another | Project 4 |
73
+ | account | name | archived |
74
+ | name: Test | Project 1 | false |
75
+ | name: Test | Project 2 | false |
76
+ | name: Test | Project 3 | true |
77
+ | name: Other | Project 3 | false |
78
+ | name: Another | Project 4 | false |
44
79
  And "joe@example.com" is a member of the "Other" account
45
80
  When I go to the projects page for the "Test" account
46
- Then I should see "Project 1" within "ul.projects"
47
- And I should see "Project 2" within "ul.projects"
81
+ Then I should see "Project 1" within "ul.projects.active"
82
+ And I should see "Project 2" within "ul.projects.active"
83
+ And I should see "Project 3" within "ul.projects.archived"
48
84
  But I should not see "Project 3" within "ul.projects"
49
85
  And I should not see "Project 4" within "ul.projects"
50
86
 
@@ -59,6 +59,7 @@ class CreateSaucyTables < ActiveRecord::Migration
59
59
  table.string :name
60
60
  table.string :keyword
61
61
  table.integer :account_id
62
+ table.boolean :archived, :default => false, :null => false
62
63
  table.datetime :created_at
63
64
  table.datetime :updated_at
64
65
  end
data/lib/saucy/account.rb CHANGED
@@ -77,7 +77,7 @@ module Saucy
77
77
  end
78
78
 
79
79
  def projects_count
80
- projects.count
80
+ projects.active.count
81
81
  end
82
82
  end
83
83
 
data/lib/saucy/project.rb CHANGED
@@ -44,6 +44,14 @@ module Saucy
44
44
  where(['projects.id IN(?)', user.project_ids])
45
45
  end
46
46
 
47
+ def archived
48
+ where(:archived => true)
49
+ end
50
+
51
+ def active
52
+ where(:archived => false)
53
+ end
54
+
47
55
  def by_name
48
56
  order("projects.name")
49
57
  end
@@ -50,7 +50,8 @@ module Saucy
50
50
  end
51
51
 
52
52
  def index
53
- @projects = current_account.projects
53
+ @active_projects = current_account.projects.active
54
+ @archived_projects = current_account.projects.archived
54
55
  end
55
56
 
56
57
  private
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe ArchivesController, "routes" do
4
+ it { should route(:delete, "/accounts/abc/projects/def/archive").
5
+ to(:action => :destroy, :account_id => 'abc', :project_id => 'def') }
6
+ it { should route(:post, "/accounts/abc/projects/def/archive").
7
+ to(:action => :create, :account_id => 'abc', :project_id => 'def') }
8
+ end
9
+
10
+ describe ArchivesController, "destroy", :as => :project_admin do
11
+ before do
12
+ delete :destroy, :project_id => project.to_param, :account_id => account.to_param
13
+ end
14
+
15
+ it { should set_the_flash.to(/unarchived/) }
16
+
17
+ it "should redirect to account_projects_url" do
18
+ should redirect_to(account_projects_url(account))
19
+ end
20
+ end
21
+
22
+ describe ArchivesController, "archive", :as => :project_admin do
23
+ before do
24
+ post :create, :project_id => project.to_param, :account_id => account.to_param
25
+ end
26
+
27
+ it { should set_the_flash.to(/archived/) }
28
+
29
+ it "should redirect to account_projects_url" do
30
+ should redirect_to(account_projects_url(account))
31
+ end
32
+ end
33
+
34
+ describe ArchivesController, "as a non-admin", :as => :project_member do
35
+ it { should deny_access.on(:delete, :destroy, :project_id => project.to_param,
36
+ :account_id => account.to_param).
37
+ flash(/admin/) }
38
+
39
+ it { should deny_access.on(:post, :create, :account_id => account.to_param, :project_id => project.to_param).
40
+ flash(/admin/) }
41
+ end
@@ -104,6 +104,7 @@ describe ProjectsController, "index", :as => :account_admin do
104
104
  let(:projects) { ['one', 'two'] }
105
105
 
106
106
  before do
107
+ projects.stubs(:archived => projects, :active => projects)
107
108
  Account.stubs(:find_by_keyword! => account)
108
109
  account.stubs(:projects => projects)
109
110
  get :index, :account_id => account.to_param
@@ -115,8 +116,9 @@ describe ProjectsController, "index", :as => :account_admin do
115
116
  end
116
117
 
117
118
  it "assigns projects" do
118
- account.should have_received(:projects)
119
- should assign_to(:projects).with(projects)
119
+ account.should have_received(:projects).times(2)
120
+ should assign_to(:active_projects).with(projects)
121
+ should assign_to(:archived_projects).with(projects)
120
122
  end
121
123
  end
122
124
 
@@ -87,8 +87,9 @@ describe Account do
87
87
  subject.users_count.should == 1
88
88
  end
89
89
 
90
- it "has a count of projects" do
91
- Factory(:project, :account => subject)
90
+ it "has a count of active projects" do
91
+ Factory(:project, :account => subject, :archived => false)
92
+ Factory(:project, :account => subject, :archived => true)
92
93
  subject.projects_count.should == 1
93
94
  end
94
95
 
@@ -36,6 +36,21 @@ describe Project do
36
36
  Project.by_name.map(&:name).should == %w(abc def ghi)
37
37
  end
38
38
 
39
+ context "archived and non-archived projects" do
40
+ before do
41
+ @archived = [Factory(:project, :archived => true), Factory(:project, :archived => true)]
42
+ @active = [Factory(:project, :archived => false)]
43
+ end
44
+
45
+ it "returns only archived projects with archived" do
46
+ Project.archived.all.should == @archived
47
+ end
48
+
49
+ it "returns only active projects with active" do
50
+ Project.active.all.should == @active
51
+ end
52
+ end
53
+
39
54
  it "should give its keyword for to_param" do
40
55
  project = Factory(:project)
41
56
  project.to_param.should == project.keyword
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saucy
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 11
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 4
9
- - 10
10
- version: 0.4.10
8
+ - 5
9
+ - 0
10
+ version: 0.5.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - thoughtbot, inc.
@@ -125,6 +125,7 @@ extensions: []
125
125
  extra_rdoc_files: []
126
126
 
127
127
  files:
128
+ - CHANGELOG.md
128
129
  - Gemfile
129
130
  - Gemfile.lock
130
131
  - Rakefile
@@ -132,6 +133,7 @@ files:
132
133
  - config/locales/en.yml
133
134
  - config/routes.rb
134
135
  - app/controllers/accounts_controller.rb
136
+ - app/controllers/archives_controller.rb
135
137
  - app/controllers/billings_controller.rb
136
138
  - app/controllers/invitations_controller.rb
137
139
  - app/controllers/memberships_controller.rb
@@ -238,6 +240,7 @@ files:
238
240
  - lib/generators/saucy/features/templates/README
239
241
  - spec/controllers/accounts_controller_spec.rb
240
242
  - spec/controllers/application_controller_spec.rb
243
+ - spec/controllers/archives_controller_spec.rb
241
244
  - spec/controllers/invitations_controller_spec.rb
242
245
  - spec/controllers/memberships_controller_spec.rb
243
246
  - spec/controllers/plans_controller_spec.rb