From 0b40abb821739fb7706e26eafa33c69dc06ba7a3 Mon Sep 17 00:00:00 2001 From: Karel Picman Date: Thu, 9 May 2013 12:17:12 +0200 Subject: [PATCH 01/10] Approval workflows copied fron 1.5.0 devel --- app/controllers/dmsf_workflows_controller.rb | 171 ++++++++++++++++++ app/helpers/dmsf_workflows_helper.rb | 45 +++++ app/models/dmsf_workflow.rb | 110 +++++++++++ app/models/dmsf_workflow_step.rb | 37 ++++ app/models/dmsf_workflow_step_action.rb | 24 +++ app/models/dmsf_workflow_step_assignment.rb | 26 +++ app/views/dmsf_workflows/_action.html.erb | 33 ++++ app/views/dmsf_workflows/_main.html.erb | 32 ++++ app/views/dmsf_workflows/_steps.html.erb | 81 +++++++++ app/views/dmsf_workflows/action.html.erb | 1 + app/views/dmsf_workflows/action.js.erb | 3 + app/views/dmsf_workflows/add_step.html.erb | 1 + .../autocomplete_for_user.js.erb | 1 + app/views/dmsf_workflows/edit.html.erb | 1 + app/views/dmsf_workflows/index.html.erb | 1 + app/views/dmsf_workflows/log.html.erb | 1 + app/views/dmsf_workflows/new.html.erb | 12 ++ app/views/dmsf_workflows/remove_step.html.erb | 1 + .../dmsf_workflows/reorder_steps.html.erb | 1 + assets/images/ticket_go.png | Bin 0 -> 608 bytes assets/javascripts/dmsf.css | 50 +++++ assets/stylesheets/dmsf.css | 5 + config/locales/en.yml | 17 ++ config/routes.rb | 13 ++ .../20120822100401_create_dmsf_workflows.rb | 13 ++ ...120822100402_create_dmsf_workflow_steps.rb | 15 ++ ...3_create_dmsf_workflow_step_assignments.rb | 17 ++ ...00404_create_dmsf_workflow_step_actions.rb | 17 ++ init.rb | 13 ++ lib/redmine_dmsf/patches/project_patch.rb | 2 +- .../patches/project_tabs_extended.rb | 5 +- test/fixtures/dmsf_workflow_step_actions.yml | 22 +++ .../dmsf_workflow_step_assignments.yml | 6 + test/fixtures/dmsf_workflow_steps.yml | 21 +++ test/fixtures/dmsf_workflows.yml | 8 + .../dmsf_workflow_controller_test.rb | 171 ++++++++++++++++++ test/unit/dmsf_workflow_step_action_test.rb | 60 ++++++ .../dmsf_workflow_step_assignment_test.rb | 53 ++++++ test/unit/dmsf_workflow_step_test.rb | 76 ++++++++ test/unit/dmsf_workflow_test.rb | 54 ++++++ 40 files changed, 1217 insertions(+), 3 deletions(-) create mode 100644 app/controllers/dmsf_workflows_controller.rb create mode 100644 app/helpers/dmsf_workflows_helper.rb create mode 100644 app/models/dmsf_workflow.rb create mode 100644 app/models/dmsf_workflow_step.rb create mode 100644 app/models/dmsf_workflow_step_action.rb create mode 100644 app/models/dmsf_workflow_step_assignment.rb create mode 100644 app/views/dmsf_workflows/_action.html.erb create mode 100644 app/views/dmsf_workflows/_main.html.erb create mode 100644 app/views/dmsf_workflows/_steps.html.erb create mode 100644 app/views/dmsf_workflows/action.html.erb create mode 100644 app/views/dmsf_workflows/action.js.erb create mode 100644 app/views/dmsf_workflows/add_step.html.erb create mode 100644 app/views/dmsf_workflows/autocomplete_for_user.js.erb create mode 100644 app/views/dmsf_workflows/edit.html.erb create mode 100644 app/views/dmsf_workflows/index.html.erb create mode 100644 app/views/dmsf_workflows/log.html.erb create mode 100644 app/views/dmsf_workflows/new.html.erb create mode 100644 app/views/dmsf_workflows/remove_step.html.erb create mode 100644 app/views/dmsf_workflows/reorder_steps.html.erb create mode 100644 assets/images/ticket_go.png create mode 100644 assets/javascripts/dmsf.css create mode 100644 db/migrate/20120822100401_create_dmsf_workflows.rb create mode 100644 db/migrate/20120822100402_create_dmsf_workflow_steps.rb create mode 100644 db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb create mode 100644 db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb create mode 100644 test/fixtures/dmsf_workflow_step_actions.yml create mode 100644 test/fixtures/dmsf_workflow_step_assignments.yml create mode 100644 test/fixtures/dmsf_workflow_steps.yml create mode 100644 test/fixtures/dmsf_workflows.yml create mode 100644 test/functional/dmsf_workflow_controller_test.rb create mode 100644 test/unit/dmsf_workflow_step_action_test.rb create mode 100644 test/unit/dmsf_workflow_step_assignment_test.rb create mode 100644 test/unit/dmsf_workflow_step_test.rb create mode 100644 test/unit/dmsf_workflow_test.rb diff --git a/app/controllers/dmsf_workflows_controller.rb b/app/controllers/dmsf_workflows_controller.rb new file mode 100644 index 00000000..34ca0555 --- /dev/null +++ b/app/controllers/dmsf_workflows_controller.rb @@ -0,0 +1,171 @@ +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2013 Karel Picman +# +# 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 DmsfWorkflowsController < ApplicationController + unloadable + layout :workflows_layout + + before_filter :find_workflow, :except => [:create, :new, :index] + before_filter :find_project + before_filter :authorize_global, :except => [:action, :new_action] + + def index + if @project + @workflow_pages, @workflows = paginate DmsfWorkflow.where(:project_id => @project.id), :per_page => 25 + else + @workflow_pages, @workflows = paginate DmsfWorkflow.where(:project_id => nil), :per_page => 25 + end + end + + def action + end + + def new_action + logger.info '>>>>>>>>>>>>>>>>>>>>>>> YES!' + end + + def log + end + + def new + @workflow = DmsfWorkflow.new + end + + def create + @workflow = DmsfWorkflow.new(:name => params[:dmsf_workflow][:name], :project_id => params[:project_id]) + if request.post? && @workflow.save + flash[:notice] = l(:notice_successful_create) + if @project + redirect_to settings_project_path(@project, :tab => 'dmsf') + else + redirect_to dmsf_workflows_path + end + else + render :action => 'new' + end + end + + def edit + end + + def update + if request.put? && @workflow.update_attributes({:name => params[:dmsf_workflow][:name]}) + flash[:notice] = l(:notice_successful_update) + if @project + redirect_to settings_project_path(@project, :tab => 'dmsf') + else + redirect_to dmsf_workflows_path + end + else + render :action => 'edit' + end + end + + def destroy + begin + @workflow.destroy + rescue + flash[:error] = l(:error_unable_delete_dmsf_workflow) + end + if @project + redirect_to settings_project_path(@project, :tab => 'dmsf') + else + redirect_to dmsf_workflows_path + end + end + + def autocomplete_for_user + respond_to do |format| + format.js + end + end + + def add_step + if request.post? + users = User.find_all_by_id(params[:user_ids]) + if params[:step] == '0' + if @workflow.steps.count > 0 + step = @workflow.steps.last + 1 + else + step = 1 + end + else + step = params[:step].to_i + end + operator = 1 ? params[:commit] == l(:dmsf_and) : 0 + users.each do |user| + @workflow.dmsf_workflow_steps << DmsfWorkflowStep.new( + :dmsf_workflow_id => @workflow.id, + :step => step, + :user_id => user.id, + :operator => operator) + end + @workflow.save + end + respond_to do |format| + format.html + end + end + + def remove_step + if request.delete? + DmsfWorkflowStep.where(:dmsf_workflow_id => @workflow.id, :step => params[:step]).each do |ws| + @workflow.dmsf_workflow_steps.delete(ws) + end + @workflow.dmsf_workflow_steps.each do |ws| + n = ws.step.to_i + if n > params[:step].to_i + ws.step = n - 1 + ws.save + end + end + end + respond_to do |format| + format.html + end + end + + def reorder_steps + if request.put? + @workflow.reorder_steps params[:step].to_i, params[:workflow_step][:move_to] + end + respond_to do |format| + format.html + end + end + + private + + def find_workflow + @workflow = DmsfWorkflow.find_by_id(params[:id]) + end + + def find_project + if @workflow + @project = @workflow.project + elsif params[:project_id].present? + @project = Project.find_by_id params[:project_id] + end + end + + def workflows_layout + find_workflow + find_project + @project ? 'base' : 'admin' + end +end diff --git a/app/helpers/dmsf_workflows_helper.rb b/app/helpers/dmsf_workflows_helper.rb new file mode 100644 index 00000000..c61c2ac5 --- /dev/null +++ b/app/helpers/dmsf_workflows_helper.rb @@ -0,0 +1,45 @@ +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2013 Karel Picman +# +# 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. + +module DmsfWorkflowsHelper + + def render_principals_for_new_dmsf_workflow_users(workflow) + scope = User.active.sorted.like(params[:q]) + principal_count = scope.count + principal_pages = Redmine::Pagination::Paginator.new principal_count, 100, params['page'] + principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all + + s = content_tag('div', principals_check_box_tags('user_ids[]', principals), :id => 'principals') + + links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options| + link_to text, autocomplete_for_user_dmsf_workflow_path(workflow, parameters.merge(:q => params[:q], :format => 'js')), :remote => true + } + + s + content_tag('p', links, :class => 'pagination') + end + + def dmsf_workflow_steps_options_for_select(steps) + options = Array.new + options << [l(:dmsf_new_step), 0] + steps.each do |step| + options << [step.to_s, step] + end + options_for_select(options, 0) + end + +end diff --git a/app/models/dmsf_workflow.rb b/app/models/dmsf_workflow.rb new file mode 100644 index 00000000..cb214588 --- /dev/null +++ b/app/models/dmsf_workflow.rb @@ -0,0 +1,110 @@ +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2013 Karel Picman +# +# 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 DmsfWorkflow < ActiveRecord::Base + belongs_to :project + + has_many :dmsf_workflow_steps, :dependent => :destroy + + validates_uniqueness_of :name + validates :name, :presence => true + validates_length_of :name, :maximum => 255 + + def self.workflows(project) + project ? where(:project_id => project) : where('project_id IS NULL') + end + + def project + @project = Project.find_by_id(project_id) unless @project + @project + end + + def to_s + name + end + + def approvals(step) + wa = Array.new + dmsf_workflow_steps.each do |s| + if s.step == step + wa << s + end + end + wa.sort_by { |obj| -obj.operator } + end + + def steps + ws = Array.new + dmsf_workflow_steps.each do |s| + unless ws.include? s.step + ws << s.step + end + end + ws.sort + end + + def reorder_steps(step, move_to) + case move_to + when 'highest' + unless step == 1 + dmsf_workflow_steps.each do |ws| + if ws.step < step + ws.update_attribute('step', ws.step + 1) + elsif ws.step == step + ws.update_attribute('step', 1) + end + end + end + when 'higher' + unless step == 1 + dmsf_workflow_steps.each do |ws| + if ws.step == step - 1 + ws.update_attribute('step', step) + elsif ws.step == step + ws.update_attribute('step', step - 1) + end + end + end + when 'lower' + unless step == steps.count + dmsf_workflow_steps.each do |ws| + if ws.step == step + 1 + ws.update_attribute('step', step) + elsif ws.step == step + ws.update_attribute('step', step + 1) + end + end + end + when 'lowest' + size = steps.count + unless step == size + dmsf_workflow_steps.each do |ws| + if ws.step > step + ws.update_attribute('step', ws.step - 1) + elsif ws.step == step + ws.update_attribute('step', size) + end + end + end + end + end + + def delegates + User.all + end +end \ No newline at end of file diff --git a/app/models/dmsf_workflow_step.rb b/app/models/dmsf_workflow_step.rb new file mode 100644 index 00000000..4d33a284 --- /dev/null +++ b/app/models/dmsf_workflow_step.rb @@ -0,0 +1,37 @@ +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2013 Karel Picman +# +# 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 DmsfWorkflowStep < ActiveRecord::Base + belongs_to :workflow + + has_many :dmsf_workflow_step_assignments, :dependent => :destroy + + validates :dmsf_workflow_id, :presence => true + validates :step, :presence => true + validates :user_id, :presence => true + validates :operator, :presence => true + validates_uniqueness_of :user_id, :scope => [:dmsf_workflow_id, :step] + + def soperator + operator == 1 ? l(:dmsf_and) : l(:dmsf_or) + end + + def user + User.find(user_id) + end +end \ No newline at end of file diff --git a/app/models/dmsf_workflow_step_action.rb b/app/models/dmsf_workflow_step_action.rb new file mode 100644 index 00000000..bdc10ee1 --- /dev/null +++ b/app/models/dmsf_workflow_step_action.rb @@ -0,0 +1,24 @@ +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2013 Karel Picman +# +# 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 DmsfWorkflowStepAction < ActiveRecord::Base + belongs_to :dmsf_workflow_step_assignment + + validates :dmsf_workflow_step_assignment_id, :presence => true + validates :action, :presence => true +end \ No newline at end of file diff --git a/app/models/dmsf_workflow_step_assignment.rb b/app/models/dmsf_workflow_step_assignment.rb new file mode 100644 index 00000000..1ffc5250 --- /dev/null +++ b/app/models/dmsf_workflow_step_assignment.rb @@ -0,0 +1,26 @@ +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2013 Karel Picman +# +# 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 DmsfWorkflowStepAssignment < ActiveRecord::Base + belongs_to :dmsf_workflow_step + + has_many :dmsf_workflow_step_actions, :dependent => :destroy + + validates :dmsf_workflow_step_id, :presence => true + validates :dmsf_file_revision_id, :presence => true +end \ No newline at end of file diff --git a/app/views/dmsf_workflows/_action.html.erb b/app/views/dmsf_workflows/_action.html.erb new file mode 100644 index 00000000..99b49e6e --- /dev/null +++ b/app/views/dmsf_workflows/_action.html.erb @@ -0,0 +1,33 @@ +

<%= l(:label_dmsf_workflow) %>

+ +<%= form_tag({:controller => 'dmsf_workflows', + :action => 'new_action', + :object_type => DmsfWorkflow, + :object_id => @workflow, + :project_id => @project}, + :remote => true, + :method => :post, + :id => 'new-action-form') do %> +


+ +

+
+ <%= text_area_tag :note, '', :placeholder => l(:message_dmsf_wokflow_note), :size => '38x2' %> +

+ +

+
+ <%= text_field_tag 'user_search', nil %> +

+ + <%= javascript_tag "observeSearchfield('user_search', 'users_for_delegate', '#{ escape_javascript autocomplete_for_user_dmsf_workflow_path(@workflow) }')" %> + +
+ <%= principals_check_box_tags 'watcher[user_ids][]', @workflow.delegates %> +
+ +

+ <%= submit_tag l(:button_add), :name => nil, :onclick => "hideModal(this);" %> + <%= submit_tag l(:button_cancel), :name => nil, :onclick => "hideModal(this);", :type => 'button' %> +

+<% end %> diff --git a/app/views/dmsf_workflows/_main.html.erb b/app/views/dmsf_workflows/_main.html.erb new file mode 100644 index 00000000..8e96b5ad --- /dev/null +++ b/app/views/dmsf_workflows/_main.html.erb @@ -0,0 +1,32 @@ +<% @workflows = DmsfWorkflow.where(:project_id => @project.id) if @project && @workflows.nil? %> + +
+<% if @project %> + <%= link_to l(:label_dmsf_workflow_new), new_dmsf_workflow_path(:project_id => @project.id), :class => 'icon icon-add' %> +<% else %> + <%= link_to l(:label_dmsf_workflow_new), new_dmsf_workflow_path, :class => 'icon icon-add' %> +<% end %> +
+ +

<%=l(:label_dmsf_workflow_plural)%>

+ + + + + + + +<% for workflow in @workflows %> + + + + +<% end %> + +
<%=l(:field_name)%>
<%= link_to(h(workflow.name), edit_dmsf_workflow_path(workflow)) %> + <%= delete_link dmsf_workflow_path(workflow) %> +
+ +<% if @workflow_pages %> +

<%= pagination_links_full @workflow_pages %>

+<% end %> \ No newline at end of file diff --git a/app/views/dmsf_workflows/_steps.html.erb b/app/views/dmsf_workflows/_steps.html.erb new file mode 100644 index 00000000..70afad2a --- /dev/null +++ b/app/views/dmsf_workflows/_steps.html.erb @@ -0,0 +1,81 @@ +<% if @workflow.project %> +

<%= link_to l(:label_dmsf_workflow_plural), settings_project_path(@project, :tab => 'dmsf') %> » <%=h @workflow %>

+<% else %> +

<%= link_to l(:label_dmsf_workflow_plural), dmsf_workflows_path %> » <%=h @workflow %>

+<% end %> + +<% if @project %> +
+ <%= link_to 'Action', action_dmsf_workflow_path(:project_id => @project.id, :id => @workflow, :step => 1), :remote => true %> +
+<% end %> + +<%= labelled_form_for @workflow do |f| %> + <%= error_messages_for 'workflow' %> +
+

<%= f.text_field :name, :required => true %><%= submit_tag l(:button_save) %>

+
+<% end %> + +
+ +
+<% if @workflow.steps.any? %> + + + + + + + + + <% @workflow.steps.each do |step| %> + + + + + + + <% end; reset_cycle %> + +
<%= l(:label_dmsf_workflow_step) %><%= l(:label_dmsf_workflow_approval_plural) %><%=l(:button_sort)%>
<%= step %> + <% @workflow.approvals(step).each_with_index do |approval, i| %> + <% if i != 0 %> + <%= approval.soperator %>  + <% end %> + <%= link_to_user approval.user %> + <% end %> + + <%= reorder_links('workflow_step', {:action => 'edit', :id => @workflow, :step => step}, :put) %> + + <%= delete_link edit_dmsf_workflow_path(@workflow, :step => step) %> +
+<% else %> +

<%= l(:label_no_data) %>

+<% end %> +
+ +
+ <%= form_for(@workflow, :url => edit_dmsf_workflow_path(@workflow), + :html => {:method => :post}) do |f| %> +
<%=l(:label_user_new)%> + +

<%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %>

+ <%= javascript_tag "observeSearchfield('user_search', null, '#{ escape_javascript autocomplete_for_user_dmsf_workflow_path(@workflow) }')" %> + +
+ <%= render_principals_for_new_dmsf_workflow_users(@workflow) %> +
+ +

+ <%= l(:label_dmsf_workflow_step) %> + <%= select_tag 'step', + dmsf_workflow_steps_options_for_select(@workflow.steps), + :id => 'selected_step', :style => "width:100px" %> +

+

<%= submit_tag l(:dmsf_and) %> <%= submit_tag l(:dmsf_or) %>

+
+ <% end %> +
+ +
\ No newline at end of file diff --git a/app/views/dmsf_workflows/action.html.erb b/app/views/dmsf_workflows/action.html.erb new file mode 100644 index 00000000..d1a62773 --- /dev/null +++ b/app/views/dmsf_workflows/action.html.erb @@ -0,0 +1 @@ +

WorkflowController#action

diff --git a/app/views/dmsf_workflows/action.js.erb b/app/views/dmsf_workflows/action.js.erb new file mode 100644 index 00000000..107ab390 --- /dev/null +++ b/app/views/dmsf_workflows/action.js.erb @@ -0,0 +1,3 @@ +$('#ajax-modal').html('<%= escape_javascript(render :partial => 'action', :locals => {:workflow => @workflow}) %>'); +showModal('ajax-modal', '400px'); +$('#ajax-modal').addClass('new-action'); diff --git a/app/views/dmsf_workflows/add_step.html.erb b/app/views/dmsf_workflows/add_step.html.erb new file mode 100644 index 00000000..88143721 --- /dev/null +++ b/app/views/dmsf_workflows/add_step.html.erb @@ -0,0 +1 @@ +<%= render 'steps' %> \ No newline at end of file diff --git a/app/views/dmsf_workflows/autocomplete_for_user.js.erb b/app/views/dmsf_workflows/autocomplete_for_user.js.erb new file mode 100644 index 00000000..e74e6b4c --- /dev/null +++ b/app/views/dmsf_workflows/autocomplete_for_user.js.erb @@ -0,0 +1 @@ +$('#users').html('<%= escape_javascript(render_principals_for_new_dmsf_workflow_users(@workflow)) %>'); diff --git a/app/views/dmsf_workflows/edit.html.erb b/app/views/dmsf_workflows/edit.html.erb new file mode 100644 index 00000000..88143721 --- /dev/null +++ b/app/views/dmsf_workflows/edit.html.erb @@ -0,0 +1 @@ +<%= render 'steps' %> \ No newline at end of file diff --git a/app/views/dmsf_workflows/index.html.erb b/app/views/dmsf_workflows/index.html.erb new file mode 100644 index 00000000..6dce40e9 --- /dev/null +++ b/app/views/dmsf_workflows/index.html.erb @@ -0,0 +1 @@ +<%= render 'main' %> \ No newline at end of file diff --git a/app/views/dmsf_workflows/log.html.erb b/app/views/dmsf_workflows/log.html.erb new file mode 100644 index 00000000..6231320b --- /dev/null +++ b/app/views/dmsf_workflows/log.html.erb @@ -0,0 +1 @@ +

WorkflowController#log

diff --git a/app/views/dmsf_workflows/new.html.erb b/app/views/dmsf_workflows/new.html.erb new file mode 100644 index 00000000..d2f0103f --- /dev/null +++ b/app/views/dmsf_workflows/new.html.erb @@ -0,0 +1,12 @@ +

<%= link_to l(:label_dmsf_workflow_plural), dmsf_workflows_path %> » <%=l(:label_dmsf_workflow_new)%>

+ +<%= labelled_form_for @workflow do |f| %> + <%= error_messages_for 'workflow' %> +
+

<%= f.text_field :name, :required => true %>

+ <% if params[:project_id] %> +

<%= hidden_field_tag :project_id, params[:project_id] %>

