Added the ability to archive projects:
* Only administrators can archive/unarchive projects. * Once archived, the project is visible on the admin project listing only. It doesn't show up anywhere else in the app. Subprojects are also archived. * Archive/unarchive preserve everything on the project (issues, members, ...). * A subproject can not be unarchived if its parent project is archived. git-svn-id: http://redmine.rubyforge.org/svn/trunk@549 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
70374d084e
commit
413247ee5b
|
@ -27,12 +27,18 @@ class AdminController < ApplicationController
|
|||
|
||||
def projects
|
||||
sort_init 'name', 'asc'
|
||||
sort_update
|
||||
@project_count = Project.count
|
||||
sort_update
|
||||
|
||||
@status = params[:status] ? params[:status].to_i : 0
|
||||
conditions = nil
|
||||
conditions = ["status=?", @status] unless @status == 0
|
||||
|
||||
@project_count = Project.count(:conditions => conditions)
|
||||
@project_pages = Paginator.new self, @project_count,
|
||||
15,
|
||||
25,
|
||||
params['page']
|
||||
@projects = Project.find :all, :order => sort_clause,
|
||||
:conditions => conditions,
|
||||
:limit => @project_pages.items_per_page,
|
||||
:offset => @project_pages.current.offset
|
||||
|
||||
|
|
|
@ -86,6 +86,11 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
# authorizes the user for the requested action.
|
||||
def authorize(ctrl = params[:controller], action = params[:action])
|
||||
unless @project.active?
|
||||
@project = nil
|
||||
render_404
|
||||
return false
|
||||
end
|
||||
# check if action is allowed on public projects
|
||||
if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ ctrl, action ]
|
||||
return true
|
||||
|
@ -105,6 +110,11 @@ class ApplicationController < ActionController::Base
|
|||
# make sure that the user is a member of the project (or admin) if project is private
|
||||
# used as a before_filter for actions that do not require any particular permission on the project
|
||||
def check_project_privacy
|
||||
unless @project.active?
|
||||
@project = nil
|
||||
render_404
|
||||
return false
|
||||
end
|
||||
return true if @project.is_public?
|
||||
return false unless logged_in_user
|
||||
return true if logged_in_user.admin? || logged_in_user_membership
|
||||
|
|
|
@ -19,9 +19,11 @@ require 'csv'
|
|||
|
||||
class ProjectsController < ApplicationController
|
||||
layout 'base'
|
||||
before_filter :find_project, :authorize, :except => [ :index, :list, :add ]
|
||||
before_filter :require_admin, :only => [ :add, :destroy ]
|
||||
before_filter :find_project, :except => [ :index, :list, :add ]
|
||||
before_filter :authorize, :except => [ :index, :list, :add, :archive, :unarchive, :destroy ]
|
||||
before_filter :require_admin, :only => [ :add, :archive, :unarchive, :destroy ]
|
||||
|
||||
cache_sweeper :project_sweeper, :only => [ :add, :edit, :archive, :unarchive, :destroy ]
|
||||
cache_sweeper :issue_sweeper, :only => [ :add_issue ]
|
||||
|
||||
helper :sort
|
||||
|
@ -86,7 +88,7 @@ class ProjectsController < ApplicationController
|
|||
def show
|
||||
@custom_values = @project.custom_values.find(:all, :include => :custom_field)
|
||||
@members_by_role = @project.members.find(:all, :include => [:user, :role], :order => 'position').group_by {|m| m.role}
|
||||
@subprojects = @project.children if @project.children.size > 0
|
||||
@subprojects = @project.active_children
|
||||
@news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
|
||||
@trackers = Tracker.find(:all, :order => 'position')
|
||||
@open_issues_by_tracker = Issue.count(:group => :tracker, :joins => "INNER JOIN #{IssueStatus.table_name} ON #{IssueStatus.table_name}.id = #{Issue.table_name}.status_id", :conditions => ["project_id=? and #{IssueStatus.table_name}.is_closed=?", @project.id, false])
|
||||
|
@ -138,12 +140,25 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def archive
|
||||
@project.archive if request.post? && @project.active?
|
||||
redirect_to :controller => 'admin', :action => 'projects'
|
||||
end
|
||||
|
||||
def unarchive
|
||||
@project.unarchive if request.post? && !@project.active?
|
||||
redirect_to :controller => 'admin', :action => 'projects'
|
||||
end
|
||||
|
||||
# Delete @project
|
||||
def destroy
|
||||
@project_to_destroy = @project
|
||||
if request.post? and params[:confirm]
|
||||
@project.destroy
|
||||
@project_to_destroy.destroy
|
||||
redirect_to :controller => 'admin', :action => 'projects'
|
||||
end
|
||||
# hide project in layout
|
||||
@project = nil
|
||||
end
|
||||
|
||||
# Add a new issue category to @project
|
||||
|
|
|
@ -55,7 +55,7 @@ class ReportsController < ApplicationController
|
|||
render :template => "reports/issue_report_details"
|
||||
when "subproject"
|
||||
@field = "project_id"
|
||||
@rows = @project.children
|
||||
@rows = @project.active_children
|
||||
@data = issues_by_subproject
|
||||
@report_title = l(:field_subproject)
|
||||
render :template => "reports/issue_report_details"
|
||||
|
@ -66,7 +66,7 @@ class ReportsController < ApplicationController
|
|||
@priorities = Enumeration::get_values('IPRI')
|
||||
@categories = @project.issue_categories
|
||||
@authors = @project.members.collect { |m| m.user }
|
||||
@subprojects = @project.children
|
||||
@subprojects = @project.active_children
|
||||
issues_by_tracker
|
||||
issues_by_version
|
||||
issues_by_priority
|
||||
|
@ -207,8 +207,8 @@ private
|
|||
#{Issue.table_name} i, #{IssueStatus.table_name} s
|
||||
where
|
||||
i.status_id=s.id
|
||||
and i.project_id IN (#{@project.children.collect{|p| p.id}.join(',')})
|
||||
group by s.id, s.is_closed, i.project_id") if @project.children.any?
|
||||
and i.project_id IN (#{@project.active_children.collect{|p| p.id}.join(',')})
|
||||
group by s.id, s.is_closed, i.project_id") if @project.active_children.any?
|
||||
@issues_by_subproject ||= []
|
||||
end
|
||||
end
|
||||
|
|
|
@ -88,7 +88,7 @@ class UsersController < ApplicationController
|
|||
end
|
||||
@auth_sources = AuthSource.find(:all)
|
||||
@roles = Role.find(:all, :order => 'position')
|
||||
@projects = Project.find(:all) - @user.projects
|
||||
@projects = Project.find(:all, :order => 'name', :conditions => "status=#{Project::STATUS_ACTIVE}") - @user.projects
|
||||
@membership ||= Member.new
|
||||
end
|
||||
|
||||
|
|
|
@ -16,4 +16,8 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module AdminHelper
|
||||
def project_status_options_for_select(selected)
|
||||
options_for_select([[l(:label_all), "*"],
|
||||
[l(:status_active), 1]], selected)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class Project < ActiveRecord::Base
|
||||
# Project statuses
|
||||
STATUS_ACTIVE = 1
|
||||
STATUS_ARCHIVED = 9
|
||||
|
||||
has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC"
|
||||
has_many :members, :dependent => :delete_all, :include => :user, :conditions => "#{User.table_name}.status=#{User::STATUS_ACTIVE}"
|
||||
has_many :users, :through => :members
|
||||
|
@ -32,6 +36,8 @@ class Project < ActiveRecord::Base
|
|||
has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", :association_foreign_key => 'custom_field_id'
|
||||
acts_as_tree :order => "name", :counter_cache => true
|
||||
|
||||
attr_protected :status
|
||||
|
||||
validates_presence_of :name, :description, :identifier
|
||||
validates_uniqueness_of :name, :identifier
|
||||
validates_associated :custom_values, :on => :update
|
||||
|
@ -52,12 +58,11 @@ class Project < ActiveRecord::Base
|
|||
|
||||
def issues_with_subprojects(include_subprojects=false)
|
||||
conditions = nil
|
||||
if include_subprojects && children.size > 0
|
||||
ids = [id] + children.collect {|c| c.id}
|
||||
if include_subprojects && !active_children.empty?
|
||||
ids = [id] + active_children.collect {|c| c.id}
|
||||
conditions = ["#{Issue.table_name}.project_id IN (#{ids.join(',')})"]
|
||||
else
|
||||
conditions = ["#{Issue.table_name}.project_id = ?", id]
|
||||
end
|
||||
conditions ||= ["#{Issue.table_name}.project_id = ?", id]
|
||||
Issue.with_scope :find => { :conditions => conditions } do
|
||||
yield
|
||||
end
|
||||
|
@ -71,14 +76,35 @@ class Project < ActiveRecord::Base
|
|||
|
||||
def self.visible_by(user=nil)
|
||||
if user && user.admin?
|
||||
return nil
|
||||
return ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"]
|
||||
elsif user && !user.memberships.empty?
|
||||
return ["#{Project.table_name}.is_public = ? or #{Project.table_name}.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')})", true]
|
||||
return ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND (#{Project.table_name}.is_public = ? or #{Project.table_name}.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')}))", true]
|
||||
else
|
||||
return ["#{Project.table_name}.is_public = ?", true]
|
||||
return ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND #{Project.table_name}.is_public = ?", true]
|
||||
end
|
||||
end
|
||||
|
||||
def active?
|
||||
self.status == STATUS_ACTIVE
|
||||
end
|
||||
|
||||
def archive
|
||||
# Archive subprojects if any
|
||||
children.each do |subproject|
|
||||
subproject.archive
|
||||
end
|
||||
update_attribute :status, STATUS_ARCHIVED
|
||||
end
|
||||
|
||||
def unarchive
|
||||
return false if parent && !parent.active?
|
||||
update_attribute :status, STATUS_ACTIVE
|
||||
end
|
||||
|
||||
def active_children
|
||||
children.select {|child| child.active?}
|
||||
end
|
||||
|
||||
# Returns an array of all custom fields enabled for project issues
|
||||
# (explictly associated custom fields and custom fields enabled for all projects)
|
||||
def custom_fields_for_issues(tracker)
|
||||
|
|
|
@ -95,8 +95,8 @@ class Query < ActiveRecord::Base
|
|||
@available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values }
|
||||
@available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => @project.issue_categories.collect{|s| [s.name, s.id.to_s] } }
|
||||
@available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.versions.sort.collect{|s| [s.name, s.id.to_s] } }
|
||||
unless @project.children.empty?
|
||||
@available_filters["subproject_id"] = { :type => :list_one_or_more, :order => 13, :values => @project.children.collect{|s| [s.name, s.id.to_s] } }
|
||||
unless @project.active_children.empty?
|
||||
@available_filters["subproject_id"] = { :type => :list_one_or_more, :order => 13, :values => @project.active_children.collect{|s| [s.name, s.id.to_s] } }
|
||||
end
|
||||
@project.all_custom_fields.select(&:is_filter?).each do |field|
|
||||
case field.field_format
|
||||
|
@ -164,7 +164,7 @@ class Query < ActiveRecord::Base
|
|||
if operator_for("subproject_id") == "="
|
||||
subproject_ids = values_for("subproject_id").each(&:to_i)
|
||||
else
|
||||
subproject_ids = project.children.collect{|p| p.id}
|
||||
subproject_ids = project.active_children.collect{|p| p.id}
|
||||
end
|
||||
sql << " AND #{Issue.table_name}.project_id IN (%d,%s)" % [project.id, subproject_ids.join(",")] if project
|
||||
else
|
||||
|
|
|
@ -23,7 +23,7 @@ class User < ActiveRecord::Base
|
|||
STATUS_REGISTERED = 2
|
||||
STATUS_LOCKED = 3
|
||||
|
||||
has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :order => "#{Project.table_name}.name", :dependent => :delete_all
|
||||
has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :conditions => "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}", :order => "#{Project.table_name}.name", :dependent => :delete_all
|
||||
has_many :projects, :through => :memberships
|
||||
has_many :custom_values, :dependent => :delete_all, :as => :customized
|
||||
has_one :preference, :dependent => :destroy, :class_name => 'UserPreference'
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# redMine - project management software
|
||||
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class ProjectSweeper < ActionController::Caching::Sweeper
|
||||
observe Project
|
||||
|
||||
def before_save(project)
|
||||
if project.new_record?
|
||||
expire_cache_for(project.parent) if project.parent
|
||||
else
|
||||
project_before_update = Project.find(project.id)
|
||||
return if project_before_update.parent_id == project.parent_id && project_before_update.status == project.status
|
||||
expire_cache_for(project.parent) if project.parent
|
||||
expire_cache_for(project_before_update.parent) if project_before_update.parent
|
||||
end
|
||||
end
|
||||
|
||||
def after_destroy(project)
|
||||
expire_cache_for(project.parent) if project.parent
|
||||
end
|
||||
|
||||
private
|
||||
def expire_cache_for(project)
|
||||
expire_fragment(Regexp.new("projects/(calendar|gantt)/#{project.id}\\."))
|
||||
end
|
||||
end
|
|
@ -4,6 +4,15 @@
|
|||
|
||||
<h2><%=l(:label_project_plural)%></h2>
|
||||
|
||||
<% form_tag() do %>
|
||||
<fieldset><legend><%= l(:label_filter_plural) %></legend>
|
||||
<label><%= l(:field_status) %> :</label>
|
||||
<%= select_tag 'status', project_status_options_for_select(@status), :class => "small", :onchange => "this.form.submit(); return false;" %>
|
||||
<%= submit_tag l(:button_apply), :class => "small" %>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
|
||||
<table class="list">
|
||||
<thead><tr>
|
||||
<%= sort_header_tag('name', :caption => l(:label_project)) %>
|
||||
|
@ -12,22 +21,29 @@
|
|||
<th><%=l(:label_subproject_plural)%></th>
|
||||
<%= sort_header_tag('created_on', :caption => l(:field_created_on)) %>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<% for project in @projects %>
|
||||
<tr class="<%= cycle("odd", "even") %>">
|
||||
<td><%= link_to project.name, :controller => 'projects', :action => 'settings', :id => project %>
|
||||
<td><%= project.active? ? link_to(project.name, :controller => 'projects', :action => 'settings', :id => project) : h(project.name) %>
|
||||
<td><%=h project.description %>
|
||||
<td align="center"><%= image_tag 'true.png' if project.is_public? %>
|
||||
<td align="center"><%= project.children.size %>
|
||||
<td align="center"><%= format_date(project.created_on) %>
|
||||
<td align="center">
|
||||
<%= button_to l(:button_delete), { :controller => 'projects', :action => 'destroy', :id => project }, :class => "button-small" %>
|
||||
<td align="center" style="width:10%">
|
||||
<small>
|
||||
<%= link_to(l(:button_archive), { :controller => 'projects', :action => 'archive', :id => project }, :method => :post, :class => 'icon icon-lock') if project.active? %>
|
||||
<%= link_to(l(:button_unarchive), { :controller => 'projects', :action => 'unarchive', :id => project }, :method => :post, :class => 'icon icon-unlock') if !project.active? && (project.parent.nil? || project.parent.active?) %>
|
||||
</small>
|
||||
</td>
|
||||
<td align="center" style="width:10%">
|
||||
<small><%= link_to(l(:button_delete), { :controller => 'projects', :action => 'destroy', :id => project }, :class => 'icon icon-del') %></small>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><%= pagination_links_full @project_pages %>
|
||||
[ <%= @project_pages.current.first_item %> - <%= @project_pages.current.last_item %> / <%= @project_count %> ]</p>
|
||||
<p><%= pagination_links_full @project_pages, :status => @status %>
|
||||
[ <%= @project_pages.current.first_item %> - <%= @project_pages.current.last_item %> / <%= @project_count %> ]</p>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<h3><%=l(:label_assigned_to_me_issues)%></h3>
|
||||
<% assigned_issues = Issue.find(:all,
|
||||
:conditions => ["assigned_to_id=? AND #{IssueStatus.table_name}.is_closed=?", user.id, false],
|
||||
:conditions => ["assigned_to_id=? AND #{IssueStatus.table_name}.is_closed=? AND #{Project.table_name}.status=#{Project::STATUS_ACTIVE}", user.id, false],
|
||||
:limit => 10,
|
||||
:include => [ :status, :project, :tracker ],
|
||||
:order => "#{Issue.table_name}.updated_on DESC") %>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<h3><%=l(:label_reported_issues)%></h3>
|
||||
<% reported_issues = Issue.find(:all,
|
||||
:conditions => ["author_id=?", user.id],
|
||||
:conditions => ["author_id=? AND #{Project.table_name}.status=#{Project::STATUS_ACTIVE}", user.id],
|
||||
:limit => 10,
|
||||
:include => [ :status, :project, :tracker ],
|
||||
:order => "#{Issue.table_name}.updated_on DESC") %>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<% watched_issues = Issue.find(:all,
|
||||
:include => [:status, :project, :tracker, :watchers],
|
||||
:limit => 10,
|
||||
:conditions => ["#{Watcher.table_name}.user_id = ?", user.id],
|
||||
:conditions => ["#{Watcher.table_name}.user_id = ? AND #{Project.table_name}.status=#{Project::STATUS_ACTIVE}", user.id],
|
||||
:order => "#{Issue.table_name}.updated_on DESC") %>
|
||||
<%= render :partial => 'issues/list_simple', :locals => { :issues => watched_issues } %>
|
||||
<% if watched_issues.length > 0 %>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<%= check_box_tag "tracker_ids[]", tracker.id, (@selected_tracker_ids.include? tracker.id.to_s) %>
|
||||
<%= tracker.name %><br />
|
||||
<% end %>
|
||||
<% if @project.children.any? %>
|
||||
<% if @project.active_children.any? %>
|
||||
<p><strong><%=l(:label_subproject_plural)%></strong></p>
|
||||
<%= check_box_tag "with_subprojects", 1, params[:with_subprojects] %> <%= l(:general_text_Yes) %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<h2><%=l(:label_confirmation)%></h2>
|
||||
<div class="box">
|
||||
<center>
|
||||
<p><strong><%= @project.name %></strong><br />
|
||||
<p><strong><%= @project_to_destroy.name %></strong><br />
|
||||
<%=l(:text_project_destroy_confirmation)%></p>
|
||||
|
||||
<p>
|
||||
<% form_tag({:controller => 'projects', :action => 'destroy', :id => @project}) do %>
|
||||
<% form_tag({:controller => 'projects', :action => 'destroy', :id => @project_to_destroy}) do %>
|
||||
<%= hidden_field_tag "confirm", 1 %>
|
||||
<%= submit_tag l(:button_delete) %>
|
||||
<% end %>
|
||||
|
|
|
@ -49,7 +49,7 @@ t_height = g_height + headers_height
|
|||
<%= check_box_tag "tracker_ids[]", tracker.id, (@selected_tracker_ids.include? tracker.id.to_s) %>
|
||||
<%= tracker.name %><br />
|
||||
<% end %>
|
||||
<% if @project.children.any? %>
|
||||
<% if @project.active_children.any? %>
|
||||
<p><strong><%=l(:label_subproject_plural)%></strong></p>
|
||||
<%= check_box_tag "with_subprojects", 1, params[:with_subprojects] %> <%= l(:general_text_Yes) %>
|
||||
<% end %>
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if @subprojects %>
|
||||
<% if @subprojects.any? %>
|
||||
<div class="box">
|
||||
<h3 class="icon22 icon22-projects"><%=l(:label_subproject_plural)%></h3>
|
||||
<%= @subprojects.collect{|p| link_to(p.name, :action => 'show', :id => p)}.join(", ") %>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
class AddProjectStatus < ActiveRecord::Migration
|
||||
def self.up
|
||||
add_column :projects, :status, :integer, :default => 1, :null => false
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_column :projects, :status
|
||||
end
|
||||
end
|
|
@ -425,6 +425,8 @@ button_rollback: Върни се към тази ревизия
|
|||
button_watch: Наблюдавай
|
||||
button_unwatch: Спри наблюдението
|
||||
button_reply: Reply
|
||||
button_archive: Archive
|
||||
button_unarchive: Unarchive
|
||||
|
||||
status_active: активен
|
||||
status_registered: регистриран
|
||||
|
|
|
@ -425,6 +425,8 @@ button_rollback: Rollback to this version
|
|||
button_watch: Watch
|
||||
button_unwatch: Unwatch
|
||||
button_reply: Reply
|
||||
button_archive: Archive
|
||||
button_unarchive: Unarchive
|
||||
|
||||
status_active: aktiv
|
||||
status_registered: angemeldet
|
||||
|
|
|
@ -425,6 +425,8 @@ button_rollback: Rollback to this version
|
|||
button_watch: Watch
|
||||
button_unwatch: Unwatch
|
||||
button_reply: Reply
|
||||
button_archive: Archive
|
||||
button_unarchive: Unarchive
|
||||
|
||||
status_active: active
|
||||
status_registered: registered
|
||||
|
|
|
@ -425,6 +425,8 @@ button_rollback: Rollback to this version
|
|||
button_watch: Watch
|
||||
button_unwatch: Unwatch
|
||||
button_reply: Reply
|
||||
button_archive: Archive
|
||||
button_unarchive: Unarchive
|
||||
|
||||
status_active: active
|
||||
status_registered: registered
|
||||
|
|
|
@ -425,6 +425,8 @@ button_rollback: Revenir à cette version
|
|||
button_watch: Surveiller
|
||||
button_unwatch: Ne plus surveiller
|
||||
button_reply: Répondre
|
||||
button_archive: Archiver
|
||||
button_unarchive: Désarchiver
|
||||
|
||||
status_active: actif
|
||||
status_registered: enregistré
|
||||
|
|
|
@ -425,6 +425,8 @@ button_rollback: Ripristina questa versione
|
|||
button_watch: Watch
|
||||
button_unwatch: Unwatch
|
||||
button_reply: Reply
|
||||
button_archive: Archive
|
||||
button_unarchive: Unarchive
|
||||
|
||||
status_active: attivo
|
||||
status_registered: registrato
|
||||
|
|
|
@ -426,6 +426,8 @@ button_rollback: このバージョンにロールバック
|
|||
button_watch: Watch
|
||||
button_unwatch: Unwatch
|
||||
button_reply: Reply
|
||||
button_archive: Archive
|
||||
button_unarchive: Unarchive
|
||||
|
||||
status_active: 有効
|
||||
status_registered: 登録
|
||||
|
|
|
@ -425,6 +425,8 @@ button_rollback: Rollback naar deze versie
|
|||
button_watch: Monitor
|
||||
button_unwatch: Niet meer monitoren
|
||||
button_reply: Antwoord
|
||||
button_archive: Archive
|
||||
button_unarchive: Unarchive
|
||||
|
||||
status_active: Actief
|
||||
status_registered: geregistreerd
|
||||
|
|
|
@ -425,6 +425,8 @@ button_rollback: Voltar para esta versao
|
|||
button_watch: Watch
|
||||
button_unwatch: Unwatch
|
||||
button_reply: Reply
|
||||
button_archive: Archive
|
||||
button_unarchive: Unarchive
|
||||
|
||||
status_active: ativo
|
||||
status_registered: registrado
|
||||
|
|
|
@ -425,6 +425,8 @@ button_rollback: Voltar para esta versão
|
|||
button_watch: Observar
|
||||
button_unwatch: Não observar
|
||||
button_reply: Reply
|
||||
button_archive: Archive
|
||||
button_unarchive: Unarchive
|
||||
|
||||
status_active: ativo
|
||||
status_registered: registrado
|
||||
|
|
|
@ -428,6 +428,8 @@ button_rollback: Rollback to this version
|
|||
button_watch: Watch
|
||||
button_unwatch: Unwatch
|
||||
button_reply: Reply
|
||||
button_archive: Archive
|
||||
button_unarchive: Unarchive
|
||||
|
||||
status_active: 激活
|
||||
status_registered: 已注册
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 643 B |
|
@ -163,6 +163,8 @@ vertical-align: middle;
|
|||
.icon-fav { background-image: url(../images/fav.png); }
|
||||
.icon-fav-off { background-image: url(../images/fav_off.png); }
|
||||
.icon-reload { background-image: url(../images/reload.png); }
|
||||
.icon-lock { background-image: url(../images/locked.png); }
|
||||
.icon-unlock { background-image: url(../images/unlock.png); }
|
||||
|
||||
.icon22-projects { background-image: url(../images/22x22/projects.png); }
|
||||
.icon22-users { background-image: url(../images/22x22/users.png); }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# redMine - project management software
|
||||
# Copyright (C) 2006 Jean-Philippe Lang
|
||||
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
@ -125,4 +125,19 @@ class ProjectsControllerTest < Test::Unit::TestCase
|
|||
assert_template 'activity'
|
||||
assert_not_nil assigns(:events_by_day)
|
||||
end
|
||||
|
||||
def test_archive
|
||||
@request.session[:user_id] = 1 # admin
|
||||
post :archive, :id => 1
|
||||
assert_redirected_to 'admin/projects'
|
||||
assert !Project.find(1).active?
|
||||
end
|
||||
|
||||
def test_unarchive
|
||||
@request.session[:user_id] = 1 # admin
|
||||
Project.find(1).archive
|
||||
post :unarchive, :id => 1
|
||||
assert_redirected_to 'admin/projects'
|
||||
assert Project.find(1).active?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# redMine - project management software
|
||||
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require "#{File.dirname(__FILE__)}/../test_helper"
|
||||
|
||||
class ProjectsTest < ActionController::IntegrationTest
|
||||
fixtures :projects, :users, :members
|
||||
|
||||
def test_archive_project
|
||||
subproject = Project.find(1).children.first
|
||||
log_user("admin", "admin")
|
||||
get "admin/projects"
|
||||
assert_response :success
|
||||
assert_template "admin/projects"
|
||||
post "projects/archive", :id => 1
|
||||
assert_redirected_to "admin/projects"
|
||||
assert !Project.find(1).active?
|
||||
|
||||
get "projects/show", :id => 1
|
||||
assert_response :missing
|
||||
get "projects/show", :id => subproject.id
|
||||
assert_response :missing
|
||||
|
||||
post "projects/unarchive", :id => 1
|
||||
assert_redirected_to "admin/projects"
|
||||
assert Project.find(1).active?
|
||||
get "projects/show", :id => 1
|
||||
assert_response :success
|
||||
end
|
||||
end
|
|
@ -1,5 +1,5 @@
|
|||
# redMine - project management software
|
||||
# Copyright (C) 2006 Jean-Philippe Lang
|
||||
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
@ -51,6 +51,34 @@ class ProjectTest < Test::Unit::TestCase
|
|||
assert_equal true, public_projects[0].is_public?
|
||||
end
|
||||
|
||||
def test_archive
|
||||
user = @ecookbook.members.first.user
|
||||
@ecookbook.archive
|
||||
@ecookbook.reload
|
||||
|
||||
assert !@ecookbook.active?
|
||||
assert !user.projects.include?(@ecookbook)
|
||||
# Subproject are also archived
|
||||
assert !@ecookbook.children.empty?
|
||||
assert @ecookbook.active_children.empty?
|
||||
end
|
||||
|
||||
def test_unarchive
|
||||
user = @ecookbook.members.first.user
|
||||
@ecookbook.archive
|
||||
# A subproject of an archived project can not be unarchived
|
||||
assert !@ecookbook_sub1.unarchive
|
||||
|
||||
# Unarchive project
|
||||
assert @ecookbook.unarchive
|
||||
@ecookbook.reload
|
||||
assert @ecookbook.active?
|
||||
assert user.projects.include?(@ecookbook)
|
||||
# Subproject can now be unarchived
|
||||
@ecookbook_sub1.reload
|
||||
assert @ecookbook_sub1.unarchive
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@ecookbook.destroy
|
||||
assert_raise(ActiveRecord::RecordNotFound) { Project.find(@ecookbook.id) }
|
||||
|
|
Loading…
Reference in New Issue