Merge branch 'master' into webdav_project_tree
This commit is contained in:
commit
2c1fcefdc9
@ -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
|
||||
|
||||
@ -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*
|
||||
------------------
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
Redmine DMSF Plugin
|
||||
===================
|
||||
|
||||
The current version of Redmine DMSF is **2.4.4 devel** [](https://travis-ci.org/danmunn/redmine_dmsf)
|
||||
The current version of Redmine DMSF is **2.4.4** [](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.
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -72,10 +72,21 @@
|
||||
</div>
|
||||
|
||||
<%= 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 %>
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
<% else %>
|
||||
<%= render partial: 'query_list', locals: { query: @query, dmsf_pages: @dmsf_pages } %>
|
||||
<span class="pagination"><%= pagination_links_full @dmsf_pages, @dmsf_count %></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<%= render partial: 'query_list', locals: { query: @query, dmsf_pages: @dmsf_pages } %>
|
||||
<span class="pagination"><%= pagination_links_full @dmsf_pages, @dmsf_count %></span>
|
||||
|
||||
<%= context_menu %>
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
<li>
|
||||
<%= context_menu_link l(:button_edit), dmsf_file_path(id: dmsf_file), class: 'icon icon-edit',
|
||||
disabled: !allowed || locked %>
|
||||
disabled: !allowed || (locked && !unlockable) %>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to "#{l(:button_copy)}/#{l(:button_move)}", copy_file_path(id: dmsf_file),
|
||||
@ -40,6 +40,7 @@
|
||||
<li>
|
||||
<% 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',
|
||||
|
||||
@ -44,4 +44,3 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<span class="pagination"><%= pagination_links_full revision_access_pages, revision_access_count %></span>
|
||||
|
||||
@ -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 %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<% end %>
|
||||
|
||||
<span class="pagination"><%= pagination_links_full @revision_pages, @file.dmsf_file_revisions.visible.count %></span>
|
||||
<span class="pagination"><%= pagination_links_full @revision_pages, @revision_count %></span>
|
||||
|
||||
<%= late_javascript_tag do %>
|
||||
$('a.delete-revision').click(function(event) {
|
||||
|
||||
89
app/views/dmsf_queries/_query_form.html.erb
Normal file
89
app/views/dmsf_queries/_query_form.html.erb
Normal file
@ -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) %>
|
||||
|
||||
<div id="query_form_with_buttons" class="hide-when-print">
|
||||
<div id="query_form_content">
|
||||
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
|
||||
<legend onclick="toggleFieldset(this);" class="icon icon-<%= @query.new_record? ? "expended" : "collapsed" %>"><%= l(:label_filter_plural) %></legend>
|
||||
<div style="<%= @query.new_record? ? "" : "display: none;" %>">
|
||||
<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<% if @query.available_columns.any? %>
|
||||
<fieldset id="options" class="collapsible collapsed">
|
||||
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed"><%= l(:label_options) %></legend>
|
||||
<div class="hidden">
|
||||
<% if @query.available_display_types.size > 1 %>
|
||||
<div>
|
||||
<span class="field"><label for='display_type'><%= l(:label_display_type) %></label></span>
|
||||
<%= available_display_types_tags(@query) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<table id="list-definition" class="<%= 'hidden' if (@query.display_type != 'list') %>">
|
||||
<% if @query.available_columns.any? %>
|
||||
<tr>
|
||||
<td class="field"><%= l(:field_column_names) %></td>
|
||||
<td><%= render_query_columns_selection(@query) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% if @query.groupable_columns.any? %>
|
||||
<tr>
|
||||
<td class="field"><label for='group_by'><%= l(:field_group_by) %></label></td>
|
||||
<td><%= group_by_column_select_tag(@query) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% if @query.available_block_columns.any? %>
|
||||
<tr>
|
||||
<td class="field"><%= l(:button_show) %></td>
|
||||
<td><%= available_block_columns_tags(@query) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% if @query.available_totalable_columns.any? %>
|
||||
<tr>
|
||||
<td><%= l(:label_total_plural) %></td>
|
||||
<td><%= available_totalable_columns_tags(@query) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<p class="buttons">
|
||||
<%= 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 %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<%= 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 %>
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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: ロック解除して他のメンバーの変更を許可する
|
||||
|
||||
@ -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: 다른 구성원들의 변경 허가 잠금 해제
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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: Разблокируйте файл, чтобы разрешить его изменение другими участниками
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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: 解除鎖定。允許其它使用者修改。
|
||||
|
||||
@ -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: 解除锁定允许其他成员修改
|
||||
|
||||
2
init.rb
2
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: {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user