+ <% end %> +
+ <%= submit_tag l(:button_create) %> +<% end %> \ No newline at end of file diff --git a/app/views/dmsf_workflows/remove_step.html.erb b/app/views/dmsf_workflows/remove_step.html.erb new file mode 100644 index 00000000..88143721 --- /dev/null +++ b/app/views/dmsf_workflows/remove_step.html.erb @@ -0,0 +1 @@ +<%= render 'steps' %> \ No newline at end of file diff --git a/app/views/dmsf_workflows/reorder_steps.html.erb b/app/views/dmsf_workflows/reorder_steps.html.erb new file mode 100644 index 00000000..88143721 --- /dev/null +++ b/app/views/dmsf_workflows/reorder_steps.html.erb @@ -0,0 +1 @@ +<%= render 'steps' %> \ No newline at end of file diff --git a/assets/images/ticket_go.png b/assets/images/ticket_go.png new file mode 100644 index 0000000000000000000000000000000000000000..2aaec3813b6df67f837ebd1a7ba3a605f9d564b0 GIT binary patch literal 608 zcmV-m0-ybfP)}|w#Zm@lU_^)(A(3I!A`K`h1kK?MJb1tVf9AaxsVe_-(g6D9rAqDxsumT8dWVWd zB|&`x&fvwM5`#0;c0P@E1H4e)a_ zt<{3%UCJ>bm?9*G5En#byA%+-!OXlvl270*sNl^e`%fGxC1z-i>hlotsLx}>QlDw!er0*7gGd#(JV|z7n40#xL{UV~_c>Ua z#RkEOaO}`2n(ErfnQc1y>zol=G4yav(>wh>*w)3`KsW0{kEy+K4+)m*&0Tm6_}~dB ziyQNtslUXQjnm_EZ|&LMR7Dy9F+^o4s#@<5PrV>F`Wzz`uYs?tGq@l~a5(SSOmdt% zewi(oPmg^bHpMwGWMB28Vo(=j;}4kHD#Qy%YZ{Q?@f!HHF~{NRIws~v7?~aZXoc43 zZ_CvAq|qB|vB6@*ax&ALy4cvk`?*mDr(aK6;lg5{CegocV@q#p<$S}{%$w=KaT{n~ u>{DB8z`p?+yQ38!$}(~A<;#64JNchU$$I%CY#&Gf0000 RedmineDmsf::Webdav::ResourceProxy, :controller_class => RedmineDmsf::Webdav::Controller ), :at => "/dmsf/webdav" + + # Approval workflow + resources :dmsf_workflows do + member do + get 'autocomplete_for_user' + get 'action' + post 'new_action' + end + end + + match 'dmsf_workflows/:id/edit', :controller => 'dmsf_workflows', :action => 'add_step', :id => /\d+/, :via => :post + match 'dmsf_workflows/:id/edit', :controller => 'dmsf_workflows', :action => 'remove_step', :id => /\d+/, :via => :delete + match 'dmsf_workflows/:id/edit', :controller => 'dmsf_workflows', :action => 'reorder_steps', :id => /\d+/, :via => :put end diff --git a/db/migrate/20120822100401_create_dmsf_workflows.rb b/db/migrate/20120822100401_create_dmsf_workflows.rb new file mode 100644 index 00000000..c6f20b9a --- /dev/null +++ b/db/migrate/20120822100401_create_dmsf_workflows.rb @@ -0,0 +1,13 @@ +class CreateDmsfWorkflows < ActiveRecord::Migration + def self.up + create_table :dmsf_workflows do |t| + t.string :name, :null => false + t.references :project + end + add_index :dmsf_workflows, [:name], :unique => true + end + + def self.down + drop_table :dmsf_workflows + end +end diff --git a/db/migrate/20120822100402_create_dmsf_workflow_steps.rb b/db/migrate/20120822100402_create_dmsf_workflow_steps.rb new file mode 100644 index 00000000..10c1f313 --- /dev/null +++ b/db/migrate/20120822100402_create_dmsf_workflow_steps.rb @@ -0,0 +1,15 @@ +class CreateDmsfWorkflowSteps < ActiveRecord::Migration + def self.up + create_table :dmsf_workflow_steps do |t| + t.references :dmsf_workflow, :null => false + t.integer :step, :null => false + t.references :user, :null => false + t.integer :operator, :null => false + end + add_index :dmsf_workflow_steps, :dmsf_workflow_id + end + + def self.down + drop_table :dmsf_workflow_steps + end +end diff --git a/db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb b/db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb new file mode 100644 index 00000000..c62f2b69 --- /dev/null +++ b/db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb @@ -0,0 +1,17 @@ +class CreateDmsfWorkflowStepAssignments < ActiveRecord::Migration + def self.up + create_table :dmsf_workflow_step_assignments do |t| + t.references :dmsf_workflow_step, :null => false + t.references :user, :null => false + t.references :dmsf_file_revision, :null => false + end + add_index :dmsf_workflow_step_assignments, + [:dmsf_workflow_step_id, :dmsf_file_revision_id], + # The default index name exceeds the index name limit + {:name => 'index_dmsf_wrkfl_step_assigns_on_wrkfl_step_id_and_frev_id'} + end + + def self.down + drop_table :dmsf_workflow_step_assignments + end +end \ No newline at end of file diff --git a/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb b/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb new file mode 100644 index 00000000..77663ab7 --- /dev/null +++ b/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb @@ -0,0 +1,17 @@ +class CreateDmsfWorkflowStepActions < ActiveRecord::Migration + def self.up + create_table :dmsf_workflow_step_actions do |t| + t.references :dmsf_workflow_step_assignment, :null => false + t.integer :action, :null => false + t.text :note + t.timestamp :created_at + end + add_index :dmsf_workflow_step_actions, + :dmsf_workflow_step_assignment_id, + # The default index name exceeds the index name limit + {:name => 'index_dmsf_workflow_step_actions_on_workflow_step_assignment_id'} + end + def self.down + drop_table :dmsf_workflow_step_actions + end +end diff --git a/init.rb b/init.rb index 54c5dbe2..1e78d64a 100644 --- a/init.rb +++ b/init.rb @@ -58,6 +58,19 @@ Redmine::Plugin.register :redmine_dmsf do permission :file_approval, {:dmsf_files => [:delete_revision, :notify_activate, :notify_deactivate], :dmsf => [:notify_activate, :notify_deactivate]} permission :force_file_unlock, {} + permission :approval_workflows, {:dmsf_workflows => [:new, :create, :destroy, :edit, :add_step, :remove_step, :reorder_steps, :update]} + end + + # Administration menu extension + Redmine::MenuManager.map :admin_menu do |menu| + menu.push :approvalworkflows, {:controller => 'dmsf_workflows', :action => 'index'}, :caption => :label_dmsf_workflow_plural + end + + # Adds javascript and stylesheet tags for project tree view + class DmsfViewListener < Redmine::Hook::ViewListener + def view_layouts_base_html_head(context) + stylesheet_link_tag('dmsf', :plugin => :redmine_dmsf) + end end Redmine::WikiFormatting::Macros.register do diff --git a/lib/redmine_dmsf/patches/project_patch.rb b/lib/redmine_dmsf/patches/project_patch.rb index 844c6847..010d49f5 100644 --- a/lib/redmine_dmsf/patches/project_patch.rb +++ b/lib/redmine_dmsf/patches/project_patch.rb @@ -33,7 +33,7 @@ module RedmineDmsf has_many :dmsf_files, :class_name => "DmsfFile", :foreign_key => "project_id", :conditions => { :dmsf_folder_id => nil } #Fix: should only be root folders not, all folders has_many :dmsf_folders, :class_name => "DmsfFolder", :foreign_key => "project_id", :conditions => {:dmsf_folder_id => nil}, :dependent => :destroy - + has_many :dmsf_workflows, :dependent => :destroy end end diff --git a/lib/redmine_dmsf/patches/project_tabs_extended.rb b/lib/redmine_dmsf/patches/project_tabs_extended.rb index 0626fd6e..7b10c642 100644 --- a/lib/redmine_dmsf/patches/project_tabs_extended.rb +++ b/lib/redmine_dmsf/patches/project_tabs_extended.rb @@ -39,8 +39,9 @@ module RedmineDmsf def project_settings_tabs_with_dmsf tabs = project_settings_tabs_without_dmsf - if @project.module_enabled?("dmsf") - tabs.push({:name => 'dmsf', :controller => :dmsf_state, :action => :user_pref_save, :partial => 'dmsf_state/user_pref', :label => :dmsf}) + if @project.module_enabled? 'dmsf' + #tabs.push({:name => 'dmsf', :controller => :dmsf_state, :action => :user_pref_save, :partial => 'dmsf_state/user_pref', :label => :dmsf}) + tabs << {:name => 'dmsf', :controller => 'dmsf_workflows', :action => 'index', :partial => 'dmsf_workflows/main', :label => 'label_dmsf'} end return tabs end diff --git a/test/fixtures/dmsf_workflow_step_actions.yml b/test/fixtures/dmsf_workflow_step_actions.yml new file mode 100644 index 00000000..f3058e6d --- /dev/null +++ b/test/fixtures/dmsf_workflow_step_actions.yml @@ -0,0 +1,22 @@ + +--- +wfsac1: + id: 1 + dmsf_workflow_step_assignment_id: 1 + action: 1 + note: 'Approval' + created_at: '2013-05-03 10:45:35' + +wfsac2: + id: 2 + dmsf_workflow_step_assignment_id: 1 + action: 2 + note: 'Rejection' + created_at: '2013-05-03 10:45:36' + +wfsac3: + id: 3 + dmsf_workflow_step_assignment_id: 1 + action: 3 + note: 'Delegation' + created_at: '2013-05-03 10:45:37' \ No newline at end of file diff --git a/test/fixtures/dmsf_workflow_step_assignments.yml b/test/fixtures/dmsf_workflow_step_assignments.yml new file mode 100644 index 00000000..0401354f --- /dev/null +++ b/test/fixtures/dmsf_workflow_step_assignments.yml @@ -0,0 +1,6 @@ +--- +wfsa1: + id: 1 + dmsf_workflow_step_id: 1 + user_id: 1 + dmsf_file_revision_id: 2 \ No newline at end of file diff --git a/test/fixtures/dmsf_workflow_steps.yml b/test/fixtures/dmsf_workflow_steps.yml new file mode 100644 index 00000000..c315cb90 --- /dev/null +++ b/test/fixtures/dmsf_workflow_steps.yml @@ -0,0 +1,21 @@ +--- +wfs1: + id: 1 + dmsf_workflow_id: 1 + step: 1 + user_id: 1 + operator: 1 + +wfs2: + id: 2 + dmsf_workflow_id: 1 + step: 2 + user_id: 2 + operator: 1 + +wfs3: + id: 3 + dmsf_workflow_id: 1 + step: 3 + user_id: 1 + operator: 1 diff --git a/test/fixtures/dmsf_workflows.yml b/test/fixtures/dmsf_workflows.yml new file mode 100644 index 00000000..f8d8ddeb --- /dev/null +++ b/test/fixtures/dmsf_workflows.yml @@ -0,0 +1,8 @@ +--- +wf1: + id: 1 + name: wf1 + +wf2: + id: 2 + name: wf2 \ No newline at end of file diff --git a/test/functional/dmsf_workflow_controller_test.rb b/test/functional/dmsf_workflow_controller_test.rb new file mode 100644 index 00000000..aa05e62d --- /dev/null +++ b/test/functional/dmsf_workflow_controller_test.rb @@ -0,0 +1,171 @@ +require File.expand_path('../../test_helper', __FILE__) + +class DmsfWorkflowsControllerTest < RedmineDmsf::Test::TestCase + fixtures :users, :dmsf_workflows, :dmsf_workflow_steps, :projects, :roles, + :members, :member_roles + + def setup + User.current = nil + + @manager_role = Role.find_by_name('Manager') + @project = Project.find(5) + end + + def test_index_admin + @request.session[:user_id] = 1 # admin + get :index + assert_response :success + assert_template 'index' + end + + def test_index_user + @request.session[:user_id] = 2 # non admin + get :index + assert_response :forbidden + end + + def test_index_member + old_controller = @controller + @controller = ProjectsController.new + + @request.session[:user_id] = 2 + get :settings, :id => @project.id + assert_response :success + assert_template 'settings' + + @controller = old_controller + end + + def test_new_admin + @request.session[:user_id] = 1 # admin + get :new + assert_response :success + assert_template 'new' + end + + def test_new_member_no_permission + @project.enable_module!(:dmsf) + @manager_role.remove_permission! :approval_workflows + @request.session[:user_id] = 2 + get :new, {:project_id => @project.id} + assert_response :forbidden + end + + def test_new_member_no_module + @project.disable_module!(:dmsf) + @manager_role.add_permission! :approval_workflows + @request.session[:user_id] = 2 + get :new, {:project_id => @project.id} + assert_response :forbidden + end + + def test_new_member + @manager_role.add_permission! :approval_workflows + @request.session[:user_id] = 2 + @project.enable_module!(:dmsf) + get :new, {:project_id => @project.id} + assert_response :success + assert_template 'new' + end + + def test_new_no_member + @manager_role.add_permission! :approval_workflows + @request.session[:user_id] = 3 + @project.enable_module!(:dmsf) + get :new, {:project_id => @project.id} + assert_response :forbidden + end + + def test_edit + @request.session[:user_id] = 1 # admin + get :edit, :id => 1 + assert_response :success + assert_template 'edit' + end + + def test_create + @request.session[:user_id] = 1 # admin + assert_difference 'DmsfWorkflow.count', +1 do + post :create, :dmsf_workflow => {:name => 'wf3'} + end + workflow = DmsfWorkflow.first(:order => 'id DESC') + assert_redirected_to dmsf_workflows_path + assert_equal 'wf3', workflow.name + end + + def test_update + @request.session[:user_id] = 1 # admin + put :update, :id => 1, :dmsf_workflow => {:name => 'wf1a'} + workflow = DmsfWorkflow.find(1) + assert_equal 'wf1a', workflow.name + end + + def test_destroy + @request.session[:user_id] = 1 # admin + assert_difference 'DmsfWorkflow.count', -1 do + delete :destroy, :id => 1 + end + assert_redirected_to dmsf_workflows_path + assert_nil DmsfWorkflow.find_by_id(1) + end + + def test_add_step + @request.session[:user_id] = 1 # admin + assert_difference 'DmsfWorkflowStep.count', +1 do + post :add_step, :commit => 'OR', :step => 1, :id => 1, :user_ids =>[3] + end + assert_response :success + ws = DmsfWorkflowStep.first(:order => 'id DESC') + assert_equal 1, ws.dmsf_workflow_id + assert_equal 1, ws.step + assert_equal 3, ws.user_id + assert_equal 0, ws.operator + end + + def test_remove_step + @request.session[:user_id] = 1 # admin + n = DmsfWorkflowStep.where(:dmsf_workflow_id => 1, :step => 1).count + assert_difference 'DmsfWorkflowStep.count', -n do + delete :remove_step, :step => 1, :id => 1 + end + assert_response :success + ws = DmsfWorkflowStep.where(:dmsf_workflow_id => 1).first(:order => 'id ASC') + assert_equal 1, ws.step + end + + def test_reorder_steps_to_lower + @request.session[:user_id] = 1 # admin + put :reorder_steps, :step => 1, :id => 1, :workflow_step => {:move_to => 'lower'} + assert_response :success + assert_equal 2, DmsfWorkflowStep.find(1).step + assert_equal 1, DmsfWorkflowStep.find(2).step + assert_equal 3, DmsfWorkflowStep.find(3).step + end + + def test_reorder_steps_to_lowest + @request.session[:user_id] = 1 # admin + put :reorder_steps, :step => 1, :id => 1, :workflow_step => {:move_to => 'lowest'} + assert_response :success + assert_equal 3, DmsfWorkflowStep.find(1).step + assert_equal 1, DmsfWorkflowStep.find(2).step + assert_equal 2, DmsfWorkflowStep.find(3).step + end + + def test_reorder_steps_to_higher + @request.session[:user_id] = 1 # admin + put :reorder_steps, :step => 2, :id => 1, :workflow_step => {:move_to => 'higher'} + assert_response :success + assert_equal 2, DmsfWorkflowStep.find(1).step + assert_equal 1, DmsfWorkflowStep.find(2).step + assert_equal 3, DmsfWorkflowStep.find(3).step + end + + def test_reorder_steps_to_highest + @request.session[:user_id] = 1 # admin + put :reorder_steps, :step => 3, :id => 1, :workflow_step => {:move_to => 'highest'} + assert_response :success + assert_equal 2, DmsfWorkflowStep.find(1).step + assert_equal 3, DmsfWorkflowStep.find(2).step + assert_equal 1, DmsfWorkflowStep.find(3).step + end +end diff --git a/test/unit/dmsf_workflow_step_action_test.rb b/test/unit/dmsf_workflow_step_action_test.rb new file mode 100644 index 00000000..e1749116 --- /dev/null +++ b/test/unit/dmsf_workflow_step_action_test.rb @@ -0,0 +1,60 @@ +require File.expand_path('../../test_helper', __FILE__) + +class DmsfWorkflowStepActionTest < RedmineDmsf::Test::UnitTest + + + fixtures :dmsf_workflow_steps + fixtures :dmsf_workflow_step_actions + + def setup + @wfsac1 = DmsfWorkflowStepAction.find(1) + @wfsac2 = DmsfWorkflowStepAction.find(2) + @wfsac3 = DmsfWorkflowStepAction.find(3) + end + + def test_truth + assert_kind_of DmsfWorkflowStepAction, @wfsac1 + assert_kind_of DmsfWorkflowStepAction, @wfsac2 + assert_kind_of DmsfWorkflowStepAction, @wfsac3 + end + + def test_create + wfsac = DmsfWorkflowStepAction.new( + :dmsf_workflow_step_assignment_id => 1, + :action => 1, + :note => 'Approvement') + assert wfsac.save + wfsac.reload + assert wfsac.created_at + end + + def test_update + @wfsac1.dmsf_workflow_step_assignment_id = 2 + @wfsac1.action = 2 + @wfsac1.note = 'Rejection' + + assert @wfsac1.save + @wfsac1.reload + + assert_equal 2, @wfsac1.dmsf_workflow_step_assignment_id + assert_equal 2, @wfsac1.action + assert_equal 'Rejection', @wfsac1.note + end + + def test_validate_workflow_step_assignment_id_presence + @wfsac1.dmsf_workflow_step_assignment_id = nil + assert !@wfsac1.save + assert_equal 1, @wfsac1.errors.count + end + + def test_validate_action_presence + @wfsac1.action = nil + assert !@wfsac1.save + assert_equal 1, @wfsac1.errors.count + end + + def test_destroy + @wfsac1.destroy + assert_nil DmsfWorkflowStepAction.find_by_id(1) + end +end diff --git a/test/unit/dmsf_workflow_step_assignment_test.rb b/test/unit/dmsf_workflow_step_assignment_test.rb new file mode 100644 index 00000000..96189bcc --- /dev/null +++ b/test/unit/dmsf_workflow_step_assignment_test.rb @@ -0,0 +1,53 @@ +require File.expand_path('../../test_helper', __FILE__) + +class WorkflowStepAssignmentTest < RedmineDmsf::Test::UnitTest + + fixtures :users, :dmsf_file_revisions, :dmsf_workflow_steps, :dmsf_workflow_step_assignments + + def setup + @wfsa1 = DmsfWorkflowStepAssignment.find(1) + end + + def test_truth + assert_kind_of DmsfWorkflowStepAssignment, @wfsa1 + end + + def test_create + wfsa = DmsfWorkflowStepAssignment.new( + :dmsf_workflow_step_id => 2, + :user_id => 2, + :dmsf_file_revision_id => 2) + assert wfsa.save + end + + def test_update + @wfsa1.dmsf_workflow_step_id = 2 + @wfsa1.user_id = 2 + @wfsa1.dmsf_file_revision_id = 2 + + assert @wfsa1.save + @wfsa1.reload + + assert_equal 2, @wfsa1.dmsf_workflow_step_id + assert_equal 2, @wfsa1.user_id + assert_equal 2, @wfsa1.dmsf_file_revision_id + end + + def test_validate_workflow_step_id_presence + @wfsa1.dmsf_workflow_step_id = nil + assert !@wfsa1.save + assert_equal 1, @wfsa1.errors.count + end + + def test_validate_workflow_entity_id_presence + @wfsa1.dmsf_file_revision_id = nil + assert !@wfsa1.save + assert_equal 1, @wfsa1.errors.count + end + + def test_destroy + @wfsa1.destroy + assert_nil DmsfWorkflowStepAssignment.find_by_id(1) + assert_nil DmsfWorkflowStepAction.find_by_id(1) + end +end diff --git a/test/unit/dmsf_workflow_step_test.rb b/test/unit/dmsf_workflow_step_test.rb new file mode 100644 index 00000000..e9cf676f --- /dev/null +++ b/test/unit/dmsf_workflow_step_test.rb @@ -0,0 +1,76 @@ +require File.expand_path('../../test_helper', __FILE__) + +class DmsfWorkflowStepTest < RedmineDmsf::Test::UnitTest + + fixtures :users, :dmsf_workflows, :dmsf_workflow_steps + + def setup + @wfs1 = DmsfWorkflowStep.find(1) + @wfs2 = DmsfWorkflowStep.find(2) + end + + def test_truth + assert_kind_of DmsfWorkflowStep, @wfs1 + end + + def test_create + wfs = DmsfWorkflowStep.new( + :dmsf_workflow_id => 1, + :step => 2, + :user_id => 1, + :operator => 1) + assert wfs.save + end + + def test_update + @wfs1.dmsf_workflow_id = 2 + @wfs1.step = 2 + @wfs1.user_id = 2 + @wfs1.operator = 2 + + assert @wfs1.save + @wfs1.reload + + assert_equal 2, @wfs1.dmsf_workflow_id + assert_equal 2, @wfs1.step + assert_equal 2, @wfs1.user_id + assert_equal 2, @wfs1.operator + end + + def test_validate_workflow_id_presence + @wfs1.dmsf_workflow_id = nil + assert !@wfs1.save + assert_equal 1, @wfs1.errors.count + end + + def test_validate_step_presence + @wfs1.step = nil + assert !@wfs1.save + assert_equal 1, @wfs1.errors.count + end + + def test_validate_user_id_presence + @wfs1.user_id = nil + assert !@wfs1.save + assert_equal 1, @wfs1.errors.count + end + + def test_validate_operator_presence + @wfs1.operator = nil + assert !@wfs1.save + assert_equal 1, @wfs1.errors.count + end + + def test_validate_user_id_uniqueness + @wfs2.user_id = @wfs1.user_id + @wfs2.dmsf_workflow_id = @wfs1.dmsf_workflow_id + @wfs2.step = @wfs1.step + assert !@wfs2.save + assert_equal 1, @wfs2.errors.count + end + + def test_destroy + @wfs2.destroy + assert_nil DmsfWorkflowStep.find_by_id(2) + end +end diff --git a/test/unit/dmsf_workflow_test.rb b/test/unit/dmsf_workflow_test.rb new file mode 100644 index 00000000..f67e8b73 --- /dev/null +++ b/test/unit/dmsf_workflow_test.rb @@ -0,0 +1,54 @@ +require File.expand_path('../../test_helper', __FILE__) + +class DmsfWorkflowTest < RedmineDmsf::Test::UnitTest + + fixtures :projects, :dmsf_workflows, :dmsf_workflow_steps + + def setup + @wf1 = DmsfWorkflow.find(1) + @wf2 = DmsfWorkflow.find(2) + @wfs1 = DmsfWorkflowStep.find(1) + end + + def test_truth + assert_kind_of DmsfWorkflow, @wf1 + end + + def test_create + workflow = DmsfWorkflow.new(:name => 'wf') + assert workflow.save + end + + def test_update + @wf1.name = 'wf1a' + @wf1.project_id = 5 + assert @wf1.save + @wf1.reload + assert_equal 'wf1a', @wf1.name + assert_equal 5, @wf1.project_id + end + + def test_validate_name_length + @wf1.name = 'a' * 256 + assert !@wf1.save + assert_equal 1, @wf1.errors.count + end + + def test_validate_name_presence + @wf1.name = '' + assert !@wf1.save + assert_equal 1, @wf1.errors.count + end + + def test_validate_name_uniqueness + @wf2.name = @wf1.name + assert !@wf2.save + assert_equal 1, @wf2.errors.count + end + + def test_destroy + @wf1.destroy + assert_nil DmsfWorkflow.find_by_id(1) + assert_nil DmsfWorkflowStep.find_by_id(@wfs1.id) + end +end From 90eedcc2dd417b94f1ab017c036f088f9f6f54bd Mon Sep 17 00:00:00 2001 From: Karel Picman Date: Thu, 9 May 2013 16:33:07 +0200 Subject: [PATCH 02/10] Wrong parent folder path in folder edit form fixed. --- app/views/dmsf/edit.html.erb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/dmsf/edit.html.erb b/app/views/dmsf/edit.html.erb index fbc70a9a..171896ca 100644 --- a/app/views/dmsf/edit.html.erb +++ b/app/views/dmsf/edit.html.erb @@ -27,8 +27,9 @@

<%= label_tag("", l(:field_folder) + ":") %> <%= f.select(:dmsf_folder_id, - options_for_select(DmsfFolder.directory_tree(@project, @folder), - :selected => @folder.nil? ? (@pathfolder.id unless @pathfolder.nil?) : (@folder.folder.id unless @folder.folder.nil?))) %> + options_for_select(DmsfFolder.directory_tree(@project, @folder), + :selected => @parent? @parent.id : (@pathfolder.id if @pathfolder))) + %>

