summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/controllers/custom_field_enumerations_controller.rb69
-rw-r--r--app/models/custom_field.rb4
-rw-r--r--app/models/custom_field_enumeration.rb74
-rw-r--r--app/views/custom_field_enumerations/create.js.erb2
-rw-r--r--app/views/custom_field_enumerations/destroy.html.erb14
-rw-r--r--app/views/custom_field_enumerations/index.html.erb49
-rw-r--r--app/views/custom_fields/formats/_enumeration.erb12
7 files changed, 224 insertions, 0 deletions
diff --git a/app/controllers/custom_field_enumerations_controller.rb b/app/controllers/custom_field_enumerations_controller.rb
new file mode 100644
index 000000000..ba746d2b5
--- /dev/null
+++ b/app/controllers/custom_field_enumerations_controller.rb
@@ -0,0 +1,69 @@
+# Redmine - project management software
+# Copyright (C) 2006-2015 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 CustomFieldEnumerationsController < ApplicationController
+ layout 'admin'
+
+ before_filter :require_admin
+ before_filter :find_custom_field
+ before_filter :find_enumeration, :only => :destroy
+
+ def index
+ @values = @custom_field.enumerations.order(:position)
+ end
+
+ def create
+ @value = @custom_field.enumerations.build(params[:custom_field_enumeration])
+ @value.save
+ respond_to do |format|
+ format.html { redirect_to custom_field_enumerations_path(@custom_field) }
+ format.js
+ end
+ end
+
+ def update_each
+ if CustomFieldEnumeration.update_each(@custom_field, params[:custom_field_enumerations])
+ flash[:notice] = l(:notice_successful_update)
+ end
+ redirect_to :action => 'index'
+ end
+
+ def destroy
+ reassign_to = @custom_field.enumerations.find_by_id(params[:reassign_to_id])
+ if reassign_to.nil? && @value.in_use?
+ @enumerations = @custom_field.enumerations - [@value]
+ render :action => 'destroy'
+ return
+ end
+ @value.destroy(reassign_to)
+ redirect_to custom_field_enumerations_path(@custom_field)
+ end
+
+ private
+
+ def find_custom_field
+ @custom_field = CustomField.find(params[:custom_field_id])
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
+
+ def find_enumeration
+ @value = @custom_field.enumerations.find(params[:id])
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
+end
diff --git a/app/models/custom_field.rb b/app/models/custom_field.rb
index ad87aa34e..a1373d12b 100644
--- a/app/models/custom_field.rb
+++ b/app/models/custom_field.rb
@@ -18,6 +18,10 @@
class CustomField < ActiveRecord::Base
include Redmine::SubclassFactory
+ has_many :enumerations,
+ lambda { order(:position) },
+ :class_name => 'CustomFieldEnumeration',
+ :dependent => :delete_all
has_many :custom_values, :dependent => :delete_all
has_and_belongs_to_many :roles, :join_table => "#{table_name_prefix}custom_fields_roles#{table_name_suffix}", :foreign_key => "custom_field_id"
acts_as_list :scope => 'type = \'#{self.class}\''
diff --git a/app/models/custom_field_enumeration.rb b/app/models/custom_field_enumeration.rb
new file mode 100644
index 000000000..26a580def
--- /dev/null
+++ b/app/models/custom_field_enumeration.rb
@@ -0,0 +1,74 @@
+# Redmine - project management software
+# Copyright (C) 2006-2015 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 CustomFieldEnumeration < ActiveRecord::Base
+ belongs_to :custom_field
+ attr_accessible :name, :active, :position
+
+ validates_presence_of :name, :position, :custom_field_id
+ validates_length_of :name, :maximum => 60
+ validates_numericality_of :position, :only_integer => true
+ before_create :set_position
+
+ scope :active, lambda { where(:active => true) }
+
+ def to_s
+ name.to_s
+ end
+
+ def objects_count
+ custom_values.count
+ end
+
+ def in_use?
+ objects_count > 0
+ end
+
+ alias :destroy_without_reassign :destroy
+ def destroy(reassign_to=nil)
+ if reassign_to
+ custom_values.update_all(:value => reassign_to.id.to_s)
+ end
+ destroy_without_reassign
+ end
+
+ def custom_values
+ custom_field.custom_values.where(:value => id.to_s)
+ end
+
+ def self.update_each(custom_field, attributes)
+ return unless attributes.is_a?(Hash)
+ transaction do
+ attributes.each do |enumeration_id, enumeration_attributes|
+ enumeration = custom_field.enumerations.find_by_id(enumeration_id)
+ if enumeration
+ enumeration.attributes = enumeration_attributes
+ unless enumeration.save
+ raise ActiveRecord::Rollback
+ end
+ end
+ end
+ end
+ end
+
+ private
+
+ def set_position
+ max = self.class.where(:custom_field_id => custom_field_id).maximum(:position) || 0
+ self.position = max + 1
+ end
+end
diff --git a/app/views/custom_field_enumerations/create.js.erb b/app/views/custom_field_enumerations/create.js.erb
new file mode 100644
index 000000000..9a9d40433
--- /dev/null
+++ b/app/views/custom_field_enumerations/create.js.erb
@@ -0,0 +1,2 @@
+$('#content').html('<%= escape_javascript(render(:template => 'custom_field_enumerations/index')) %>');
+$('#custom_field_enumeration_name').focus();
diff --git a/app/views/custom_field_enumerations/destroy.html.erb b/app/views/custom_field_enumerations/destroy.html.erb
new file mode 100644
index 000000000..d2ae2ed79
--- /dev/null
+++ b/app/views/custom_field_enumerations/destroy.html.erb
@@ -0,0 +1,14 @@
+<%= title [l(:label_custom_field_plural), custom_fields_path],
+ [l(@custom_field.type_name), custom_fields_path(:tab => @custom_field.class.name)],
+ @custom_field.name %>
+
+<%= form_tag(custom_field_enumeration_path(@custom_field, @value), :method => :delete) do %>
+<div class="box">
+<p><strong><%= l(:text_enumeration_destroy_question, :name => @value.name, :count => @value.objects_count) %></strong></p>
+<p><label for='reassign_to_id'><%= l(:text_enumeration_category_reassign_to) %></label>
+<%= select_tag('reassign_to_id', content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---", :value => '') + options_from_collection_for_select(@enumerations, 'id', 'name')) %></p>
+</div>
+
+<%= submit_tag l(:button_apply) %>
+<%= link_to l(:button_cancel), custom_field_enumerations_path(@custom_field) %>
+<% end %>
diff --git a/app/views/custom_field_enumerations/index.html.erb b/app/views/custom_field_enumerations/index.html.erb
new file mode 100644
index 000000000..9ca9314eb
--- /dev/null
+++ b/app/views/custom_field_enumerations/index.html.erb
@@ -0,0 +1,49 @@
+<%= title [l(:label_custom_field_plural), custom_fields_path],
+ [l(@custom_field.type_name), custom_fields_path(:tab => @custom_field.class.name)],
+ @custom_field.name %>
+
+<% if @custom_field.enumerations.any? %>
+<%= form_tag custom_field_enumerations_path(@custom_field), :method => 'put' do %>
+<div class="box">
+ <ul id="custom_field_enumerations" class="flat">
+ <% @custom_field.enumerations.each_with_index do |value, position| %>
+ <li>
+ <span class="sort-handle ui-icon ui-icon-arrowthick-2-n-s"></span>
+ <%= hidden_field_tag "custom_field_enumerations[#{value.id}][position]", position, :class => 'position' %>
+ <%= text_field_tag "custom_field_enumerations[#{value.id}][name]", value.name, :size => 40 %>
+ <%= hidden_field_tag "custom_field_enumerations[#{value.id}][active]", 0 %>
+ <label>
+ <%= check_box_tag "custom_field_enumerations[#{value.id}][active]", 1, value.active? %>
+ <%= l(:field_active) %>
+ </label>
+ <%= delete_link custom_field_enumeration_path(@custom_field, value) %>
+ </li>
+ <% end %>
+ </ul>
+</div>
+<p>
+ <%= submit_tag(l(:button_save)) %> |
+ <%= link_to l(:button_back), edit_custom_field_path(@custom_field) %>
+</p>
+<% end %>
+<% end %>
+
+<p><%= l(:label_enumeration_new) %></p>
+
+<%= form_tag custom_field_enumerations_path(@custom_field), :method => 'post', :remote => true do %>
+ <p><%= text_field_tag 'custom_field_enumeration[name]', '', :size => 40 %>
+ <%= submit_tag(l(:button_add)) %></p>
+<% end %>
+
+<%= javascript_tag do %>
+$(function() {
+ $("#custom_field_enumerations").sortable({
+ handle: ".sort-handle",
+ update: function(event, ui) {
+ $("#custom_field_enumerations li").each(function(){
+ $(this).find("input.position").val($(this).index()+1);
+ });
+ }
+ });
+});
+<% end %>
diff --git a/app/views/custom_fields/formats/_enumeration.erb b/app/views/custom_fields/formats/_enumeration.erb
new file mode 100644
index 000000000..07e4cf463
--- /dev/null
+++ b/app/views/custom_fields/formats/_enumeration.erb
@@ -0,0 +1,12 @@
+<% unless @custom_field.new_record? %>
+<p>
+ <label><%= l(:field_possible_values) %></label>
+ <%= link_to l(:button_edit), custom_field_enumerations_path(@custom_field), :class => 'icon icon-edit' %>
+</p>
+<% if @custom_field.enumerations.active.any? %>
+ <p><%= f.select :default_value, @custom_field.enumerations.active.map{|v| [v.name, v.id.to_s]}, :include_blank => true %></p>
+<% end %>
+<% end %>
+
+<p><%= f.text_field :url_pattern, :size => 50, :label => :label_link_values_to %></p>
+<p><%= edit_tag_style_tag f %></p>