diff --git a/.travis.yml b/.travis.yml index 012dc77d..47f092e6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,6 +49,9 @@ after_script: - bash -x ./test/ci/redmine_install.sh -u env: + - DB=sqlite REDMINE_GIT_TAG=4.0-stable + - DB=mysql REDMINE_GIT_TAG=4.0-stable + - DB=postgres REDMINE_GIT_TAG=4.0-stable - DB=sqlite REDMINE_GIT_TAG=4.1-stable - DB=mysql REDMINE_GIT_TAG=4.1-stable - DB=postgres REDMINE_GIT_TAG=4.1-stable diff --git a/CHANGELOG.md b/CHANGELOG.md index f2bfe4d8..ceeeb0f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,13 @@ Changelog for Redmine DMSF ========================== -2.4.4 *????-??-??* +2.4.4 *2020-07-10* ------------------ - ? + Maintenance release + +* New: #1144 - Who has locked the document information is missing. +* Bug: #1142 - How to configure "Direct document or document link sending via email"? 2.4.3 *2020-06-12* ------------------ diff --git a/README.md b/README.md index 7911897b..da28f89a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Redmine DMSF Plugin =================== -The current version of Redmine DMSF is **2.4.4 devel** [![Build Status](https://api.travis-ci.org/danmunn/redmine_dmsf.png)](https://travis-ci.org/danmunn/redmine_dmsf) +The current version of Redmine DMSF is **2.4.4** [![Build Status](https://api.travis-ci.org/danmunn/redmine_dmsf.png)](https://travis-ci.org/danmunn/redmine_dmsf) Redmine DMSF is Document Management System Features plugin for Redmine issue tracking system; It is aimed to replace current Redmine's Documents module. @@ -36,12 +36,12 @@ Features * Documents and folders symbolic links * Trash bin * Documents attachable to issues - * Compatible with Redmine 4.1.x + * Compatible with Redmine 4.0.x and 4.1.x Dependencies ------------ - * Redmine 4.1.0 or higher + * Redmine 4.0.0 or higher ### Full-text search (optional) @@ -224,7 +224,7 @@ You can either clone the master branch or download the latest zipped version. Be `RAILS_ENV=production bundle exec rake db:migrate` - `RAILS_ENV=production bundle exec rake plugins:migrate NAME=redmine_dmsf` + `RAILS_ENV=production bundle exec rake redmine:plugins:migrate NAME=redmine_dmsf` 5. The access rights must be set for web server, example: `chown -R www-data:www-data plugins/redmine_dmsf`. 6. Restart the web server, e.g. `systemctl apache2 restart` 7. You should configure the plugin via Redmine interface: Administration -> Plugins -> DMSF -> Configure. diff --git a/app/controllers/dmsf_controller.rb b/app/controllers/dmsf_controller.rb index 45e70e15..b4a462b9 100644 --- a/app/controllers/dmsf_controller.rb +++ b/app/controllers/dmsf_controller.rb @@ -69,18 +69,30 @@ class DmsfController < ApplicationController render_404 return end - respond_to do |format| - format.html { - @dmsf_count = @query.dmsf_count - @dmsf_pages = Paginator.new @dmsf_count, per_page_option, params['page'] - render layout: !request.xhr? - } - format.api { - @offset, @limit = api_offset_and_limit - } - format.csv { - send_data query_to_csv(@query.dmsf_nodes, @query), type: 'text/csv; header=present', filename: 'dmsf.csv' - } + if @query.valid? + respond_to do |format| + format.html { + @dmsf_count = @query.dmsf_count + @dmsf_pages = Paginator.new @dmsf_count, per_page_option, params['page'] + render layout: !request.xhr? + } + format.api { + @offset, @limit = api_offset_and_limit + } + format.csv { + send_data query_to_csv(@query.dmsf_nodes, @query), type: 'text/csv; header=present', filename: 'dmsf.csv' + } + end + else + respond_to do |format| + format.html { + @dmsf_count = 0 + @dmsf_pages = Paginator.new @dmsf_count, per_page_option, params['page'] + render layout: !request.xhr? + } + format.any(:atom, :csv, :pdf) { head 422 } + format.api { render_validation_errors(@query) } + end end end diff --git a/app/controllers/dmsf_files_controller.rb b/app/controllers/dmsf_files_controller.rb index a988bc09..b12e138a 100644 --- a/app/controllers/dmsf_files_controller.rb +++ b/app/controllers/dmsf_files_controller.rb @@ -85,7 +85,8 @@ class DmsfFilesController < ApplicationController @revision = @file.last_revision @file_delete_allowed = User.current.allowed_to?(:file_delete, @project) @file_manipulation_allowed = User.current.allowed_to?(:file_manipulation, @project) - @revision_pages = Paginator.new @file.dmsf_file_revisions.visible.count, params['per_page'] ? params['per_page'].to_i : 25, params['page'] + @revision_count = @file.dmsf_file_revisions.visible.all.size + @revision_pages = Paginator.new @revision_count, params['per_page'] ? params['per_page'].to_i : 25, params['page'] respond_to do |format| format.html { diff --git a/app/models/dmsf_file.rb b/app/models/dmsf_file.rb index 424125ed..2dd09089 100644 --- a/app/models/dmsf_file.rb +++ b/app/models/dmsf_file.rb @@ -128,6 +128,16 @@ class DmsfFile < ActiveRecord::Base deleted == STATUS_DELETED end + def locked_by + if lock && lock.reverse[0] + user = lock.reverse[0].user + if user + return (user == User.current) ? l(:label_me) : user.name + end + end + '' + end + def delete(commit) if locked_for_user? && (!User.current.allowed_to?(:force_file_unlock, project)) Rails.logger.info l(:error_file_is_locked) diff --git a/app/models/dmsf_file_revision_access_query.rb b/app/models/dmsf_file_revision_access_query.rb index 515ce693..5f9fe8a0 100644 --- a/app/models/dmsf_file_revision_access_query.rb +++ b/app/models/dmsf_file_revision_access_query.rb @@ -35,7 +35,7 @@ class DmsfFileRevisionAccessQuery < Query QueryColumn.new(:last_at, frozen: true) ] - def initialize(attributes) + def initialize(attributes=nil, *args) super attributes self.sort_criteria = [] self.filters = {} @@ -73,8 +73,6 @@ class DmsfFileRevisionAccessQuery < Query @available_columns end - #alias default_columns_names available_columns - ###################################################################################################################### # New @@ -82,7 +80,7 @@ class DmsfFileRevisionAccessQuery < Query base_scope. access_grouped. joins(:user). - order('`count` DESC'). + order(Arel.sql('COUNT(*) DESC')). limit(options[:limit]). offset(options[:offset]) end diff --git a/app/models/dmsf_mailer.rb b/app/models/dmsf_mailer.rb index 5e4b2657..9e0e4a4c 100644 --- a/app/models/dmsf_mailer.rb +++ b/app/models/dmsf_mailer.rb @@ -91,8 +91,21 @@ class DmsfMailer < Mailer Rails.logger.error "Cannot attach #{email_params[:zipped_content]}, it doesn't exist." end end - mail to: email_params[:to], cc: email_params[:cc], subject: email_params[:subject], 'From' => email_params[:from], - 'Reply-To' => email_params[:reply_to] + skip_no_self_notified = false + begin + # We need to switch off no_self_notified temporarily otherwise the email won't be sent + if (author == User.current) && author.pref.no_self_notified + author.pref.no_self_notified = false + skip_no_self_notified = true + end + res = mail(to: email_params[:to], cc: email_params[:cc], subject: email_params[:subject], 'From' => email_params[:from], + 'Reply-To' => email_params[:reply_to]) + ensure + if skip_no_self_notified + author.pref.no_self_notified = true + end + end + res end def self.deliver_workflow_notification(users, workflow, revision, subject_id, text1_id, text2_id, notice = nil) diff --git a/app/models/dmsf_query.rb b/app/models/dmsf_query.rb index 963679dd..3c4dd9a4 100644 --- a/app/models/dmsf_query.rb +++ b/app/models/dmsf_query.rb @@ -41,7 +41,7 @@ class DmsfQuery < Query def initialize(attributes=nil, *args) super attributes self.sort_criteria = [] - self.filters = {} + self.filters ||= { 'title' => { operator: '~', values: ['']} } end ###################################################################################################################### @@ -110,15 +110,19 @@ class DmsfQuery < Query def statement unless @statement + @filter_dmsf_folder_id = false filters_clauses = [] filters.each_key do |field| v = values_for(field).clone next unless v and !v.empty? operator = operator_for(field) - if field == 'author' + case field + when 'author' if v.delete('me') - v.push User.current.id.to_s + v.push User.current.id.to_s end + when 'title' + next if v.include?('') end filters_clauses << '(' + sql_for_field(field, operator, v, queried_table_name, field) + ')' end @@ -128,11 +132,19 @@ class DmsfQuery < Query @statement end + def validate_query_filters + # Skip validation for empty title (default filter) + filter = filters.delete('title') + super + # Add it back + filters['title'] = filter if filter + end + ###################################################################################################################### # New def dmsf_nodes(options={}) - order_option = ['sort', group_by_sort_order, (options[:order] || sort_clause[0]), 'title'].flatten.reject(&:blank?) + order_option = ['sort', group_by_sort_order, (options[:order] || sort_clause[0])].flatten.reject(&:blank?) if order_option.size > 2 DmsfFileRevisionCustomField.visible.pluck(:id, :name).each do |id, name| order_option[1].gsub!("COALESCE(cf_#{id}.value, '')", "\"#{name}\"") @@ -157,7 +169,7 @@ class DmsfQuery < Query def dmsf_folders_scope cf_columns = +'' - if filters.any? + if statement.present? DmsfFileRevisionCustomField.visible.order(:position).pluck(:id).each do |id| cf_columns << ",(SELECT value from custom_values WHERE custom_field_id = #{id} AND customized_type = 'DmsfFolder' AND customized_id = dmsf_folders.id) AS cf_#{id}" end @@ -183,13 +195,11 @@ class DmsfQuery < Query 0 AS sort #{cf_columns}}). joins('LEFT JOIN users ON dmsf_folders.user_id = users.id'). visible(!deleted) - if deleted - scope.where dmsf_folders: { project_id: project.id, deleted: deleted } + if dmsf_folder_id + scope.where dmsf_folders: { dmsf_folder_id: dmsf_folder_id, deleted: deleted } else - if filters.any? + if statement.present? || deleted scope.where dmsf_folders: { project_id: project.id, deleted: deleted } - elsif dmsf_folder_id - scope.where dmsf_folders: { dmsf_folder_id: dmsf_folder_id, deleted: deleted } else scope.where dmsf_folders: { project_id: project.id, dmsf_folder_id: nil, deleted: deleted } end @@ -198,7 +208,7 @@ class DmsfQuery < Query def dmsf_folder_links_scope cf_columns = +'' - if filters.any? + if statement.present? DmsfFileRevisionCustomField.visible.order(:position).pluck(:id).each do |id| cf_columns << ",(SELECT value from custom_values WHERE custom_field_id = #{id} AND customized_type = 'DmsfFolder' AND customized_id = dmsf_folders.id) AS cf_#{id}" end @@ -224,13 +234,11 @@ class DmsfQuery < Query 0 AS sort #{cf_columns}}). joins('LEFT JOIN dmsf_folders ON dmsf_links.target_id = dmsf_folders.id'). joins('LEFT JOIN users ON users.id = COALESCE(dmsf_folders.user_id, dmsf_links.user_id)') - if deleted - scope.where dmsf_links: { target_type: 'DmsfFolder', project_id: project.id, deleted: deleted } + if dmsf_folder_id + scope.where dmsf_links: { target_type: 'DmsfFolder', dmsf_folder_id: dmsf_folder_id, deleted: deleted } else - if filters.any? + if statement.present? || deleted scope.where dmsf_links: { target_type: 'DmsfFolder', project_id: project.id, deleted: deleted } - elsif dmsf_folder_id - scope.where dmsf_links: { target_type: 'DmsfFolder', dmsf_folder_id: dmsf_folder_id, deleted: deleted } else scope.where dmsf_links: { target_type: 'DmsfFolder', project_id: project.id, dmsf_folder_id: nil, deleted: deleted } end @@ -239,7 +247,7 @@ class DmsfQuery < Query def dmsf_files_scope cf_columns = +'' - if filters.any? + if statement.present? DmsfFileRevisionCustomField.visible.order(:position).pluck(:id).each do |id| cf_columns << ",(SELECT value from custom_values WHERE custom_field_id = #{id} AND customized_type = 'DmsfFileRevision' AND customized_id = dmsf_file_revisions.id) AS cf_#{id}" end @@ -266,22 +274,20 @@ class DmsfQuery < Query joins(:dmsf_file_revisions). joins('LEFT JOIN users ON dmsf_file_revisions.user_id = users.id '). where('dmsf_file_revisions.created_at = (SELECT MAX(r.created_at) FROM dmsf_file_revisions r WHERE r.dmsf_file_id = dmsf_file_revisions.dmsf_file_id)') - if deleted - scope.where dmsf_files: { project_id: project.id, deleted: deleted } - else - if filters.any? - scope.where dmsf_files: { project_id: project.id, deleted: deleted } - elsif dmsf_folder_id + if dmsf_folder_id scope.where dmsf_files: { dmsf_folder_id: dmsf_folder_id, deleted: deleted } else - scope.where dmsf_files: { project_id: project.id, dmsf_folder_id: nil, deleted: deleted } + if statement.present? || deleted + scope.where dmsf_files: { project_id: project.id, deleted: deleted } + else + scope.where dmsf_files: { project_id: project.id, dmsf_folder_id: nil, deleted: deleted } + end end - end end def dmsf_file_links_scope cf_columns = +'' - if filters.any? + if statement.present? DmsfFileRevisionCustomField.visible.order(:position).pluck(:id).each do |id| cf_columns << ",(SELECT value from custom_values WHERE custom_field_id = #{id} AND customized_type = 'DmsfFileRevision' AND customized_id = dmsf_file_revisions.id) AS cf_#{id}" end @@ -309,22 +315,21 @@ class DmsfQuery < Query joins('JOIN dmsf_file_revisions ON dmsf_file_revisions.dmsf_file_id = dmsf_files.id'). joins('LEFT JOIN users ON dmsf_file_revisions.user_id = users.id '). where('dmsf_file_revisions.created_at = (SELECT MAX(r.created_at) FROM dmsf_file_revisions r WHERE r.dmsf_file_id = dmsf_file_revisions.dmsf_file_id)') - if deleted - scope.where project_id: project.id, deleted: deleted + if dmsf_folder_id + scope.where dmsf_links: { target_type: 'DmsfFile', dmsf_folder_id: dmsf_folder_id, deleted: deleted } else - if filters.any? - scope.where project_id: project.id, deleted: deleted - elsif dmsf_folder_id - scope.where dmsf_folder_id: dmsf_folder_id, deleted: deleted + if statement.present? || deleted + scope.where dmsf_links: { target_type: 'DmsfFile', project_id: project.id, deleted: deleted } else - scope.where project_id: project.id, dmsf_folder_id: nil, deleted: deleted + scope.where dmsf_links: { target_type: 'DmsfFile', project_id: project.id, dmsf_folder_id: nil, deleted: deleted } end end + end def dmsf_url_links_scope cf_columns = +'' - if filters.any? + if statement.present? DmsfFileRevisionCustomField.visible.order(:position).pluck(:id).each do |id| cf_columns << ",NULL AS cf_#{id}" end @@ -349,17 +354,16 @@ class DmsfQuery < Query dmsf_links.deleted AS deleted, 1 AS sort #{cf_columns}}). joins('LEFT JOIN users ON dmsf_links.user_id = users.id ') - if deleted - scope.where target_type: 'DmsfUrl', project_id: project.id, deleted: deleted + if dmsf_folder_id + scope.where dmsf_links: { target_type: 'DmsfUrl', dmsf_folder_id: dmsf_folder_id, deleted: deleted } else - if filters.any? - scope.where target_type: 'DmsfUrl', project_id: project.id, deleted: deleted - elsif dmsf_folder_id - scope.where target_type: 'DmsfUrl', dmsf_folder_id: dmsf_folder_id, deleted: deleted + if statement.present? || deleted + scope.where dmsf_links: { target_type: 'DmsfUrl', project_id: project.id, deleted: deleted } else - scope.where target_type: 'DmsfUrl', project_id: project.id, dmsf_folder_id: nil, deleted: deleted + scope.where dmsf_links: { target_type: 'DmsfUrl', project_id: project.id, dmsf_folder_id: nil, deleted: deleted } end end + end end diff --git a/app/models/dmsf_upload.rb b/app/models/dmsf_upload.rb index 50237f6e..9b851ffb 100644 --- a/app/models/dmsf_upload.rb +++ b/app/models/dmsf_upload.rb @@ -41,7 +41,7 @@ class DmsfUpload end def self.create_from_uploaded_attachment(project, folder, uploaded_file) - a = Attachment.find_by_token(uploaded_file[:token]) + a = Attachment.find_by_token(uploaded_file[:token]) if uploaded_file[:token].present? if a uploaded = { disk_filename: DmsfHelper.temp_filename(a.filename), @@ -50,7 +50,7 @@ class DmsfUpload comment: uploaded_file[:description], tempfile_path: a.diskfile } - DmsfUpload.new(project, folder, uploaded) + DmsfUpload.new project, folder, uploaded else Rails.logger.error "An attachment not found by its token: #{uploaded_file[:token]}" nil diff --git a/app/views/dmsf/show.html.erb b/app/views/dmsf/show.html.erb index bf6ec323..a2c32198 100644 --- a/app/views/dmsf/show.html.erb +++ b/app/views/dmsf/show.html.erb @@ -72,10 +72,21 @@ <%= form_tag(dmsf_folder_path(id: @project, folder_id: @folder), method: :get, id: 'query_form', class: 'dmsf-query-form') do %> - <%= render partial: 'queries/query_form' %> + <%= hidden_field_tag('folder_id', @folder.id) if @folder %> + <% if defined?(EasyExtensions) %> + <%= render partial: 'dmsf_queries/query_form' %> + <% else %> + <%= render partial: 'queries/query_form' %> + <% end %> +<% end %> +<% if @query.valid? %> + <% if @dmsf_count == 0 %> +