From cce36da72e268c65a42d97f96dfc8a458927f92d Mon Sep 17 00:00:00 2001 From: Karel Picman Date: Fri, 17 May 2013 08:35:47 +0200 Subject: [PATCH 03/10] Assigning workflows to revisions --- app/controllers/dmsf_files_controller.rb | 6 +- app/controllers/dmsf_upload_controller.rb | 8 ++- app/controllers/dmsf_workflows_controller.rb | 17 ++++-- app/helpers/dmsf_workflows_helper.rb | 8 +++ app/models/dmsf_file_revision.rb | 44 ++++++++++----- app/models/dmsf_workflow.rb | 36 ++++++++++++ app/models/dmsf_workflow_step.rb | 53 ++++++++++++++++++ app/models/dmsf_workflow_step_action.rb | 15 +++++ app/views/dmsf/show.html.erb | 33 +++++++++-- .../dmsf_files/_file_new_revision.html.erb | 31 +++------- app/views/dmsf_files/show.html.erb | 12 ++-- app/views/dmsf_upload/_upload_file.html.erb | 34 ++++++----- .../dmsf_upload/_upload_file_locked.html.erb | 12 ++-- app/views/dmsf_workflows/_action.html.erb | 18 +++--- app/views/dmsf_workflows/action.js.erb | 2 +- app/views/dmsf_workflows/new_action.js.erb | 2 + assets/images/draft.png | Bin 0 -> 461 bytes assets/javascripts/dmsf.css | 50 ----------------- config/locales/en.yml | 11 ++-- .../20120822100401_create_dmsf_workflows.rb | 23 ++++++++ ...120822100402_create_dmsf_workflow_steps.rb | 18 ++++++ ...3_create_dmsf_workflow_step_assignments.rb | 18 ++++++ ...00404_create_dmsf_workflow_step_actions.rb | 18 ++++++ init.rb | 4 +- 24 files changed, 329 insertions(+), 144 deletions(-) create mode 100644 app/views/dmsf_workflows/new_action.js.erb create mode 100644 assets/images/draft.png delete mode 100644 assets/javascripts/dmsf.css diff --git a/app/controllers/dmsf_files_controller.rb b/app/controllers/dmsf_files_controller.rb index c8d7d8ea..6b0187eb 100644 --- a/app/controllers/dmsf_files_controller.rb +++ b/app/controllers/dmsf_files_controller.rb @@ -26,6 +26,7 @@ class DmsfFilesController < ApplicationController before_filter :authorize helper :all + helper :dmsf_workflows def show # download is put here to provide more clear and usable links @@ -82,7 +83,7 @@ class DmsfFilesController < ApplicationController @revision.major_version = last_revision.major_version @revision.minor_version = last_revision.minor_version - @revision.workflow = last_revision.workflow + #@revision.workflow = last_revision.workflow version = params[:version].to_i file_upload = params[:file_upload] if file_upload.nil? @@ -96,13 +97,14 @@ class DmsfFilesController < ApplicationController @revision.disk_filename = @revision.new_storage_filename @revision.mime_type = Redmine::MimeType.of(file_upload.original_filename) end - @revision.set_workflow(params[:workflow]) + @revision.set_workflow(params[:dmsf_workflow_id], params[:commit]) @file.name = @revision.name @file.folder = @revision.folder if @revision.valid? && @file.valid? @revision.save! + @revision.assign_workflow(params[:dmsf_workflow_id]) unless file_upload.nil? @revision.copy_file_content(file_upload) end diff --git a/app/controllers/dmsf_upload_controller.rb b/app/controllers/dmsf_upload_controller.rb index 27e40fe4..7c817886 100644 --- a/app/controllers/dmsf_upload_controller.rb +++ b/app/controllers/dmsf_upload_controller.rb @@ -26,6 +26,7 @@ class DmsfUploadController < ApplicationController before_filter :find_folder, :except => [:upload_file] helper :all + helper :dmsf_workflows def upload_files uploaded_files = params[:uploaded_files] @@ -107,7 +108,7 @@ class DmsfUploadController < ApplicationController new_revision.source_revision = last_revision new_revision.major_version = last_revision.major_version new_revision.minor_version = last_revision.minor_version - new_revision.workflow = last_revision.workflow + #new_revision.workflow = last_revision.workflow end commited_disk_filepath = "#{DmsfHelper.temp_dir}/#{commited_file["disk_filename"].gsub(/[\/\\]/,'')}" @@ -120,8 +121,8 @@ class DmsfUploadController < ApplicationController new_revision.title = commited_file["title"] new_revision.description = commited_file["description"] new_revision.comment = commited_file["comment"] - new_revision.increase_version(commited_file["version"].to_i, true) - new_revision.set_workflow(commited_file["workflow"]) + new_revision.increase_version(commited_file["version"].to_i, true) + new_revision.set_workflow(commited_file[:dmsf_workflow_id], nil) new_revision.mime_type = Redmine::MimeType.of(new_revision.name) new_revision.size = File.size(commited_disk_filepath) @@ -147,6 +148,7 @@ class DmsfUploadController < ApplicationController end if new_revision.save + new_revision.assign_workflow(commited_file[:dmsf_workflow_id]) file.reload new_revision.copy_file_content(file_upload) diff --git a/app/controllers/dmsf_workflows_controller.rb b/app/controllers/dmsf_workflows_controller.rb index 34ca0555..33bb5806 100644 --- a/app/controllers/dmsf_workflows_controller.rb +++ b/app/controllers/dmsf_workflows_controller.rb @@ -32,11 +32,20 @@ class DmsfWorkflowsController < ApplicationController end end - def action + def action end - def new_action - logger.info '>>>>>>>>>>>>>>>>>>>>>>> YES!' + def new_action + action = DmsfWorkflowStepAction.new( + :dmsf_workflow_step_assignment_id => params[:dmsf_workflow_step_assignment_id], + :action => params[:step_action], + :note => params[:note]) + if request.post? && action.save + @workflow.try_finish params[:dmsf_file_revision_id] + flash[:notice] = l(:notice_successful_create) + end + # TODO: Refresh the page! + redirect_to :back end def log @@ -156,7 +165,7 @@ class DmsfWorkflowsController < ApplicationController end def find_project - if @workflow + if @workflow && @workflow.project @project = @workflow.project elsif params[:project_id].present? @project = Project.find_by_id params[:project_id] diff --git a/app/helpers/dmsf_workflows_helper.rb b/app/helpers/dmsf_workflows_helper.rb index c61c2ac5..65a9371d 100644 --- a/app/helpers/dmsf_workflows_helper.rb +++ b/app/helpers/dmsf_workflows_helper.rb @@ -42,4 +42,12 @@ module DmsfWorkflowsHelper options_for_select(options, 0) end + def dmsf_workflows_for_select(project, dmsf_workflow_id) + options = Array.new + options << [l(:option_workflow_none), nil] + DmsfWorkflow.where(['project_id = ? OR project_id IS NULL', project.id]).each do |wf| + options << [wf.name, wf.id] + end + options_for_select(options, :selected => dmsf_workflow_id) + end end diff --git a/app/models/dmsf_file_revision.rb b/app/models/dmsf_file_revision.rb index c23ff2e5..a28c96be 100644 --- a/app/models/dmsf_file_revision.rb +++ b/app/models/dmsf_file_revision.rb @@ -25,6 +25,7 @@ class DmsfFileRevision < ActiveRecord::Base belongs_to :deleted_by_user, :class_name => "User", :foreign_key => "deleted_by_user_id" belongs_to :project has_many :access, :class_name => "DmsfFileRevisionAccess", :foreign_key => "dmsf_file_revision_id", :dependent => :destroy + has_many :dmsf_workflow_step_assignment, :dependent => :destroy #Returns a list of revisions that are not deleted here, or deleted at parent level either scope :visible, lambda {|*args| joins(:file).where(DmsfFile.visible_condition(args.shift || User.current, *args)).where("#{self.table_name}.deleted = :false", :false => false ).readonly(false) } @@ -154,32 +155,47 @@ class DmsfFileRevision < ActiveRecord::Base return new_revision end - - #TODO: validate if it isn't doubled or move it to view + def workflow_str + str = '' + if dmsf_workflow_id + wf = DmsfWorkflow.find_by_id(dmsf_workflow_id) + str = "#{wf.name} - " if wf + end case workflow - when 1 then l(:title_waiting_for_approval) - when 2 then l(:title_approved) - else nil + when 1 + str + l(:title_waiting_for_approval) + when 2 + str + l(:title_approved) + when 3 + str + l(:title_draft) + else + str end end - def set_workflow(workflow) + def set_workflow(dmsf_workflow_id, commit) if User.current.allowed_to?(:file_approval, self.file.project) - self.workflow = workflow - else - if self.source_revision.nil? - self.workflow = workflow == 2 ? 1 : workflow - else - if workflow == 2 || self.source_revision.workflow == 1 || self.source_revision.workflow == 2 - self.workflow = 1 + unless dmsf_workflow_id.blank? + self.dmsf_workflow_id = dmsf_workflow_id + if commit == l(:label_dmsf_wokflow_action_start) + self.workflow = 1 # Waiting for approval else - self.workflow = workflow + self.workflow = 3 # Draft end end end end + def assign_workflow(dmsf_workflow_id) + if User.current.allowed_to?(:file_approval, self.file.project) + if self.workflow == 1 # Waiting for approval + wf = DmsfWorkflow.find_by_id(dmsf_workflow_id) + wf.assign(self.id) if wf && self.id + end + end + end + def increase_version(version_to_increase, new_content) if new_content self.minor_version = case version_to_increase diff --git a/app/models/dmsf_workflow.rb b/app/models/dmsf_workflow.rb index cb214588..74708290 100644 --- a/app/models/dmsf_workflow.rb +++ b/app/models/dmsf_workflow.rb @@ -24,6 +24,12 @@ class DmsfWorkflow < ActiveRecord::Base validates_uniqueness_of :name validates :name, :presence => true validates_length_of :name, :maximum => 255 + + STATE_NONE = nil + STATE_DRAFT = 3 + STATE_WAITING_FOR_APPROVAL = 1 + STATE_APPROVED = 2 + STATE_REJECTED = 4 def self.workflows(project) project ? where(:project_id => project) : where('project_id IS NULL') @@ -107,4 +113,34 @@ class DmsfWorkflow < ActiveRecord::Base def delegates User.all end + + def get_free_assignment(user, dmsf_file_revision_id) + steps = DmsfWorkflowStep.where(:dmsf_workflow_id => self.id).all(:order => 'step ASC') + steps.each do |step| + unless step.finished?(dmsf_file_revision_id) + return step.get_free_assignment(dmsf_file_revision_id, user) + end + end + return nil + end + + def assign(dmsf_file_revision_id) + dmsf_workflow_steps.each do |ws| + ws.assign(dmsf_file_revision_id) + end + end + + def try_finish(dmsf_file_revision_id) + res = nil + steps = DmsfWorkflowStep.where(:dmsf_workflow_id => self.id).all + steps.each do |step| + res = step.result dmsf_file_revision_id + unless step.finished? dmsf_file_revision_id + return + end + end + revision = DmsfFileRevision.find_by_id dmsf_file_revision_id + revision.update_attribute(:workflow, res) if revision && res + end + end \ No newline at end of file diff --git a/app/models/dmsf_workflow_step.rb b/app/models/dmsf_workflow_step.rb index 4d33a284..de8baa72 100644 --- a/app/models/dmsf_workflow_step.rb +++ b/app/models/dmsf_workflow_step.rb @@ -34,4 +34,57 @@ class DmsfWorkflowStep < ActiveRecord::Base def user User.find(user_id) end + + def assign(dmsf_file_revision_id) + step_assignment = DmsfWorkflowStepAssignment.new( + :dmsf_workflow_step_id => id, + :user_id => user_id, + :dmsf_file_revision_id => dmsf_file_revision_id) + step_assignment.save + end + + def finished?(dmsf_file_revision_id) + res = result(dmsf_file_revision_id) + res == DmsfWorkflow::STATE_APPROVED || res == DmsfWorkflow::STATE_REJECTED + end + + def result(dmsf_file_revision_id) + assignments = DmsfWorkflowStepAssignment.where( + :dmsf_workflow_step_id => self.id, :dmsf_file_revision_id => dmsf_file_revision_id).all + assignments.each do |assignment| + actions = DmsfWorkflowStepAction.where( + :dmsf_workflow_step_assignment_id => assignment.id).all + if actions.empty? + return + end + actions.each do |action| + if DmsfWorkflowStepAction.is_finished?(action.action) + case action.action + when DmsfWorkflowStepAction::ACTION_APPROVE + return DmsfWorkflow::STATE_APPROVED + when DmsfWorkflowStepAction::ACTION_REJECT + return DmsfWorkflow::STATE_REJECTED + else + return + end + end + end + end + end + + def get_free_assignment(dmsf_file_revision_id, user) + assignment = DmsfWorkflowStepAssignment.where( + :dmsf_workflow_step_id => self.id, + :dmsf_file_revision_id => dmsf_file_revision_id, + :user_id => user.id).first + actions = DmsfWorkflowStepAction.where( + :dmsf_workflow_step_assignment_id => assignment.id).all + actions.each do |action| + if action && action.is_finished? + return + end + end + return assignment.id + end + end \ No newline at end of file diff --git a/app/models/dmsf_workflow_step_action.rb b/app/models/dmsf_workflow_step_action.rb index bdc10ee1..9748aa3b 100644 --- a/app/models/dmsf_workflow_step_action.rb +++ b/app/models/dmsf_workflow_step_action.rb @@ -17,8 +17,23 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class DmsfWorkflowStepAction < ActiveRecord::Base + belongs_to :dmsf_workflow_step_assignment validates :dmsf_workflow_step_assignment_id, :presence => true validates :action, :presence => true + + ACTION_APPROVE = 1 + ACTION_REJECT = 2 + ACTION_DELEGATE = 3 + + def self.is_finished?(action) + action == DmsfWorkflowStepAction::ACTION_APPROVE || + action == DmsfWorkflowStepAction::ACTION_REJECT + end + + def is_finished? + DmsfWorkflowStepAction.is_finished? self.action + end + end \ No newline at end of file diff --git a/app/views/dmsf/show.html.erb b/app/views/dmsf/show.html.erb index cb423fd8..9702a086 100644 --- a/app/views/dmsf/show.html.erb +++ b/app/views/dmsf/show.html.erb @@ -43,6 +43,9 @@ <%= render "custom_fields", :object => @folder %> + +<%= error_messages_for('dmsf_workflow') %> + <%= form_tag({:action => :entries_operation, :id => @project, :folder_id => @folder}, :method => :post, :class => "dmfs_entries", :id => "entries_form") do %> <%= hidden_field_tag("action") %> @@ -170,11 +173,31 @@ <%= file.last_revision.version %> - <% case file.last_revision.workflow - when 1 then %><%= image_tag("waitingforapproval.png", :title => l(:title_waiting_for_approval), - :plugin => :redmine_dmsf) %> - <% when 2 then %><%= image_tag("approved.png", :title => l(:title_approved), - :plugin => :redmine_dmsf) %> + <% case file.last_revision.workflow %> + <% when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL %> + <% wf = DmsfWorkflow.find_by_id(file.last_revision.dmsf_workflow_id) %> + <% if wf %> + <% dmsf_workflow_step_assignment_id = wf.get_free_assignment(User.current, file.last_revision.id) %> + <% if dmsf_workflow_step_assignment_id %> + <%= link_to( + image_tag('waitingforapproval.png', :plugin => :redmine_dmsf), + action_dmsf_workflow_path( + :project_id => @project.id, + :id => wf.id, + :dmsf_workflow_step_assignment_id => dmsf_workflow_step_assignment_id, + :dmsf_file_revision_id => file.last_revision.id), + :title => l(:title_waiting_for_approval), + :remote => true) %> + <% else %> + <%= image_tag('waitingforapproval.png', :title => l(:title_waiting_for_approval), :plugin => :redmine_dmsf) %> + <% end %> + <% end %> + <% when DmsfWorkflow::STATE_APPROVED %> + <%= image_tag('approved.png', :title => l(:title_approved), :plugin => :redmine_dmsf) %> + <% when DmsfWorkflow::STATE_DRAFT %> + <%= image_tag('draft.png', :title => l(:title_draft), :plugin => :redmine_dmsf) %> + <% when DmsfWorkflow::STATE_REJECTED %> + <%= image_tag('delete.png', :title => l(:title_rejected), :plugin => :redmine_dmsf) %> <% end %> <%= h(file.last_revision.user) %> diff --git a/app/views/dmsf_files/_file_new_revision.html.erb b/app/views/dmsf_files/_file_new_revision.html.erb index a3a1546c..87a97d33 100644 --- a/app/views/dmsf_files/_file_new_revision.html.erb +++ b/app/views/dmsf_files/_file_new_revision.html.erb @@ -4,21 +4,6 @@ <% if @file.locked_for_user? %>

<%= l(:info_file_locked) %>

<% else %> -<% -disabled_workflow = [] -selected_workflow = nil -if !User.current.allowed_to?(:file_approval, @project) - disabled_workflow << 2 - current_workflow = @file.last_revision.workflow - if current_workflow == 1 || current_workflow == 2 - disabled_workflow << nil - selected_workflow = 1 - end -else - selected_workflow = @file.last_revision.workflow -end -%> - <%= form_for(@revision, :url => {:action => "create_revision", :id => @file}, :html => {:method=>:post, :multipart => true, :id => "new_revision_form"}) do |f| %>
@@ -60,12 +45,13 @@ end

<%= label_tag("workflow", l(:label_workflow) + ":") %> - <%= select_tag("workflow", - options_for_select([ - [l(:option_workflow_none), nil], - [l(:option_workflow_waiting_for_approval), 1], - [l(:option_workflow_approved), 2]], - :selected => selected_workflow, :disabled => disabled_workflow)) %> + <%= select_tag( + 'dmsf_workflow_id', + dmsf_workflows_for_select(@project, @file.last_revision.dmsf_workflow_id))%> + <% if @file.last_revision.dmsf_workflow_id && @file.last_revision.workflow == 3%> + <%= submit_tag(l(:label_dmsf_wokflow_action_start)) %> + <% end %> +

@@ -78,7 +64,7 @@ end (<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
-

+


@@ -96,6 +82,7 @@ end

<%= submit_tag(l(:submit_create)) %> + <% end %> <% end %> diff --git a/app/views/dmsf_files/show.html.erb b/app/views/dmsf_files/show.html.erb index a0263f83..edd3573f 100644 --- a/app/views/dmsf_files/show.html.erb +++ b/app/views/dmsf_files/show.html.erb @@ -101,11 +101,13 @@

<%= label_tag("", l(:label_workflow) + ":") %> - <%= case revision.workflow - when 1 then l(:option_workflow_waiting_for_approval) - when 2 then l(:option_workflow_approved) - else l(:option_workflow_none) - end %> + <%= #case revision.workflow + # when 1 then l(:option_workflow_waiting_for_approval) + # when 2 then l(:option_workflow_approved) + # else l(:option_workflow_none) + # end + revision.workflow_str + %>

diff --git a/app/views/dmsf_upload/_upload_file.html.erb b/app/views/dmsf_upload/_upload_file.html.erb index 3264915a..4f52aef8 100644 --- a/app/views/dmsf_upload/_upload_file.html.erb +++ b/app/views/dmsf_upload/_upload_file.html.erb @@ -1,16 +1,16 @@ <% -disabled_workflow = [] -selected_workflow = nil -unless User.current.allowed_to?(:file_approval, @project) - disabled_workflow << 2 - current_workflow = upload.workflow - if current_workflow == 1 || current_workflow == 2 - disabled_workflow << nil - selected_workflow = 1 - end -else - selected_workflow = upload.workflow -end +#disabled_workflow = [] +#selected_workflow = nil +#unless User.current.allowed_to?(:file_approval, @project) + #disabled_workflow << 2 + #current_workflow = upload.workflow + #if current_workflow == 1 || current_workflow == 2 + #disabled_workflow << nil + #selected_workflow = 1 + #end +#else + #selected_workflow = upload.workflow +#end %>
<%= hidden_field_tag("commited_files[#{i}][disk_filename]", upload.disk_filename) %> @@ -47,12 +47,10 @@ end

<%= label_tag("commited_files[#{i}][workflow]", l(:label_workflow) + ":") %> - <%= select_tag("commited_files[#{i}][workflow]", - options_for_select([ - [l(:option_workflow_none), nil], - [l(:option_workflow_waiting_for_approval), 1], - [l(:option_workflow_approved), 2]], - :selected => selected_workflow, :disabled => disabled_workflow)) %> + <%= select_tag( + "commited_files[#{i}][dmsf_workflow_id]", + dmsf_workflows_for_select(@project, nil))%> +

diff --git a/app/views/dmsf_upload/_upload_file_locked.html.erb b/app/views/dmsf_upload/_upload_file_locked.html.erb index b536ad54..dec8da17 100644 --- a/app/views/dmsf_upload/_upload_file_locked.html.erb +++ b/app/views/dmsf_upload/_upload_file_locked.html.erb @@ -30,11 +30,13 @@

<%= label_tag("", l(:label_workflow) + ":") %> - <%= case upload.workflow - when 1 then l(:option_workflow_waiting_for_approval) - when 2 then l(:option_workflow_approved) - else l(:option_workflow_none) - end %> + <%= #case upload.workflow + # when 1 then l(:option_workflow_waiting_for_approval) + # when 2 then l(:option_workflow_approved) + # else l(:option_workflow_none) + # end + upload.workflow_str + %>

diff --git a/app/views/dmsf_workflows/_action.html.erb b/app/views/dmsf_workflows/_action.html.erb index 99b49e6e..4c35e181 100644 --- a/app/views/dmsf_workflows/_action.html.erb +++ b/app/views/dmsf_workflows/_action.html.erb @@ -3,20 +3,22 @@ <%= form_tag({:controller => 'dmsf_workflows', :action => 'new_action', :object_type => DmsfWorkflow, - :object_id => @workflow, - :project_id => @project}, + :object_id => @workflow.id, + :project_id => @project.id}, :remote => true, :method => :post, - :id => 'new-action-form') do %> -


+ :id => 'new-action-form') do %> + <%= hidden_field_tag :dmsf_workflow_step_assignment_id, params[:dmsf_workflow_step_assignment_id] %> + <%= hidden_field_tag :dmsf_file_revision_id, params[:dmsf_file_revision_id] %> +


-
+
<%= text_area_tag :note, '', :placeholder => l(:message_dmsf_wokflow_note), :size => '38x2' %>

-
+
<%= text_field_tag 'user_search', nil %>

@@ -27,7 +29,7 @@

- <%= submit_tag l(:button_add), :name => nil, :onclick => "hideModal(this);" %> - <%= submit_tag l(:button_cancel), :name => nil, :onclick => "hideModal(this);", :type => 'button' %> + <%= submit_tag l(:submit_commit), :name => nil, :onclick => 'hideModal(this);' %> + <%= submit_tag l(:button_cancel), :name => nil, :onclick => 'hideModal(this);' %>

