* worinkg on Issue #19: DMSF document and folder can have custom fields
git-svn-id: http://redmine-dmsf.googlecode.com/svn/trunk/redmine_dmsf@280 5e329b0b-a2ee-ea63-e329-299493fc886d
This commit is contained in:
parent
4cd8f7f958
commit
d2cb53a027
@ -27,6 +27,8 @@ class DmsfController < ApplicationController
|
||||
verify :method => :post, :only => [:delete_entries, :create, :save, :delete, :save_root, :notify_activate, :notify_deactivate],
|
||||
:render => { :nothing => true, :status => :method_not_allowed }
|
||||
|
||||
helper :all
|
||||
|
||||
def show
|
||||
if @folder.nil?
|
||||
@subfolders = DmsfFolder.project_root_folders(@project)
|
||||
|
||||
@ -28,6 +28,8 @@ class DmsfFilesController < ApplicationController
|
||||
verify :method => :post, :only => [:create_revision, :delete_revision, :delete, :lock, :unlock, :notify_activate, :notify_deactivate],
|
||||
:render => { :nothing => true, :status => :method_not_allowed }
|
||||
|
||||
helper :all
|
||||
|
||||
def show
|
||||
# download is put here to provide more clear and usable links
|
||||
if params.has_key?(:download)
|
||||
|
||||
@ -26,6 +26,8 @@ class DmsfFilesCopyController < ApplicationController
|
||||
|
||||
verify :method => :post, :only => [:create, :move], :render => { :nothing => true, :status => :method_not_allowed }
|
||||
|
||||
helper :all
|
||||
|
||||
def new
|
||||
@target_project = DmsfFile.allowed_target_projects_on_copy.detect {|p| p.id.to_s == params[:target_project_id]} if params[:target_project_id]
|
||||
@target_project ||= @project if User.current.allowed_to?(:file_manipulation, @project)
|
||||
|
||||
@ -26,6 +26,8 @@ class DmsfStateController < ApplicationController
|
||||
|
||||
verify :method => :post, :only => [:user_pref_save], :render => { :nothing => true, :status => :method_not_allowed }
|
||||
|
||||
helper :all
|
||||
|
||||
def user_pref_save
|
||||
member = @project.members.find(:first, :conditions => {:user_id => User.current.id})
|
||||
if member
|
||||
|
||||
@ -28,6 +28,8 @@ class DmsfUploadController < ApplicationController
|
||||
verify :method => :post, :only => [:upload_files, :upload_file, :commit_files],
|
||||
:render => { :nothing => true, :status => :method_not_allowed }
|
||||
|
||||
helper :all
|
||||
|
||||
def upload_files
|
||||
uploaded_files = params[:uploaded_files]
|
||||
@uploads = []
|
||||
@ -141,6 +143,14 @@ class DmsfUploadController < ApplicationController
|
||||
File.delete(commited_disk_filepath)
|
||||
|
||||
files.push(file)
|
||||
|
||||
unless commited_file["dmsf_file_revision"].blank?
|
||||
commited_file["dmsf_file_revision"]["custom_field_values"].each do |v|
|
||||
cv = CustomValue.find(:first, :conditions => ["customized_id = " + new_revision.id.to_s + " AND custom_field_id = " + v[0]])
|
||||
cv.value = v[1]
|
||||
cv.save
|
||||
end
|
||||
end
|
||||
else
|
||||
failed_uploads.push(commited_file)
|
||||
end
|
||||
|
||||
@ -90,6 +90,9 @@ class DmsfFile < ActiveRecord::Base
|
||||
return false
|
||||
end
|
||||
if Setting.plugin_redmine_dmsf["dmsf_really_delete_files"]
|
||||
CustomValue.find(:all, :conditions => "customized_id = " + self.id.to_s).each do |v|
|
||||
v.destroy
|
||||
end
|
||||
self.revisions.each {|r| r.delete(true)}
|
||||
self.destroy
|
||||
else
|
||||
@ -187,6 +190,21 @@ class DmsfFile < ActiveRecord::Base
|
||||
projects
|
||||
end
|
||||
|
||||
# Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
|
||||
def available_custom_fields
|
||||
search_project = nil
|
||||
if self.project.present?
|
||||
search_project = self.project
|
||||
elsif self.project_id.present?
|
||||
search_project = Project.find(self.project_id)
|
||||
end
|
||||
if search_project
|
||||
search_project.all_dmsf_custom_fields
|
||||
else
|
||||
DmsfFileRevisionCustomField.all
|
||||
end
|
||||
end
|
||||
|
||||
def move_to(project, folder)
|
||||
if self.locked_for_user?
|
||||
errors.add_to_base(l(:error_file_is_locked))
|
||||
@ -199,6 +217,18 @@ class DmsfFile < ActiveRecord::Base
|
||||
new_revision.project = folder ? folder.project : project
|
||||
new_revision.comment = l(:comment_moved_from, :source => "#{self.project.identifier}:#{self.dmsf_path_str}")
|
||||
|
||||
new_revision.custom_values = []
|
||||
temp_custom_values = self.last_revision.custom_values.select{|cv| new_revision.project.all_dmsf_custom_fields.include?(cv.custom_field)}.map(&:clone)
|
||||
new_revision.custom_values = temp_custom_values
|
||||
|
||||
#add default value for CFs not existing
|
||||
present_custom_fields = new_revision.custom_values.collect(&:custom_field).uniq
|
||||
Project.find(new_revision.project_id).all_dmsf_custom_fields.each do |cf|
|
||||
unless present_custom_fields.include?(cf)
|
||||
new_revision.custom_values << CustomValue.new({:custom_field => cf, :value => cf.default_value})
|
||||
end
|
||||
end
|
||||
|
||||
self.folder = new_revision.folder
|
||||
self.project = new_revision.project
|
||||
|
||||
@ -212,14 +242,30 @@ class DmsfFile < ActiveRecord::Base
|
||||
file.name = self.name
|
||||
file.notification = !Setting.plugin_redmine_dmsf["dmsf_default_notifications"].blank?
|
||||
|
||||
new_revision = self.last_revision.clone
|
||||
if file.save
|
||||
new_revision = self.last_revision.clone
|
||||
|
||||
new_revision.file = file
|
||||
new_revision.folder = folder ? folder : nil
|
||||
new_revision.project = folder ? folder.project : project
|
||||
new_revision.comment = l(:comment_copied_from, :source => "#{self.project.identifier}:#{self.dmsf_path_str}")
|
||||
new_revision.file = file
|
||||
new_revision.folder = folder ? folder : nil
|
||||
new_revision.project = folder ? folder.project : project
|
||||
new_revision.comment = l(:comment_copied_from, :source => "#{self.project.identifier}: #{self.dmsf_path_str}")
|
||||
|
||||
new_revision.save if file.save
|
||||
new_revision.custom_values = []
|
||||
temp_custom_values = self.last_revision.custom_values.select{|cv| new_revision.project.all_dmsf_custom_fields.include?(cv.custom_field)}.map(&:clone)
|
||||
new_revision.custom_values = temp_custom_values
|
||||
|
||||
#add default value for CFs not existing
|
||||
present_custom_fields = new_revision.custom_values.collect(&:custom_field).uniq
|
||||
new_revision.project.all_dmsf_custom_fields.each do |cf|
|
||||
unless present_custom_fields.include?(cf)
|
||||
new_revision.custom_values << CustomValue.new({:custom_field => cf, :value => cf.default_value})
|
||||
end
|
||||
end
|
||||
|
||||
unless new_revision.save
|
||||
file.delete
|
||||
end
|
||||
end
|
||||
|
||||
return file
|
||||
end
|
||||
|
||||
@ -25,6 +25,8 @@ class DmsfFileRevision < ActiveRecord::Base
|
||||
belongs_to :deleted_by_user, :class_name => "User", :foreign_key => "deleted_by_user_id"
|
||||
belongs_to :project
|
||||
|
||||
acts_as_customizable
|
||||
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_dmsf_updated)}: #{o.file.dmsf_path_str}"},
|
||||
:url => Proc.new {|o| {:controller => 'dmsf_files', :action => 'show', :id => o.file}},
|
||||
:datetime => Proc.new {|o| o.updated_at },
|
||||
@ -77,6 +79,9 @@ class DmsfFileRevision < ActiveRecord::Base
|
||||
["disk_filename = :filename", {:filename => self.disk_filename}])
|
||||
File.delete(self.disk_file) if dependent.length <= 1 && File.exist?(self.disk_file)
|
||||
DmsfFileRevisionAccess.find(:all, :conditions => ["dmsf_file_revision_id = ?", self.id]).each {|a| a.destroy}
|
||||
CustomValue.find(:all, :conditions => "customized_id = " + self.id.to_s).each do |v|
|
||||
v.destroy
|
||||
end
|
||||
self.destroy
|
||||
else
|
||||
self.deleted = true
|
||||
@ -129,6 +134,8 @@ class DmsfFileRevision < ActiveRecord::Base
|
||||
new_revision.name = self.name
|
||||
new_revision.folder = self.folder
|
||||
|
||||
new_revision.custom_values = self.custom_values.map(&:clone)
|
||||
|
||||
return new_revision
|
||||
end
|
||||
|
||||
@ -203,4 +210,19 @@ class DmsfFileRevision < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
# Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
|
||||
def available_custom_fields
|
||||
search_project = nil
|
||||
if self.project.present?
|
||||
search_project = self.project
|
||||
elsif self.project_id.present?
|
||||
search_project = Project.find(self.project_id)
|
||||
end
|
||||
if search_project
|
||||
search_project.all_dmsf_custom_fields
|
||||
else
|
||||
DmsfFileRevisionCustomField.all
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
13
app/models/dmsf_file_revision_custom_field.rb
Normal file
13
app/models/dmsf_file_revision_custom_field.rb
Normal file
@ -0,0 +1,13 @@
|
||||
class DmsfFileRevisionCustomField < CustomField
|
||||
unloadable
|
||||
has_and_belongs_to_many :projects, :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", :foreign_key => "custom_field_id"
|
||||
|
||||
def initialize(attributes = nil)
|
||||
super
|
||||
self.searchable = true
|
||||
end
|
||||
|
||||
def type_name
|
||||
:DMSF_custom_field
|
||||
end
|
||||
end
|
||||
@ -29,6 +29,8 @@ class DmsfFolder < ActiveRecord::Base
|
||||
:conditions => { :deleted => false }
|
||||
belongs_to :user
|
||||
|
||||
acts_as_customizable
|
||||
|
||||
validates_presence_of :title
|
||||
validates_uniqueness_of :title, :scope => [:dmsf_folder_id, :project_id]
|
||||
|
||||
@ -153,6 +155,19 @@ class DmsfFolder < ActiveRecord::Base
|
||||
new_folder.description = self.description
|
||||
new_folder.user = User.current
|
||||
|
||||
#copy only cfs present in destination project
|
||||
temp_custom_values = self.custom_values.select{|cv| new_folder.project.all_dmsf_custom_fields.include?(cv.custom_field)}.map(&:clone)
|
||||
|
||||
new_folder.custom_values = temp_custom_values
|
||||
|
||||
#add default value for CFs not existing
|
||||
present_custom_fields = new_folder.custom_values.collect(&:custom_field).uniq
|
||||
new_folder.project.all_dmsf_custom_fields.each do |cf|
|
||||
unless present_custom_fields.include?(cf)
|
||||
new_folder.custom_values << CustomValue.new({:custom_field => cf, :value => cf.default_value})
|
||||
end
|
||||
end
|
||||
|
||||
return new_folder unless new_folder.save
|
||||
|
||||
self.files.each do |f|
|
||||
@ -166,6 +181,21 @@ class DmsfFolder < ActiveRecord::Base
|
||||
return new_folder
|
||||
end
|
||||
|
||||
# Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
|
||||
def available_custom_fields
|
||||
search_project = nil
|
||||
if self.project.present?
|
||||
search_project = self.project
|
||||
elsif self.project_id.present?
|
||||
search_project = Project.find(self.project_id)
|
||||
end
|
||||
if search_project
|
||||
search_project.all_dmsf_custom_fields
|
||||
else
|
||||
DmsfFileRevisionCustomField.all
|
||||
end
|
||||
end
|
||||
|
||||
# To fullfill searchable module expectations
|
||||
def self.search(tokens, projects=nil, options={})
|
||||
tokens = [] << tokens unless tokens.is_a?(Array)
|
||||
|
||||
9
app/views/dmsf/_custom_fields.html.erb
Normal file
9
app/views/dmsf/_custom_fields.html.erb
Normal file
@ -0,0 +1,9 @@
|
||||
<% unless object.nil? %>
|
||||
<div class="dmsf-customfields">
|
||||
<% object.show_custom_field_values.each do |custom_value| %>
|
||||
<div class="dmsf-customfield-<%= custom_value.custom_field.id %> dmsf-customfield customfield">
|
||||
<%= label_tag("", h(custom_value.custom_field.name) + ":") %> <%= show_value(custom_value) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
@ -36,6 +36,10 @@
|
||||
<div class="wiki data clear">
|
||||
<%= f.text_area(:description, :rows => 15, :class => "wiki-edit") %>
|
||||
</div>
|
||||
<% values = @folder ? @folder.custom_field_values : @parent ? @parent.custom_field_values : DmsfFolder.new(:project => @project).custom_field_values %>
|
||||
<% values.each do |value| %>
|
||||
<p><%= custom_field_tag_with_label(:dmsf_folder, value) %></p>
|
||||
<% end %>
|
||||
</div>
|
||||
<%= submit_tag(create ? l(:submit_create) : l(:submit_save)) %>
|
||||
<% end %>
|
||||
|
||||
@ -19,10 +19,12 @@
|
||||
<%= render(:partial => 'path', :locals => {:path => path}) %>
|
||||
</h2>
|
||||
|
||||
<div class="wiki">
|
||||
<%= textilizable(@folder.nil? ? @project.dmsf_description : @folder.description) %>
|
||||
<div class="dmsf-header">
|
||||
<div class="wiki">
|
||||
<%= textilizable(@folder.nil? ? @project.dmsf_description : @folder.description) %>
|
||||
</div>
|
||||
<%= render "custom_fields", :object => @folder %>
|
||||
</div>
|
||||
|
||||
<%
|
||||
form_tag({:action => "entries_operation", :id => @project, :folder_id => @folder}, :method => :post,
|
||||
:class => "dmfs_entries", :id => "entries_form") do
|
||||
@ -60,6 +62,7 @@ form_tag({:action => "entries_operation", :id => @project, :folder_id => @folder
|
||||
{:action => "show", :id => @project, :folder_id => subfolder},
|
||||
:class => "icon icon-folder") %>
|
||||
<div class="filename" title="<%= l(:title_number_of_files_in_directory)%>">[<%= subfolder.deep_file_count %>]</div>
|
||||
<%= render "custom_fields", :object => subfolder %>
|
||||
</td>
|
||||
<td class="size" title="<%= l(:title_total_size_of_all_files)%>"><%= number_to_human_size(subfolder.deep_size) %></td>
|
||||
<td class="modified"><%= subfolder.updated_at.strftime("%Y-%m-%d %H:%M") %></td>
|
||||
@ -110,6 +113,7 @@ form_tag({:action => "entries_operation", :id => @project, :folder_id => @folder
|
||||
:title => l(:title_title_version_version_download, :title => h(file.title), :version => file.version),
|
||||
"data-downloadurl" => "#{file.last_revision.detect_content_type}:#{h(file.name)}:#{file_download_url}") %>
|
||||
<div class="filename" title="<%= l(:title_filename_for_download)%>"><%= h(file.display_name) %></div>
|
||||
<%= render "custom_fields", :object => file.last_revision %>
|
||||
</td>
|
||||
<td class="size"><%= number_to_human_size(file.last_revision.size) %></td>
|
||||
<td class="modified">
|
||||
|
||||
@ -81,12 +81,19 @@ form_for(:dmsf_file_revision, @revision, :url => {:action => "create_revision",
|
||||
</p>
|
||||
</div>
|
||||
<br style="clear: both"/>
|
||||
<p>
|
||||
<%= label_tag("dmsf_file_revision_comment", l(:label_comment) + ":") %>
|
||||
<div class="data">
|
||||
<%= f.text_area(:comment, :rows=> "2", :style => "width: 99%;") %>
|
||||
</div>
|
||||
</p>
|
||||
<div class="custom_fields">
|
||||
<% @revision.custom_field_values.each do |value| %>
|
||||
<p><%= custom_field_tag_with_label(:dmsf_file_revision, value) %></p>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="comment">
|
||||
<p>
|
||||
<%= label_tag("dmsf_file_revision_comment", l(:label_comment) + ":") %>
|
||||
<div class="data">
|
||||
<%= f.text_area(:comment, :rows=> "2", :style => "width: 99%;") %>
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
<br />
|
||||
<%= submit_tag(l(:submit_create)) %>
|
||||
<% end %>
|
||||
|
||||
@ -117,6 +117,9 @@
|
||||
</p>
|
||||
</div>
|
||||
<br style="clear: both"/>
|
||||
<div class="no-ident clear">
|
||||
<%= render "dmsf/custom_fields", :object => revision %>
|
||||
</div>
|
||||
<p class="no-ident clear">
|
||||
<%= label_tag("", l(:label_comment) + ":") %>
|
||||
<%= h(revision.comment) %>
|
||||
|
||||
@ -15,6 +15,24 @@
|
||||
<%= submit_tag(l(:submit_save), :title => l(:title_save_preferences)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% form_for :project, @project, :url => project_path(@project), :html => {:method=>:post} do %>
|
||||
<% custom_fields = DmsfFileRevisionCustomField.find(:all) %>
|
||||
<% unless custom_fields.empty? %>
|
||||
<fieldset id="project_issue_custom_fields"><legend><%=l(:label_custom_field_plural)%></legend>
|
||||
<% custom_fields.each do |custom_field| %>
|
||||
<label class="floating">
|
||||
<%= check_box_tag 'project[dmsf_file_revision_custom_field_ids][]', custom_field.id, (@project.all_dmsf_custom_fields.include? custom_field), (custom_field.is_for_all? ? {:disabled => "disabled"} : {}) %>
|
||||
<%= custom_field.name %>
|
||||
</label>
|
||||
<% end %>
|
||||
<%= hidden_field_tag 'project[dmsf_file_revision_custom_field_ids][]', '' %>
|
||||
<%= hidden_field_tag '_method', 'put' %>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<%= submit_tag(l(:submit_save), :title => l(:title_save_preferences)) %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% content_for :header_tags do %>
|
||||
|
||||
@ -66,6 +66,11 @@ end
|
||||
</p>
|
||||
</div>
|
||||
<br style="clear: both"/>
|
||||
<% @folder ? folder_exists = true : folder_exists = false %>
|
||||
<% values = folder_exists ? @folder.custom_field_values : DmsfFileRevision.new(:file => DmsfFile.new(:project => @project)).custom_field_values %>
|
||||
<% values.each do |value| %>
|
||||
<p><%= custom_field_tag_with_label("commited_files[#{i}][dmsf_file_revision]", value) %></p>
|
||||
<% end %>
|
||||
<p>
|
||||
<%= label_tag("commited_files[#{i}][comment]", l(:label_comment) + ":") %>
|
||||
<div class="data">
|
||||
|
||||
@ -217,3 +217,19 @@ p.no-ident {
|
||||
table.access-table tbody td, table.access-table tbody tr:hover td {
|
||||
border: solid 1px #D7D7D7;
|
||||
}
|
||||
|
||||
/* Custom field */
|
||||
.dmsf-customfields {
|
||||
margin: 5px 0 5px 25px;
|
||||
}
|
||||
|
||||
.dmsf-customfields .customfield {
|
||||
|
||||
}
|
||||
|
||||
.dmsf-customfields .customfield label {
|
||||
font-weight: bold;
|
||||
width: 100px;
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
6
init.rb
6
init.rb
@ -23,6 +23,12 @@ Dispatcher.to_prepare :redmine_dmsf do
|
||||
unless ProjectsHelper.included_modules.include?(ProjectTabsExtended)
|
||||
ProjectsHelper.send(:include, ProjectTabsExtended)
|
||||
end
|
||||
|
||||
unless CustomFieldsHelper.included_modules.include?(CustomFieldsHelper)
|
||||
CustomFieldsHelper.send(:include, RedmineDmsf::Patches::CustomFieldsHelper)
|
||||
end
|
||||
|
||||
Project.send(:include, RedmineDmsf::Patches::ProjectPatch)
|
||||
end
|
||||
|
||||
Redmine::Plugin.register :redmine_dmsf do
|
||||
|
||||
6
lib/redmine_dmsf.rb
Normal file
6
lib/redmine_dmsf.rb
Normal file
@ -0,0 +1,6 @@
|
||||
require 'redmine_dmsf/patches/custom_fields_helper'
|
||||
require 'redmine_dmsf/patches/acts_as_customizable'
|
||||
require 'redmine_dmsf/patches/project_patch'
|
||||
|
||||
module RedmineDmsf
|
||||
end
|
||||
16
lib/redmine_dmsf/patches/acts_as_customizable.rb
Normal file
16
lib/redmine_dmsf/patches/acts_as_customizable.rb
Normal file
@ -0,0 +1,16 @@
|
||||
module Redmine
|
||||
module Acts
|
||||
module Customizable
|
||||
module InstanceMethods
|
||||
def available_custom_fields
|
||||
cf_classname = self.class.name == 'DmsfFolder' ? 'DmsfFileRevision' : self.class.name
|
||||
CustomField.find(:all, :conditions => "type = '#{cf_classname}CustomField'", :order => 'position')
|
||||
end
|
||||
|
||||
def show_custom_field_values
|
||||
custom_field_values.delete_if { |x| (!x.id && x.id.blank?) || x.value.blank? }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
16
lib/redmine_dmsf/patches/custom_fields_helper.rb
Normal file
16
lib/redmine_dmsf/patches/custom_fields_helper.rb
Normal file
@ -0,0 +1,16 @@
|
||||
module RedmineDmsf
|
||||
module Patches
|
||||
module CustomFieldsHelper
|
||||
def self.included(base)
|
||||
base.class_eval do
|
||||
alias_method_chain :custom_fields_tabs, :customer_tab
|
||||
end
|
||||
end
|
||||
|
||||
def custom_fields_tabs_with_customer_tab
|
||||
tabs = custom_fields_tabs_without_customer_tab
|
||||
tabs << {:name => 'DmsfFileRevisionCustomField', :partial => 'custom_fields/index', :label => :DMSF_custom_field}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
9
lib/redmine_dmsf/patches/project_patch.rb
Normal file
9
lib/redmine_dmsf/patches/project_patch.rb
Normal file
@ -0,0 +1,9 @@
|
||||
module RedmineDmsf
|
||||
module Patches
|
||||
module ProjectPatch
|
||||
def all_dmsf_custom_fields
|
||||
@all_dmsf_custom_fields ||= (DmsfFileRevisionCustomField.for_all + dmsf_file_revision_custom_fields).uniq.sort
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user