<%= l(:label_no_data) %>

+ <% else %> + <%= render partial: 'query_list', locals: { query: @query, dmsf_pages: @dmsf_pages } %> + <%= pagination_links_full @dmsf_pages, @dmsf_count %> + <% end %> <% end %> -<%= render partial: 'query_list', locals: { query: @query, dmsf_pages: @dmsf_pages } %> -<%= pagination_links_full @dmsf_pages, @dmsf_count %> <%= context_menu %> diff --git a/app/views/dmsf_context_menus/_file.html.erb b/app/views/dmsf_context_menus/_file.html.erb index f94169d8..1f0a738e 100644 --- a/app/views/dmsf_context_menus/_file.html.erb +++ b/app/views/dmsf_context_menus/_file.html.erb @@ -22,7 +22,7 @@
  • <%= context_menu_link l(:button_edit), dmsf_file_path(id: dmsf_file), class: 'icon icon-edit', - disabled: !allowed || locked %> + disabled: !allowed || (locked && !unlockable) %>
  • <%= link_to "#{l(:button_copy)}/#{l(:button_move)}", copy_file_path(id: dmsf_file), @@ -40,6 +40,7 @@
  • <% if locked %> <%= context_menu_link l(:button_unlock), unlock_dmsf_files_path(id: dmsf_file), class: 'icon icon-unlock', + title: l(:title_locked_by_user, user: dmsf_file.locked_by), disabled: !allowed || !unlockable %> <% else %> <%= context_menu_link l(:button_lock), lock_dmsf_files_path(id: dmsf_file), class: 'icon icon-lock', diff --git a/app/views/dmsf_files/_revision_access.html.erb b/app/views/dmsf_files/_revision_access.html.erb index 937297cf..92bcbe5f 100644 --- a/app/views/dmsf_files/_revision_access.html.erb +++ b/app/views/dmsf_files/_revision_access.html.erb @@ -44,4 +44,3 @@ -<%= pagination_links_full revision_access_pages, revision_access_count %> diff --git a/app/views/dmsf_files/show.html.erb b/app/views/dmsf_files/show.html.erb index e0e7a9d5..4ace6ff5 100644 --- a/app/views/dmsf_files/show.html.erb +++ b/app/views/dmsf_files/show.html.erb @@ -158,20 +158,14 @@ <% if @file_manipulation_allowed %> <% revision_access_query = DmsfFileRevisionAccessQuery.new %> <% revision_access_query.revision_id = revision.id %> - <% revision_access_count = revision_access_query.access_count %> - <% revision_access_pages = Redmine::Pagination::Paginator.new revision_access_count, - Setting.per_page_options_array.first || 25, params['page'] %> - <%= render partial: 'revision_access', locals: { revision: revision, query: revision_access_query, - revision_access_count: revision_access_count, - revision_access_pages: revision_access_pages } %> + <%= render partial: 'revision_access', locals: { revision: revision, query: revision_access_query } %> <% end %>
    <% end %> - -<%= pagination_links_full @revision_pages, @file.dmsf_file_revisions.visible.count %> +<%= pagination_links_full @revision_pages, @revision_count %> <%= late_javascript_tag do %> $('a.delete-revision').click(function(event) { diff --git a/app/views/dmsf_queries/_query_form.html.erb b/app/views/dmsf_queries/_query_form.html.erb new file mode 100644 index 00000000..67fe0abd --- /dev/null +++ b/app/views/dmsf_queries/_query_form.html.erb @@ -0,0 +1,89 @@ +<%= hidden_field_tag 'set_filter', '1' %> +<%= hidden_field_tag 'type', @query.type, :disabled => true, :id => 'query_type' %> +<%= query_hidden_sort_tag(@query) %> + +
    +
    +
    "> + "><%= l(:label_filter_plural) %> +
    "> + <%= render :partial => 'queries/filters', :locals => {:query => @query} %> +
    +
    + + <% if @query.available_columns.any? %> + + <% end %> +
    + +

    + <%= link_to_function l(:button_apply), '$("#query_form").submit()', :class => 'icon icon-checked' %> + <%= link_to l(:button_clear), { :set_filter => 1, :sort => '', :project_id => @project }, :class => 'icon icon-reload' %> + <% if @query.new_record? %> + <% if User.current.allowed_to?(:save_queries, @project, :global => true) %> + <%= link_to_function l(:button_save), + "$('#query_type').prop('disabled',false);$('#query_form').attr('action', '#{ @project ? new_project_query_path(@project) : new_query_path }').submit()", + :class => 'icon icon-save' %> + <% end %> + <% else %> + <% if @query.editable_by?(User.current) %> + <%= link_to l(:button_edit), edit_query_path(@query), :class => 'icon icon-edit' %> + <%= delete_link query_path(@query) %> + <% end %> + <% end %> +

    +
    + +<%= error_messages_for @query %> +<%# DMS modification do %> +<%#= javascript_tag do %> +<%= late_javascript_tag do %> +<%# end %> +$(function ($) { + $('input[name=display_type]').change(function (e) { + if ($("#display_type_list").is(':checked')) { + $('table#list-definition').show(); + } else { + $('table#list-definition').hide(); + } + + }) +}); + +<% end %> diff --git a/assets/stylesheets/easy_extensions.css b/assets/stylesheets/easy_extensions.css index 1def596f..2d62f73f 100644 --- a/assets/stylesheets/easy_extensions.css +++ b/assets/stylesheets/easy_extensions.css @@ -65,3 +65,13 @@ table.dmsf a.sort.asc.icon.icon-sorted-desc { #query_form.dmsf-query-form .collapsed#filters { opacity: 1; } + +#query_form.dmsf-query-form .add-filter { + float: right; + text-align: right; + vertical-align: top; +} + +#query_form.dmsf-query-form td.values span:first-child { + display: inline !important; +} diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 3173acc5..415fe0a5 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -80,7 +80,6 @@ cs: title_notifications_not_active_activate: "Notifikace nejsou aktivní: Aktivovat" title_title_version_version_download: "%{title} verze %{version} stáhnout" title_locked_by_user: "Zamčeno uživatelem %{user}" - title_locked_by_you: Zamčeno Vámi title_waiting_for_approval: Čeká na schválení title_approved: Schváleno title_unlock_file: Odemknout a umožnit změny ostatním uživatelům diff --git a/config/locales/de.yml b/config/locales/de.yml index c60dfe0c..e82a2cc9 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -80,7 +80,6 @@ de: title_notifications_not_active_activate: "Benachrichtigungen sind nicht aktiv: Einschalten" title_title_version_version_download: "%{title} Version %{version} Download" title_locked_by_user: "Gesperrt von %{user}" - title_locked_by_you: Gesperrt von dir title_waiting_for_approval: Warte auf Zustimmung title_approved: Zugestimmt title_unlock_file: Hebe Sperre auf um Änderungen anderer Nutzer zu ermöglichen diff --git a/config/locales/en.yml b/config/locales/en.yml index 7fcd9bb5..cfd232b7 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -80,7 +80,6 @@ en: title_notifications_not_active_activate: "Notifications not active: Activate" title_title_version_version_download: "%{title} version %{version} download" 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_unlock_file: Unlock to allow changes for other members diff --git a/config/locales/es.yml b/config/locales/es.yml index 28e4f4db..d00777d5 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -80,7 +80,6 @@ es: title_notifications_not_active_activate: "Notificacciones No Activas: Activadas" title_title_version_version_download: "%{title} version %{version} descargar" title_locked_by_user: "bloqueado por %{user}" - title_locked_by_you: Bloqueado por ti title_waiting_for_approval: Esperando Aprobación title_approved: Aprobado title_unlock_file: Desbloquear para que otros miembros puedan editarlo diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 4f0ae963..089e20e9 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -80,7 +80,6 @@ fr: title_notifications_not_active_activate: "Notifications désactivées : cliquer pour activer" title_title_version_version_download: "Télécharger la version %{version} de %{title}" title_locked_by_user: "Verrouillé par %{user}" - title_locked_by_you: Verrouillé par vous-même title_waiting_for_approval: Attente de validation title_approved: Validé title_unlock_file: Déverrouiller afin de permettre la modification par les membres du projet diff --git a/config/locales/hu.yml b/config/locales/hu.yml index d04b9faa..5c8561f9 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -80,7 +80,6 @@ hu: title_notifications_not_active_activate: "Értesítések nincsnek bekapcsolva: Bekapcsolás" title_title_version_version_download: "%{title} verzió %{version} letöltés" title_locked_by_user: "Zárolva %{user}" - title_locked_by_you: Ön zárolta title_waiting_for_approval: Elfogadásra vár title_approved: Elfogadva title_unlock_file: Zárolás megszüntetése, hogy más felhasználók is változtatni tudjanak diff --git a/config/locales/it.yml b/config/locales/it.yml index 7e2841aa..6d0befa2 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -80,7 +80,6 @@ it: # Italian strings thx 2 Matteo Arceci! title_notifications_not_active_activate: "Notifiche disattivate: Attiva" title_title_version_version_download: "%{title} versione %{version} download" title_locked_by_user: "Bloccato da %{user}" - title_locked_by_you: Bloccato da te title_waiting_for_approval: In attesa di Approvazione title_approved: Approvato title_unlock_file: Sblocca per consentire modifiche degli altri membri diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 87f26c59..29f68af5 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -80,7 +80,6 @@ ja: title_notifications_not_active_activate: "通知は無効です: 有効にする" title_title_version_version_download: "%{title} のバージョン %{version} をダウンロードする" title_locked_by_user: "%{user} によってロックされています" - title_locked_by_you: あなたがロックしています title_waiting_for_approval: 承認待ち title_approved: 承認済み title_unlock_file: ロック解除して他のメンバーの変更を許可する diff --git a/config/locales/ko.yml b/config/locales/ko.yml index e5add1cb..74e69c17 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -80,7 +80,6 @@ ko: title_notifications_not_active_activate: "알림 비활성화: 활성화" title_title_version_version_download: "%{title} 버전 %{version} 다운로드" title_locked_by_user: "%{user} 에 의해 잠겨짐" - title_locked_by_you: 사용자에 의해 잠겨짐 title_waiting_for_approval: 승인을 기다리는 중 title_approved: 승인됨 title_unlock_file: 다른 구성원들의 변경 허가 잠금 해제 diff --git a/config/locales/nl.yml b/config/locales/nl.yml index a063bb10..e24946be 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -80,7 +80,6 @@ nl: title_notifications_not_active_activate: "Notificaties niet actief: Activeren" title_title_version_version_download: "%{title} versie %{version} downloaden" title_locked_by_user: "Vergrendeld door %{user}" - title_locked_by_you: Vergrendeld door u title_waiting_for_approval: Wacht op goedkeuring title_approved: Goedgekeurd title_unlock_file: Ontgrendel om wijzigingen door andere leden toe te staan diff --git a/config/locales/pl.yml b/config/locales/pl.yml index ff02980d..6d3b4155 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -80,7 +80,6 @@ pl: title_notifications_not_active_activate: "Powiadomienia wyłączone: Aktywuj" title_title_version_version_download: "pobierz %{title} wersja %{version}" title_locked_by_user: "Zablokowany przez %{user}" - title_locked_by_you: Zablokowany przez Ciebie title_waiting_for_approval: Oczekiwanie na akceptację title_approved: Zaakceptowany title_unlock_file: Odblokuj aby umożliwić wprowadzanie zmian innym użytkownikom diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index fa147da3..d5e01306 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -80,7 +80,6 @@ pt-BR: title_notifications_not_active_activate: "Notificações não ativas: Ativar" title_title_version_version_download: "%{title} revisão %{version} download" title_locked_by_user: "Bloqueado por %{user}" - title_locked_by_you: Bloqueado por você title_waiting_for_approval: Aguardando aprovação title_approved: Aprovado title_unlock_file: Clique aqui para permitir alterações por outro usuário diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 5aed298c..88cfae8c 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -80,7 +80,6 @@ ru: title_notifications_not_active_activate: "Уведомления не включены: Включить" title_title_version_version_download: "Скачать %{title} редакции %{version}" title_locked_by_user: "Заблокировано пользователем %{user}" - title_locked_by_you: Заблокировано Вами title_waiting_for_approval: Ожидается утверждение title_approved: Утверждено title_unlock_file: Разблокируйте файл, чтобы разрешить его изменение другими участниками diff --git a/config/locales/sl.yml b/config/locales/sl.yml index 8a8a9c5a..93ebde3d 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -80,7 +80,6 @@ sl: title_notifications_not_active_activate: "Obveščanje ni aktivno: Aktiviraj" title_title_version_version_download: "%{title} verzija %{version} prenesi dol" title_locked_by_user: "Zaklenil %{user}" - title_locked_by_you: Zaklenili ste title_waiting_for_approval: V postopku odobritve title_approved: Odobreno title_unlock_file: Odkleni drugim članom za posodabljanje diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 8e06266f..180d727d 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -80,7 +80,6 @@ zh-TW: title_notifications_not_active_activate: "通知關閉中: 點擊啟用通知" title_title_version_version_download: " 版本: %{version} 檔案: %{title} 下載" title_locked_by_user: "被使用者%{user},鎖定了。" - title_locked_by_you: 被您鎖定了。 title_waiting_for_approval: 等待批准 title_approved: 已經被批准 title_unlock_file: 解除鎖定。允許其它使用者修改。 diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 601c24ed..8a475064 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -80,7 +80,6 @@ zh: title_notifications_not_active_activate: "通知无效:点击激活通知" title_title_version_version_download: " 下载‘%{title}’版本‘%{version}’" title_locked_by_user: "%{user}锁定" - title_locked_by_you: 您锁定 title_waiting_for_approval: 待批准 title_approved: 已批准 title_unlock_file: 解除锁定允许其他成员修改 diff --git a/init.rb b/init.rb index bb103aab..507bc000 100644 --- a/init.rb +++ b/init.rb @@ -35,7 +35,7 @@ Redmine::Plugin.register :redmine_dmsf do description 'Document Management System Features' version '2.4.4 devel' - requires_redmine version_or_higher: '4.1.0' + requires_redmine version_or_higher: '4.0.0' settings partial: 'settings/dmsf_settings', default: { diff --git a/test/functional/dmsf_controller_test.rb b/test/functional/dmsf_controller_test.rb index deb4ae6c..eb4a314e 100644 --- a/test/functional/dmsf_controller_test.rb +++ b/test/functional/dmsf_controller_test.rb @@ -219,10 +219,13 @@ class DmsfControllerTest < RedmineDmsf::Test::TestCase @role.add_permission! :view_dmsf_files @role.add_permission! :view_dmsf_folders @role.add_permission! :file_manipulation + @role.add_permission! :folder_manipulation get :show, params: { id: @project.id } assert_response :success # New file link assert_select 'a[href$=?]', '/dmsf/upload/multi_upload' + # New folder link + assert_select 'a[href$=?]', '/dmsf/new' # Filters assert_select 'fieldset#filters' # Options diff --git a/test/unit/dmsf_file_test.rb b/test/unit/dmsf_file_test.rb index caf8afe4..af41b0e1 100644 --- a/test/unit/dmsf_file_test.rb +++ b/test/unit/dmsf_file_test.rb @@ -291,4 +291,11 @@ class DmsfFileTest < RedmineDmsf::Test::UnitTest assert @file7.assigned?(@jsmith) end + def test_locked_by + # Locked file + assert_equal @jsmith.name, @file2.locked_by + # Unlocked file + assert_equal '', @file1.locked_by + end + end \ No newline at end of file