<% end %> diff --git a/app/views/dmsf_workflows/action.js.erb b/app/views/dmsf_workflows/action.js.erb index 107ab390..b4294050 100644 --- a/app/views/dmsf_workflows/action.js.erb +++ b/app/views/dmsf_workflows/action.js.erb @@ -1,3 +1,3 @@ $('#ajax-modal').html('<%= escape_javascript(render :partial => 'action', :locals => {:workflow => @workflow}) %>'); showModal('ajax-modal', '400px'); -$('#ajax-modal').addClass('new-action'); +$('#ajax-modal').addClass('new-action'); \ No newline at end of file diff --git a/app/views/dmsf_workflows/new_action.js.erb b/app/views/dmsf_workflows/new_action.js.erb new file mode 100644 index 00000000..92d31fd2 --- /dev/null +++ b/app/views/dmsf_workflows/new_action.js.erb @@ -0,0 +1,2 @@ +$('#ajax-modal').modal('hide').empty(); +window.location.reload(); \ No newline at end of file diff --git a/assets/images/draft.png b/assets/images/draft.png new file mode 100644 index 0000000000000000000000000000000000000000..6902ab0cc75af10f160eb1b5f143c77b7f6dc3f8 GIT binary patch literal 461 zcmV;;0W$uHP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m?d01m?e$8V@)00007bV*G`2i*k^ z2puUwI-kD)00B)&L_t(2&vlSbCeG^&Ux!%-(Xnern{Y$XAYxD5tvASz>`=aPP7H}U6 zM7x^M8>$U|ZLq?p3BlH}4M6JD0pRdl@#NA4K(A{iSQ((0p}*4rpu1f$+@b@})~wT_ z>&0l=(_8+h;CbwwDaWI%V&+OYU)U~JuG(|?Z~Q=FE#<`G1Ik$w>X)7lgM)L2!LUJn zl^~J6!M=ZW#GhKn03Sdk+{pM)D*&&#PuBNcl9{_KF!FDOrX`(+=XY;WUU;S@KTJzb zm+jlMr*tV|6r{Ac(J{&{|QmLNSH00000NkvXXu0mjf DQQ6Jc literal 0 HcmV?d00001 diff --git a/assets/javascripts/dmsf.css b/assets/javascripts/dmsf.css deleted file mode 100644 index 72eaa000..00000000 --- a/assets/javascripts/dmsf.css +++ /dev/null @@ -1,50 +0,0 @@ -/* An image next to the approval workflow item in the administration menu */ -#admin-menu a.workflow { background-image: url(../images/ticket_go.png); } - -.dmsf-entity-container { - padding: 0% 2%; -} - -.dmsf-entity-container .dmsf-entity { - padding: 5px; - line-height: 28px; -} - -li.dmsf-entity-file, -li.dmsf-entity-folder { - border: 1px solid #628DB6; - border-width: 1px 0; - list-style: none; - zoom: 1; - overflow: hidden; -} - -.dmsf-entity-container .dmsf-entity .dmsf-col { - float: left; - padding-top: 1px; -} - -.dmsf-entity-container .dmsf-entity .dmsf-col.dmsf-entity-name { - width: 30%; -} - -.dmsf-entity-container .dmsf-entity .dmsf-col.dmsf-entity-cat { - width: 15%; -} - -.dmsf-entity-container .dmsf-entity .dmsf-col.dmsf-entity-lock { - width: 5%; -} - -.dmsf-entity-container .dmsf-entity .dmsf-col.dmsf-entity-size { - width: 10%; -} -.dmsf-entity-container .dmsf-entity .dmsf-col.dmsf-entity-modified { - width: 10%; -} -.dmsf-entity-container .dmsf-entity .dmsf-col.dmsf-entity-action { - width: 20%; -} - -#users_for_delegate {height: 200px; overflow:auto;} -#users_for_delegate label {display: block;} \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 41a96af5..bf4019e4 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -55,7 +55,7 @@ en: :title_locked_by_user: "Locked by %{user}" :title_locked_by_you: "Locked by you" :title_waiting_for_approval: "Waiting for Approval" - :title_approved: "Approved" + :title_approved: "Approved" :title_unlock_file: "Unlock to allow changes for other members" :title_lock_file: "Lock to prevent changes for other members" :submit_download: "Download" @@ -95,9 +95,7 @@ en: :info_changed_by_user: "%{changed} by %{user}" :label_filename: "Filename" :label_version: "Version" - :label_workflow: "Workflow" - :option_workflow_waiting_for_approval: "Waiting for approval" - :option_workflow_approved: "Approved" + :label_workflow: "Workflow" :option_workflow_none: "None" :label_mime: "Mime" :label_size: "Size" @@ -223,5 +221,8 @@ en: label_dmsf: DMSF label_dmsf_wokflow_action_approve: Approve label_dmsf_wokflow_action_reject: Reject - label_dmsf_wokflow_action_delegate: 'Delegate to:' + label_dmsf_wokflow_action_delegate: 'Delegate to' message_dmsf_wokflow_note: Your note... + title_draft: Draft + title_rejected: Rejected + label_dmsf_wokflow_action_start: Start workflow \ No newline at end of file diff --git a/db/migrate/20120822100401_create_dmsf_workflows.rb b/db/migrate/20120822100401_create_dmsf_workflows.rb index c6f20b9a..fbb00c29 100644 --- a/db/migrate/20120822100401_create_dmsf_workflows.rb +++ b/db/migrate/20120822100401_create_dmsf_workflows.rb @@ -1,3 +1,21 @@ +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2013 Karel Picman +# +# 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 CreateDmsfWorkflows < ActiveRecord::Migration def self.up create_table :dmsf_workflows do |t| @@ -5,9 +23,14 @@ class CreateDmsfWorkflows < ActiveRecord::Migration t.references :project end add_index :dmsf_workflows, [:name], :unique => true + + change_table :dmsf_file_revisions do |t| + t.references :dmsf_workflow + end end def self.down + remove_column :dmsf_file_revisions, :dmsf_workflow_id drop_table :dmsf_workflows end end diff --git a/db/migrate/20120822100402_create_dmsf_workflow_steps.rb b/db/migrate/20120822100402_create_dmsf_workflow_steps.rb index 10c1f313..8d8b3c3a 100644 --- a/db/migrate/20120822100402_create_dmsf_workflow_steps.rb +++ b/db/migrate/20120822100402_create_dmsf_workflow_steps.rb @@ -1,3 +1,21 @@ +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2013 Karel Picman +# +# 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 CreateDmsfWorkflowSteps < ActiveRecord::Migration def self.up create_table :dmsf_workflow_steps do |t| diff --git a/db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb b/db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb index c62f2b69..aff1e31f 100644 --- a/db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb +++ b/db/migrate/20120822100403_create_dmsf_workflow_step_assignments.rb @@ -1,3 +1,21 @@ +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2013 Karel Picman +# +# 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 CreateDmsfWorkflowStepAssignments < ActiveRecord::Migration def self.up create_table :dmsf_workflow_step_assignments do |t| diff --git a/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb b/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb index 77663ab7..e7704c5e 100644 --- a/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb +++ b/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb @@ -1,3 +1,21 @@ +# Redmine plugin for Document Management System "Features" +# +# Copyright (C) 2013 Karel Picman +# +# 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 CreateDmsfWorkflowStepActions < ActiveRecord::Migration def self.up create_table :dmsf_workflow_step_actions do |t| diff --git a/init.rb b/init.rb index 1e78d64a..f864c5d9 100644 --- a/init.rb +++ b/init.rb @@ -66,9 +66,9 @@ Redmine::Plugin.register :redmine_dmsf do menu.push :approvalworkflows, {:controller => 'dmsf_workflows', :action => 'index'}, :caption => :label_dmsf_workflow_plural end - # Adds javascript and stylesheet tags for project tree view + # Adds stylesheet tag class DmsfViewListener < Redmine::Hook::ViewListener - def view_layouts_base_html_head(context) + def view_layouts_base_html_head(context) stylesheet_link_tag('dmsf', :plugin => :redmine_dmsf) end end From 64d8c521df3a6c162c76026629f444b22bf6b77c Mon Sep 17 00:00:00 2001 From: Karel Picman Date: Fri, 24 May 2013 14:25:36 +0200 Subject: [PATCH 04/10] Assigning of approval workflows to revisions --- app/controllers/dmsf_controller.rb | 18 +++- app/controllers/dmsf_workflows_controller.rb | 68 ++++++++++---- app/helpers/dmsf_workflows_helper.rb | 21 ++++- app/models/dmsf_file_revision.rb | 27 +++--- app/models/dmsf_workflow.rb | 52 ++++++++--- app/models/dmsf_workflow_step.rb | 14 +-- app/models/dmsf_workflow_step_action.rb | 1 + app/views/dmsf/show.html.erb | 87 ++++++++++-------- .../dmsf_files/_file_new_revision.html.erb | 2 +- app/views/dmsf_files/show.html.erb | 71 ++++++-------- app/views/dmsf_mailer/files_updated.html.erb | 2 +- app/views/dmsf_mailer/files_updated.text.erb | 2 +- .../dmsf_mailer/files_updated.text.html.rhtml | 2 +- .../files_updated.text.plain.rhtml | 2 +- app/views/dmsf_upload/_upload_file.html.erb | 15 +-- .../dmsf_upload/_upload_file_locked.html.erb | 8 +- app/views/dmsf_workflows/_action.html.erb | 26 ++---- app/views/dmsf_workflows/_assign.html.erb | 21 +++++ app/views/dmsf_workflows/_steps.html.erb | 4 +- app/views/dmsf_workflows/action.html.erb | 1 - app/views/dmsf_workflows/assign.js.erb | 3 + .../autocomplete_for_user.html.erb | 1 + .../autocomplete_for_user.js.erb | 1 - assets/images/approve.png | Bin 535 -> 0 bytes assets/images/approved.png | Bin 262 -> 752 bytes assets/images/askforapproval.png | Bin 641 -> 0 bytes assets/images/draft.png | Bin 461 -> 459 bytes assets/images/none.png | Bin 0 -> 776 bytes assets/images/rejected.png | Bin 0 -> 631 bytes assets/images/waiting_for_approval.png | Bin 0 -> 630 bytes assets/images/waitingforapproval.png | Bin 412 -> 0 bytes assets/images/workflowdisabled.png | Bin 1392 -> 0 bytes assets/stylesheets/dmsf.css | 28 +++++- config/locales/en.yml | 9 +- config/routes.rb | 5 +- init.rb | 10 +- 36 files changed, 309 insertions(+), 192 deletions(-) create mode 100644 app/views/dmsf_workflows/_assign.html.erb delete mode 100644 app/views/dmsf_workflows/action.html.erb create mode 100644 app/views/dmsf_workflows/assign.js.erb create mode 100644 app/views/dmsf_workflows/autocomplete_for_user.html.erb delete mode 100644 app/views/dmsf_workflows/autocomplete_for_user.js.erb delete mode 100644 assets/images/approve.png delete mode 100644 assets/images/askforapproval.png create mode 100644 assets/images/none.png create mode 100644 assets/images/rejected.png create mode 100644 assets/images/waiting_for_approval.png delete mode 100644 assets/images/waitingforapproval.png delete mode 100644 assets/images/workflowdisabled.png diff --git a/app/controllers/dmsf_controller.rb b/app/controllers/dmsf_controller.rb index 579ca759..211f4d4b 100644 --- a/app/controllers/dmsf_controller.rb +++ b/app/controllers/dmsf_controller.rb @@ -255,8 +255,22 @@ class DmsfController < ApplicationController redirect_to params[:current] ? params[:current] : {:controller => "dmsf", :action => "show", :id => @project, :folder_id => @folder.folder} end - - + + def assign + end + + def assignment + revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id] + if revision + revision.set_workflow(params[:dmsf_workflow_id], params[:action]) + revision.assign_workflow(params[:dmsf_workflow_id]) + if request.post? && revision.save + flash[:notice] = l(:notice_successful_create) + end + end + redirect_to params[:current] ? params[:current] : + {:controller => "dmsf", :action => "show", :id => @project, :folder_id => @folder.folder} + end private diff --git a/app/controllers/dmsf_workflows_controller.rb b/app/controllers/dmsf_workflows_controller.rb index 33bb5806..9416ea3b 100644 --- a/app/controllers/dmsf_workflows_controller.rb +++ b/app/controllers/dmsf_workflows_controller.rb @@ -20,9 +20,9 @@ class DmsfWorkflowsController < ApplicationController unloadable layout :workflows_layout - before_filter :find_workflow, :except => [:create, :new, :index] - before_filter :find_project - before_filter :authorize_global, :except => [:action, :new_action] + before_filter :find_workflow, :except => [:create, :new, :index, :assign, :assignment] + before_filter :find_project, :except => [:start] + before_filter :authorize_global #, :except => [:action, :new_action] def index if @project @@ -35,18 +35,40 @@ class DmsfWorkflowsController < ApplicationController def action end - def new_action - action = DmsfWorkflowStepAction.new( - :dmsf_workflow_step_assignment_id => params[:dmsf_workflow_step_assignment_id], - :action => params[:step_action], - :note => params[:note]) - if request.post? && action.save - @workflow.try_finish params[:dmsf_file_revision_id] - flash[:notice] = l(:notice_successful_create) - end - # TODO: Refresh the page! + def new_action + if params[:commit] == l(:submit_commit) + action = DmsfWorkflowStepAction.new( + :dmsf_workflow_step_assignment_id => params[:dmsf_workflow_step_assignment_id], + :action => params[:step_action], + :note => params[:note]) + if request.post? + if action.save + @workflow.try_finish params[:dmsf_file_revision_id], action, params[:user_id] + flash[:notice] = l(:notice_successful_update) + else + flash[:error] = l(:error_empty_note) + end + end + end redirect_to :back end + + def assign + end + + def assignment + if params[:commit] == l(:button_assign) + revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id] + if revision + revision.set_workflow(params[:dmsf_workflow_id], params[:action]) + revision.assign_workflow(params[:dmsf_workflow_id]) + if request.post? && revision.save + flash[:notice] = l(:notice_successful_update) + end + end + end + redirect_to :back + end def log end @@ -87,7 +109,8 @@ class DmsfWorkflowsController < ApplicationController def destroy begin - @workflow.destroy + @workflow.destroy + flash[:notice] = l(:notice_successful_delete) rescue flash[:error] = l(:error_unable_delete_dmsf_workflow) end @@ -98,10 +121,8 @@ class DmsfWorkflowsController < ApplicationController end end - def autocomplete_for_user - respond_to do |format| - format.js - end + def autocomplete_for_user + render :layout => false end def add_step @@ -158,6 +179,17 @@ class DmsfWorkflowsController < ApplicationController end end + def start + revision = DmsfFileRevision.find_by_id(params[:dmsf_file_revision_id]) + if revision + revision.set_workflow(@workflow.id, params[:action]) + if request.post? && revision.save + flash[:notice] = l(:notice_successful_update) + end + end + redirect_to :back + end + private def find_workflow diff --git a/app/helpers/dmsf_workflows_helper.rb b/app/helpers/dmsf_workflows_helper.rb index 65a9371d..690e109d 100644 --- a/app/helpers/dmsf_workflows_helper.rb +++ b/app/helpers/dmsf_workflows_helper.rb @@ -18,19 +18,24 @@ module DmsfWorkflowsHelper - def render_principals_for_new_dmsf_workflow_users(workflow) - scope = User.active.sorted.like(params[:q]) + def render_principals_for_new_dmsf_workflow_users(workflow, dmsf_workflow_step_assignment_id, dmsf_file_revision_id) + scope = workflow.delegates(params[:q], dmsf_workflow_step_assignment_id, dmsf_file_revision_id, nil) principal_count = scope.count - principal_pages = Redmine::Pagination::Paginator.new principal_count, 100, params['page'] + principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page'] principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all - s = content_tag('div', principals_check_box_tags('user_ids[]', principals), :id => 'principals') + if dmsf_workflow_step_assignment_id + s = content_tag('div', principals_radio_button_tags('step_action', principals), :id => 'users_for_delegate') + else + s = content_tag('div', principals_check_box_tags('user_ids[]', principals), :id => 'users') + end links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options| link_to text, autocomplete_for_user_dmsf_workflow_path(workflow, parameters.merge(:q => params[:q], :format => 'js')), :remote => true } s + content_tag('p', links, :class => 'pagination') + s.html_safe end def dmsf_workflow_steps_options_for_select(steps) @@ -50,4 +55,12 @@ module DmsfWorkflowsHelper end options_for_select(options, :selected => dmsf_workflow_id) end + + def principals_radio_button_tags(name, principals) + s = '' + principals.each do |principal| + s << "\n" + end + s.html_safe + end end diff --git a/app/models/dmsf_file_revision.rb b/app/models/dmsf_file_revision.rb index a28c96be..0ce4c46f 100644 --- a/app/models/dmsf_file_revision.rb +++ b/app/models/dmsf_file_revision.rb @@ -156,19 +156,22 @@ class DmsfFileRevision < ActiveRecord::Base return new_revision end - def workflow_str - str = '' - if dmsf_workflow_id + def workflow_str(name) + if name && dmsf_workflow_id wf = DmsfWorkflow.find_by_id(dmsf_workflow_id) str = "#{wf.name} - " if wf + else + str = '' end case workflow - when 1 + when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL str + l(:title_waiting_for_approval) - when 2 + when DmsfWorkflow::STATE_APPROVED str + l(:title_approved) - when 3 + when DmsfWorkflow::STATE_DRAFT str + l(:title_draft) + when DmsfWorkflow::STATE_REJECTED + str + l(:title_rejected) else str end @@ -178,21 +181,21 @@ class DmsfFileRevision < ActiveRecord::Base if User.current.allowed_to?(:file_approval, self.file.project) unless dmsf_workflow_id.blank? self.dmsf_workflow_id = dmsf_workflow_id - if commit == l(:label_dmsf_wokflow_action_start) - self.workflow = 1 # Waiting for approval + if commit == 'start' + self.workflow = DmsfWorkflow::STATE_WAITING_FOR_APPROVAL # Waiting for approval else - self.workflow = 3 # Draft - end + self.workflow = DmsfWorkflow::STATE_DRAFT # Draft + end end end end def assign_workflow(dmsf_workflow_id) if User.current.allowed_to?(:file_approval, self.file.project) - if self.workflow == 1 # Waiting for approval + #if self.workflow == DmsfWorkflow::STATE_DRAFT # Waiting for approval wf = DmsfWorkflow.find_by_id(dmsf_workflow_id) wf.assign(self.id) if wf && self.id - end + #end end end diff --git a/app/models/dmsf_workflow.rb b/app/models/dmsf_workflow.rb index 74708290..7b995ee3 100644 --- a/app/models/dmsf_workflow.rb +++ b/app/models/dmsf_workflow.rb @@ -42,7 +42,7 @@ class DmsfWorkflow < ActiveRecord::Base def to_s name - end + end def approvals(step) wa = Array.new @@ -109,9 +109,24 @@ class DmsfWorkflow < ActiveRecord::Base end end end - - def delegates - User.all + + def delegates(q, dmsf_workflow_step_assignment_id, dmsf_file_revision_id, project_id) + if project_id + sql = ['id IN (SELECT user_id FROM members WHERE project_id = ?', project_id] + elsif dmsf_workflow_step_assignment_id && dmsf_file_revision_id + sql = [ + 'id NOT IN (SELECT a.user_id FROM dmsf_workflow_step_assignments a WHERE id = ?) AND id IN (SELECT m.user_id FROM members m JOIN dmsf_file_revisions r ON m.project_id = r.project_id WHERE r.id = ?)', + dmsf_workflow_step_assignment_id, + dmsf_file_revision_id] + else + sql = '1=1' + end + + unless q.nil? || q.empty? + User.active.sorted.where(sql).like(q) + else + User.active.sorted.where(sql) + end end def get_free_assignment(user, dmsf_file_revision_id) @@ -130,17 +145,28 @@ class DmsfWorkflow < ActiveRecord::Base end end - def try_finish(dmsf_file_revision_id) + def try_finish(dmsf_file_revision_id, action, user_id) res = nil - steps = DmsfWorkflowStep.where(:dmsf_workflow_id => self.id).all - steps.each do |step| - res = step.result dmsf_file_revision_id - unless step.finished? dmsf_file_revision_id - return - end + case action.action + when DmsfWorkflowStepAction::ACTION_APPROVE + steps = DmsfWorkflowStep.where(:dmsf_workflow_id => self.id).all + steps.each do |step| + res = step.result dmsf_file_revision_id + unless step.finished? dmsf_file_revision_id + return + end + end + when DmsfWorkflowStepAction::ACTION_REJECT + res = DmsfWorkflow::STATE_REJECTED + when DmsfWorkflowStepAction::ACTION_DELEGATE + assignment = DmsfWorkflowStepAssignment.find_by_id(action.dmsf_workflow_step_assignment_id) + assignment.update_attribute(:user_id, user_id) if assignment + end + + if res + revision = DmsfFileRevision.find_by_id dmsf_file_revision_id + revision.update_attribute(:workflow, res) if revision end - revision = DmsfFileRevision.find_by_id dmsf_file_revision_id - revision.update_attribute(:workflow, res) if revision && res end end \ No newline at end of file diff --git a/app/models/dmsf_workflow_step.rb b/app/models/dmsf_workflow_step.rb index de8baa72..52458ed6 100644 --- a/app/models/dmsf_workflow_step.rb +++ b/app/models/dmsf_workflow_step.rb @@ -77,14 +77,16 @@ class DmsfWorkflowStep < ActiveRecord::Base :dmsf_workflow_step_id => self.id, :dmsf_file_revision_id => dmsf_file_revision_id, :user_id => user.id).first - actions = DmsfWorkflowStepAction.where( - :dmsf_workflow_step_assignment_id => assignment.id).all - actions.each do |action| - if action && action.is_finished? - return + if assignment + actions = DmsfWorkflowStepAction.where( + :dmsf_workflow_step_assignment_id => assignment.id).all + actions.each do |action| + if action && action.is_finished? + return + end end + return assignment.id end - return assignment.id end end \ No newline at end of file diff --git a/app/models/dmsf_workflow_step_action.rb b/app/models/dmsf_workflow_step_action.rb index 9748aa3b..568e4252 100644 --- a/app/models/dmsf_workflow_step_action.rb +++ b/app/models/dmsf_workflow_step_action.rb @@ -22,6 +22,7 @@ class DmsfWorkflowStepAction < ActiveRecord::Base validates :dmsf_workflow_step_assignment_id, :presence => true validates :action, :presence => true + validates :note, :presence => true, :unless => lambda { self.action == DmsfWorkflowStepAction::ACTION_APPROVE } ACTION_APPROVE = 1 ACTION_REJECT = 2 diff --git a/app/views/dmsf/show.html.erb b/app/views/dmsf/show.html.erb index 9702a086..aec9a1c3 100644 --- a/app/views/dmsf/show.html.erb +++ b/app/views/dmsf/show.html.erb @@ -65,7 +65,7 @@ <%= l(:link_title) %> <%= l(:link_size) %> <%= l(:link_modified) %> - <%= l(:link_ver) %> + <%= l(:link_ver) %> <%= l(:link_author) %> @@ -93,11 +93,11 @@ <%= image_tag("lockedbycurrent.png", :title => l(:title_locked_by_you), :plugin => :redmine_dmsf) %> <% end %> - + <%= h(subfolder.user) %> <% if User.current.allowed_to?(:file_approval, @project) %> -
+
<% if subfolder.notification %> <%= link_to_function(image_tag("notify.png", :plugin => :redmine_dmsf), "manipulation_link('#{url_for(:action => 'notify_deactivate', :id => @project, :folder_id => subfolder)}')", @@ -106,7 +106,7 @@ <%= link_to_function(image_tag("notifynot.png", :plugin => :redmine_dmsf), "manipulation_link('#{url_for(:action => 'notify_activate', :id => @project, :folder_id => subfolder)}')", :title => l(:title_notifications_not_active_activate)) %> - <% end %> + <% end %>
<% end %>
@@ -147,7 +147,7 @@ <%= subfolder.deep_size %> <% end %> - <% @files.each do |file| %> + <% @files.each do |file| %> <%= check_box_tag("files[]", file.id, false, :title => l(:title_check_for_zip_download_or_email)) %> @@ -172,38 +172,12 @@ <% end %> - <%= file.last_revision.version %> - <% case file.last_revision.workflow %> - <% when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL %> - <% wf = DmsfWorkflow.find_by_id(file.last_revision.dmsf_workflow_id) %> - <% if wf %> - <% dmsf_workflow_step_assignment_id = wf.get_free_assignment(User.current, file.last_revision.id) %> - <% if dmsf_workflow_step_assignment_id %> - <%= link_to( - image_tag('waitingforapproval.png', :plugin => :redmine_dmsf), - action_dmsf_workflow_path( - :project_id => @project.id, - :id => wf.id, - :dmsf_workflow_step_assignment_id => dmsf_workflow_step_assignment_id, - :dmsf_file_revision_id => file.last_revision.id), - :title => l(:title_waiting_for_approval), - :remote => true) %> - <% else %> - <%= image_tag('waitingforapproval.png', :title => l(:title_waiting_for_approval), :plugin => :redmine_dmsf) %> - <% end %> - <% end %> - <% when DmsfWorkflow::STATE_APPROVED %> - <%= image_tag('approved.png', :title => l(:title_approved), :plugin => :redmine_dmsf) %> - <% when DmsfWorkflow::STATE_DRAFT %> - <%= image_tag('draft.png', :title => l(:title_draft), :plugin => :redmine_dmsf) %> - <% when DmsfWorkflow::STATE_REJECTED %> - <%= image_tag('delete.png', :title => l(:title_rejected), :plugin => :redmine_dmsf) %> - <% end %> - + <%= "#{file.last_revision.version} #{file.last_revision.workflow_str(false)}" %> + <%= h(file.last_revision.user) %> <% if User.current.allowed_to?(:file_approval, @project) %> -
+
<% if file.notification %> <%= link_to_function(image_tag("notify.png", :plugin => :redmine_dmsf), "manipulation_link('#{url_for(:controller => "dmsf_files", :action => 'notify_deactivate', :id => file)}')", @@ -213,9 +187,48 @@ "manipulation_link('#{url_for(:controller => "dmsf_files", :action => 'notify_activate', :id => file)}')", :title => l(:title_notifications_not_active_activate)) %> <% end %> -
+ <% case file.last_revision.workflow %> + <% when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL %> + <% wf = DmsfWorkflow.find_by_id(file.last_revision.dmsf_workflow_id) %> + <% if wf %> + <% dmsf_workflow_step_assignment_id = wf.get_free_assignment(User.current, file.last_revision.id) %> + <% if dmsf_workflow_step_assignment_id %> + <%= link_to( + image_tag('waiting_for_approval.png', :plugin => :redmine_dmsf), + action_dmsf_workflow_path( + :project_id => @project.id, + :id => wf.id, + :dmsf_workflow_step_assignment_id => dmsf_workflow_step_assignment_id, + :dmsf_file_revision_id => file.last_revision.id), + :title => l(:title_waiting_for_approval), + :remote => true) %> + <% else %> + <%= image_tag('waiting_for_approval.png', :title => "#{l(:label_dmsf_wokflow_action_approve)} #{l(:label_dmsf_wokflow_action_reject)} #{l(:label_dmsf_wokflow_action_delegate)}", :plugin => :redmine_dmsf) %> + <% end %> + <% end %> + <% when DmsfWorkflow::STATE_APPROVED %> + <%= image_tag('approved.png', :title => l(:title_approved), :plugin => :redmine_dmsf) %> + <% when DmsfWorkflow::STATE_DRAFT %> + <%= link_to_function(image_tag('draft.png', :plugin => :redmine_dmsf), + "manipulation_link('#{start_dmsf_workflow_path( + :id => file.last_revision.dmsf_workflow_id, + :dmsf_file_revision_id => file.last_revision.id)}')", + :title => l(:label_dmsf_wokflow_action_start)) %> + <% when DmsfWorkflow::STATE_REJECTED %> + <%= image_tag('rejected.png', :title => l(:title_rejected), :plugin => :redmine_dmsf) %> + <% else %> + <%= link_to( + image_tag('none.png', :plugin => :redmine_dmsf), + assign_dmsf_workflow_path( + :project_id => @project.id, + :dmsf_workflow_step_assignment_id => dmsf_workflow_step_assignment_id, + :dmsf_file_revision_id => file.last_revision.id), + :title => l(:label_dmsf_wokflow_action_assign), + :remote => true) %> + <% end %> +
<% end %> -
+
<%= link_to(image_tag("filedetails.png", :plugin => :redmine_dmsf, :class =>"detail_icon"), {:controller => "dmsf_files", :action => :show, :id => file }, @@ -242,7 +255,7 @@ <%= link_to_function(image_tag("delete.png", :plugin => :redmine_dmsf), "confirmation_link('#{url_for(:controller => "dmsf_files", :action => 'delete', :id => file)}')", :title => l(:title_delete)) %> - <% end %> + <% end %>

diff --git a/app/views/dmsf_files/_file_new_revision.html.erb b/app/views/dmsf_files/_file_new_revision.html.erb index 87a97d33..2a58bf45 100644 --- a/app/views/dmsf_files/_file_new_revision.html.erb +++ b/app/views/dmsf_files/_file_new_revision.html.erb @@ -44,7 +44,7 @@ <%= @file.last_revision.major_version + 1 %>.0 <%= l(:option_version_major) %>

- <%= label_tag("workflow", l(:label_workflow) + ":") %> + <%= label_tag('workflow', l(:label_workflow) + ':') %> <%= select_tag( 'dmsf_workflow_id', dmsf_workflows_for_select(@project, @file.last_revision.dmsf_workflow_id))%> diff --git a/app/views/dmsf_files/show.html.erb b/app/views/dmsf_files/show.html.erb index edd3573f..f1458a6a 100644 --- a/app/views/dmsf_files/show.html.erb +++ b/app/views/dmsf_files/show.html.erb @@ -57,7 +57,8 @@

<%= l(:heading_revisions) %>

<% @file.revisions.visible[@revision_pages.current.offset,@revision_pages.items_per_page].each do |revision| %> -
+
+
<%= link_to(image_tag("download.png", :plugin => "redmine_dmsf"), {:action => "show", :id => @file, :download => revision}, @@ -69,22 +70,20 @@ :title => l(:title_delete_revision)) %> <% end %>
-

- <%=label_tag("", (revision.source_revision.nil? ? l(:label_created) : l(:label_changed)) + ":")%> + + <%= label_tag('', l(:info_revision, :rev => revision.id)) %> + <%= (revision.source_revision.nil? ? l(:label_created) : l(:label_changed)).downcase %> <%= l(:info_changed_by_user, :changed => format_time(revision.updated_at), :user => h(revision.user)) %> -

+ +
-
-

- <%= label_tag("", l(:label_title) + ":") %> - <%= h(revision.title) %> -

+
+ <%= label_tag("", l(:label_title) + ":") %> + <%= h(revision.title) %>
-
-

- <%= label_tag("", l(:label_file) + ":") %> - <%= (h(revision.folder.dmsf_path_str) + "/") unless revision.folder.nil? %><%= h(revision.name) %> -

+
+ <%= label_tag("", l(:label_file) + ":") %> + <%= (h(revision.folder.dmsf_path_str) + "/") unless revision.folder.nil? %><%= h(revision.name) %>

@@ -94,42 +93,30 @@ <%= textilizable(revision.description) %>

-
-

- <%= label_tag("", l(:label_version) + ":") %> - <%= revision.major_version %>.<%= revision.minor_version %> -

-

- <%= label_tag("", l(:label_workflow) + ":") %> - <%= #case revision.workflow - # when 1 then l(:option_workflow_waiting_for_approval) - # when 2 then l(:option_workflow_approved) - # else l(:option_workflow_none) - # end - revision.workflow_str - %> -

+
+ <%= label_tag("", l(:label_version) + ":") %> + <%= revision.major_version %>.<%= revision.minor_version %> +
+ <%= label_tag('', l(:label_workflow) + ':') %> + <%= revision.workflow_str true %>
-
-

- <%= label_tag("", l(:label_mime) + ":") %> - <%= h(revision.mime_type) %>  -

-

- <%= label_tag("", l(:label_size) + ":") %> - <%= number_to_human_size(revision.size) %> -

-
-
+
+ <%= label_tag("", l(:label_mime) + ":") %> + <%= h(revision.mime_type) %>  +
+ <%= label_tag("", l(:label_size) + ":") %> + <%= number_to_human_size(revision.size) %> +
<%= render "dmsf/custom_fields", :object => revision %>
-

+

<%= label_tag("", l(:label_comment) + ":") %> <%= h(revision.comment) %> -

+
<%= render(:partial => "revision_access", :locals => {:revision => revision}) if User.current.allowed_to?(:file_approval, @file.project) %>
+
<% end %>

<%= pagination_links_full @revision_pages, @file.revisions.visible.count %>

diff --git a/app/views/dmsf_mailer/files_updated.html.erb b/app/views/dmsf_mailer/files_updated.html.erb index 545256e2..5c6c2bc0 100644 --- a/app/views/dmsf_mailer/files_updated.html.erb +++ b/app/views/dmsf_mailer/files_updated.html.erb @@ -13,7 +13,7 @@ :download => ""}) %> (<%= file.name %>), <%= number_to_human_size(file.last_revision.size) %>, version: <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %>, - <%= "#{file.last_revision.workflow_str}," unless file.last_revision.workflow_str.blank? %> + <%= "#{file.last_revision.workflow_str(true)}," unless file.last_revision.workflow_str(true).blank? %> <%= link_to("Details", {:only_path => false, :controller => "dmsf_files", :action => "show", :id => file}) %> <% unless file.last_revision.comment.blank? %> diff --git a/app/views/dmsf_mailer/files_updated.text.erb b/app/views/dmsf_mailer/files_updated.text.erb index b78bd7c2..fcd0ea79 100644 --- a/app/views/dmsf_mailer/files_updated.text.erb +++ b/app/views/dmsf_mailer/files_updated.text.erb @@ -1,6 +1,6 @@ User <%= @user %> actualized DMSF files in project <%= @project.name %>: <% @files.each do |file| %> - <%= file.dmsf_path_str %> (<%= file.name %>), <%= number_to_human_size(file.last_revision.size) %>, version: <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %><%= ", #{file.last_revision.workflow_str}" unless file.last_revision.workflow_str.blank? %> + <%= file.dmsf_path_str %> (<%= file.name %>), <%= number_to_human_size(file.last_revision.size) %>, version: <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %><%= ", #{file.last_revision.workflow_str(true)}" unless file.last_revision.workflow_str(true).blank? %> <%= url_for({:only_path => false, :controller => "dmsf_files", :action => "show", :id => file}) %> <% unless file.last_revision.comment.blank? %> comment: <%= file.last_revision.comment %><% end %> <% end %> \ No newline at end of file diff --git a/app/views/dmsf_mailer/files_updated.text.html.rhtml b/app/views/dmsf_mailer/files_updated.text.html.rhtml index 545256e2..5c6c2bc0 100644 --- a/app/views/dmsf_mailer/files_updated.text.html.rhtml +++ b/app/views/dmsf_mailer/files_updated.text.html.rhtml @@ -13,7 +13,7 @@ :download => ""}) %> (<%= file.name %>), <%= number_to_human_size(file.last_revision.size) %>, version: <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %>, - <%= "#{file.last_revision.workflow_str}," unless file.last_revision.workflow_str.blank? %> + <%= "#{file.last_revision.workflow_str(true)}," unless file.last_revision.workflow_str(true).blank? %> <%= link_to("Details", {:only_path => false, :controller => "dmsf_files", :action => "show", :id => file}) %> <% unless file.last_revision.comment.blank? %> diff --git a/app/views/dmsf_mailer/files_updated.text.plain.rhtml b/app/views/dmsf_mailer/files_updated.text.plain.rhtml index b78bd7c2..fcd0ea79 100644 --- a/app/views/dmsf_mailer/files_updated.text.plain.rhtml +++ b/app/views/dmsf_mailer/files_updated.text.plain.rhtml @@ -1,6 +1,6 @@ User <%= @user %> actualized DMSF files in project <%= @project.name %>: <% @files.each do |file| %> - <%= file.dmsf_path_str %> (<%= file.name %>), <%= number_to_human_size(file.last_revision.size) %>, version: <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %><%= ", #{file.last_revision.workflow_str}" unless file.last_revision.workflow_str.blank? %> + <%= file.dmsf_path_str %> (<%= file.name %>), <%= number_to_human_size(file.last_revision.size) %>, version: <%= file.last_revision.major_version %>.<%= file.last_revision.minor_version %><%= ", #{file.last_revision.workflow_str(true)}" unless file.last_revision.workflow_str(true).blank? %> <%= url_for({:only_path => false, :controller => "dmsf_files", :action => "show", :id => file}) %> <% unless file.last_revision.comment.blank? %> comment: <%= file.last_revision.comment %><% end %> <% end %> \ No newline at end of file diff --git a/app/views/dmsf_upload/_upload_file.html.erb b/app/views/dmsf_upload/_upload_file.html.erb index 4f52aef8..8e56cf62 100644 --- a/app/views/dmsf_upload/_upload_file.html.erb +++ b/app/views/dmsf_upload/_upload_file.html.erb @@ -1,17 +1,4 @@ -<% -#disabled_workflow = [] -#selected_workflow = nil -#unless User.current.allowed_to?(:file_approval, @project) - #disabled_workflow << 2 - #current_workflow = upload.workflow - #if current_workflow == 1 || current_workflow == 2 - #disabled_workflow << nil - #selected_workflow = 1 - #end -#else - #selected_workflow = upload.workflow -#end -%> +
<%= hidden_field_tag("commited_files[#{i}][disk_filename]", upload.disk_filename) %>
diff --git a/app/views/dmsf_upload/_upload_file_locked.html.erb b/app/views/dmsf_upload/_upload_file_locked.html.erb index dec8da17..f994bbb6 100644 --- a/app/views/dmsf_upload/_upload_file_locked.html.erb +++ b/app/views/dmsf_upload/_upload_file_locked.html.erb @@ -30,13 +30,7 @@

<%= label_tag("", l(:label_workflow) + ":") %> - <%= #case upload.workflow - # when 1 then l(:option_workflow_waiting_for_approval) - # when 2 then l(:option_workflow_approved) - # else l(:option_workflow_none) - # end - upload.workflow_str - %> + <%= upload.workflow_str true %>

diff --git a/app/views/dmsf_workflows/_action.html.erb b/app/views/dmsf_workflows/_action.html.erb index 4c35e181..251982fd 100644 --- a/app/views/dmsf_workflows/_action.html.erb +++ b/app/views/dmsf_workflows/_action.html.erb @@ -1,13 +1,9 @@

<%= l(:label_dmsf_workflow) %>

-<%= form_tag({:controller => 'dmsf_workflows', - :action => 'new_action', - :object_type => DmsfWorkflow, - :object_id => @workflow.id, - :project_id => @project.id}, - :remote => true, +<%= form_tag({:controller => 'dmsf_workflows', :action => 'new_action'}, :method => :post, - :id => 'new-action-form') do %> + :id => 'new-action-form') do %> + <%= hidden_field_tag :dmsf_workflow_step_assignment_id, params[:dmsf_workflow_step_assignment_id] %> <%= hidden_field_tag :dmsf_file_revision_id, params[:dmsf_file_revision_id] %>


@@ -18,18 +14,14 @@

-
- <%= text_field_tag 'user_search', nil %> + <%= label_tag 'delegate', l(:label_dmsf_wokflow_action_delegate) %>
+ <%= text_field_tag 'user_search', nil %> + <%= javascript_tag "observeSearchfield('user_search', 'users_for_delegate', '#{ escape_javascript autocomplete_for_user_dmsf_workflow_path(@workflow, :dmsf_workflow_step_assignment_id => params[:dmsf_workflow_step_assignment_id], :dmsf_file_revision_id => params[:dmsf_file_revision_id]) }')" %> + <%= content_tag('div', principals_radio_button_tags('step_action', @workflow.delegates(nil, params[:dmsf_workflow_step_assignment_id], params[:dmsf_file_revision_id], nil)), :id => 'users_for_delegate') %>

- <%= javascript_tag "observeSearchfield('user_search', 'users_for_delegate', '#{ escape_javascript autocomplete_for_user_dmsf_workflow_path(@workflow) }')" %> - -
- <%= principals_check_box_tags 'watcher[user_ids][]', @workflow.delegates %> -
-

- <%= submit_tag l(:submit_commit), :name => nil, :onclick => 'hideModal(this);' %> - <%= submit_tag l(:button_cancel), :name => nil, :onclick => 'hideModal(this);' %> + <%= submit_tag l(:submit_commit), :name => 'commit', :onclick => 'hideModal(this);' %> + <%= submit_tag l(:button_cancel), :name => 'commit', :onclick => 'hideModal(this);' %>

<% end %> diff --git a/app/views/dmsf_workflows/_assign.html.erb b/app/views/dmsf_workflows/_assign.html.erb new file mode 100644 index 00000000..f2be82d6 --- /dev/null +++ b/app/views/dmsf_workflows/_assign.html.erb @@ -0,0 +1,21 @@ +

<%= l(:label_dmsf_workflow) %>

+ +<%= form_tag({:controller => 'dmsf_workflows', :action => 'assignment'}, + :method => :post, + :id => 'assignment-form') do %> + + <%= hidden_field_tag :dmsf_workflow_step_assignment_id, params[:dmsf_workflow_step_assignment_id] %> + <%= hidden_field_tag :dmsf_file_revision_id, params[:dmsf_file_revision_id] %> + +

+ <%= label_tag('workflow', l(:label_workflow) + ':') %> + <%= select_tag( + 'dmsf_workflow_id', + dmsf_workflows_for_select(@project, nil))%> +

+ +

+ <%= submit_tag l(:button_assign), :name => 'commit', :onclick => 'hideModal(this);' %> + <%= submit_tag l(:button_cancel), :name => 'commit', :onclick => 'hideModal(this);' %> +

+<% end %> diff --git a/app/views/dmsf_workflows/_steps.html.erb b/app/views/dmsf_workflows/_steps.html.erb index 70afad2a..2d57c895 100644 --- a/app/views/dmsf_workflows/_steps.html.erb +++ b/app/views/dmsf_workflows/_steps.html.erb @@ -61,10 +61,10 @@
<%=l(:label_user_new)%>

<%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %>

- <%= javascript_tag "observeSearchfield('user_search', null, '#{ escape_javascript autocomplete_for_user_dmsf_workflow_path(@workflow) }')" %> + <%= javascript_tag "observeSearchfield('user_search', 'users', '#{ escape_javascript autocomplete_for_user_dmsf_workflow_path(@workflow, :dmsf_workflow_step_assignment_id => nil, :dmsf_file_revision_id => nil, :project_id => @project ? @project.id : nil) }')" %>
- <%= render_principals_for_new_dmsf_workflow_users(@workflow) %> + <%= render_principals_for_new_dmsf_workflow_users(@workflow, nil, nil) %>

diff --git a/app/views/dmsf_workflows/action.html.erb b/app/views/dmsf_workflows/action.html.erb deleted file mode 100644 index d1a62773..00000000 --- a/app/views/dmsf_workflows/action.html.erb +++ /dev/null @@ -1 +0,0 @@ -

WorkflowController#action

diff --git a/app/views/dmsf_workflows/assign.js.erb b/app/views/dmsf_workflows/assign.js.erb new file mode 100644 index 00000000..ded50f0c --- /dev/null +++ b/app/views/dmsf_workflows/assign.js.erb @@ -0,0 +1,3 @@ +$('#ajax-modal').html('<%= escape_javascript(render :partial => 'assign', :locals => {:workflow => @workflow}) %>'); +showModal('ajax-modal', '400px'); +$('#ajax-modal').addClass('assignment'); \ No newline at end of file diff --git a/app/views/dmsf_workflows/autocomplete_for_user.html.erb b/app/views/dmsf_workflows/autocomplete_for_user.html.erb new file mode 100644 index 00000000..8510d370 --- /dev/null +++ b/app/views/dmsf_workflows/autocomplete_for_user.html.erb @@ -0,0 +1 @@ +<%= render_principals_for_new_dmsf_workflow_users(@workflow, params[:dmsf_workflow_step_assignment_id], params[:dmsf_file_revision_id]) %> diff --git a/app/views/dmsf_workflows/autocomplete_for_user.js.erb b/app/views/dmsf_workflows/autocomplete_for_user.js.erb deleted file mode 100644 index e74e6b4c..00000000 --- a/app/views/dmsf_workflows/autocomplete_for_user.js.erb +++ /dev/null @@ -1 +0,0 @@ -$('#users').html('<%= escape_javascript(render_principals_for_new_dmsf_workflow_users(@workflow)) %>'); diff --git a/assets/images/approve.png b/assets/images/approve.png deleted file mode 100644 index fc25958ac6f97b4bf2cf483d593cddb8e83be9fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 535 zcmV+y0_gpTP)}Iq3IoUi+*)0klzL{a?_kGKB0bT!tv)HK^)#MmPVg&ue zFqQai%CiAVudboJ7(|=)Q;78=qJ4;n4_CnY76rTN!nWjYb$pZO{KO%5p!|MVUK-e@ zXiyVaW?r(=L^#-1gAJ5ZXtgH>6?$UeeQ!syEn(SO{dvUH2e;!Vn_OOzG{Fbi|2 zp>B6TdmE5}1$1SsDF>xIB;^}YzUau>{Ao<_hV1>V?tplDo?3Zc$|D`}bxNs0Df=B+ z`*KnSUXr=H!5zrQ&Y&eii1<0gyR(SdesVL%n(`?}E`ILCT$w=`TF;5l#yWojYUC*5 z^;K%ckCFt{T$J4NUbL@u`M8viQ2cZdGe7OfSK#{ diff --git a/assets/images/approved.png b/assets/images/approved.png index da85f26df2d93b6407d52b869fb13c52b3797136..37c88de94f23085c3a83af6676a4ba8d307eba68 100644 GIT binary patch literal 752 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*l1 z3^om!?NO@$00MAHL_t(I%axMfOH*+e#-H>3o*y31)RVskF6$^OF-w;>1?slMgw4#n ztH79Dc~$lo*#3ffhMdCJiCbEX=_ zW~zoEO@#e$4Kn$3drA(tJFG?Gqzvf%JQ#t2DdBUTL)8YhnrI*_8-HgP8d?>!XCaf1J<-3kWP=prQ@x9-Pr* zkO@OPuCl8LCpF}Xd5|~*9?d-gOW4-QCRHQog2yZuO*@X(_2i@-nnpJ~zdX*!P^< zft_WTGfLo(tY9jr`Y1!)drJryz`#pbORQpZH-sCf+h8xOa#2D@TTiuMha@2J5;($R z=+iJLq0O%vC$*n0(Fi$|(9YUTR>buf;(83WLK})@1r^4V*uXlDh(+-F#;~CI+%GRo z^!=6(4B@%IHlS>7Z(3|7E8>V_Z8wODoC<`of&4Th{NVtGJ`Stn4R5ae5ikJIpXmdk zdQFLJM=aF^RUnkXYBGpSJ_{m|(EI)&wv!2m@4=VAz5)Ocf0`JGIbzCuXx?Hq)gVjA zM4n)TcX130+M?U*81G9d^Cuo3?{U7U(+Ai4_3ouky>7%h{jYguzvh|2%G&}JZVHsw iD51?G^b3IGX%~^VGY4O(NwdaaZ48Qo<`@IKIWA*;*1{Rj3DHVA#j+%xz6HSiMZf> z1K)W7>!(%u=C<+CmFTBS>#thw!hOfq=kfOWxXt2MhPQK?!|SVE_~W$ZpEBvIJNW6S zroPyXt-zlt`1}3c=keaAvwz3lP$=kWOE z@Au^H_xbz%;OX*kn8NF=Uhu<%{PWZN^U?b4vR;e2^7s1e^ZM!W_~PvL=kNFB?DTAv z!0xtj^wFO1%6Ra{a`47(^7i`g_4@Ag`t9@j>+|{I>ho`x!SK0x{Px@U=bZTEmG|S1 ze4xj@(d6;=`tkMp@b&uX@b;|3+>NZx^u>(*_ucsDqWI^X%-idGpvPZ~yI_pFT8Ow| zjk{=)zNWv~@o z^}>bpzkc+(cJa1u@Ums_tzCoUq^JM@00DGTPE!Ct=GbNc004POL_t&-83nmu$=hrWg!qSQ&m+}RaI40Rr&zHdyT$T@!O^v-3f_mbYSj4 zr8mqSe;bS@EOQTx7Oa!S?P(ZIu(;Xpj3#hA^LawA0D;i~Twc)6S&sm?ma1yttE#HX b_E1&-{~a7)@`du200000NkvXXu0mjf&HJJF diff --git a/assets/images/draft.png b/assets/images/draft.png index 6902ab0cc75af10f160eb1b5f143c77b7f6dc3f8..0257b1d8c11a997228863a7ce7430a21365c5b98 100644 GIT binary patch literal 459 zcmV;+0W|)JP)Px#0%A)?L;(MXkIcUS000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*l13^pv) zghBNH00B=)L_t(2&u!2>NJ3#0#_|9AUMhr7!-uII7JCU8V+TInW?uWL-L;K!1;0Dc?71jrOAjzvlNwGi|JXF zX^%EajgltKfDF4d7elzQt(trY>w}R6YF*q9l$aMQEhZ?T#QVU0aC~)|4<>o%xhSIo zLb}jJ{wNP{pvtEWRiVu=S-#fxGBOl%=H?Uj+*S-g#&p#|i!mN)#`iKHLdGTo2yQ8# z4xBmCe(H=+`G#+`AT``2rCxk~xOqh7AazPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m?d01m?e$8V@)00007bV*G`2i*k^ z2puUwI-kD)00B)&L_t(2&vlSbCeG^&Ux!%-(Xnern{Y$XAYxD5tvASz>`=aPP7H}U6 zM7x^M8>$U|ZLq?p3BlH}4M6JD0pRdl@#NA4K(A{iSQ((0p}*4rpu1f$+@b@})~wT_ z>&0l=(_8+h;CbwwDaWI%V&+OYU)U~JuG(|?Z~Q=FE#<`G1Ik$w>X)7lgM)L2!LUJn zl^~J6!M=ZW#GhKn03Sdk+{pM)D*&&#PuBNcl9{_KF!FDOrX`(+=XY;WUU;S@KTJzb zm+jlMr*tV|6r{Ac(J{&{|QmLNSH00000NkvXXu0mjf DQQ6Jc diff --git a/assets/images/none.png b/assets/images/none.png new file mode 100644 index 0000000000000000000000000000000000000000..3051be29c0d726f5f2e505cd50fdac0e48b71743 GIT binary patch literal 776 zcmV+j1NZ!iP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*l1 z4J-%9*C<&400M|fL_t(I%axKrNK%F&Ur=-Yg z{*FI>-_H-e-!BK3m`EhTBjPNjl&6&L6G9%)ONiZwxbFA+d6&xts;WY-qmaAJ^TV6!G7K_DBP?99Y#dc6&Aw zi73Aqrvw54x6|oN8iw(vwY4?4x3?G8G%Xp6#Wnx{C;-TzP$+J-T3`3|^*zaCGV=8F zwA*U6K65&q;laVdjcT>}p{=crsjB*-P$+yy#Kid%j^lta2Gwfyo2F^^$HvBTq9}$D zaeZWD%$#@M*UVp&P2)80m- zaeZxV?dU=P06;pOUL6`5;!CAcR1gHT*=*Eqw~yxY`SEhOoRB1Gxv9?2&(AL{E-s$! z?(Uv#Z*QM1EG%UIb0z`0 literal 0 HcmV?d00001 diff --git a/assets/images/rejected.png b/assets/images/rejected.png new file mode 100644 index 0000000000000000000000000000000000000000..d75d8ec7c62a2d1063e9c7b2396d0107e7921c3f GIT binary patch literal 631 zcmV--0*L*IP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*l1 z4Fn`N?e~EI00H+&L_t(I%axKbNLyhPg}?vhPe{olzDE*G=#nWQ)DRtF!Gfvi_`OVY&@+{Hl}5$z&0p|}Xr1XOg;CImtAlDxk|XtAZO$$`7w?{M$o z2nNsrgf&=qLD&s77rYw;HV&a`2LejPV#*E#)Hf(;{TgWScFN@nGcyCGiI|4+-_*MAsU6_V~E(> zA_k!lv|11j!_g64%gVW6A3%Hpm6)FgT}Nmd_r)S#p`gQuAe4M-YtU%G@Gx9n(%syw zIbd8s<5!5n>qXS-sAiLAtE>y50(?Y3_k3$v!hmfC=GRg8X+}(j?!RRQo+bF|8 zoS#E3R}r>7{+EKmD@c_)or2ohf?yE*ez>{9tDy^^wSdpuR!G-LnU{Q*F(sw)uw RMx6iv002ovPDHLkV1igQ5$ON` literal 0 HcmV?d00001 diff --git a/assets/images/waiting_for_approval.png b/assets/images/waiting_for_approval.png new file mode 100644 index 0000000000000000000000000000000000000000..97cdace94954b0956029d15bd123998c7f9a160d GIT binary patch literal 630 zcmV-+0*U>JP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*l1 z4JtCoK1=)n00H(%L_t(I%axL`OCwPbhrhSab&b&&gcMQG1+ywHlI?Pcg0Z{8;>vWX zqrnZPm;42>u$Sv>1A<(mVi7QnTd1XpSR`nQh@x3d^or#q-YFNSdykple7~6yd?nIp z9U(T5Qb$!QNSW#RLU9lw4w#+Q85)AyTe!T`m97PZurUmsNCbR7Fbwed7P})@TeHx# z4NTMP+!5UoC`z7K3{(}`Z3u_q>I$UX{J+5ZdXjK>k@0c3zlV_#xVwXDwSuDL1OTa& zg%B1(IBab>9mPSUEVH~EL`ryh@%$Hy;JR_L*+Yd?Do-eM!pzJze*X#SbpB01$~@6% zkU#)hEf^k#av7eUHpylW0eTR^W^N98d%-lJRI;({Ae#1*!NDZaC_FwwDD-D_6%-}+ zeu#a2UXts=(h^KfB~g?E=I22O&@_+|90wHT2boOc4U$+a$iu@o48!x-Zo}lH*KuqN zo}VEQfb(;>xyg~q>~zjpQY!sodRnL1v@i^Kef4NYM?K$uKQtQPI1aX*_Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+*LgRNQs009h1L_t(2Q+<%VP6AO7h4&eF1mi>T0G2k? zhMHJdT3C=66ASH3h#^*5sf7uIzX&V8>jI+usHnufb2xKlaSLFQbCbFAow;|$iKntL z>Xe#M*q|%cwjCZ9XE#;+1_qlVbKlTrH8liA1miD3|6Slu1l~x{8Vc&Kg4&CLOKI#K z-@@5FytYY?pg$IL2shsZPYbxxGbs6ghW+!0f5S83HoIDQAgJ~Y6fP3Zdl5tUCH+o= zUEP7fBjIw_pg=fBIPV4ah2+T{mP6|t(a_g&9b@Oxhz=dDH3(Ol&X$(m(Z>%oXRTn@ zx+++3yTfS+elt(51oe`|gQLr$cKoCgYrzG)MW{~gtOMt%mtj<^-8i`b0000NSs56Z83KGlT!G@XwYBy2^$iUTjg5^>O-;?s%`Gi0t*xyc9UYyWon2jBJv}|W zy}kYY{Szikm^^v%%$YN1&6>4n(V}I`mMveteATK|>(;GXzkdCO4I4IY+_-u3=B-<| zZriqP`}XZSckbM^YuE1GyZ7zew}1csLx&C>K79Ddkt4^CA3t&8#L1H$h*;e*F0H z>({T}zkmPv^XKp1zd+B9g3%B_4uMCv*lz&y2}4PcU-18t4H$yIv#SEbhO@vUvY3HE zs04%=@1@CC00kvWTq8Ealo z5uDn0T&&4JfFb#4pGMgmQSB}+CM6dElNbO0`|^COylDC6wt4Xl)*tL2^g}Au*G~WZ zvf{@330xaKaaFc0c0Ky6HK4(1o~c$?xpVN;$BFufwM4o9FVQlZo-*lT$hLGQn@=9k zr|om!z;1J(`K{9&)jzXeTYV_gW4I$0d)(&--xl4=MxR|cn(~&cKe0_uKvL&GQ&i@Q zyQl0pCa^sgZkW9*DW0x=F6*2UngHG+IqU!c diff --git a/assets/stylesheets/dmsf.css b/assets/stylesheets/dmsf.css index 47b98577..18fbde1f 100644 --- a/assets/stylesheets/dmsf.css +++ b/assets/stylesheets/dmsf.css @@ -19,8 +19,8 @@ table.entries td.modified { } table.entries td.actions { - min-width: 108px; - width: 108px; + min-width: 116px; + width: 116px; } table.entries td.title { @@ -237,4 +237,26 @@ table.access-table tbody td, table.access-table tbody tr:hover td { /* Approval workflow */ #admin-menu a.approvalworkflows { background-image: url(../images/ticket_go.png); } #users_for_delegate {height: 200px; overflow:auto;} -#users_for_delegate label {display: block;} \ No newline at end of file +#users_for_delegate label {display: block;} + +.revision_box{ + padding: 0px 0px 0px 0px; + margin-bottom: 10px; + background-color:#f6f6f6; + color:#505050; + line-height:1.5em; + /*border: 1px solid #e4e4e4;*/ +} + +div.revision_box .ui-widget-header { + font-weight: normal; +} + +td.workflow { + font-size: 0.8em; + white-space: nowrap; +} + +td.workflow img { + vertical-align:text-top; +} \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index bf4019e4..2b4d38fb 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -45,7 +45,7 @@ en: :link_title: "Title" :link_size: "Size" :link_modified: "Modified" - :link_ver: "Ver." + :link_ver: "Version" :link_author: "Author" :title_check_for_zip_download_or_email: "Check for Zip download or email" :title_delete: "Delete" @@ -222,7 +222,12 @@ en: label_dmsf_wokflow_action_approve: Approve label_dmsf_wokflow_action_reject: Reject label_dmsf_wokflow_action_delegate: 'Delegate to' + label_dmsf_wokflow_action_assign: 'Assign an approval workflow' message_dmsf_wokflow_note: Your note... title_draft: Draft title_rejected: Rejected - label_dmsf_wokflow_action_start: Start workflow \ No newline at end of file + label_dmsf_wokflow_action_start: Start workflow + info_revision: "r%{rev}" + link_workflow: Workflow + button_assign: Assign + error_empty_note: "The note can't be empty" \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 4ecc978c..83b8e729 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -106,11 +106,14 @@ RedmineApp::Application.routes.draw do member do get 'autocomplete_for_user' get 'action' + get 'assign' post 'new_action' + post 'start' + post 'assignment' end end match 'dmsf_workflows/:id/edit', :controller => 'dmsf_workflows', :action => 'add_step', :id => /\d+/, :via => :post match 'dmsf_workflows/:id/edit', :controller => 'dmsf_workflows', :action => 'remove_step', :id => /\d+/, :via => :delete - match 'dmsf_workflows/:id/edit', :controller => 'dmsf_workflows', :action => 'reorder_steps', :id => /\d+/, :via => :put + match 'dmsf_workflows/:id/edit', :controller => 'dmsf_workflows', :action => 'reorder_steps', :id => /\d+/, :via => :put end diff --git a/init.rb b/init.rb index f864c5d9..f61b03d2 100644 --- a/init.rb +++ b/init.rb @@ -51,14 +51,14 @@ Redmine::Plugin.register :redmine_dmsf do permission :view_dmsf_folders, {:dmsf => [:show], :dmsf_folders_copy => [:new, :copy_to, :move_to]} permission :user_preferences, {:dmsf_state => [:user_pref_save]} permission :view_dmsf_files, {:dmsf => [:entries_operation, :entries_email], - :dmsf_files => [:show], :dmsf_files_copy => [:new, :create, :move]} + :dmsf_files => [:show], :dmsf_files_copy => [:new, :create, :move]} permission :folder_manipulation, {:dmsf => [:new, :create, :delete, :edit, :save, :edit_root, :save_root, :lock, :unlock]} permission :file_manipulation, {:dmsf_files => [:create_revision, :delete, :lock, :unlock], - :dmsf_upload => [:upload_files, :upload_file, :commit_files]} + :dmsf_upload => [:upload_files, :upload_file, :commit_files]} permission :file_approval, {:dmsf_files => [:delete_revision, :notify_activate, :notify_deactivate], - :dmsf => [:notify_activate, :notify_deactivate]} - permission :force_file_unlock, {} - permission :approval_workflows, {:dmsf_workflows => [:new, :create, :destroy, :edit, :add_step, :remove_step, :reorder_steps, :update]} + :dmsf => [:notify_activate, :notify_deactivate], + :dmsf_workflows => [:new, :create, :destroy, :edit, :add_step, :remove_step, :reorder_steps, :update, :start, :assign, :assignment, :action, :new_action]} + permission :force_file_unlock, {} end # Administration menu extension From a2c0e1f47154ffd082abd273b97823c8cbb7965c Mon Sep 17 00:00:00 2001 From: Karel Picman Date: Tue, 28 May 2013 14:56:07 +0200 Subject: [PATCH 05/10] Revision view optimized for better reading --- .../dmsf_files/_file_new_revision.html.erb | 12 +- app/views/dmsf_files/show.html.erb | 126 +++++++++--------- assets/images/rev_delete.png | Bin 0 -> 647 bytes assets/images/rev_download.png | Bin 0 -> 656 bytes assets/images/rev_downloads.png | Bin 0 -> 642 bytes assets/stylesheets/dmsf.css | 3 +- config/locales/en.yml | 2 +- 7 files changed, 69 insertions(+), 74 deletions(-) create mode 100644 assets/images/rev_delete.png create mode 100644 assets/images/rev_download.png create mode 100644 assets/images/rev_downloads.png diff --git a/app/views/dmsf_files/_file_new_revision.html.erb b/app/views/dmsf_files/_file_new_revision.html.erb index 2a58bf45..e09f73f7 100644 --- a/app/views/dmsf_files/_file_new_revision.html.erb +++ b/app/views/dmsf_files/_file_new_revision.html.erb @@ -42,17 +42,7 @@ <%= @file.last_revision.major_version %>.<%= @file.last_revision.minor_version + 1 %> <%= l(:option_version_minor) %>
<%= radio_button_tag("version", 2, @revision.major_version != @file.last_revision.major_version) %> <%= @file.last_revision.major_version + 1 %>.0 <%= l(:option_version_major) %>
-
-

- <%= label_tag('workflow', l(:label_workflow) + ':') %> - <%= select_tag( - 'dmsf_workflow_id', - dmsf_workflows_for_select(@project, @file.last_revision.dmsf_workflow_id))%> - <% if @file.last_revision.dmsf_workflow_id && @file.last_revision.workflow == 3%> - <%= submit_tag(l(:label_dmsf_wokflow_action_start)) %> - <% end %> - -

+

diff --git a/app/views/dmsf_files/show.html.erb b/app/views/dmsf_files/show.html.erb index f1458a6a..2c86be27 100644 --- a/app/views/dmsf_files/show.html.erb +++ b/app/views/dmsf_files/show.html.erb @@ -57,66 +57,72 @@

<%= l(:heading_revisions) %>

<% @file.revisions.visible[@revision_pages.current.offset,@revision_pages.items_per_page].each do |revision| %> -
-
-
- <%= link_to(image_tag("download.png", :plugin => "redmine_dmsf"), - {:action => "show", :id => @file, :download => revision}, - :title => l(:title_title_version_version_download, :title => h(revision.title), :version => revision.version)) %> - <% if User.current.allowed_to?(:file_approval, @project) %> -   - <%= link_to_function(image_tag("delete.png", :plugin => "redmine_dmsf"), - "confirmation_link('#{url_for(:action => 'delete_revision', :id => revision)}', '#{l(:question_do_you_really_want_to_delete_this_revision)}')", - :title => l(:title_delete_revision)) %> - <% end %> -
- - <%= label_tag('', l(:info_revision, :rev => revision.id)) %> - <%= (revision.source_revision.nil? ? l(:label_created) : l(:label_changed)).downcase %> - <%= l(:info_changed_by_user, :changed => format_time(revision.updated_at), :user => h(revision.user)) %> - -
-
-
- <%= label_tag("", l(:label_title) + ":") %> - <%= h(revision.title) %> -
-
- <%= label_tag("", l(:label_file) + ":") %> - <%= (h(revision.folder.dmsf_path_str) + "/") unless revision.folder.nil? %><%= h(revision.name) %> -
-
-

- <%= label_tag("", l(:label_description) + ":") %> -

-
- <%= textilizable(revision.description) %> -
- -
- <%= label_tag("", l(:label_version) + ":") %> - <%= revision.major_version %>.<%= revision.minor_version %> -
- <%= label_tag('', l(:label_workflow) + ':') %> - <%= revision.workflow_str true %> -
-
- <%= label_tag("", l(:label_mime) + ":") %> - <%= h(revision.mime_type) %>  -
- <%= label_tag("", l(:label_size) + ":") %> - <%= number_to_human_size(revision.size) %> -
-
- <%= render "dmsf/custom_fields", :object => revision %> -
-
- <%= label_tag("", l(:label_comment) + ":") %> - <%= h(revision.comment) %> -
- <%= render(:partial => "revision_access", :locals => {:revision => revision}) if User.current.allowed_to?(:file_approval, @file.project) %> -
-
+
+
+
+
+ <%= link_to_function(image_tag('rev_downloads.png', :plugin => 'redmine_dmsf'), "$('#revision_access-#{revision.id}').toggle()", :title => 'Download entries')%> + <%= link_to(image_tag('rev_download.png', :plugin => 'redmine_dmsf'), + {:action => 'show', :id => @file, :download => revision}, + :title => l(:title_title_version_version_download, :title => h(revision.title), :version => revision.version)) %> + <% if User.current.allowed_to?(:file_approval, @project) %> + <%= link_to_function(image_tag('rev_delete.png', :plugin => 'redmine_dmsf'), + "confirmation_link('#{url_for(:action => 'delete_revision', :id => revision)}', '#{l(:question_do_you_really_want_to_delete_this_revision)}')", + :title => l(:title_delete_revision)) %> + <% end %> +
+ <%= l(:info_revision, :rev => revision.id) %> + <%= (revision.source_revision.nil? ? l(:label_created) : l(:label_changed)).downcase %> + <%= l(:info_changed_by_user, :changed => format_time(revision.updated_at)) %> + <%= link_to(revision.user) %> +
+
+
+
+
+ <%= label_tag("", l(:label_title) + ":") %> + <%= h(revision.title) %> +
+
+ <%= label_tag("", l(:label_file) + ":") %> + <%= (h(revision.folder.dmsf_path_str) + "/") unless revision.folder.nil? %><%= h(revision.name) %> +
+
+

+ <%= label_tag("", l(:label_description) + ":") %> +

+
+ <%= textilizable(revision.description) %> +
+
+ <%= label_tag("", l(:label_version) + ":") %> + <%= revision.major_version %>.<%= revision.minor_version %> +
+ <%= label_tag('', l(:label_workflow) + ':') %> + <%= revision.workflow_str true %> +
+
+ <%= label_tag("", l(:label_mime) + ":") %> + <%= h(revision.mime_type) %>  +
+ <%= label_tag("", l(:label_size) + ":") %> + <%= number_to_human_size(revision.size) %> +
+
+ <%= render "dmsf/custom_fields", :object => revision %> +
+
+ <%= label_tag("", l(:label_comment) + ":") %> + <%= h(revision.comment) %> +
+
+
" style="display:none"> + <%= render(:partial => "revision_access", :locals => {:revision => revision}) if User.current.allowed_to?(:file_approval, @file.project) %> +
+
+
+
+
<% end %>

<%= pagination_links_full @revision_pages, @file.revisions.visible.count %>

diff --git a/assets/images/rev_delete.png b/assets/images/rev_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..8c631734658b8fb36ec8f7bcdff5e6810299a6c0 GIT binary patch literal 647 zcmV;20(kw2P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*l6 z3KkK|_CX>@2HM@dakSAh-}0005vNklg`YRCm9EhxpI5k== zf!4Wl*(NLb1p&it_ha_GztNUn>Q{P>oI5aNtSJw&#@R zp%xZs@9ydxI9;y`af~@Q;A58ce;9N5QkuRx+F*o04n%IuOyRJw=z?WcD&$E*9>-Xf z3htlY)tLsN$bAQH`o3?QZkM0NppC(FyZF9umti9k*&5f3KjNkXcWbsSd6x0r7&^wJ zLogMkq@)x@$6-H7bPC%Itsfm31R@Tw<0-Z3K(P;WjM2a~AO~J7D&^Qf0{J&%z5wT& zTBmC4BQ53d#)euSGGMc*_4C64SAnNCoan=T5iVZP`s=g=P6Z-+p~$@{+?_zA6^Sg( hJf>*}^Ecc-<2Os>zR&j^rZoTn002ovPDHLkV1n%&7c>9> literal 0 HcmV?d00001 diff --git a/assets/images/rev_download.png b/assets/images/rev_download.png new file mode 100644 index 0000000000000000000000000000000000000000..c3c74e1a323e1c1ffef0b7f810720ff76328b319 GIT binary patch literal 656 zcmV;B0&o3^P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*l6 z3k3kddD)@>00Iz6L_t(I%e9hCXcJKsh0mS$nwU;I5^a^Dn`#$kr)Z-g;t#kHMK=ab z2tuI2h(j>h3WDMybfw@{BHf6(@h>>wu0lT12qo{N%FQ(Fb` zt{#VTzsJ4z5IX9}%Rc(-x-A~T)S%5 z*J`O$3bg<3K~e|R(|z0f3m(Pu!^^zhEsD2m{caq0$*H%v!fD2unQB<|vy<09R#@4X zhZfK*8c@7DyLX)MC>|!HkP0cZ`nwd86IXoP$7kzvt!AZpsgyFm$`uVgNu@yK2|wYnRRVyEg#f_xr(2(?mL*Mq%`2qjz6#$sNGq z9D07N1Y7>2Qa)7fkm05JS8bnMK;xy6wWS7gE*k>MA|A2A>E0YEew z#fC}LG!0Tp5Yc#WEOgPc$Md?fP%TgAt3xR^P#~(8&Y$5A^{+ qGMW7Qbj9QG6+kcu0MK=PL+?-J-_xIPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*l6 z3j_;KurX@@00II@L_t(I%e9g}s8Vqh$G^Ydy{T7GxEQ+J&6ek$4K4*OL0d>E5?oL) zl1tvTsU`$896+~w_hcDmrfphpW z9F(r>g5x;Cp}yPg$TUs6*=*9jE*=^sNqSC1X(F;NHO3gTEbEMjUIX}iEkIF}6VCZ< z#u)YhST2`8hQs08KLQ-bvGE;-jYh)`g+ix3pYN8}>pkI|vrEWD z2LLvo&o`6F)dFdB_o<#PFjZQFJ-nMAAAI-bNpAOIo)W9*}* zX^%xwd~cd&uhZ!~Td&tERaIda#`VESrBYY3rfK&wnaoW9$Y!&DpRRN|4FHJ6VgP`A cKL1 Date: Mon, 3 Jun 2013 07:10:32 +0200 Subject: [PATCH 06/10] Approval workflow - log view --- app/models/dmsf_file_revision.rb | 16 +++--- app/models/dmsf_workflow_step_action.rb | 12 ++++- app/views/dmsf/show.html.erb | 32 ++++++++---- app/views/dmsf_workflows/_log.html.erb | 49 +++++++++++++++++++ app/views/dmsf_workflows/log.html.erb | 1 - app/views/dmsf_workflows/log.js.erb | 3 ++ app/views/dmsf_workflows/new_action.js.erb | 2 - assets/stylesheets/dmsf.css | 20 ++++---- config/locales/en.yml | 7 ++- config/routes.rb | 1 + .../20120822100401_create_dmsf_workflows.rb | 8 +++ ...00404_create_dmsf_workflow_step_actions.rb | 1 + init.rb | 2 +- 13 files changed, 120 insertions(+), 34 deletions(-) create mode 100644 app/views/dmsf_workflows/_log.html.erb delete mode 100644 app/views/dmsf_workflows/log.html.erb create mode 100644 app/views/dmsf_workflows/log.js.erb delete mode 100644 app/views/dmsf_workflows/new_action.js.erb diff --git a/app/models/dmsf_file_revision.rb b/app/models/dmsf_file_revision.rb index 0ce4c46f..c9afb538 100644 --- a/app/models/dmsf_file_revision.rb +++ b/app/models/dmsf_file_revision.rb @@ -182,20 +182,22 @@ class DmsfFileRevision < ActiveRecord::Base unless dmsf_workflow_id.blank? self.dmsf_workflow_id = dmsf_workflow_id if commit == 'start' - self.workflow = DmsfWorkflow::STATE_WAITING_FOR_APPROVAL # Waiting for approval + self.workflow = DmsfWorkflow::STATE_WAITING_FOR_APPROVAL + self.dmsf_workflow_started_by = User.current.id if User.current + self.dmsf_workflow_started_at = DateTime.now else - self.workflow = DmsfWorkflow::STATE_DRAFT # Draft + self.workflow = DmsfWorkflow::STATE_DRAFT + self.dmsf_workflow_assigned_by = User.current.id if User.current + self.dmsf_workflow_assigned_at = DateTime.now end end end end def assign_workflow(dmsf_workflow_id) - if User.current.allowed_to?(:file_approval, self.file.project) - #if self.workflow == DmsfWorkflow::STATE_DRAFT # Waiting for approval - wf = DmsfWorkflow.find_by_id(dmsf_workflow_id) - wf.assign(self.id) if wf && self.id - #end + if User.current.allowed_to?(:file_approval, self.file.project) + wf = DmsfWorkflow.find_by_id(dmsf_workflow_id) + wf.assign(self.id) if wf && self.id end end diff --git a/app/models/dmsf_workflow_step_action.rb b/app/models/dmsf_workflow_step_action.rb index 568e4252..718bb16d 100644 --- a/app/models/dmsf_workflow_step_action.rb +++ b/app/models/dmsf_workflow_step_action.rb @@ -17,17 +17,25 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class DmsfWorkflowStepAction < ActiveRecord::Base - + belongs_to :dmsf_workflow_step_assignment validates :dmsf_workflow_step_assignment_id, :presence => true validates :action, :presence => true validates :note, :presence => true, :unless => lambda { self.action == DmsfWorkflowStepAction::ACTION_APPROVE } + validates :author_id, :presence => true ACTION_APPROVE = 1 ACTION_REJECT = 2 ACTION_DELEGATE = 3 + ACTION_ASSIGN = 4 + ACTION_START = 5 + def initialize(*args) + super + self.author_id = User.current.id if User.current + end + def self.is_finished?(action) action == DmsfWorkflowStepAction::ACTION_APPROVE || action == DmsfWorkflowStepAction::ACTION_REJECT @@ -36,5 +44,5 @@ class DmsfWorkflowStepAction < ActiveRecord::Base def is_finished? DmsfWorkflowStepAction.is_finished? self.action end - + end \ No newline at end of file diff --git a/app/views/dmsf/show.html.erb b/app/views/dmsf/show.html.erb index aec9a1c3..52f8ae8b 100644 --- a/app/views/dmsf/show.html.erb +++ b/app/views/dmsf/show.html.erb @@ -65,8 +65,9 @@ <%= l(:link_title) %> <%= l(:link_size) %> <%= l(:link_modified) %> - <%= l(:link_ver) %> - <%= l(:link_author) %> + <%= l(:link_ver) %> + <%= l(:link_workflow) %> + <%= l(:link_author) %> @@ -93,7 +94,8 @@ <%= image_tag("lockedbycurrent.png", :title => l(:title_locked_by_you), :plugin => :redmine_dmsf) %> <% end %> - + + <%= h(subfolder.user) %> <% if User.current.allowed_to?(:file_approval, @project) %> @@ -171,9 +173,21 @@ <%= image_tag("lockedbycurrent.png", :title => l(:title_locked_by_you), :plugin => :redmine_dmsf) %> <% end %> - - <%= "#{file.last_revision.version} #{file.last_revision.workflow_str(false)}" %> - + <%= file.last_revision.version %> + + <% wf = DmsfWorkflow.find_by_id(file.last_revision.dmsf_workflow_id) %> + <% if wf %> + <%= link_to( + file.last_revision.workflow_str(false), + log_dmsf_workflow_path( + :project_id => @project.id, + :id => wf.id, + #:dmsf_workflow_step_assignment_id => dmsf_workflow_step_assignment_id, + :dmsf_file_revision_id => file.last_revision.id), + #:title => l(:title_waiting_for_approval), + :remote => true) %> + <% end %> + <%= h(file.last_revision.user) %> <% if User.current.allowed_to?(:file_approval, @project) %> @@ -314,9 +328,9 @@ sUrl = "jquery.dataTables/#{I18n.locale.to_s.downcase}.json" if I18n.locale && ! "aaSorting": [[1,'asc']], "aaSortingFixed": [[7,'asc']], "aoColumnDefs": [ - { "bSearchable": false, "aTargets": [0, 6, 7, 8] }, - { "bSortable": false, "aTargets": [0, 6, 7] }, - { "iDataSort": 8, "aTargets": [ 2 ] } + { "bSearchable": false, "aTargets": [0, 7, 8, 9] }, + { "bSortable": false, "aTargets": [0, 7, 8] }, + { "iDataSort": 9, "aTargets": [ 2 ] } ], "fnInitComplete": function() { jQuery("div.controls").prependTo(jQuery("#browser_wrapper div.fg-toolbar")[0]); diff --git a/app/views/dmsf_workflows/_log.html.erb b/app/views/dmsf_workflows/_log.html.erb new file mode 100644 index 00000000..ac84c720 --- /dev/null +++ b/app/views/dmsf_workflows/_log.html.erb @@ -0,0 +1,49 @@ +

<%= l(:title_dmsf_workflow_log) %>

+ +

+ <% if params[:dmsf_file_revision_id].present? %> + <% revision = DmsfFileRevision.find_by_id(params[:dmsf_file_revision_id]) %> + <% if revision %> + <%= link_to @workflow.name, edit_dmsf_workflow_path(@workflow) %><%= " - #{revision.workflow_str false}" %> +

+ + + + + + + + + + + + + + + + + + + + + + + + <% sql = "SELECT c.action, c.note, c.created_at, c.author_id, a.user_id, s.step FROM dmsf_workflow_step_actions c RIGHT JOIN dmsf_workflow_step_assignments a ON a.id = c.dmsf_workflow_step_assignment_id JOIN dmsf_workflow_steps s ON s.id = a.dmsf_workflow_step_id WHERE a.dmsf_file_revision_id = #{revision.id} ORDER BY c.created_at" %> + <% result = DmsfWorkflowStep.connection.execute sql %> + <% result.each_with_index do |row, i| %> + + + + + + + + <% end; reset_cycle %> + +
<%= l(:label_dmsf_workflow_step) %><%= l(:label_user) %> <%= l(:label_action) %><%= l(:label_note) %><%=l(:label_date)%>
-<%= link_to_user User.find_by_id(revision.dmsf_workflow_assigned_by) if revision.dmsf_workflow_assigned_by %>Assigned<%= format_time(revision.dmsf_workflow_assigned_at) if revision.dmsf_workflow_assigned_at %>
-<%= link_to_user User.find_by_id(revision.dmsf_workflow_started_by) if revision.dmsf_workflow_started_by %>Started<%= format_time(revision.dmsf_workflow_started_at) if revision.dmsf_workflow_started_at %>
<%= row[5] %><%= link_to_user User.find_by_id(row[3].present? ? row[3] : row[4]) %><%= revision.workflow_str false %><%= row[1] %><%= format_time(row[2]) if row[2].present? %>
+
+ <% end %> + <% end %> +

+ diff --git a/app/views/dmsf_workflows/log.html.erb b/app/views/dmsf_workflows/log.html.erb deleted file mode 100644 index 6231320b..00000000 --- a/app/views/dmsf_workflows/log.html.erb +++ /dev/null @@ -1 +0,0 @@ -

WorkflowController#log

diff --git a/app/views/dmsf_workflows/log.js.erb b/app/views/dmsf_workflows/log.js.erb new file mode 100644 index 00000000..de409eaa --- /dev/null +++ b/app/views/dmsf_workflows/log.js.erb @@ -0,0 +1,3 @@ +$('#ajax-modal').html('<%= escape_javascript(render :partial => 'log', :locals => {:workflow => @workflow}) %>'); +showModal('ajax-modal', '640px'); +$('#ajax-modal').addClass('workflow-log'); \ No newline at end of file diff --git a/app/views/dmsf_workflows/new_action.js.erb b/app/views/dmsf_workflows/new_action.js.erb deleted file mode 100644 index 92d31fd2..00000000 --- a/app/views/dmsf_workflows/new_action.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').modal('hide').empty(); -window.location.reload(); \ No newline at end of file diff --git a/assets/stylesheets/dmsf.css b/assets/stylesheets/dmsf.css index 21f077df..5c8623cb 100644 --- a/assets/stylesheets/dmsf.css +++ b/assets/stylesheets/dmsf.css @@ -14,8 +14,8 @@ table.entries { } table.entries td.modified { - min-width: 140px; - width: 140px; + min-width: 104px; + width: 104px; } table.entries td.actions { @@ -24,7 +24,7 @@ table.entries td.actions { } table.entries td.title { - width: 50%; + width: 40%; } table.entries th.check, table.entries td.check { @@ -136,6 +136,11 @@ td.version img { vertical-align:text-top; } +td.workflow { + font-size: 0.8em; + white-space: nowrap; +} + /* DMSF entries list icons */ div.right_icon_box { @@ -251,11 +256,6 @@ div.revision_box .ui-widget-header { font-weight: normal; } -td.workflow { - font-size: 0.8em; - white-space: nowrap; +table.steps td.note { + width: 30%; } - -td.workflow img { - vertical-align:text-top; -} \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 60c31ada..5e6cd109 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -45,7 +45,7 @@ en: :link_title: "Title" :link_size: "Size" :link_modified: "Modified" - :link_ver: "Version" + :link_ver: "Ver." :link_author: "Author" :title_check_for_zip_download_or_email: "Check for Zip download or email" :title_delete: "Delete" @@ -230,4 +230,7 @@ en: info_revision: "r%{rev}" link_workflow: Workflow button_assign: Assign - error_empty_note: "The note can't be empty" \ No newline at end of file + error_empty_note: "The note can't be empty" + title_dmsf_workflow_log: 'Approval workflow log' + label_action: Action + label_note: Note \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 83b8e729..193a6379 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -107,6 +107,7 @@ RedmineApp::Application.routes.draw do get 'autocomplete_for_user' get 'action' get 'assign' + get 'log' post 'new_action' post 'start' post 'assignment' diff --git a/db/migrate/20120822100401_create_dmsf_workflows.rb b/db/migrate/20120822100401_create_dmsf_workflows.rb index fbb00c29..8bc9de19 100644 --- a/db/migrate/20120822100401_create_dmsf_workflows.rb +++ b/db/migrate/20120822100401_create_dmsf_workflows.rb @@ -26,11 +26,19 @@ class CreateDmsfWorkflows < ActiveRecord::Migration change_table :dmsf_file_revisions do |t| t.references :dmsf_workflow + t.integer :dmsf_workflow_assigned_by + t.datetime :dmsf_workflow_assigned_at + t.integer :dmsf_workflow_started_by + t.datetime :dmsf_workflow_started_at end end def self.down remove_column :dmsf_file_revisions, :dmsf_workflow_id + remove_column :dmsf_file_revisions, :dmsf_workflow_assigned_by + remove_column :dmsf_file_revisions, :dmsf_workflow_assigned_at + remove_column :dmsf_file_revisions, :dmsf_workflow_started_by + remove_column :dmsf_file_revisions, :dmsf_workflow_started_at drop_table :dmsf_workflows end end diff --git a/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb b/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb index e7704c5e..2ee590e3 100644 --- a/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb +++ b/db/migrate/20120822100404_create_dmsf_workflow_step_actions.rb @@ -23,6 +23,7 @@ class CreateDmsfWorkflowStepActions < ActiveRecord::Migration t.integer :action, :null => false t.text :note t.timestamp :created_at + t.integer :author_id, :null => false end add_index :dmsf_workflow_step_actions, :dmsf_workflow_step_assignment_id, diff --git a/init.rb b/init.rb index f61b03d2..23f74632 100644 --- a/init.rb +++ b/init.rb @@ -57,7 +57,7 @@ Redmine::Plugin.register :redmine_dmsf do :dmsf_upload => [:upload_files, :upload_file, :commit_files]} permission :file_approval, {:dmsf_files => [:delete_revision, :notify_activate, :notify_deactivate], :dmsf => [:notify_activate, :notify_deactivate], - :dmsf_workflows => [:new, :create, :destroy, :edit, :add_step, :remove_step, :reorder_steps, :update, :start, :assign, :assignment, :action, :new_action]} + :dmsf_workflows => [:new, :create, :destroy, :edit, :add_step, :remove_step, :reorder_steps, :update, :start, :assign, :assignment, :action, :new_action, :log]} permission :force_file_unlock, {} end From d4cde32eb39ff900b9f6cc183caee70c10fdaeb9 Mon Sep 17 00:00:00 2001 From: Karel Picman Date: Mon, 3 Jun 2013 09:12:53 +0200 Subject: [PATCH 07/10] Log view steps reordering --- app/models/dmsf_workflow_step_action.rb | 17 +++++++++++++++++ app/views/dmsf_workflows/_log.html.erb | 8 ++++---- config/locales/en.yml | 3 +++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/app/models/dmsf_workflow_step_action.rb b/app/models/dmsf_workflow_step_action.rb index 718bb16d..2e5f49aa 100644 --- a/app/models/dmsf_workflow_step_action.rb +++ b/app/models/dmsf_workflow_step_action.rb @@ -44,5 +44,22 @@ class DmsfWorkflowStepAction < ActiveRecord::Base def is_finished? DmsfWorkflowStepAction.is_finished? self.action end + + def self.action_str(action) + if action + case action.to_i + when ACTION_APPROVE + l(:title_approved) + when ACTION_REJECT + l(:title_rejected) + when ACTION_DELEGATE + l(:title_delegated) + when ACTION_ASSIGN + l(:title_assigned) + when ACTION_START + l(:title_started) + end + end + end end \ No newline at end of file diff --git a/app/views/dmsf_workflows/_log.html.erb b/app/views/dmsf_workflows/_log.html.erb index ac84c720..5524da96 100644 --- a/app/views/dmsf_workflows/_log.html.erb +++ b/app/views/dmsf_workflows/_log.html.erb @@ -18,24 +18,24 @@ - <%= link_to_user User.find_by_id(revision.dmsf_workflow_assigned_by) if revision.dmsf_workflow_assigned_by %> - Assigned + <%= DmsfWorkflowStepAction.action_str(DmsfWorkflowStepAction::ACTION_ASSIGN) %> <%= format_time(revision.dmsf_workflow_assigned_at) if revision.dmsf_workflow_assigned_at %> - <%= link_to_user User.find_by_id(revision.dmsf_workflow_started_by) if revision.dmsf_workflow_started_by %> - Started + <%= DmsfWorkflowStepAction.action_str(DmsfWorkflowStepAction::ACTION_START) %> <%= format_time(revision.dmsf_workflow_started_at) if revision.dmsf_workflow_started_at %> - <% sql = "SELECT c.action, c.note, c.created_at, c.author_id, a.user_id, s.step FROM dmsf_workflow_step_actions c RIGHT JOIN dmsf_workflow_step_assignments a ON a.id = c.dmsf_workflow_step_assignment_id JOIN dmsf_workflow_steps s ON s.id = a.dmsf_workflow_step_id WHERE a.dmsf_file_revision_id = #{revision.id} ORDER BY c.created_at" %> + <% sql = "SELECT c.action, c.note, c.created_at, c.author_id, a.user_id, s.step FROM dmsf_workflow_step_actions c RIGHT JOIN dmsf_workflow_step_assignments a ON a.id = c.dmsf_workflow_step_assignment_id JOIN dmsf_workflow_steps s ON s.id = a.dmsf_workflow_step_id WHERE a.dmsf_file_revision_id = #{revision.id} ORDER BY s.step, c.created_at" %> <% result = DmsfWorkflowStep.connection.execute sql %> <% result.each_with_index do |row, i| %> <%= row[5] %> <%= link_to_user User.find_by_id(row[3].present? ? row[3] : row[4]) %> - <%= revision.workflow_str false %> + <%= DmsfWorkflowStepAction.action_str(row[0]) %> <%= row[1] %> <%= format_time(row[2]) if row[2].present? %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 5e6cd109..03eb745c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -226,6 +226,9 @@ en: message_dmsf_wokflow_note: Your note... title_draft: Draft title_rejected: Rejected + title_delegated: Delegated + title_assigned: Assigned + title_started: Started label_dmsf_wokflow_action_start: Start workflow info_revision: "r%{rev}" link_workflow: Workflow From 1bb238296314d6b24a9ff12b86f44c625c31ebe1 Mon Sep 17 00:00:00 2001 From: Karel Picman Date: Mon, 3 Jun 2013 09:25:27 +0200 Subject: [PATCH 08/10] jquery-ui upgraded to 1.9.2 --- app/views/dmsf/show.html.erb | 2 +- app/views/dmsf_files/show.html.erb | 2 +- .../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 0 -> 260 bytes .../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 0 -> 251 bytes .../images/ui-bg_flat_10_000000_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_100_eef5fd_1x400.png | Bin 0 -> 113 bytes .../images/ui-bg_glass_100_f6f6f6_1x400.png | Bin 0 -> 104 bytes .../ui-bg_gloss-wave_35_759fcf_500x100.png | Bin 0 -> 3945 bytes .../ui-bg_highlight-soft_100_eeeeee_1x100.png | Bin 0 -> 90 bytes .../ui-bg_highlight-soft_75_759fcf_1x100.png | Bin 0 -> 126 bytes .../images/ui-icons_759fcf_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffd27a_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 4369 bytes .../jquery-ui/jquery-ui-1.8.13.css | 578 ------------------ .../stylesheets/jquery-ui/jquery-ui-1.9.2.css | 5 + 15 files changed, 7 insertions(+), 580 deletions(-) create mode 100644 assets/stylesheets/jquery-ui/images/ui-bg_diagonals-thick_18_b81900_40x40.png create mode 100644 assets/stylesheets/jquery-ui/images/ui-bg_diagonals-thick_20_666666_40x40.png create mode 100644 assets/stylesheets/jquery-ui/images/ui-bg_flat_10_000000_40x100.png create mode 100644 assets/stylesheets/jquery-ui/images/ui-bg_glass_100_eef5fd_1x400.png create mode 100644 assets/stylesheets/jquery-ui/images/ui-bg_glass_100_f6f6f6_1x400.png create mode 100644 assets/stylesheets/jquery-ui/images/ui-bg_gloss-wave_35_759fcf_500x100.png create mode 100644 assets/stylesheets/jquery-ui/images/ui-bg_highlight-soft_100_eeeeee_1x100.png create mode 100644 assets/stylesheets/jquery-ui/images/ui-bg_highlight-soft_75_759fcf_1x100.png create mode 100644 assets/stylesheets/jquery-ui/images/ui-icons_759fcf_256x240.png create mode 100644 assets/stylesheets/jquery-ui/images/ui-icons_ffd27a_256x240.png create mode 100644 assets/stylesheets/jquery-ui/images/ui-icons_ffffff_256x240.png delete mode 100644 assets/stylesheets/jquery-ui/jquery-ui-1.8.13.css create mode 100644 assets/stylesheets/jquery-ui/jquery-ui-1.9.2.css diff --git a/app/views/dmsf/show.html.erb b/app/views/dmsf/show.html.erb index 52f8ae8b..d1a1f17b 100644 --- a/app/views/dmsf/show.html.erb +++ b/app/views/dmsf/show.html.erb @@ -307,7 +307,7 @@ sUrl = "jquery.dataTables/#{I18n.locale.to_s.downcase}.json" if I18n.locale && ! %> <% content_for :header_tags do %> - <%= stylesheet_link_tag "jquery-ui/jquery-ui-1.8.13.css", :plugin => "redmine_dmsf" %> + <%= stylesheet_link_tag "jquery-ui/jquery-ui-1.9.2.css", :plugin => "redmine_dmsf" %> <%= stylesheet_link_tag "plupload/jquery.ui.plupload.css", :plugin => "redmine_dmsf" %> <%= stylesheet_link_tag "jquery.dataTables/jquery-ui.dataTables.css", :plugin => "redmine_dmsf" %> <%= stylesheet_link_tag "dmsf", :plugin => "redmine_dmsf" %> diff --git a/app/views/dmsf_files/show.html.erb b/app/views/dmsf_files/show.html.erb index 2c86be27..8235422b 100644 --- a/app/views/dmsf_files/show.html.erb +++ b/app/views/dmsf_files/show.html.erb @@ -171,7 +171,7 @@ sUrl = "jquery.dataTables/#{I18n.locale.to_s.downcase}.json" if I18n.locale && ! <% end %> <% content_for :header_tags do %> - <%= stylesheet_link_tag "jquery-ui/jquery-ui-1.8.13.css", :plugin => "redmine_dmsf" %> + <%= stylesheet_link_tag "jquery-ui/jquery-ui-1.9.2.css", :plugin => "redmine_dmsf" %> <%= stylesheet_link_tag "jquery.dataTables/jquery-ui.dataTables.css", :plugin => "redmine_dmsf" %> <%= stylesheet_link_tag "dmsf", :plugin => "redmine_dmsf" %> <%= javascript_include_tag "jquery-1.6.1.min.js", :plugin => "redmine_dmsf" %> diff --git a/assets/stylesheets/jquery-ui/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/assets/stylesheets/jquery-ui/images/ui-bg_diagonals-thick_18_b81900_40x40.png new file mode 100644 index 0000000000000000000000000000000000000000..954e22dbd99e8c6dd7091335599abf2d10bf8003 GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU1|)m_?Z^dEr#)R9Ln2z=UU%d=WFXS=@V?HT z#xG*`>Yvsgk=}99w^d^D^d*@m74oMo<%#FcopJf?u00-~YVKV2wzrI*_R6;UORMea zBFVSEnN~eiVA6V&z`E)YLz5Aok^D)In}Yn=OzDpgR5Wv0XfT8pOkmV{sKAJ-PO9#T zZK}IXj&Q-V!U)!LcB_3K0&C*{ literal 0 HcmV?d00001 diff --git a/assets/stylesheets/jquery-ui/images/ui-bg_diagonals-thick_20_666666_40x40.png b/assets/stylesheets/jquery-ui/images/ui-bg_diagonals-thick_20_666666_40x40.png new file mode 100644 index 0000000000000000000000000000000000000000..64ece5707d91a6edf9fad4bfcce0c4dbcafcf58d GIT binary patch literal 251 zcmVbvPcjKS|RKP(6sDcCAB(_QB%0978a<$Ah$!b|E zwn;|HO0i8cQj@~)s!ajF0S002ovPDHLkV1oEp BYH0uf literal 0 HcmV?d00001 diff --git a/assets/stylesheets/jquery-ui/images/ui-bg_flat_10_000000_40x100.png b/assets/stylesheets/jquery-ui/images/ui-bg_flat_10_000000_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..abdc01082bf3534eafecc5819d28c9574d44ea89 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQY-ImG zFPf9b{J;c_6SHRK%WcbN_hZpM=(Ry;4Rxv2@@2Y=$K57eF$X$=!PC{xWt~$(69B)$ BI)4BF literal 0 HcmV?d00001 diff --git a/assets/stylesheets/jquery-ui/images/ui-bg_glass_100_eef5fd_1x400.png b/assets/stylesheets/jquery-ui/images/ui-bg_glass_100_eef5fd_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..c3492e336d2018bda4d6d48dca8f447c077253a6 GIT binary patch literal 113 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq%1sL978O6lYe~r{Jvg|jg74> zFlmZ}YMbuI*Ze(4PaHUK;K%`vWW%IH#gk4d5`ka(gccvsFx22=m=nm!7p(ip251I@ Mr>mdKI;Vst0O$E40A|lcT8| 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 SeP)gTCw&4>)Eztj&wm3=PZNp& literal 0 HcmV?d00001 diff --git a/assets/stylesheets/jquery-ui/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/assets/stylesheets/jquery-ui/images/ui-bg_highlight-soft_100_eeeeee_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..f1273672d253263b7564e9e21d69d7d9d0b337d9 GIT binary patch literal 90 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 literal 0 HcmV?d00001 diff --git a/assets/stylesheets/jquery-ui/images/ui-icons_ffd27a_256x240.png b/assets/stylesheets/jquery-ui/images/ui-icons_ffd27a_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..e117effa3dca24e7978cfc5f8b967f661e81044f GIT binary patch literal 4369 zcmd^?`8O2)_s3@pGmLE*`#M>&Z`mr_kcwz5Nh&g=McJ3E!;CE1E0ryV5Ro;>nvtvt zk&I==Xd;cVGZ@>q_xtnx{1u%7-D)N|5YqOB>i;(bZ#o62{J2Y9&^D3~R^$o+X? zwbxAEIb)xwCwK3TSR4QVym6N1rVgPmmt0caryBUceHP_&u}{?^Jn7f0PT$#h>UDqI zr!q(F&1jJ2_!jxdAB<)7H$foI*2zuncvu;;$SoU7br=AiJ@4=BC4vNO>DS`&UIB=K z;2)0F*t^FBvVfPuT4FVMSwUw%Xksjyl+;#*DDy%=ocFOyzDLvLR(`zCSOuJ=?FWYn z5ZD!UaoF>-$@=Vt?a&;UQYM$Oqe0ZB?Je?8ZnMxDe&uzzs*zlHd)V58nfJPc8S^({_4bj5HQ_B&EXHWj6wx@B;!mr04b_Mx)UFL)W7`V!c zpMp#C!a!!sh3h491y}^qfimXVY%!+sYu0_DWoJMqpN(FR9LM#jdZ{vJzEck`P^9(1N=4J za9%u4$2J8TAkUaJk_FX%iHuv#svL_mMmp{SR}ifc#ZcXv%CFsT?*>N^6r(%D?1YnU zAaT?UZGlOna6UXXs0m)3YDp}d%hb@)@Y!lK_A&D6{OPlNnj zYY*$b>vnRzL8=CDbQSi!DL3D!P^xhNtwrYByo?h-&OvQZYJ6ka{Re# zSc0ry_d(K$_Q2M{Y^O~DOK(szDOnMi_*h_Rx%eSRxA%n|FuC&=F=)B z_Qsgmj8g!GA+LZOX)gOW}vbo9|l8QW3iYw9qCD{o~xt^HIU>;dV5MJgc0#uHTA z80%Ee_r;G`GUjssm z*AhtwpW%Ly;X4Lq1Zq#ZpuwzrZE$sR087dN{w7PA6|Mo#6wwJP085K+h7+D>NyeX# zk|?MJ^Es)JtP-2eNr0EQe*ZM`&}OU zCD*uSSviE&p}uX|@1g_%|3*ra*MbBV#~cshdcFQ(dGLnTqaO-3{u==x1;Pp2im!#` zuZ2`ThfAmiSzb|4h`c4?^ZoGOF*oXYcV}(ge!v@^bse?daA`Ma+bSZLIg;pIN17vM zIOYfK=@s_Pj?~#lqnY2o?d1$MpoqsYQw%eX%X6Y4*^27{hMWGqILEMnVYUEMW#x7f zu^I*nzXQ@6HJ8n;26 zo^1+Ewi$fN$Unum1(FTb8I#cYgcGklwIExt#Mb(D=x~OTeZ^ubJ)S-ywfdZS?SRCq zDm=eU+CCWO@8S_m!W{alT)zj zZJbjxm5&No5xe_~Jw-i7`&G}=r)POGGfFq+c@kQbB#)ay`coj&C3- z(#&xV@Q3@VJd{qdH4g@4ZJi&mx9e@Io7@~(o5vTrkW>QEO1T-gmlTRHH+3)gcUC0P zk07rvDnf*7Y5J}8!>F_7D^Z3IoH^uGH}_a(ax{Q(IrvV$olf3WN&DY?uYZfvXI(;Vv&EAoQtfH;+4VI_a>yh*J+Cj!?h!QX?O`QXk@@G7AjloJe51Cw*rPXQ>#y?B^^ExRQFui zolmv*C5K|-p){rZiCNai^0H`1(Qr(Hz3v%7NnmriXu2tD>xsbN#*R3*wsZhRj6Lvb zn0Cu=qkC?*e4{NF_3=^bTb1f!g?@ryFH6Zw2tz%A zzz&o{w`dDv66!6Wk9w1-dglS#Sm{doxw&h5Z8&ONmlBBte{J)puaDzc!LC==rPRQK zQNH23?-rIo^MQdt3Tk!B@8l#}fxVtrlc8Y<>ORaVE($DKc{77qV^`+`%_DotrUD=8 z4}L7QnZi3RgUy*tteY-=$SqA2@IZWe(}mI`nzhAT{qC)my#rJsfoS*)xCXj!Tk6=3)cr@Jw#OcNqgS3pg7x|4!A$|w15X!huR*vB3q9Ya4 zF{xuzEQz{9YPl(gk`}Gffut%jotgqp$jZvzRO4EsExf~93vY~04AxH=lR>R3v3Qs2 zy$v4SN%ee@Kz#kDtARaQD`d!R%}#@T1=v8DAow*r>+0d1KS{ZtA~KMtgm)+$JHumW zw=;@qWk&MuG@LKx#K3@&WMw?r=jD2_)(*$LmkCm4_@};QZI|SPe8hIC6xqBy!LQyK z01_xmfNA9UlBU@Kzu7;zQYxHE>OCADA$gwaVqm`eN?XQF@NkrocB}lU4hcCf>wqir z>Ya=PcE!Xm#JG8v@G0lj&~)hScM}X57vGw3g<$^SUls53f|Bk>5FQwqE&{%u(f$!1 zl8+53vyYZ`mEEp&YT<=(krhKrw?~pS{N)?q{0qBR#2Y!w4!hWMdj`a(@A@r$zVB+u z06Hb@_9(cQ_AxbXI|-2w>#QUhp7k<+`z9+(jkh~v-Renr#C9U+&jL4vg6-E$f7@UU z(1fxB8{U2vq}h3rE!Z+n7=(>D&}@9~3mJ^R5}|WVG@!RSh3r{!>QHwg!t29YS&jiR ztyn_q*k9H0efZ7hO*b(WR|G!TDY`rol~Ob4&1OwdM8kbGj`^$~L5gdWYceWwL=PB{~NX=cu3p-{S;hqaE?bSHv$g+SA6bxy+VU3YVTPDj6CN zKLb_(9gM2Y#KW8ONxjH9To^Y)r?ql2cq8+WE438uIF$hjfdLs6-;!jv55jGcc3Ipg z;}aT32NAEGeU;J}&j5=+u`4?%xlwL7?NDn%2={4WS39yn3f;&r=|}5=M-Y2yrxeSw zv%*PmV{_{#Qk1sD>?M2KDapb~z3!E*-LPmCe9q86D%MGSe;4~~K-jKQxq6b^902_{ z%>4G>@Xqk8muR*|vGe5{@7sds2i|i;g}oMkd!o^0=HG+vcPrcN54A zLGv$PlTePRxp~-OSb_*aACO1qc{MpfS-fv(@UmRv%UO)cSt;ee@9(S)f>|~bwU@eZ z=kTS*sdjLclwMZG#?%U3)bq-uj?@@vj~6tq)ZS||Jxz`+di-M5SXM=h3EL`?pB>W9A;`V2vM)vk&%KFy|TAh#AQA zb_?J==3f@%LL{`vU$3Z@A2a9C3aC-YY43dR> pI7J0n@;b3~`)ubvsr|iU(l;L{A#E6J`}eC4usn-0uQEf&{2ws1m(ltoqJ#RmwV2==ic*rz7lOw=eaq=H~;_ux21)-Jpcgw zdj+hrf&W^f<%Qk9Zpqf#;q3n5{{POY;f!wmTR1An9(4&I0z1LNX50QSTV2M%4|y9c z#{ZQIVJKu~aY5?ZaZP*GIGqGs=e@q6o|EPhZB3CC?@LnORK8O@z{{<0KtSn5?#~OW zy=L;x8T&*%xqElS;s5~Pjk7d2bqIaA)xZbovnZd7eX17WNxx=w`p(8vulwUZ zl{so}MuRNJx5!8S5G;$o2?BApPHt+)!^#*Ww`?rcVE}mcyuY`X2o|uVUyI9o1t11O zemGWR?;aD#0$vJhiPhv~0iXS#iLq!>Qd$` zU{}<|Vb9Md>$4TMbL7C3GP#r;4Wc$}Z;^j;n}yc!E3d;`wry$!JkmJP0%(tIh!!TET8=+{rhUi^60G0t2HJSxXv-*DgC(HrJd8`|Dp3NvL5yg>xAvU zho|fEA~w^-HrW&H-JwkqNX2I-bEXBR&Uhp+y2^)1h1IIlNCzC!v-Mz@&z&VPz+cl1 z=f&f6Y*U~C`ixm4Sy1hl$hg(4%Dy;bq~k7d1<@K&%%NLT`L+A)-QXyKVswX?op90( zB#yeFEih@c{OXU8Oq~1CFI_38GXmns3(`;W(i+bslovCx4u7gvK>DrGOug*?G|1nz z_OR}|ZYS3pq-p?rS7G0qa`TM}r5XqDT4cV>%Qyk#9ES}`jc+Ww|DcbZrF6UG>CeXp zOVIV}K1e#z9@tu#?X)Ri=?zXMB`X3G-_I7FL-Zq`nbfWtX_EO1*!+U6pJW-_k&+vk zMd}THh}{(Ch_wPk(PI4vVB_KT76kGxVytLxpWg}&bHw`a3G#QzxV@ICNax&@hk3<_ zBh`Tq66G{-tCw$V{(y0v7l!tp20~@gdFXjzFbF#bJE7i>T4ux zQdrF3org^wFcnw$#bQMv@SfN3$Fuo7HnB_`2ZGB{ZqGr>%xP;2_!Q{=N-ZhU1c~^5 zdt=OO#wmcpkXJyCG?{{&n=R{Sn=Ytg;<09CH)l7TA&wkt{Q;>RrA2Ia6-QixEPLrU z%0)N$3Nh0?U825&v($Sz}0G_(!v&xSSAzje4{rup+^W@^}ByqOb95$E0sbwK*%#GP}!6`%*Z@L;&C z3^dE&>5%bWAXmP*X1 z_m}Pivs*u7@9i>qA!58fDCwj^M<1P(u^m;urVdlM@>aIf+E3-d9ZW>fc4cS7w5O3sCmKKn z+94A?VyfSBb9{}rEbCIYtXORJBCv__fnZ>?a}edaA%bP$jI?J^q0UKO!mduA8U!3b z0CJ_Js}NWQZoebapVUHP%pPOUm?1<)zd%`hzUM-Y6g1z|@@3G_kio?S0bcbjQuxJd>vU$Uyz(4*peEDSVc-G;O;% z9Y97%Tq}TRsH+oN%2u(oyC=W<9`e@&m;i;jC%L;sP(9RBDQnth3;ZMEQNFH3GEf0c zU<3RF!hNG-vCDooYFS^nPlFnv4(ElI1=vNcr42TF^uq67f{MoN>{f&>xA91r4pz5Zc&@P^i-9||`98v$Si!U@}ouZ88W zg;YL=OQ;4}UQtkpyd~lD{qWy0H|lwJXKmenz#E=*9kt$YX*X!wDk7ITlIUGWnj>a7 z<_GQR752@J)Y(U)ncu(dIit7P}oBq8x$FP85)&Nsw<#rOW z8U_x(1J)Zgm(8tZXU%+(yYcO+Z7#ZszPwa2`ygiMPayX9KondtFMRK!7x`9uWN;(f zfWW?8yOdj;GA3We0YAW92gWipn(d>zcbA+vZ_21BxF?-pfcW` zbqY??6ie(6M)p@6@WQ?Tl7 zoKrKEj|x~2yZehhMLkFRRnOC>XL&L+N;m0B{_OQ9gzzTYb!!Jct=bk?_hIpY9rOwY zMnr69R(?8EN52qR+k!~qnCYc-KmV&*d$&NY?t5cjR)V+ncMor=puTRoo?{5dH;@!* z<~RrV!+ljAN+;Qx2LraY&JWnz^|sYbZjP+Y;|pC#DuHUH+>F~x3PqTkx)=OAE0X9( z(AO6gp~AH^{nq+n)LHYDD8mQN?DDFcd!U&d4PaajzSD1~lXq3p{x=^vItrq3gD^4O z=hYS`?&C-0&KuAV>Jv}T?ba0IafL$~+bZ}p$9lwyyx=-uPN`Hpvv<)Ia>OWHa4+N4 z6zscrW$^XA32EJw^7hYtkRJr{Q8 zQ|*1pp_q6Mno|D6EX!kgSv0h0I3~ef_l%$DTFjL`0y16n%^dGNQn;2V82mqoIi9i{15vu zLq&(BTl9CInUjZlTIa>^!!HlMK3W8Sd_Ow0+E8IT?h$=55$^Z)$WYIuig=O;Lp_1Q z4wOT;XbWQ!>Mh`pdXuSo=KBba;wT!wK`Hf1Ueh04*%D7Kfj*#b~BNfvz zsbf?uiMm5-xhaQ|7Om2OrYbU>ngUM9%F5nU<65IFyu(`yZ;Vb1)=wCd!L2K?c$ezE z4IbS|^?Z>)eEp}ZfjwF)Waw?pPJ?{~*g%;efxO~Nx7dQGLWZ)cPQ*T!((W- zGm2?tM)K}7oG<0Xz<`ltWjxvE<$AH!4*R{A2~uYGr@m!vm*j+e#CE9^*}Oc#uihB| z5;#kMY2^8mrr80%*+02bDx6B{Jsch(d7kQGV7~iGTgFZBu$Pf`tNf`B2{|t7fGhIq zos0xF#l$bfxOtcGDd*MDbdKBaCKxgCEbr8JTNd_1bjWC{Ubgk z9~)9;A1&=FyIt$l!VBXfD~6VCk0fjO%QwLJ7k00RH*%I8cCqF542VzP^;`OU-_?=< zbV}OoQE)HqV`|)X5+WbgSxGWH>t+7-O;(l~Z+FJJ)sygu^+eF01#Suj+pnAcw!s>p z$-xF}c>7t9X6H$^V9hvT5H{jKv+=zzWHA0pgw8e5fZpm9vIphVq3%S4*N3%&jsY^Q zK%sSPuj=?d{ATs0o0y6#0w3%YT^@-_sTuTUwI(Q{;l3KjeAbVk#Wmi%PDxm`zoqQ~ z((<-}*FSP%5gt7uI3t1&75ne{@1^bpdW1;MMGNkSr~UAuDbB4+VQi|x(gdO^zin_) zncfs2hj8xdiiy)@vVkfkItLKvsGtJhrTb0T~tFl4Q3J!flauS==b& z6Bm!g%dDvlCf(St$kVofvH90|9yl-gmvRvcKS&Ye9DdoTK@2m}iSvC{3m%4E0 z@TJD7c1V?!URM7+t?f3)%{X(6JXg~A9TvGQyX6n(^Yt0NX;>vDPcr~mICPooLWA_` z<1A>FuXr|C)dtDr*PQt%Xs5WePWUB&gBj$zZ#BIY%?jDdpbSA-PV0`dGf^oa_Jp}Z zlrGV7oe`#B^+nPIQ`ZDJeJas=ru#=*YL#+n?Go}f33>1GsZ{TTy2bdBihj}mz*mp! zOzn%{WgLM=*CpiuKUs*GnHa{B$2siJqfNi|Z;|rH%stM*8b26kAMCYY&NHwPGtlYn z7UVx_^sgR$Z8x27foS63FCPt|gtcG_ zy#@C|!VQV~TY}G5e57qp?F4jRxqq~@h6^?-cvD>ySwVLl2m7=gERtEn>Fw_@ND%pO oiVC*mbz<%I+0K1Z`+LWvZ$3~$+A!Gm?^hpSc@||}WrmLVKLvuzv;Y7A literal 0 HcmV?d00001 diff --git a/assets/stylesheets/jquery-ui/jquery-ui-1.8.13.css b/assets/stylesheets/jquery-ui/jquery-ui-1.8.13.css deleted file mode 100644 index d3fb1c76..00000000 --- a/assets/stylesheets/jquery-ui/jquery-ui-1.8.13.css +++ /dev/null @@ -1,578 +0,0 @@ -/* - * jQuery UI CSS Framework 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Theming/API - */ - -/* Layout helpers -----------------------------------*/ -.ui-helper-hidden { display: none; } -.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } -.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } -.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } -.ui-helper-clearfix { display: inline-block; } -/* required comment for clearfix to work in Opera \*/ -* html .ui-helper-clearfix { height:1%; } -.ui-helper-clearfix { display:block; } -/* end clearfix */ -.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } - - -/* Interaction Cues -----------------------------------*/ -.ui-state-disabled { cursor: default !important; } - - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } - - -/* Misc visuals -----------------------------------*/ - -/* Overlays */ -.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } - - -/* - * jQuery UI CSS Framework 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Theming/API - * - * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px - */ - - -/* Component containers -----------------------------------*/ -.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } -.ui-widget .ui-widget { font-size: 1em; } -.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } -.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } -.ui-widget-content a { color: #222222; } -.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } -.ui-widget-header a { color: #222222; } - -/* Interaction states -----------------------------------*/ -.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } -.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } -.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } -.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } -.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } -.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } -.ui-widget :active { outline: none; } - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } -.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } -.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } -.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } -.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } -.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } -.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } -.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } -.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } -.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } -.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } -.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } -.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } -.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } -.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } - -/* positioning */ -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-off { background-position: -96px -144px; } -.ui-icon-radio-on { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } -.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } -.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } -.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } -.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } -.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } -.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } -.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } -.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } - -/* Overlays */ -.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } -.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* - * jQuery UI Resizable 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Resizable#theming - */ -.ui-resizable { position: relative;} -.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; - /* http://bugs.jqueryui.com/ticket/7233 - - Resizable: resizable handles fail to work in IE if transparent and content overlaps - */ - background-image:url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=); -} -.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } -.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } -.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } -.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } -.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } -.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } -.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } -.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } -.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* - * jQuery UI Selectable 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Selectable#theming - */ -.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } -/* - * jQuery UI Accordion 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Accordion#theming - */ -/* IE/Win - Fix animation bug - #4615 */ -.ui-accordion { width: 100%; } -.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } -.ui-accordion .ui-accordion-li-fix { display: inline; } -.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } -.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } -.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } -.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } -.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } -.ui-accordion .ui-accordion-content-active { display: block; } -/* - * jQuery UI Autocomplete 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Autocomplete#theming - */ -.ui-autocomplete { position: absolute; cursor: default; } - -/* workarounds */ -* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ - -/* - * jQuery UI Menu 1.8.13 - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Menu#theming - */ -.ui-menu { - list-style:none; - padding: 2px; - margin: 0; - display:block; - float: left; -} -.ui-menu .ui-menu { - margin-top: -3px; -} -.ui-menu .ui-menu-item { - margin:0; - padding: 0; - zoom: 1; - float: left; - clear: left; - width: 100%; -} -.ui-menu .ui-menu-item a { - text-decoration:none; - display:block; - padding:.2em .4em; - line-height:1.5; - zoom:1; -} -.ui-menu .ui-menu-item a.ui-state-hover, -.ui-menu .ui-menu-item a.ui-state-active { - font-weight: normal; - margin: -1px; -} -/* - * jQuery UI Button 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Button#theming - */ -.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ -.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ -button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ -.ui-button-icons-only { width: 3.4em; } -button.ui-button-icons-only { width: 3.7em; } - -/*button text element */ -.ui-button .ui-button-text { display: block; line-height: 1.4; } -.ui-button-text-only .ui-button-text { padding: .4em 1em; } -.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } -.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } -.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } -.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } -/* no icon support for input elements, provide padding by default */ -input.ui-button { padding: .4em 1em; } - -/*button icon element(s) */ -.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } -.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } -.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } -.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } -.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } - -/*button sets*/ -.ui-buttonset { margin-right: 7px; } -.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } - -/* workarounds */ -button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ -/* - * jQuery UI Dialog 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Dialog#theming - */ -.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } -.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } -.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } -.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } -.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } -.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } -.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } -.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } -.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } -.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } -.ui-draggable .ui-dialog-titlebar { cursor: move; } -/* - * jQuery UI Slider 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Slider#theming - */ -.ui-slider { position: relative; text-align: left; } -.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } -.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } - -.ui-slider-horizontal { height: .8em; } -.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } -.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } -.ui-slider-horizontal .ui-slider-range-min { left: 0; } -.ui-slider-horizontal .ui-slider-range-max { right: 0; } - -.ui-slider-vertical { width: .8em; height: 100px; } -.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } -.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } -.ui-slider-vertical .ui-slider-range-min { bottom: 0; } -.ui-slider-vertical .ui-slider-range-max { top: 0; }/* - * jQuery UI Tabs 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Tabs#theming - */ -.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ -.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } -.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } -.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } -.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } -.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } -.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ -.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } -.ui-tabs .ui-tabs-hide { display: none !important; } -/* - * jQuery UI Datepicker 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Datepicker#theming - */ -.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } -.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } -.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } -.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } -.ui-datepicker .ui-datepicker-prev { left:2px; } -.ui-datepicker .ui-datepicker-next { right:2px; } -.ui-datepicker .ui-datepicker-prev-hover { left:1px; } -.ui-datepicker .ui-datepicker-next-hover { right:1px; } -.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } -.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } -.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } -.ui-datepicker select.ui-datepicker-month-year {width: 100%;} -.ui-datepicker select.ui-datepicker-month, -.ui-datepicker select.ui-datepicker-year { width: 49%;} -.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } -.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } -.ui-datepicker td { border: 0; padding: 1px; } -.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } -.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } -.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } -.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } - -/* with multiple calendars */ -.ui-datepicker.ui-datepicker-multi { width:auto; } -.ui-datepicker-multi .ui-datepicker-group { float:left; } -.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } -.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } -.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } -.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } -.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } -.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } -.ui-datepicker-row-break { clear:both; width:100%; } - -/* RTL support */ -.ui-datepicker-rtl { direction: rtl; } -.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } -.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } -.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } -.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } -.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } -.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } -.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } -.ui-datepicker-rtl .ui-datepicker-group { float:right; } -.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } -.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } - -/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ -.ui-datepicker-cover { - display: none; /*sorry for IE5*/ - display/**/: block; /*sorry for IE5*/ - position: absolute; /*must have*/ - z-index: -1; /*must have*/ - filter: mask(); /*must have*/ - top: -4px; /*must have*/ - left: -4px; /*must have*/ - width: 200px; /*must have*/ - height: 200px; /*must have*/ -}/* - * jQuery UI Progressbar 1.8.13 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Progressbar#theming - */ -.ui-progressbar { height:2em; text-align: left; } -.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file diff --git a/assets/stylesheets/jquery-ui/jquery-ui-1.9.2.css b/assets/stylesheets/jquery-ui/jquery-ui-1.9.2.css new file mode 100644 index 00000000..090d220d --- /dev/null +++ b/assets/stylesheets/jquery-ui/jquery-ui-1.9.2.css @@ -0,0 +1,5 @@ +/*! jQuery UI - v1.9.2 - 2012-12-26 +* http://jqueryui.com +* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2C%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=759fcf&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=628db6&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=628db6&iconColorDefault=759fcf&bgColorHover=eef5fd&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=628db6&fcHover=628db6&iconColorHover=759fcf&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=628db6&fcActive=628db6&iconColorActive=759fcf&bgColorHighlight=759fcf&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=628db6&fcHighlight=363636&iconColorHighlight=759fcf&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px +* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{zoom:1}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;zoom:1}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto;zoom:1}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}* html .ui-autocomplete{width:1px}.ui-button{display:inline-block;position:relative;padding:0;margin-right:.1em;cursor:pointer;text-align:center;zoom:1;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:1.4}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0em}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current{float:right}.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-cover{position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;width:300px;overflow:hidden}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 16px .1em 0}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:19px;margin:-10px 0 0 0;padding:1px;height:18px}.ui-dialog .ui-dialog-titlebar-close span{display:block;margin:1px}.ui-dialog .ui-dialog-titlebar-close:hover,.ui-dialog .ui-dialog-titlebar-close:focus{padding:0}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto;zoom:1}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin:.5em 0 0 0;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:14px;height:14px;right:3px;bottom:3px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;zoom:1;width:100%}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;zoom:1;font-weight:normal}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em;zoom:1}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}* html .ui-tooltip{background-image:none}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Verdana,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #628db6;background:#759fcf url(images/ui-bg_gloss-wave_35_759fcf_500x100.png) 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#628db6}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#628db6;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #628db6;background:#eef5fd url(images/ui-bg_glass_100_eef5fd_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#628db6}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#628db6;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #628db6;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#628db6}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#628db6;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #628db6;background:#759fcf url(images/ui-bg_highlight-soft_75_759fcf_1x100.png) 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_ffffff_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_759fcf_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_759fcf_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_759fcf_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_759fcf_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_ffd27a_256x240.png)}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-khtml-border-top-left-radius:4px;border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-khtml-border-top-right-radius:4px;border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;-khtml-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;-khtml-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);-moz-border-radius:5px;-khtml-border-radius:5px;-webkit-border-radius:5px;border-radius:5px} From 2b03827aac3d307575d23d797d0072aa465b2afb Mon Sep 17 00:00:00 2001 From: Karel Picman Date: Mon, 3 Jun 2013 09:39:53 +0200 Subject: [PATCH 09/10] Workflow option removed from upload forms --- app/views/dmsf_upload/_upload_file.html.erb | 9 +-------- app/views/dmsf_upload/_upload_file_locked.html.erb | 6 +----- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/app/views/dmsf_upload/_upload_file.html.erb b/app/views/dmsf_upload/_upload_file.html.erb index 8e56cf62..0f88f88b 100644 --- a/app/views/dmsf_upload/_upload_file.html.erb +++ b/app/views/dmsf_upload/_upload_file.html.erb @@ -31,14 +31,7 @@ <%= upload.major_version %>.<%= upload.minor_version + 1 %> <%= l(:option_version_minor) %>
<%= radio_button_tag("commited_files[#{i}][version]", 2) %> <%= upload.major_version + 1 %>.0 <%= l(:option_version_major) %>
-
-

- <%= label_tag("commited_files[#{i}][workflow]", l(:label_workflow) + ":") %> - <%= select_tag( - "commited_files[#{i}][dmsf_workflow_id]", - dmsf_workflows_for_select(@project, nil))%> - -

+

diff --git a/app/views/dmsf_upload/_upload_file_locked.html.erb b/app/views/dmsf_upload/_upload_file_locked.html.erb index f994bbb6..cf31c347 100644 --- a/app/views/dmsf_upload/_upload_file_locked.html.erb +++ b/app/views/dmsf_upload/_upload_file_locked.html.erb @@ -27,11 +27,7 @@

<%= label_tag("", l(:label_version) + ":") %> <%= upload.major_version %>.<%= upload.minor_version %> -

-

- <%= label_tag("", l(:label_workflow) + ":") %> - <%= upload.workflow_str true %> -

+

From c9a4c35f1094d1c5d9d5fec89c0027d58093c3b1 Mon Sep 17 00:00:00 2001 From: Karel Picman Date: Thu, 6 Jun 2013 10:27:08 +0200 Subject: [PATCH 10/10] Approval workflow log view face changed --- app/controllers/dmsf_workflows_controller.rb | 16 ++++--- app/models/dmsf_workflow.rb | 47 ++++++++++++-------- app/models/dmsf_workflow_step.rb | 34 +++++++------- app/models/dmsf_workflow_step_assignment.rb | 1 + app/views/dmsf/show.html.erb | 34 +++++++------- app/views/dmsf_workflows/_action.html.erb | 2 +- app/views/dmsf_workflows/_assign.html.erb | 13 ++---- app/views/dmsf_workflows/_log.html.erb | 24 ++++++---- assets/stylesheets/dmsf.css | 28 +++++++++++- config/locales/en.yml | 34 +++++++------- 10 files changed, 142 insertions(+), 91 deletions(-) diff --git a/app/controllers/dmsf_workflows_controller.rb b/app/controllers/dmsf_workflows_controller.rb index 9416ea3b..d85d993c 100644 --- a/app/controllers/dmsf_workflows_controller.rb +++ b/app/controllers/dmsf_workflows_controller.rb @@ -22,7 +22,7 @@ class DmsfWorkflowsController < ApplicationController before_filter :find_workflow, :except => [:create, :new, :index, :assign, :assignment] before_filter :find_project, :except => [:start] - before_filter :authorize_global #, :except => [:action, :new_action] + before_filter :authorize_global def index if @project @@ -36,7 +36,7 @@ class DmsfWorkflowsController < ApplicationController end def new_action - if params[:commit] == l(:submit_commit) + if params[:commit] == l(:button_submit) action = DmsfWorkflowStepAction.new( :dmsf_workflow_step_assignment_id => params[:dmsf_workflow_step_assignment_id], :action => params[:step_action], @@ -57,13 +57,17 @@ class DmsfWorkflowsController < ApplicationController end def assignment - if params[:commit] == l(:button_assign) + if params[:commit] == l(:button_submit) revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id] if revision revision.set_workflow(params[:dmsf_workflow_id], params[:action]) revision.assign_workflow(params[:dmsf_workflow_id]) - if request.post? && revision.save - flash[:notice] = l(:notice_successful_update) + if request.post? + if revision.save + flash[:notice] = l(:notice_successful_update) + else + flash[:error] = l(:error_workflow_assign) + end end end end @@ -137,7 +141,7 @@ class DmsfWorkflowsController < ApplicationController else step = params[:step].to_i end - operator = 1 ? params[:commit] == l(:dmsf_and) : 0 + operator = (params[:commit] == l(:dmsf_and)) ? DmsfWorkflowStep::OPERATOR_AND : DmsfWorkflowStep::OPERATOR_OR users.each do |user| @workflow.dmsf_workflow_steps << DmsfWorkflowStep.new( :dmsf_workflow_id => @workflow.id, diff --git a/app/models/dmsf_workflow.rb b/app/models/dmsf_workflow.rb index 7b995ee3..54d573d5 100644 --- a/app/models/dmsf_workflow.rb +++ b/app/models/dmsf_workflow.rb @@ -16,10 +16,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -class DmsfWorkflow < ActiveRecord::Base - belongs_to :project - - has_many :dmsf_workflow_steps, :dependent => :destroy +class DmsfWorkflow < ActiveRecord::Base + has_many :dmsf_workflow_steps, :dependent => :destroy, :order => 'step ASC, operator DESC' validates_uniqueness_of :name validates :name, :presence => true @@ -35,9 +33,8 @@ class DmsfWorkflow < ActiveRecord::Base project ? where(:project_id => project) : where('project_id IS NULL') end - def project - @project = Project.find_by_id(project_id) unless @project - @project + def project + Project.find_by_id(project_id) if project_id end def to_s @@ -50,8 +47,8 @@ class DmsfWorkflow < ActiveRecord::Base if s.step == step wa << s end - end - wa.sort_by { |obj| -obj.operator } + end + wa end def steps @@ -60,8 +57,8 @@ class DmsfWorkflow < ActiveRecord::Base unless ws.include? s.step ws << s.step end - end - ws.sort + end + ws end def reorder_steps(step, move_to) @@ -129,16 +126,31 @@ class DmsfWorkflow < ActiveRecord::Base end end - def get_free_assignment(user, dmsf_file_revision_id) - steps = DmsfWorkflowStep.where(:dmsf_workflow_id => self.id).all(:order => 'step ASC') - steps.each do |step| + def next_assignments(dmsf_file_revision_id) + self.dmsf_workflow_steps.each do |step| unless step.finished?(dmsf_file_revision_id) - return step.get_free_assignment(dmsf_file_revision_id, user) + return step.next_assignments(dmsf_file_revision_id) end end return nil end + def self.assignments_to_users_str(assignments) + str = '' + if assignments + assignments.each_with_index do |assignment, index| + user = User.find_by_id assignment.user_id + if user + if index > 0 + str << ', ' + end + str << user.name + end + end + end + str + end + def assign(dmsf_file_revision_id) dmsf_workflow_steps.each do |ws| ws.assign(dmsf_file_revision_id) @@ -148,9 +160,8 @@ class DmsfWorkflow < ActiveRecord::Base def try_finish(dmsf_file_revision_id, action, user_id) res = nil case action.action - when DmsfWorkflowStepAction::ACTION_APPROVE - steps = DmsfWorkflowStep.where(:dmsf_workflow_id => self.id).all - steps.each do |step| + when DmsfWorkflowStepAction::ACTION_APPROVE + self.dmsf_workflow_steps.each do |step| res = step.result dmsf_file_revision_id unless step.finished? dmsf_file_revision_id return diff --git a/app/models/dmsf_workflow_step.rb b/app/models/dmsf_workflow_step.rb index 52458ed6..2593fea4 100644 --- a/app/models/dmsf_workflow_step.rb +++ b/app/models/dmsf_workflow_step.rb @@ -26,6 +26,9 @@ class DmsfWorkflowStep < ActiveRecord::Base validates :user_id, :presence => true validates :operator, :presence => true validates_uniqueness_of :user_id, :scope => [:dmsf_workflow_id, :step] + + OPERATOR_OR = 0 + OPERATOR_AND = 1 def soperator operator == 1 ? l(:dmsf_and) : l(:dmsf_or) @@ -44,7 +47,7 @@ class DmsfWorkflowStep < ActiveRecord::Base end def finished?(dmsf_file_revision_id) - res = result(dmsf_file_revision_id) + res = self.result(dmsf_file_revision_id) res == DmsfWorkflow::STATE_APPROVED || res == DmsfWorkflow::STATE_REJECTED end @@ -72,21 +75,22 @@ class DmsfWorkflowStep < ActiveRecord::Base end end - def get_free_assignment(dmsf_file_revision_id, user) - assignment = DmsfWorkflowStepAssignment.where( + def next_assignments(dmsf_file_revision_id) + results = Array.new + assignments = DmsfWorkflowStepAssignment.where( :dmsf_workflow_step_id => self.id, - :dmsf_file_revision_id => dmsf_file_revision_id, - :user_id => user.id).first - if assignment - actions = DmsfWorkflowStepAction.where( - :dmsf_workflow_step_assignment_id => assignment.id).all - actions.each do |action| - if action && action.is_finished? - return - end - end - return assignment.id - end + :dmsf_file_revision_id => dmsf_file_revision_id) + assignments.each do |assignment| + add = true + assignment.dmsf_workflow_step_actions.each do |action| + if action.is_finished? + add = false + break + end + end + results << assignment if add + end + return results end end \ No newline at end of file diff --git a/app/models/dmsf_workflow_step_assignment.rb b/app/models/dmsf_workflow_step_assignment.rb index 1ffc5250..7dd52f12 100644 --- a/app/models/dmsf_workflow_step_assignment.rb +++ b/app/models/dmsf_workflow_step_assignment.rb @@ -20,6 +20,7 @@ class DmsfWorkflowStepAssignment < ActiveRecord::Base belongs_to :dmsf_workflow_step has_many :dmsf_workflow_step_actions, :dependent => :destroy + has_one :dmsf_workflow_step_assignment validates :dmsf_workflow_step_id, :presence => true validates :dmsf_file_revision_id, :presence => true diff --git a/app/views/dmsf/show.html.erb b/app/views/dmsf/show.html.erb index d1a1f17b..bc022dca 100644 --- a/app/views/dmsf/show.html.erb +++ b/app/views/dmsf/show.html.erb @@ -149,7 +149,8 @@ <%= subfolder.deep_size %> <% end %> - <% @files.each do |file| %> + <% @files.each do |file| %> + <% wf = DmsfWorkflow.find_by_id(file.last_revision.dmsf_workflow_id) %> <%= check_box_tag("files[]", file.id, false, :title => l(:title_check_for_zip_download_or_email)) %> @@ -174,17 +175,15 @@ <% end %> <%= file.last_revision.version %> - - <% wf = DmsfWorkflow.find_by_id(file.last_revision.dmsf_workflow_id) %> + <% if wf %> <%= link_to( file.last_revision.workflow_str(false), log_dmsf_workflow_path( :project_id => @project.id, - :id => wf.id, - #:dmsf_workflow_step_assignment_id => dmsf_workflow_step_assignment_id, + :id => wf.id, :dmsf_file_revision_id => file.last_revision.id), - #:title => l(:title_waiting_for_approval), + :title => DmsfWorkflow.assignments_to_users_str(wf.next_assignments(file.last_revision.id)), :remote => true) %> <% end %> @@ -202,17 +201,17 @@ :title => l(:title_notifications_not_active_activate)) %> <% end %> <% case file.last_revision.workflow %> - <% when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL %> - <% wf = DmsfWorkflow.find_by_id(file.last_revision.dmsf_workflow_id) %> + <% when DmsfWorkflow::STATE_WAITING_FOR_APPROVAL %> <% if wf %> - <% dmsf_workflow_step_assignment_id = wf.get_free_assignment(User.current, file.last_revision.id) %> - <% if dmsf_workflow_step_assignment_id %> + <% assignments = wf.next_assignments(file.last_revision.id) %> + <% index = assignments.find_index{|assignment| assignment.user_id == User.current.id} if assignments %> + <% if index %> <%= link_to( image_tag('waiting_for_approval.png', :plugin => :redmine_dmsf), action_dmsf_workflow_path( :project_id => @project.id, :id => wf.id, - :dmsf_workflow_step_assignment_id => dmsf_workflow_step_assignment_id, + :dmsf_workflow_step_assignment_id => assignments[index].id, :dmsf_file_revision_id => file.last_revision.id), :title => l(:title_waiting_for_approval), :remote => true) %> @@ -222,20 +221,23 @@ <% end %> <% when DmsfWorkflow::STATE_APPROVED %> <%= image_tag('approved.png', :title => l(:title_approved), :plugin => :redmine_dmsf) %> - <% when DmsfWorkflow::STATE_DRAFT %> - <%= link_to_function(image_tag('draft.png', :plugin => :redmine_dmsf), + <% when DmsfWorkflow::STATE_DRAFT %> + <% if User.current && (file.last_revision.dmsf_workflow_assigned_by == User.current.id) %> + <%= link_to_function(image_tag('draft.png', :plugin => :redmine_dmsf), "manipulation_link('#{start_dmsf_workflow_path( :id => file.last_revision.dmsf_workflow_id, :dmsf_file_revision_id => file.last_revision.id)}')", - :title => l(:label_dmsf_wokflow_action_start)) %> + :title => l(:label_dmsf_wokflow_action_start)) %> + <% else %> + <%= image_tag('draft.png', :title => l(:label_dmsf_wokflow_action_start), :plugin => :redmine_dmsf) %> + <% end %> <% when DmsfWorkflow::STATE_REJECTED %> <%= image_tag('rejected.png', :title => l(:title_rejected), :plugin => :redmine_dmsf) %> <% else %> <%= link_to( image_tag('none.png', :plugin => :redmine_dmsf), assign_dmsf_workflow_path( - :project_id => @project.id, - :dmsf_workflow_step_assignment_id => dmsf_workflow_step_assignment_id, + :project_id => @project.id, :dmsf_file_revision_id => file.last_revision.id), :title => l(:label_dmsf_wokflow_action_assign), :remote => true) %> diff --git a/app/views/dmsf_workflows/_action.html.erb b/app/views/dmsf_workflows/_action.html.erb index 251982fd..84f99413 100644 --- a/app/views/dmsf_workflows/_action.html.erb +++ b/app/views/dmsf_workflows/_action.html.erb @@ -21,7 +21,7 @@

- <%= submit_tag l(:submit_commit), :name => 'commit', :onclick => 'hideModal(this);' %> + <%= submit_tag l(:button_submit), :name => 'commit', :onclick => 'hideModal(this);' %> <%= submit_tag l(:button_cancel), :name => 'commit', :onclick => 'hideModal(this);' %>

<% end %> diff --git a/app/views/dmsf_workflows/_assign.html.erb b/app/views/dmsf_workflows/_assign.html.erb index f2be82d6..ec5c5c2c 100644 --- a/app/views/dmsf_workflows/_assign.html.erb +++ b/app/views/dmsf_workflows/_assign.html.erb @@ -1,21 +1,16 @@

<%= l(:label_dmsf_workflow) %>

- <%= form_tag({:controller => 'dmsf_workflows', :action => 'assignment'}, :method => :post, - :id => 'assignment-form') do %> - - <%= hidden_field_tag :dmsf_workflow_step_assignment_id, params[:dmsf_workflow_step_assignment_id] %> - <%= hidden_field_tag :dmsf_file_revision_id, params[:dmsf_file_revision_id] %> - + :id => 'assignment-form') do %> + <%= hidden_field_tag :dmsf_file_revision_id, params[:dmsf_file_revision_id] %>

<%= label_tag('workflow', l(:label_workflow) + ':') %> <%= select_tag( 'dmsf_workflow_id', dmsf_workflows_for_select(@project, nil))%> -

- +

- <%= submit_tag l(:button_assign), :name => 'commit', :onclick => 'hideModal(this);' %> + <%= submit_tag l(:button_submit), :name => 'commit', :onclick => 'hideModal(this);' %> <%= submit_tag l(:button_cancel), :name => 'commit', :onclick => 'hideModal(this);' %>

<% end %> diff --git a/app/views/dmsf_workflows/_log.html.erb b/app/views/dmsf_workflows/_log.html.erb index 5524da96..eb649cdc 100644 --- a/app/views/dmsf_workflows/_log.html.erb +++ b/app/views/dmsf_workflows/_log.html.erb @@ -1,12 +1,20 @@

<%= l(:title_dmsf_workflow_log) %>

-

<% if params[:dmsf_file_revision_id].present? %> <% revision = DmsfFileRevision.find_by_id(params[:dmsf_file_revision_id]) %> <% if revision %> - <%= link_to @workflow.name, edit_dmsf_workflow_path(@workflow) %><%= " - #{revision.workflow_str false}" %> +

+
+ <%= label_tag 'workflow_name', "#{l(:field_name)}: " %> + <%= link_to @workflow.name, edit_dmsf_workflow_path(@workflow) %> +
+
+ <%= label_tag 'workflow_status', "#{l(:field_status)}: " %> + <%= revision.workflow_str false %> +
+
- +
@@ -15,15 +23,15 @@ - - + + - - + + @@ -32,7 +40,7 @@ <% sql = "SELECT c.action, c.note, c.created_at, c.author_id, a.user_id, s.step FROM dmsf_workflow_step_actions c RIGHT JOIN dmsf_workflow_step_assignments a ON a.id = c.dmsf_workflow_step_assignment_id JOIN dmsf_workflow_steps s ON s.id = a.dmsf_workflow_step_id WHERE a.dmsf_file_revision_id = #{revision.id} ORDER BY s.step, c.created_at" %> <% result = DmsfWorkflowStep.connection.execute sql %> <% result.each_with_index do |row, i| %> - + diff --git a/assets/stylesheets/dmsf.css b/assets/stylesheets/dmsf.css index 5c8623cb..13e64c1c 100644 --- a/assets/stylesheets/dmsf.css +++ b/assets/stylesheets/dmsf.css @@ -256,6 +256,30 @@ div.revision_box .ui-widget-header { font-weight: normal; } -table.steps td.note { - width: 30%; +table.list td.note { + width: 30%; } + +table.list td.step, td.date { + text-align: center; +} + +.log_header_box{ + padding:6px; + margin-bottom: 10px; +} +.log_header_left { + width: 50%; + float: left; +} + +.log_header_box label{ + font-weight: bold; + margin-left: 0px; + margin-right: 3px; + padding: 3px 0 3px 0; +} + +.modal a, a:link, a:visited{ color: #169; text-decoration: none; } +.modal a:hover, a:active{ color: #c61a1a; text-decoration: underline;} +.modal{ font-size: 12px} \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 03eb745c..7f4d56a0 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -207,33 +207,35 @@ en: :label_webdav_strategy: "Webdav strategy" :note_webdav_strategy: "Enables the administrator to decide if webdav is a read-only or read-write platform for end users." - label_dmsf_workflow_new: New approval workflow - label_dmsf_workflow: Approval workflow - label_dmsf_workflow_plural: Approval workflows - error_unable_delete_dmsf_workflow: Unable to delete the workflow + error_unable_delete_dmsf_workflow: 'Unable to delete the workflow' + error_empty_note: "The note can't be empty" + error_workflow_assign: 'An error occured while assigning' + label_dmsf_workflow_new: 'New approval workflow' + label_dmsf_workflow: 'Approval workflow' + label_dmsf_workflow_plural: 'Approval workflows' label_dmsf_workflow_step: Step label_dmsf_workflow_step_plural: Steps label_dmsf_workflow_approval: Approval label_dmsf_workflow_approval_plural: Approvals - dmsf_and: AND - dmsf_or: OR - dmsf_new_step: New step label_dmsf: DMSF label_dmsf_wokflow_action_approve: Approve label_dmsf_wokflow_action_reject: Reject label_dmsf_wokflow_action_delegate: 'Delegate to' label_dmsf_wokflow_action_assign: 'Assign an approval workflow' - message_dmsf_wokflow_note: Your note... + label_dmsf_wokflow_action_start: 'Start workflow' + label_action: Action + label_note: Note title_draft: Draft title_rejected: Rejected title_delegated: Delegated title_assigned: Assigned - title_started: Started - label_dmsf_wokflow_action_start: Start workflow - info_revision: "r%{rev}" - link_workflow: Workflow - button_assign: Assign - error_empty_note: "The note can't be empty" + title_started: Started title_dmsf_workflow_log: 'Approval workflow log' - label_action: Action - label_note: Note \ No newline at end of file + dmsf_and: AND + dmsf_or: OR + dmsf_new_step: New step + message_dmsf_wokflow_note: Your note... + info_revision: "r%{rev}" + link_workflow: Workflow + + \ No newline at end of file
<%= l(:label_dmsf_workflow_step) %> <%= l(:label_user) %> <%=l(:label_date)%>
-
<%= link_to_user User.find_by_id(revision.dmsf_workflow_assigned_by) if revision.dmsf_workflow_assigned_by %> <%= DmsfWorkflowStepAction.action_str(DmsfWorkflowStepAction::ACTION_ASSIGN) %> <%= format_time(revision.dmsf_workflow_assigned_at) if revision.dmsf_workflow_assigned_at %>
-
<%= link_to_user User.find_by_id(revision.dmsf_workflow_started_by) if revision.dmsf_workflow_started_by %> <%= DmsfWorkflowStepAction.action_str(DmsfWorkflowStepAction::ACTION_START) %>
<%= row[5] %> <%= link_to_user User.find_by_id(row[3].present? ? row[3] : row[4]) %> <%= DmsfWorkflowStepAction.action_str(row[0]) %>