devel-1.4.6 merged to master

This commit is contained in:
Karel Picman 2016-01-25 13:54:28 +01:00
commit a3d227796c
51 changed files with 766 additions and 440 deletions

View File

@ -1,6 +1,27 @@
Changelog for Redmine DMSF
==========================
1.5.6 *2015-01-25*
------------------
Uploading of large files (>2GB)
* Bug: #494 - Unable to upload files with ruby > ruby-2.0.0-p598
* Bug: #491 - Still using original uploaded filename after filename renamed (PDF file)
* Bug: #488 - Available projects for 'link to' operation
* Bug: #487 - Not able to view the url link file, but able to Download
* Bug: #480 - Big files ( > 500mb) uploading problems
* Bug: #471 - Converting Documents to DMSF is not working
* Bug: #470 - sort function
* Bug: #469 - dmsfd doesn't reuse Wiki syntax in Wiki page
* New: #468 - Display contents of text file in Wiki page
* Bug: #465 - Install using debian 8 (jessie)
* Bug: #459 - WebDav Windows
* Bug: #458 - Cannot upload big files
* New #44 - Append File Revision on filename when downloading file
Maintenance release II.
1.5.5 *2015-10-19*
------------------

27
Gemfile
View File

@ -1,3 +1,25 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# 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.
source 'https://rubygems.org'
gem 'rubyzip', '>= 1.0.0'
@ -10,7 +32,6 @@ group :production do
gem 'nokogiri', '>= 1.5.10'
end
#Allows --without=xapian
group :xapian do
group :xapian do
gem 'xapian-full-alaveteli', :require => false
end
end

View File

@ -1,7 +1,7 @@
Redmine DMSF Plugin
===================
The current version of Redmine DMSF is **1.5.5** [![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 **1.5.6** [![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.
@ -77,26 +77,20 @@ From Omega documentation:
On Debian use:
```
apt-get install libxapian-ruby1.9.1 xapian-omega libxapian-dev xpdf \
xpdf-utils antiword unzip catdoc libwpd-0.9-9 libwps-0.2-2 gzip unrtf \
catdvi djview djview3 uuid uuid-dev xz-utils
```
```sudo apt-get install xapian-omega libxapian-dev xpdf xpdf-utils \
antiword unzip catdoc libwpd-tools libwps-tools gzip unrtf catdvi \
djview djview3 uuid uuid-dev xz-utils```
On Ubuntu use:
```
sudo apt-get install libxapian-ruby1.9.1 xapian-omega libxapian-dev xpdf \
antiword unzip catdoc libwpd-0.9-9 libwps-0.2-2 gzip unrtf catdvi djview \
djview3 uuid uuid-dev xz-utils
```
```sudo apt-get install xapian-omega libxapian-dev xpdf xpdf-utils antiword \
unzip catdoc libwpd-tools libwps-tools gzip unrtf catdvi djview djview3 \
uuid uuid-dev xz-utils```
On CentOS user:
```
sudo yum install libxapian-ruby1.9.1 xapian-omega libxapian-dev xpdf \
antiword unzip catdoc libwpd-0.9-9 libwps-0.2-2 gzip unrtf catdvi djview \
djview3 uuid uuid-dev xz
```
```sudo yum install xapian-omega libxapian-dev xpdf xpdf-utils antiword \
unzip catdoc libwpd-tools libwps-tools gzip unrtf catdvi djview djview3 \
uuid uuid-dev xz```
Usage
-----
@ -116,6 +110,9 @@ Search will now automatically search DMSF content when a Redmine search is perfo
####Link to the description of a file with id 17
`{{dmsfd(17)}}`
####Link to the preview of the first 5 lines from a file with id 17
`{{dmsft(17, 5)}}`
####An inline picture of the file with id 8; it must be an image file such as JPEG, PNG,...
`{{dmsf_image(8)}}`
@ -177,13 +174,14 @@ Setup / Upgrade
Before installing ensure that the Redmine instance is stopped.
1. In case of upgrade BACKUP YOUR DATABASE first
2. Put redmine_dmsf plugin directory into plugins
3. Initialize/Update database: `bundle exec rake redmine:plugins:migrate RAILS_ENV="production"`
4. The access rights must be set for web server, example: `chown -R www-data:www-data plugins/redmine_dmsf`
5. Restart web server
6. You should configure plugin via Redmine interface: Administration -> Plugins -> DMSF -> Configure
7. Assign DMSF permissions to appropriate roles
8. There are two rake tasks:
2. Put redmine_dmsf plugin directory into plugins.
3. Install dependencies: `bundle install`.
4. Initialize/Update database: `bundle exec rake redmine:plugins:migrate RAILS_ENV="production"`.
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.
7. You should configure the plugin via Redmine interface: Administration -> Plugins -> DMSF -> Configure.
8. Assign DMSF permissions to appropriate roles.
9. There are two rake tasks:
a) To convert documents from the standard Redmine document module
@ -241,4 +239,4 @@ Additional Documentation
------------------------
[CHANGELOG.md](CHANGELOG.md) - Project changelog
[dmsf_user_guide.odt](dmsf_user_guide.odt) - User's guide
[dmsf_user_guide.odt](dmsf_user_guide.odt) - User's guide

View File

@ -30,7 +30,7 @@ class DmsfController < ApplicationController
before_filter :find_project
before_filter :authorize
before_filter :find_folder, :except => [:new, :create, :edit_root, :save_root]
before_filter :find_parent, :only => [:new, :create]
before_filter :find_parent, :only => [:new, :create]
accept_api_auth :show, :create
@ -200,8 +200,7 @@ class DmsfController < ApplicationController
link = DmsfLink.find_by_id id
selected_files << link.target_id if link && !selected_files.include?(link.target_id.to_s)
end
end
end
if params[:email_entries].present?
email_entries(selected_folders, selected_files)
elsif params[:restore_entries].present?
@ -225,7 +224,7 @@ class DmsfController < ApplicationController
rescue FileNotFound
render_404
rescue DmsfAccessError
render_403
render_403
end
def tag_changed
@ -457,8 +456,8 @@ class DmsfController < ApplicationController
:files => selected_files
}
render :action => 'email_entries'
rescue Exception => e
flash[:error] = e.message
rescue Exception
raise
ensure
zip.close if zip
end
@ -482,19 +481,20 @@ class DmsfController < ApplicationController
:filename => filename_for_content_disposition("#{@project.name}-#{DateTime.now.strftime('%y%m%d%H%M%S')}.zip"),
:type => 'application/zip',
:disposition => 'attachment')
rescue Exception => e
flash[:error] = e.message
rescue Exception
raise
ensure
zip.close if zip
end
end
def zip_entries(zip, selected_folders, selected_files)
member = Member.where(:user_id => User.current.id, :project_id => @project.id).first
if selected_folders && selected_folders.is_a?(Array)
selected_folders.each do |selected_folder_id|
folder = DmsfFolder.visible.find_by_id selected_folder_id
if folder
zip.add_folder(folder, (folder.folder.dmsf_path_str if folder.folder))
zip.add_folder(folder, member, (folder.folder.dmsf_path_str if folder.folder))
else
raise FileNotFound
end
@ -503,8 +503,11 @@ class DmsfController < ApplicationController
if selected_files && selected_files.is_a?(Array)
selected_files.each do |selected_file_id|
file = DmsfFile.visible.find_by_id selected_file_id
unless (file.project == @project) || User.current.allowed_to?(:view_dmsf_files, file.project)
raise DmsfAccessError
end
if file && file.last_revision && File.exists?(file.last_revision.disk_file)
zip.add_file(file, (file.folder.dmsf_path_str if file.folder)) if file
zip.add_file(file, member, (file.folder.dmsf_path_str if file.folder)) if file
else
raise FileNotFound
end

View File

@ -26,7 +26,7 @@ class DmsfFilesController < ApplicationController
before_filter :find_file, :except => [:delete_revision]
before_filter :find_revision, :only => [:delete_revision]
before_filter :authorize
before_filter :authorize
accept_api_auth :show
@ -34,17 +34,14 @@ class DmsfFilesController < ApplicationController
helper :dmsf_workflows
def view
if params[:download].blank?
@revision = @file.last_revision
else
@revision = DmsfFileRevision.find(params[:download].to_i)
if @revision.file != @file
render_403
return
end
end
check_project(@revision.file)
begin
if params[:download].blank?
@revision = @file.last_revision
else
@revision = DmsfFileRevision.find(params[:download].to_i)
raise DmsfAccessError if @revision.file != @file
end
check_project(@revision.file)
raise ActionController::MissingFile if @file.deleted
log_activity('downloaded')
access = DmsfFileRevisionAccess.new
@ -52,11 +49,16 @@ class DmsfFilesController < ApplicationController
access.revision = @revision
access.action = DmsfFileRevisionAccess::DownloadAction
access.save!
send_file(@revision.disk_file,
:filename => filename_for_content_disposition(@revision.name),
member = Member.where(:user_id => User.current.id, :project_id => @file.project.id).first
send_file(@revision.disk_file,
:filename => filename_for_content_disposition(@revision.formatted_name(member ? member.title_format : nil)),
:type => @revision.detect_content_type,
:disposition => 'inline')
rescue ActionController::MissingFile
:disposition => 'inline')
rescue DmsfAccessError => e
Rails.logger.error e.message
render_403
rescue Exception => e
Rails.logger.error e.message
render_404
end
end
@ -64,17 +66,14 @@ class DmsfFilesController < ApplicationController
def show
# The download is put here to provide more clear and usable links
if params.has_key?(:download)
if params[:download].blank?
@revision = @file.last_revision
else
@revision = DmsfFileRevision.find(params[:download].to_i)
if @revision.file != @file
render_403
return
end
end
check_project(@revision.file)
begin
if params[:download].blank?
@revision = @file.last_revision
else
@revision = DmsfFileRevision.find(params[:download].to_i)
raise DmsfAccessError if @revision.file != @file
end
check_project(@revision.file)
raise ActionController::MissingFile if @revision.file.deleted
log_activity('downloaded')
access = DmsfFileRevisionAccess.new
@ -82,11 +81,16 @@ class DmsfFilesController < ApplicationController
access.revision = @revision
access.action = DmsfFileRevisionAccess::DownloadAction
access.save!
send_file(@revision.disk_file,
:filename => filename_for_content_disposition(@revision.name),
member = Member.where(:user_id => User.current.id, :project_id => @file.project.id).first
send_file(@revision.disk_file,
:filename => filename_for_content_disposition(@revision.formatted_name(member ? member.title_format : nil)),
:type => @revision.detect_content_type,
:disposition => 'attachment')
rescue ActionController::MissingFile
rescue DmsfAccessError => e
Rails.logger.error e.message
render_403
rescue Exception => e
Rails.logger.error e.message
render_404
end
return
@ -319,7 +323,7 @@ class DmsfFilesController < ApplicationController
rescue ActiveRecord::RecordNotFound
render_404
end
def check_project(entry)
if entry && entry.project != @project
raise DmsfAccessError, l(:error_entry_project_does_not_match_current_project)

View File

@ -1,7 +1,9 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2011-14 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -29,12 +31,22 @@ class DmsfStateController < ApplicationController
member = @project.members.where(:user_id => User.current.id).first
if member
member.dmsf_mail_notification = params[:email_notify]
member.save!
flash[:notice] = l(:notice_your_preferences_were_saved)
member.title_format = params[:title_format]
if format_valid?(member.title_format) && member.save
flash[:notice] = l(:notice_your_preferences_were_saved)
else
flash[:error] = l(:notice_your_preferences_were_not_saved)
end
else
flash[:warning] = l(:user_is_not_project_member)
end
redirect_to settings_project_path(@project, :tab => 'dmsf')
end
private
def format_valid?(format)
format.blank? || ((format =~ /%(t|d|v|i|r)/) && format.length < 256)
end
end

View File

@ -3,7 +3,7 @@
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-16 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -39,7 +39,8 @@ class DmsfUploadController < ApplicationController
if uploaded_files && uploaded_files.is_a?(Hash)
# standard file input uploads
uploaded_files.each_value do |uploaded_file|
@uploads.push(DmsfUpload.create_from_uploaded_attachment(@project, @folder, uploaded_file))
upload = DmsfUpload.create_from_uploaded_attachment(@project, @folder, uploaded_file)
@uploads.push(upload) if upload
end
else
# plupload multi upload completed
@ -94,6 +95,7 @@ class DmsfUploadController < ApplicationController
@attachment = Attachment.new(:file => request.raw_post)
@attachment.author = User.current
@attachment.filename = params[:filename].presence || Redmine::Utils.random_hex(16)
@attachment.content_type = params[:content_type].presence
saved = @attachment.save
respond_to do |format|

View File

@ -51,8 +51,7 @@ class DmsfWorkflowsController < ApplicationController
begin
file.unlock! true
rescue DmsfLockError => e
flash[:info] = e.message
#logger.warn e.message
flash[:info] = e.message
end
end
if revision.workflow == DmsfWorkflow::STATE_APPROVED
@ -171,28 +170,27 @@ class DmsfWorkflowsController < ApplicationController
end
def assignment
if params[:commit] == l(:button_submit)
if (params[:commit] == l(:button_submit)) &&
params[:dmsf_workflow_id].present? && (params[:dmsf_workflow_id] != '-1')
revision = DmsfFileRevision.find_by_id params[:dmsf_file_revision_id]
if revision
revision.set_workflow(params[:dmsf_workflow_id], params[:action])
if params[:dmsf_workflow_id].present?
revision.assign_workflow(params[:dmsf_workflow_id])
if request.post?
if revision.save
file = DmsfFile.find_by_id revision.dmsf_file_id
if file
begin
file.lock!
rescue DmsfLockError => e
logger.warn e.message
end
flash[:notice] = l(:notice_successful_update)
revision.set_workflow(params[:dmsf_workflow_id], params[:action])
revision.assign_workflow(params[:dmsf_workflow_id])
if request.post?
if revision.save
file = DmsfFile.find_by_id revision.dmsf_file_id
if file
begin
file.lock!
rescue DmsfLockError => e
logger.warn e.message
end
else
flash[:error] = l(:error_workflow_assign)
flash[:notice] = l(:notice_successful_update)
end
else
flash[:error] = l(:error_workflow_assign)
end
end
end
end
end
redirect_to :back

View File

@ -55,6 +55,7 @@ module DmsfWorkflowsHelper
def dmsf_workflows_for_select(project, dmsf_workflow_id)
options = Array.new
options << ['', -1]
DmsfWorkflow.sorted.where(['project_id = ? OR project_id IS NULL', project.id]).each do |wf|
if wf.project_id
options << [wf.name, wf.id]

View File

@ -98,7 +98,7 @@ class DmsfFile < ActiveRecord::Base
def self.storage_path
unless @@storage_path.present?
@@storage_path = Setting.plugin_redmine_dmsf['dmsf_storage_directory'].strip
@@storage_path = Setting.plugin_redmine_dmsf['dmsf_storage_directory'].strip if Setting.plugin_redmine_dmsf['dmsf_storage_directory'].present?
@@storage_path = Pathname(Redmine::Configuration['attachments_storage_path']).join('dmsf') if @@storage_path.blank? && Redmine::Configuration['attachments_storage_path'].present?
@@storage_path = Rails.root.join('files/dmsf').to_s if @@storage_path.blank?
Dir.mkdir(@@storage_path) unless File.exists?(@@storage_path)
@ -216,9 +216,9 @@ class DmsfFile < ActiveRecord::Base
def self.allowed_target_projects_on_copy
projects = []
if User.current.admin?
projects = Project.visible.all
projects = Project.visible.has_module('dmsf').all
elsif User.current.logged?
User.current.memberships.each {|m| projects << m.project if m.roles.detect {|r| r.allowed_to?(:file_manipulation)}}
User.current.memberships.each {|m| projects << m.project if m.roles.detect {|r| r.allowed_to?(:file_manipulation)} && m.project.module_enabled?('dmsf')}
end
projects
end
@ -362,7 +362,7 @@ class DmsfFile < ActiveRecord::Base
if matchset
matchset.matches.each { |m|
docdata = m.document.data{url}
dochash = Hash[*docdata.scan(/(url|sample|modtime|type|size)=\/?([^\n\]]+)/).flatten]
dochash = Hash[*docdata.scan(/(url|sample|modtime|author|type|size)=\/?([^\n\]]+)/).flatten]
filename = dochash['url']
if filename
dmsf_attrs = filename.scan(/^([^\/]+\/[^_]+)_([\d]+)_(.*)$/)
@ -406,5 +406,35 @@ class DmsfFile < ActiveRecord::Base
def image?
self.last_revision && !!(self.last_revision.disk_filename =~ /\.(bmp|gif|jpg|jpe|jpeg|png)$/i)
end
def preview(limit)
result = 'No preview available'
if (self.last_revision.disk_filename =~ /\.(txt|ini|diff|c|cpp|php|csv|rb|h|erb|html|css)$/i)
begin
f = File.new(self.last_revision.disk_file)
f.each_line do |line|
case f.lineno
when 1
result = line
when limit.to_i + 1
break
else
result << line
end
end
rescue Exception => e
result = e.message
end
end
result
end
def formatted_name(format)
if self.last_revision
self.last_revision.formatted_name(format)
else
self.name
end
end
end
end

View File

@ -247,5 +247,21 @@ class DmsfFileRevision < ActiveRecord::Base
parts = self.version.split '.'
parts.size == 2 ? parts[0].to_i * 1000 + parts[1].to_i : 0
end
def formatted_name(format)
return self.name if format.blank?
if self.name =~ /(.*)(\..*)$/
filename = $1
ext = $2
else
filename = self.name
end
format.sub!('%t', filename)
format.sub!('%d', self.updated_at.strftime('%Y%m%d%H%M%S'))
format.sub!('%v', self.version)
format.sub!('%i', self.file.id.to_s)
format.sub!('%r', self.id.to_s)
format + ext
end
end

View File

@ -188,7 +188,7 @@ class DmsfFolder < ActiveRecord::Base
def self.file_list(files)
options = Array.new
options.push ['', nil]
options.push ['', nil, :label => 'none']
files.each do |f|
options.push [f.title, f.id]
end

View File

@ -47,8 +47,11 @@ class DmsfUpload
}
FileUtils.mv(a.diskfile, "#{DmsfHelper.temp_dir}/#{uploaded[:disk_filename]}")
a.destroy
DmsfUpload.new(project, folder, uploaded)
upload = DmsfUpload.new(project, folder, uploaded)
else
Rails.logger.error "An attachment not found by its token: #{uploaded_file[:token]}"
end
upload
end
def initialize(project, folder, uploaded)

View File

@ -24,7 +24,7 @@
<% locked = subfolder && subfolder.locked? %>
<td class="check"><%= check_box_tag(name, id, false,
:title => l(:title_check_for_zip_download_or_email)) %></td>
:title => l(:title_check_for_zip_download_or_email), :id => "subfolder_#{id}") %></td>
<td class="title">
<%= link_to(h(title),
dmsf_folder_path(:id => project, :folder_id => subfolder),

View File

@ -21,7 +21,7 @@
%>
<td class="check"><%= check_box_tag(name, id, false,
:title => l(:title_check_for_restore_or_delete)) %></td>
:title => l(:title_check_for_restore_or_delete), :id => "subfolder_#{id}") %></td>
<td class="title">
<%= content_tag(:span, h(title),
:title => h(title),

View File

@ -25,7 +25,7 @@
<% wf = DmsfWorkflow.find_by_id(file.last_revision.dmsf_workflow_id) %>
<td class="check"><%= check_box_tag(name, id, false,
:title => l(:title_check_for_zip_download_or_email)) %></td>
:title => l(:title_check_for_zip_download_or_email), :id => "file_#{id}") %></td>
<td class="title">
<% file_view_url = url_for({:controller => :dmsf_files, :action => 'view', :id => file}) %>
<%= link_to(h(title),

View File

@ -21,7 +21,7 @@
%>
<td class="check"><%= check_box_tag(name, id, false,
:title => l(:title_check_for_restore_or_delete)) %></td>
:title => l(:title_check_for_restore_or_delete), :id => "file_#{id}") %></td>
<td class="title">
<%= content_tag(:span, h(title),
:title => h(title),

View File

@ -39,7 +39,7 @@
<span class="icon"></span>
<span class="icon"></span>
<span class="icon"></span>
<%= link_to('delete.png',
<%= link_to(image_tag('delete.png'),
dmsf_link_path(link),
:data => {:confirm => l(:text_are_you_sure)},
:method => :delete,
@ -55,4 +55,4 @@
<td class="invisible">1</td>
<td class="invisible"></td>
<td class="invisible">link.updated_at.to_i</td>
<td class="invisible"></td>
<td class="invisible"></td>

View File

@ -234,12 +234,9 @@
});
</script>
<%
if I18n.locale && !I18n.locale.to_s.match(/^en.*/)
sUrl = "jquery.dataTables/#{I18n.locale.to_s.downcase}.json"
else
sUrl = 'jquery.dataTables/en.json'
end
<%
sUrl = "jquery.dataTables/#{I18n.locale.to_s.downcase}.json"
sUrl = 'jquery.dataTables/en.json' unless File.exist?(sUrl)
%>
<% content_for :header_tags do %>

View File

@ -153,11 +153,8 @@
</script>
<%
if I18n.locale && !I18n.locale.to_s.match(/^en.*/)
sUrl = "jquery.dataTables/#{I18n.locale.to_s.downcase}.json"
else
sUrl = 'jquery.dataTables/en.json'
end
sUrl = "jquery.dataTables/#{I18n.locale.to_s.downcase}.json"
sUrl = 'jquery.dataTables/en.json' unless File.exist?(sUrl)
%>
<% content_for :header_tags do %>
@ -171,7 +168,7 @@
'oLanguage': {
'sUrl': "<%= plugin_asset_path(:redmine_dmsf, 'javascripts', sUrl) %>"
},
'bAutoWidth': false,
'bAutoWidth': false,
'bPaginate': false,
'aaSorting': [[1,'asc']],
'aaSortingFixed': [[8,'asc']],

View File

@ -52,7 +52,7 @@
</div>
<div class="splitcontentleft">
<p>
<%= label_tag('fileMinorVersionRadio', "#{l(:label_version)}:") %>
<%= label_tag('version_0', "#{l(:label_version)}:") %>
</p>
<div class="data clear">
<%= radio_button_tag('version', 0,
@ -79,7 +79,7 @@
</p>
<span class="add_attachment">
<%= file_field_tag 'file_upload',
:id => nil,
:id => 'file_upload',
:class => 'file_selector',
:multiple => false,
:onchange => "$('#dmsf_file_revision_name').val(this.files[0].name)",

View File

@ -4,5 +4,5 @@ api.dmsf_file do
api.project_id @file.project_id
api.dmsf_folder_id @file.folder if @file.dmsf_folder_id
api.version "#{@file.last_revision.major_version}.#{@file.last_revision.minor_version}" if @file.last_revision
api.content_url url_for(:controller => :dmsf_files, :action => 'show', :download => '', :id => @file, :only_path => false)
api.content_url url_for(:controller => :dmsf_files, :action => 'show', :download => '', :id => @file)
end

View File

@ -5,7 +5,7 @@
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-16 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -150,7 +150,7 @@
<br/>
<% end %>
<p class="pagination"><%= pagination_links_full @revision_pages, @file.revisions.visible.count %></p>
<span class="pagination"><%= pagination_links_full @revision_pages, @file.revisions.visible.count %></span>
<%
url = 'jquery.dataTables/en.json'

View File

@ -37,7 +37,7 @@
<div class="box dmsf_detail">
<% if @type == 'link_from' %>
<p>
<%= radio_button_tag(:external_link, 'false', @link_external == false) %> <%= l(:label_internal) %></br>
<%= radio_button_tag(:external_link, 'false', @link_external == false) %> <%= l(:label_internal) %><br/>
<%= radio_button_tag(:external_link, 'true', @link_external) %> <%= l(:label_external) %>
</p>
<% end %>
@ -82,7 +82,7 @@
</div>
<%= label_tag('dmsf_link[name]', l(:label_link_name), :class => 'required') %>
<%= text_field_tag 'dmsf_link[name]', @dmsf_link.name, :size => 40, :maxlength => 255 %>
</p>
<!--</p>-->
</div>
<%= f.submit l(:button_create) %>
<% end %>

View File

@ -18,19 +18,28 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
<p><strong><%=l(:link_user_preferences)%></strong></p>
<div class="box">
<%= form_tag({:controller => 'dmsf_state', :action => 'user_pref_save', :id => @project}, :method => :post) do %>
<div>
<% member = @project.members.where(:user_id => User.current.id).first %>
<% mail_notification = member ? member.dmsf_mail_notification : nil %>
<%= l(:label_notifications) %>:
<% member = @project.members.where(:user_id => User.current.id).first %>
<% if member %>
<% mail_notification = member.dmsf_mail_notification %>
<% title_format = member.title_format %>
<% end %>
<%= form_tag(dmsf_user_pref_save_path(@project)) do %>
<fieldset class="box tabular">
<legend><%= l(:link_user_preferences) %></legend>
<p>
<%= content_tag(:label, "#{l(:label_notifications)}:") %>
<%= select_tag(
'email_notify',
options_for_select([[l(:select_option_default), nil],
[l(:select_option_activated), true], [l(:select_option_deactivated), false]],
:selected => mail_notification)) %>
<%= submit_tag(l(:submit_save), :title => l(:title_save_preferences)) %>
</div>
<% end %>
</div>
'email_notify',
options_for_select([[l(:select_option_default), nil],
[l(:select_option_activated), true], [l(:select_option_deactivated), false]],
:selected => mail_notification)) %>
</p>
<p>
<%= content_tag(:label, "#{l(:label_title_format)}:") %>
<%= text_field_tag 'title_format', title_format, :size => 10 %>
<em class="info"><%= l(:text_title_format) %></em>
</p>
</fieldset>
<%= submit_tag(l(:submit_save), :title => l(:title_save_preferences)) %>
<% end %>

View File

@ -1,6 +1,6 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011/15 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
<%# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-16 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -49,6 +49,6 @@
<p><%= link_to l(:label_dmsf_workflow_new), new_dmsf_workflow_path(:project_id => @project.id), :class => 'icon icon-add' %></p>
<% else %>
<% if @workflow_pages %>
<p class="pagination"><%= pagination_links_full @workflow_pages %></p>
<span class="pagination"><%= pagination_links_full @workflow_pages %></span>
<% end %>
<% end %>

View File

@ -43,7 +43,7 @@
<th><%= l(:label_dmsf_workflow_step) %></th>
<th><%= l(:label_dmsf_workflow_approval_plural) %></th>
<th><%= l(:button_sort)%></th>
<th/>
<th></th>
</tr></thead>
<tbody>
<% steps.each do |i|%>

View File

@ -19,45 +19,47 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.%>
<p>
<%= content_tag(:label, "#{l(:label_maximum_files_upload)}:") %>
<%= text_field_tag 'settings[dmsf_max_file_upload]', @settings['dmsf_max_file_upload'], :size => 10 %><br/>
(<%= l(:label_default) %>: 0)
<br/>
<%= l(:note_maximum_number_of_files_uploaded) %>
<%= content_tag(:label, l(:label_maximum_files_upload)) %>
<%= text_field_tag 'settings[dmsf_max_file_upload]', @settings['dmsf_max_file_upload'], :size => 10 %>
<em class="info">
<%= l(:note_maximum_number_of_files_uploaded) %> <%= l(:label_default) %>: 0
</em>
</p>
<p>
<%= content_tag(:label, "#{l(:label_maximum_files_download)}:") %>
<%= text_field_tag 'settings[dmsf_max_file_download]', @settings['dmsf_max_file_download'], :size => 10 %><br/>
(<%= l(:label_default) %>: 0)
<br/>
<%= l(:note_maximum_number_of_files_downloaded) %>
<%= content_tag(:label, l(:label_maximum_files_download)) %>
<%= text_field_tag 'settings[dmsf_max_file_download]', @settings['dmsf_max_file_download'], :size => 10 %>
<em class="info">
<%= l(:note_maximum_number_of_files_downloaded) %> <%= l(:label_default) %>: 0
</em>
</p>
<p>
<%= content_tag(:label, "#{l(:label_maximum_email_filesize)}:") %>
<%= text_field_tag 'settings[dmsf_max_email_filesize]', @settings['dmsf_max_email_filesize'], :size => 10 %><br/>
(<%= l(:label_default) %>: 0)
<br/>
<%= l(:note_maximum_email_filesize) %>
<%= content_tag(:label, l(:label_maximum_email_filesize)) %>
<%= text_field_tag 'settings[dmsf_max_email_filesize]', @settings['dmsf_max_email_filesize'], :size => 10 %>
<em class="info">
<%= l(:note_maximum_email_filesize) %> <%= l(:label_default) %>: 0
</em>
</p>
<p>
<%= content_tag(:label, "#{l(:label_maximum_ajax_upload_filesize)}:") %>
<%= text_field_tag 'settings[dmsf_max_ajax_upload_filesize]', @settings['dmsf_max_ajax_upload_filesize'], :size => 10 %><br/>
(<%= l(:label_default) %>: 100)
<br/>
<%= l(:note_maximum_ajax_upload_filesize) %>
<%= content_tag(:label, l(:label_maximum_ajax_upload_filesize)) %>
<%= text_field_tag 'settings[dmsf_max_ajax_upload_filesize]', @settings['dmsf_max_ajax_upload_filesize'], :size => 10 %>
<em class="info">
<%= l(:note_maximum_ajax_upload_filesize) %> <%= l(:label_default) %>: 100
</em>
</p>
<p>
<%= content_tag(:label, "#{l(:label_file_storage_directory)}:") %>
<%= content_tag(:label, l(:label_file_storage_directory)) %>
<%
storage_dir = @settings['dmsf_storage_directory'].strip
storage_dir = @settings['dmsf_storage_directory'].strip if @settings['dmsf_storage_directory'].present?
storage_dir = "#{Rails.root}/files/dmsf" if storage_dir.blank?
%>
<%= text_field_tag 'settings[dmsf_storage_directory]', storage_dir, :size => 50 %><br/>
(<%= l(:label_default) %>: <%= "#{Rails.root}/files/dmsf" %>)
<%= text_field_tag 'settings[dmsf_storage_directory]', storage_dir, :size => 50 %>
<em class="info">
<%= l(:label_default) %>: <%= "#{Rails.root}/files/dmsf" %>
</em>
</p>
<% unless File.exists?(storage_dir) %>
<% begin %>
@ -79,62 +81,66 @@
<% end %>
<p>
<%= content_tag(:label, "#{l(:label_physical_file_delete)}:") %>
<%= check_box_tag('settings[dmsf_really_delete_files]', true, @settings['dmsf_really_delete_files']) %><br/>
(<%=l(:label_default)%>: <%=l(:general_text_No)%>)
<%= content_tag(:label, l(:label_physical_file_delete)) %>
<%= check_box_tag('settings[dmsf_really_delete_files]', true, @settings['dmsf_really_delete_files']) %>
<em class="info">
<%= l(:label_default)%>: <%= l(:general_text_No)%>
</em>
</p>
<p>
<%= content_tag(:label, "#{l(:label_default_notifications)}:") %>
<%= content_tag(:label, l(:label_default_notifications)) %>
<%= select_tag('settings[dmsf_default_notifications]',
options_for_select([
[l(:select_option_deactivated), nil],
[l(:select_option_activated), '1']],
:selected => @settings['dmsf_default_notifications'])) %><br/>
(<%= l(:label_default) %>: <%= l(:select_option_deactivated) %>)
:selected => @settings['dmsf_default_notifications'])) %>
<em class="info">
<%= l(:label_default) %>: <%= l(:select_option_deactivated) %>
</em>
</p>
<p>
<%= content_tag(:label, "#{l(:label_display_notified_recipients)}:") %>
<%= content_tag(:label, l(:label_display_notified_recipients)) %>
<%= select_tag('settings[dmsf_display_notified_recipients]',
options_for_select([
[l(:select_option_deactivated), nil],
[l(:select_option_activated), '1']],
:selected => @settings['dmsf_display_notified_recipients'])) %><br/>
(<%= l(:label_default) %>: <%= l(:select_option_deactivated) %>)
<br/>
<%= l(:note_display_notified_recipients).html_safe %>
:selected => @settings['dmsf_display_notified_recipients'])) %>
<em class="info">
<%= l(:note_display_notified_recipients).html_safe %> <%= l(:label_default) %>: <%= l(:select_option_deactivated) %>
</em>
</p>
<hr />
<hr/>
<p>
<%= content_tag(:label, "#{l(:label_webdav)}:") %>
<%= content_tag(:label, l(:label_webdav)) %>
<%= select_tag('settings[dmsf_webdav]',
options_for_select([
[l(:select_option_deactivated), nil],
[l(:select_option_activated), '1']],
:selected => @settings['dmsf_webdav'])) %><br/>
(<%= l(:label_default) %>: <%= l(:select_option_activated) %>)
<br/>
<%= l(:note_webdav, :protocol => Setting.protocol, :domain => Setting.host_name).html_safe %>
:selected => @settings['dmsf_webdav'])) %>
<em class="info">
<%= l(:note_webdav, :protocol => Setting.protocol, :domain => Setting.host_name).html_safe %> <%= l(:label_default) %>: <%= l(:select_option_activated) %>
</em>
</p>
<% if @settings['dmsf_webdav'].nil? || !@settings['dmsf_webdav'].empty? %>
<p>
<%= content_tag(:label, "#{l(:label_webdav_strategy)}:") %>
<%= content_tag(:label, l(:label_webdav_strategy)) %>
<%= select_tag('settings[dmsf_webdav_strategy]',
options_for_select([
[l(:select_option_webdav_readonly), 'WEBDAV_READ_ONLY'],
[l(:select_option_webdav_readwrite), 'WEBDAV_READ_WRITE']],
:selected => @settings['dmsf_webdav_strategy'])) %><br/>
(<%= l(:label_default) %>: <%= l(:select_option_webdav_readonly) %>)
<br/>
<%= l(:note_webdav_strategy).html_safe %>
<em class="info">
<%= l(:note_webdav_strategy).html_safe %> <%= l(:label_default) %>: <%= l(:select_option_webdav_readonly) %>
</em>
</p>
<% end %>
<hr />
<hr/>
<% begin %>
<% require 'xapian' %>
@ -145,29 +151,33 @@
<% end %>
<p>
<%= content_tag(:label, "#{l(:label_index_database)}:") %>
<%= text_field_tag 'settings[dmsf_index_database]', @settings['dmsf_index_database'], :disabled => xapian_disabled, :size => 50 %><br/>
(<%= l(:label_default) %>: <%= "#{Rails.root}/files/dmsf_index" %>)
<%= content_tag(:label, l(:label_index_database)) %>
<%= text_field_tag 'settings[dmsf_index_database]', @settings['dmsf_index_database'], :disabled => xapian_disabled, :size => 50 %>
<em class="info">
<%= l(:label_default) %>: <%= "#{Rails.root}/files/dmsf_index" %>
</em>
</p>
<% stem_langs = %w(danish dutch english finnish french german hungarian italian norwegian portuguese romanian russian spanish swedish turkish) %>
<p>
<%= content_tag(:label, l(:label_stemming_language)) %>
<%= select_tag('settings[dmsf_stemming_lang]', options_for_select(stem_langs, @settings['dmsf_stemming_lang']))%>
<em class="info">
<%= l(:note_possible_values) %>: <%= stem_langs.join(', ') %>. <%= "#{l(:label_default)}: #{stem_langs[2]}" %>
</em>
</p>
<p>
<%= content_tag(:label, "#{l(:label_stemming_language)}:") %>
<%= text_field_tag 'settings[dmsf_stemming_lang]', @settings['dmsf_stemming_lang'], :disabled => xapian_disabled %><br/>
(<%= l(:label_default)%>: english )<br/>
<br/>
<%= l(:note_possible_values)%>: danish dutch english finnish french german german2 hungarian italian kraaij_pohlmann lovins norwegian porter portuguese romanian russian spanish swedish turkish (<%= l(:note_pass_none_to_disable_stemming) %>)</p>
<p>
<%= content_tag(:label, l(:label_stem_strategy) + ":")%>
<%= radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_NONE', @settings['dmsf_stemming_strategy'] == 'STEM_NONE', :disabled => xapian_disabled, :checked=>true %> <%= l(:option_stem_none) %><br>
<%= radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_SOME', @settings['dmsf_stemming_strategy'] == 'STEM_SOME', :disabled => xapian_disabled %> <%= l(:option_stem_some) %><br>
<%= radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_ALL', @settings['dmsf_stemming_strategy'] == 'STEM_ALL', :disabled => xapian_disabled %> <%= l(:option_stem_all) %><br>
<br/>
<%= l(:label_stemming_description) %>:
<br>
STEM_NONE: <%=l(:note_do_not_stem) %><br>
STEM_SOME: <%=l(:note_stem_some) %><br>
STEM_ALL: <%=l(:note_stem_all) %><br>
<br/>
<%= l(:note_stemming_applied) %><br>
<%= content_tag(:label, l(:label_stem_strategy)) %>
<%= radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_NONE', @settings['dmsf_stemming_strategy'] == 'STEM_NONE', :disabled => xapian_disabled, :checked => true %> <%= l(:option_stem_none) %><br/>
<%= radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_SOME', @settings['dmsf_stemming_strategy'] == 'STEM_SOME', :disabled => xapian_disabled %> <%= l(:option_stem_some) %><br/>
<%= radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_ALL', @settings['dmsf_stemming_strategy'] == 'STEM_ALL', :disabled => xapian_disabled %> <%= l(:option_stem_all) %><br/>
<em class="info">
<%= l(:label_stemming_description) %>:<br/>
&nbsp;&nbsp;STEM_NONE: <%= l(:note_do_not_stem) %><br/>
&nbsp;&nbsp;STEM_SOME: <%= l(:note_stem_some) %><br/>
&nbsp;&nbsp;STEM_ALL: <%= l(:note_stem_all) %><br/>
<%= l(:note_stemming_applied) %>
</em>
</p>

View File

@ -0,0 +1,17 @@
{
"sProcessing": "Przetwarzanie...",
"sLengthMenu": "Pokaż _MENU_",
"sZeroRecords": "Nie znaleziono wpisów pasujących do zapytania",
"sInfo": "Pokaż wszystkie",
"sInfoEmpty": "Brak informacji ",
"sInfoFiltered": "(przefiltrowano wszystkie wpisy)",
"sInfoPostFix": "",
"sSearch": "Szukaj/Filtruj:",
"sUrl": "",
"oPaginate": {
"sFirst": "Pierwszy",
"sPrevious": "Poprzedni",
"sNext": "Następny",
"sLast": "Ostatni"
}
}

View File

@ -50,6 +50,7 @@ cs:
notice_file_unlocked: Soubor byl odemčen
notice_file_revision_created: vytvořena nová revize
notice_your_preferences_were_saved: Vaše nastavení bylo uloženo
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: Notifikace složky již byly aktivovány
notice_folder_notifications_activated: Notifikace složky byly aktivovány
warning_folder_notifications_already_deactivated: Notifikace složky již byly deaktivovány
@ -107,6 +108,8 @@ cs:
select_option_default: Výchozí
select_option_deactivated: Deaktivováno
select_option_activated: Aktivováno
label_title_format: Formát názvu
text_title_format: "Formát názvu souboru pro stažení (%t - název, %d - datum, %v- verze, %i - ID, %r - revize). Např.: %t_%v"
title_save_preferences: Uložit nastavení
heading_revisions: Revize
title_download: Stáhnout

View File

@ -40,8 +40,8 @@ de:
notice_folder_deleted: Ordner gelöscht
error_folder_is_not_empty: Ordner ist nicht leer
error_folder_title_is_already_used: Titel wird schon benutzt. Denk dir was Neues aus.
notice_folder_details_were_saved: Ordnerdetails wurden gespeichert
error_folder_is_locked: Order ist gesperrt
notice_folder_details_were_saved: Ordnerdetails wurden gespeichert
error_folder_is_locked: Ordner ist gesperrt
error_file_is_locked: Datei ist gesperrt
notice_file_deleted: Datei gelöscht
error_at_least_one_revision_must_be_present: Es muss mindestens eine Version existieren
@ -50,6 +50,7 @@ de:
notice_file_unlocked: Dateisperre gelöst
notice_file_revision_created: Dateiversion erstellt
notice_your_preferences_were_saved: Deine Einstellungen wurden gespeichert
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: Ordnerbenachrichtigungen sind schon aktiviert
notice_folder_notifications_activated: Ordnerbenachrichtigungen aktiviert
warning_folder_notifications_already_deactivated: Ordnerbenachrichtigungen sind schon deaktiviert
@ -107,6 +108,8 @@ de:
select_option_default: Voreinstellung
select_option_deactivated: Aus
select_option_activated: Ein
label_title_format: Title format
text_title_format: "Document title format for download (%t - title, %d - date, %v- version, %i - ID, %r - revision). Example: %t_%v"
title_save_preferences: Einstellungen speichern
heading_revisions: Versionen
title_download: Download
@ -168,7 +171,7 @@ de:
title_delete_checked: Löschen ausgewählt
title_items: items
title_filename_for_download: Dateiname beim Herunterladen oder in ZIP-Archiv verwenden
label_number_of_folders: Order
label_number_of_folders: Ordner
label_number_of_documents: Dokumente
error_file_storage_directory_does_not_exist: Der Dateiablageordner existiert nicht auf dem Server und kann nicht erstellt werden.
error_file_can_not_be_created: Datei kann nicht in dem gewählten Ordner erstellt werden.

View File

@ -40,7 +40,7 @@ en:
notice_folder_deleted: Folder deleted
error_folder_is_not_empty: Folder is not empty
error_folder_title_is_already_used: Title is already used
notice_folder_details_were_saved: Folder details were saved
notice_folder_details_were_saved: Folder details were saved
error_folder_is_locked: Folder is locked
error_file_is_locked: File is locked
notice_file_deleted: File deleted
@ -50,6 +50,7 @@ en:
notice_file_unlocked: File unlocked
notice_file_revision_created: File revision created
notice_your_preferences_were_saved: Your preferences were saved
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: Folder notifications already activated
notice_folder_notifications_activated: Folder notifications activated
warning_folder_notifications_already_deactivated: Folder notifications already deactivated
@ -107,6 +108,8 @@ en:
select_option_default: Default
select_option_deactivated: Deactivated
select_option_activated: Activated
label_title_format: Title format
text_title_format: "Document title format for download (%t - title, %d - date, %v- version, %i - ID, %r - revision). Example: %t_%v"
title_save_preferences: Save preferences
heading_revisions: Revisions
title_download: Download

View File

@ -40,7 +40,7 @@ es:
notice_folder_deleted: Carpeta borrada
error_folder_is_not_empty: La carpeta no está vacía
error_folder_title_is_already_used: El título ingresado ya está siendo usado por otro documento
notice_folder_details_were_saved: Los detalles de la carpeta fueron grabados correctamente
notice_folder_details_were_saved: Los detalles de la carpeta fueron grabados correctamente
error_folder_is_locked: Carpeta bloqueado
error_file_is_locked: Archivo bloqueado
notice_file_deleted: Archivo borrado
@ -50,6 +50,7 @@ es:
notice_file_unlocked: Archivo desbloqueado
notice_file_revision_created: Revision de archivos creada correctamente
notice_your_preferences_were_saved: Sus preferencias han sido guardadas correctamente
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: Las notificaciones de la carpeta seleccionada ya están activadas previamente
notice_folder_notifications_activated: Notificaciones de carpeta activadas
warning_folder_notifications_already_deactivated: Las notificaciones de la carpeta seleccionada ya están desactivadas previamente
@ -107,6 +108,8 @@ es:
select_option_default: Default
select_option_deactivated: Desactivado
select_option_activated: Activado
label_title_format: Title format
text_title_format: "Document title format for download (%t - title, %d - date, %v- version, %i - ID, %r - revision). Example: %t_%v"
title_save_preferences: Guardar Preferencias
heading_revisions: Revisiones
title_download: Descargar

View File

@ -40,7 +40,7 @@ fr:
notice_folder_deleted: Dossier supprimé
error_folder_is_not_empty: "Le dossier n'est pas vide"
error_folder_title_is_already_used: Le titre du fichier est déjà utilisé
notice_folder_details_were_saved: Les détails du dossier ont été enregistrés
notice_folder_details_were_saved: Les détails du dossier ont été enregistrés
error_folder_is_locked: Le dossier est verrouillé
error_file_is_locked: Le fichier est verrouillé
notice_file_deleted: Le fichier a été supprimé
@ -50,6 +50,7 @@ fr:
notice_file_unlocked: Fichier déverrouillé
notice_file_revision_created: La révision du fichier a été ajoutée
notice_your_preferences_were_saved: Vos paramètres ont été enregistrés
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: Les notifications du dossier sont déjà activées
notice_folder_notifications_activated: Les notifications du dossier ont été activées
warning_folder_notifications_already_deactivated: Les notifications du dossier sont déjà désactivées
@ -107,6 +108,8 @@ fr:
select_option_default: Défaut
select_option_deactivated: Désactivé
select_option_activated: Activé
label_title_format: Title format
text_title_format: "Document title format for download (%t - title, %d - date, %v- version, %i - ID, %r - revision). Example: %t_%v"
title_save_preferences: Enregistrer les préférences
heading_revisions: Révisions
title_download: Télécharger

View File

@ -40,7 +40,7 @@ ja:
notice_folder_deleted: フォルダを削除しました
error_folder_is_not_empty: フォルダが空ではありません
error_folder_title_is_already_used: タイトルは既に使われています
notice_folder_details_were_saved: フォルダの詳細を保存しました
notice_folder_details_were_saved: フォルダの詳細を保存しました
error_folder_is_locked: Folder is locked
error_file_is_locked: ファイルはロックされています
notice_file_deleted: ファイルを削除しました
@ -50,6 +50,7 @@ ja:
notice_file_unlocked: ファイルをロック解除しました
notice_file_revision_created: ファイルのリビジョンを作成しました
notice_your_preferences_were_saved: あなたの設定を保存しました
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: フォルダ通知は既に有効です
notice_folder_notifications_activated: フォルダ通知を有効にしました
warning_folder_notifications_already_deactivated: フォルダ通知は既に無効です
@ -107,6 +108,8 @@ ja:
select_option_default: 既定値
select_option_deactivated: 無効
select_option_activated: 有効
label_title_format: Title format
text_title_format: "Document title format for download (%t - title, %d - date, %v- version, %i - ID, %r - revision). Example: %t_%v"
title_save_preferences: 設定を保存します
heading_revisions: リビジョン
title_download: ダウンロードします

View File

@ -40,7 +40,7 @@ pl:
error_folder_title_must_be_entered: Musisz podać tytuł
notice_folder_deleted: Folder został usunięty
error_folder_is_not_empty: Folder zawiera pliki
error_folder_title_is_already_used: Podany tytuł jest już w użyciu
error_folder_title_is_already_used: Podany tytuł jest już w użyciu
notice_folder_details_were_saved: Szczegóły folderu zostały zapisane
error_folder_is_locked: Folder jest zablokowany
error_file_is_locked: Plik jest zablokowany
@ -51,6 +51,7 @@ pl:
notice_file_unlocked: Plik odblokowany
notice_file_revision_created: Utworzono wersję pliku
notice_your_preferences_were_saved: Twoje preferencje zostały zapisane
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: Powiadomienia dla folderu zostały już aktywowane
notice_folder_notifications_activated: Aktywowano powiadomienia dla folderu
warning_folder_notifications_already_deactivated: Powiadomienia dla folderu zostały już wyłączone
@ -107,6 +108,8 @@ pl:
label_notifications: Powiadomienia
select_option_default: Domyślny
select_option_deactivated: Wyłączono
label_title_format: Title format
text_title_format: "Document title format for download (%t - title, %d - date, %v- version, %i - ID, %r - revision). Example: %t_%v"
select_option_activated: Aktywowano
title_save_preferences: Zapisz ustawienia
heading_revisions: Wersje

View File

@ -40,7 +40,7 @@ pt-BR:
notice_folder_deleted: Pasta deletada
error_folder_is_not_empty: Pasta não está vazia
error_folder_title_is_already_used: Título já utilizado
notice_folder_details_were_saved: Pasta atualizada
notice_folder_details_were_saved: Pasta atualizada
error_folder_is_locked: Pasta está bloqueada
error_file_is_locked: Arquivo está bloqueado
notice_file_deleted: Arquivo excluído
@ -50,6 +50,7 @@ pt-BR:
notice_file_unlocked: Arquivo desbloqueado
notice_file_revision_created: Revisão do arquivo criado
notice_your_preferences_were_saved: Suas atualizações foram salvas
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: Notificações de pasta atualizadas
notice_folder_notifications_activated: Notificações da pasta ativas
warning_folder_notifications_already_deactivateNd: Notificações da pasta desativadas
@ -107,6 +108,8 @@ pt-BR:
select_option_default: Padrão
select_option_deactivated: Desativado
select_option_activated: Ativado
label_title_format: Title format
text_title_format: "Document title format for download (%t - title, %d - date, %v- version, %i - ID, %r - revision). Example: %t_%v"
title_save_preferences: Salvar preferências
heading_revisions: Revisões
title_download: Download

View File

@ -40,7 +40,7 @@ ru:
notice_folder_deleted: Папка удалена
error_folder_is_not_empty: Папка не пустая
error_folder_title_is_already_used: Название папки уже используется
notice_folder_details_were_saved: Описание папки было сохранено
notice_folder_details_were_saved: Описание папки было сохранено
error_folder_is_locked: Папка заблокированa
error_file_is_locked: Файл заблокирован
notice_file_deleted: Файл удален
@ -50,6 +50,7 @@ ru:
notice_file_unlocked: Файл разблокирован
notice_file_revision_created: Редакция файла создана
notice_your_preferences_were_saved: Ваши настройки были сохранены
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: Уведомления папки уже включены
notice_folder_notifications_activated: Уведомления папки включены
warning_folder_notifications_already_deactivated: Уведомления папки уже отключены
@ -107,6 +108,8 @@ ru:
select_option_default: По умолчанию
select_option_deactivated: Отключено
select_option_activated: Включено
label_title_format: Title format
text_title_format: "Document title format for download (%t - title, %d - date, %v- version, %i - ID, %r - revision). Example: %t_%v"
title_save_preferences: Сохранить настройки
heading_revisions: Редакции
title_download: Скачать

View File

@ -40,7 +40,7 @@ sl:
notice_folder_deleted: Mapa izbrisana
error_folder_is_not_empty: Mapa ni prazna
error_folder_title_is_already_used: Naslov je že uporabljen
notice_folder_details_were_saved: Podatki o mapi so shranjeni
notice_folder_details_were_saved: Podatki o mapi so shranjeni
error_folder_is_locked: Папка заблокированa
error_file_is_locked: Mapa je zaklenjena
notice_file_deleted: Datoteka izbrisana
@ -50,6 +50,7 @@ sl:
notice_file_unlocked: Datoteka odklenjena
notice_file_revision_created: Verzija datoteke kreirana
notice_your_preferences_were_saved: Vaše nastavitve so shranjene
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: Obveščanje o mapi je že aktivno
notice_folder_notifications_activated: Obveščanje o mapi je aktivirano
warning_folder_notifications_already_deactivated: Obveščanje o mapi je že neaktivno
@ -107,6 +108,8 @@ sl:
select_option_default: Privzeto
select_option_deactivated: Deaktivirano
select_option_activated: Aktivirano
label_title_format: Title format
text_title_format: "Document title format for download (%t - title, %d - date, %v- version, %i - ID, %r - revision). Example: %t_%v"
title_save_preferences: Save preferences
heading_revisions: Verzije
title_download: Prenesi dol

View File

@ -40,7 +40,7 @@ zh-TW:
notice_folder_deleted: 資料夾己刪除
error_folder_is_not_empty: 資料夾尚未清空
error_folder_title_is_already_used: 標題己經被使用了
notice_folder_details_were_saved: 資料夾描述己儲存
notice_folder_details_were_saved: 資料夾描述己儲存
error_folder_is_locked: 資料夾己經鎖定
error_file_is_locked: 檔案己經被鎖定了
notice_file_deleted: 檔案己經被刪除了
@ -50,6 +50,7 @@ zh-TW:
notice_file_unlocked: 檔案己經解除鎖定
notice_file_revision_created: 檔案修訂版本己建立
notice_your_preferences_were_saved: 您的偏好設定己經儲存
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: 資料夾通知己經啟用了
notice_folder_notifications_activated: 資料夾通知啟用了
warning_folder_notifications_already_deactivated: 資料夾通知己經關閉了
@ -107,6 +108,8 @@ zh-TW:
select_option_default: 預設
select_option_deactivated: 關閉
select_option_activated: 啟用
label_title_format: Title format
text_title_format: "Document title format for download (%t - title, %d - date, %v- version, %i - ID, %r - revision). Example: %t_%v"
title_save_preferences: 儲存偏好設定
heading_revisions: 修訂版本
title_download: 下載

View File

@ -50,6 +50,7 @@ zh:
notice_file_unlocked: 文件解锁
notice_file_revision_created: 文件修订版本已创建
notice_your_preferences_were_saved: 您的偏好设定已保存
notice_your_preferences_were_not_saved: Your preferences were not saved
warning_folder_notifications_already_activated: 文件夹通知已激活
notice_folder_notifications_activated: 文件夹通知激活
warning_folder_notifications_already_deactivated: 文件夹通知已注销
@ -108,6 +109,8 @@ zh:
select_option_deactivated: 注销
select_option_activated: 激活
title_save_preferences: 保存偏好设定
label_title_format: Title format
text_title_format: "Document title format for download (%t - title, %d - date, %v- version, %i - ID, %r - revision). Example: %t_%v"
heading_revisions: 修订版本
title_download: 下载
title_delete_revision: 删除此修订

View File

@ -49,7 +49,7 @@ RedmineApp::Application.routes.draw do
# dmsf_state controller
# /projects/<project>/dmsf/state
##
post '/projects/:id/dmsf/state', :controller => 'dmsf_state', :action => 'user_pref_save'
post '/projects/:id/dmsf/state', :controller => 'dmsf_state', :action => 'user_pref_save', :as => 'dmsf_user_pref_save'
#
# dmsf_upload controller

View File

@ -0,0 +1,29 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
#
# 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 LargeFiles < ActiveRecord::Migration
def up
change_column :dmsf_file_revisions, :size, :bigint, :null => true
end
def down
change_column :dmsf_file_revisions, :size, :int, :null => true
end
end

View File

@ -0,0 +1,29 @@
# encoding: utf-8
#
# Redmine plugin for Document Management System "Features"
#
# Copyright (C) 2015 Karel Pičman <karel.picman@kontorn.com>
#
# 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 TitleFormat < ActiveRecord::Migration
def self.up
add_column :members, :title_format, :text, :null => true, :limit => 100
end
def self.down
remove_column :members, :title_format
end
end

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -29,8 +29,8 @@
# Redmine installation directory
$redmine_root = '/opt/redmine'
# Files location
$files = 'files'
# DMSF document location $redmine_root/$files
$files = 'dmsf'
# scriptindex binary path
$scriptindex = '/usr/bin/scriptindex'
@ -39,18 +39,18 @@ $scriptindex = '/usr/bin/scriptindex'
$omindex = '/usr/bin/omindex'
# Directory containing xapian databases for omindex (Attachments indexing)
$dbrootpath = '/var/tmp/omindex'
$dbrootpath = '/var/tmp/dmsf-index'
# Verbose output, values of 0 no verbose, greater than 0 verbose output
$verbose = 0
# Define stemmed languages to index attachments Ej [ 'english', 'italian', 'spanish' ]
# Define stemmed languages to index attachments Eg. [ 'english', 'italian', 'spanish' ]
# Repository database will be always indexed in english
# Available languages are danish dutch english finnish french german german2 hungarian italian kraaij_pohlmann lovins norwegian porter portuguese romanian russian spanish swedish turkish:
$stem_langs = ['english']
# Project identifiers that will be indexed eg. [ 'prj_id1', 'prj_id2' ]
projects = [ 'prj_id1', 'prj_id2' ]
$projects = [ 'prj_id1', 'prj_id2' ]
# Temporary directory for indexing, it can be tmpfs
$tempdir = '/tmp'
@ -69,7 +69,7 @@ $unrtf = '/usr/bin/unrtf -t text 2>/dev/null'
################################################################################################
$environment = File.join($redmine_root, 'config/environment.rb')
$project = nil
$projects = Array.new
$databasepath = nil
$repositories = nil
$onlyfiles = nil
@ -120,7 +120,7 @@ optparse = OptionParser.new do |opts|
opts.separator('')
opts.separator('')
opts.separator('Options:')
opts.on('-p', '--projects a,b,c', Array, 'Comma separated list of projects to index') { |p| projects = p }
opts.on('-p', '--projects a,b,c', Array, 'Comma separated list of projects to index') { |p| $projects = p }
opts.on('-s', '--stemming_lang a,b,c', Array,'Comma separated list of stemming languages for indexing') { |s| $stem_langs = s }
opts.on('-v', '--verbose', 'verbose') {$verbose += 1}
opts.on('-f', '--files', 'Only index Redmine attachments') { $onlyfiles = 1 }
@ -155,15 +155,14 @@ def repo_name(repository)
end
def indexing(databasepath, project, repository)
Rails.logger.info("Fetch changesets: #{project.name} - #{repo_name(repository)}")
log("- Fetch changesets: #{project.name} - #{repo_name(repository)}", :level => 1)
log "Fetch changesets: #{project.name} - #{repo_name(repository)}"
repository.fetch_changesets
repository.reload.changesets.reload
latest_changeset = repository.changesets.first
return if not latest_changeset
return unless latest_changeset
Rails.logger.debug("Latest revision: #{project.name} - #{repo_name(repository)} - #{latest_changeset.revision}")
log "Latest revision: #{project.name} - #{repo_name(repository)} - #{latest_changeset.revision}"
latest_indexed = Indexinglog.where(:repository_id => repository.id, :status => STATUS_SUCCESS).last
Rails.logger.debug "Debug latest_indexed #{latest_indexed.inspect}"
begin
@ -172,13 +171,11 @@ def indexing(databasepath, project, repository)
indexconf.write "body : index truncate=400 field=sample\n"
indexconf.write "date: field=date\n"
indexconf.close
if not latest_indexed
Rails.logger.debug "Repository #{repo_name(repository)} not indexed, indexing all"
log("\t>repo #{repo_name(repository)} not indexed, indexing all", :level => 1)
unless latest_indexed
log "Repository #{repo_name(repository)} not indexed, indexing all"
indexing_all(databasepath, indexconf, project, repository)
else
Rails.logger.debug "Repository #{repo_name(repository)} indexed, indexing diff"
log("\t>repo #{repo_name(repository)} already indexed, indexing only diff", :level => 1)
log "Repository #{repo_name(repository)} indexed, indexing diff"
indexing_diff(databasepath, indexconf, project, repository,
latest_indexed.changeset, latest_changeset)
end
@ -187,7 +184,7 @@ def indexing(databasepath, project, repository)
add_log(repository, latest_changeset, STATUS_FAIL, e.message)
else
add_log(repository, latest_changeset, STATUS_SUCCESS)
Rails.logger.info("Successfully indexed: #{project.name} - #{repo_name(repository)} - #{latest_changeset.revision}")
log "Successfully indexed: #{project.name} - #{repo_name(repository)} - #{latest_changeset.revision}"
end
end
@ -200,22 +197,20 @@ end
def add_log(repository, changeset, status, message = nil)
log = Indexinglog.where(:repository_id => repository.id).last
if not log
unless log
log = Indexinglog.new
log.repository = repository
log.changeset = changeset
log.status = status
log.message = message if message
log.save!
Rails.logger.info "New log for repo #{repo_name(repository)} saved!"
log("\t>New log for repo #{repo_name(repository)} saved!", :level => 1)
log "New log for repo #{repo_name(repository)} saved!"
else
log.changeset_id=changeset.id
log.status=status
log.message = message if message
log.save!
Rails.logger.info "Log for repo #{repo_name(repository)} updated!"
log("\t>Log for repo #{repo_name(repository)} updated!", :level => 1)
log "Log for repo #{repo_name(repository)} updated!"
end
end
@ -226,22 +221,20 @@ def update_log(repository, changeset, status, message = nil)
log.status = status if status
log.message = message if message
log.save!
Rails.logger.info("Log for repo #{repo_name(repository)} updated!")
log("\t>Log for repo #{repo_name(repository)} updated!", :level => 1)
log "Log for repo #{repo_name(repository)} updated!"
end
end
def delete_log(repository)
Indexinglog.delete_all(:repository_id => repository.id)
Rails.logger.info("Log for repo #{repo_name(repository)} removed!")
log("\t>Log for repo #{repo_name(repository)} removed!", :level => 1)
log "Log for repo #{repo_name(repository)} removed!"
end
def walk(databasepath, indexconf, project, repository, identifier, entries)
return if entries.nil? || entries.size < 1
Rails.logger.debug "Walk entries size: #{entries.size}"
log "Walk entries size: #{entries.size}"
entries.each do |entry|
Rails.logger.debug "Walking into: #{entry.lastrev.time}"
log "Walking into: #{entry.lastrev.time}"
if entry.is_dir?
walk(databasepath, indexconf, project, repository, identifier, repository.entries(entry.path, identifier))
elsif entry.is_file?
@ -255,24 +248,24 @@ def indexing_all(databasepath, indexconf, project, repository)
Rails.logger.info "Indexing all: #{repo_name(repository)}"
if repository.branches
repository.branches.each do |branch|
Rails.logger.debug "Walking in branch: #{repo_name(repository)} - #{branch}"
log "Walking in branch: #{repo_name(repository)} - #{branch}"
walk(databasepath, indexconf, project, repository, branch, repository.entries(nil, branch))
end
else
Rails.logger.debug "Walking in branch: #{repo_name(repository)} - [NOBRANCH]"
log "Walking in branch: #{repo_name(repository)} - [NOBRANCH]"
walk(databasepath, indexconf, project, repository, nil, repository.entries(nil, nil))
end
if repository.tags
repository.tags.each do |tag|
Rails.logger.debug "Walking in tag: #{repo_name(repository)} - #{tag}"
log "Walking in tag: #{repo_name(repository)} - #{tag}"
walk(databasepath, indexconf, project, repository, tag, repository.entries(nil, tag))
end
end
end
def walkin(databasepath, indexconf, project, repository, identifier, changesets)
Rails.logger.debug "Walking into #{changesets.inspect}"
return if not changesets or changesets.size <= 0
log "Walking into #{changesets.inspect}"
return unless changesets or changesets.size <= 0
changesets.sort! { |a, b| a.id <=> b.id }
actions = Hash::new
@ -282,7 +275,7 @@ def walkin(databasepath, indexconf, project, repository, identifier, changesets)
# * R - Replaced
# * D - Deleted
changesets.each do |changeset|
Rails.logger.debug "Changeset changes for #{changeset.id} #{changeset.filechanges.inspect}"
log "Changeset changes for #{changeset.id} #{changeset.filechanges.inspect}"
next unless changeset.filechanges
changeset.filechanges.each do |change|
actions[change.path] = (change.action == 'D') ? DELETE : ADD_OR_UPDATE
@ -292,9 +285,8 @@ def walkin(databasepath, indexconf, project, repository, identifier, changesets)
actions.each do |path, action|
entry = repository.entry(path, identifier)
if ((!entry.nil? && entry.is_file?) || action == DELETE)
log("Error indexing path: #{path.inspect}, action: #{action.inspect}, identifier: #{identifier.inspect}",
:level => 1) if (entry.nil? && action != DELETE)
Rails.logger.debug "Entry to index #{entry.inspect}"
log("Error indexing path: #{path.inspect}, action: #{action.inspect}, identifier: #{identifier.inspect}", true) if (entry.nil? && action != DELETE)
log "Entry to index #{entry.inspect}"
lastrev = entry.lastrev unless entry.nil?
add_or_update_index(databasepath, indexconf, project, repository,
identifier, path, lastrev, action, MIME_TYPES[Redmine::MimeType.of(path)]) if(supported_mime_type(path) || action == DELETE)
@ -304,28 +296,27 @@ def walkin(databasepath, indexconf, project, repository, identifier, changesets)
def indexing_diff(databasepath, indexconf, project, repository, diff_from, diff_to)
if diff_from.id >= diff_to.id
Rails.logger.info "Already indexed: #{repo_name(repository)} (from: #{diff_from.id} to #{diff_to.id})"
log("\t>Already indexed: #{repo_name(repository)} (from #{diff_from.id} to #{diff_to.id})", :level => 1)
log "Already indexed: #{repo_name(repository)} (from: #{diff_from.id} to #{diff_to.id})"
return
end
Rails.logger.info "Indexing diff: #{repo_name(repository)} (from: #{diff_from.id} to #{diff_to.id})"
Rails.logger.info "Indexing all: #{repo_name(repository)}"
log "Indexing diff: #{repo_name(repository)} (from: #{diff_from.id} to #{diff_to.id})"
log "Indexing all: #{repo_name(repository)}"
if repository.branches
repository.branches.each do |branch|
Rails.logger.debug "Walking in branch: #{repo_name(repository)} - #{branch}"
log "Walking in branch: #{repo_name(repository)} - #{branch}"
walkin(databasepath, indexconf, project, repository, branch, repository.latest_changesets('', branch, diff_to.id - diff_from.id).select { |changeset|
changeset.id > diff_from.id and changeset.id <= diff_to.id})
end
else
Rails.logger.debug "Walking in branch: #{repo_name(repository)} - [NOBRANCH]"
log "Walking in branch: #{repo_name(repository)} - [NOBRANCH]"
walkin(databasepath, indexconf, project, repository, nil, repository.latest_changesets('', nil, diff_to.id - diff_from.id).select { |changeset|
changeset.id > diff_from.id and changeset.id <= diff_to.id})
end
if repository.tags
repository.tags.each do |tag|
Rails.logger.debug "Walking in tag: #{repo_name(repository)} - #{tag}"
log "Walking in tag: #{repo_name(repository)} - #{tag}"
walkin(databasepath, indexconf, project, repository, tag, repository.latest_changesets('', tag, diff_to.id - diff_from.id).select { |changeset|
changeset.id > diff_from.id and changeset.id <= diff_to.id})
end
@ -334,18 +325,13 @@ end
def generate_uri(project, repository, identifier, path)
return url_for(:controller => 'repositories',
:action => 'entry',
:id => project.identifier,
:repository_id => repository.identifier,
:rev => identifier,
:path => repository.relative_path(path),
:only_path => true)
end
def print_and_flush(str)
print str
$stdout.flush
end
:action => 'entry',
:id => project.identifier,
:repository_id => repository.identifier,
:rev => identifier,
:path => repository.relative_path(path),
:only_path => true)
end
def convert_to_text(fpath, type)
text = nil
@ -369,7 +355,7 @@ def convert_to_text(fpath, type)
text = File.read(fout)
FileUtils.rm_rf("#{$tempdir}/temp")
rescue Exception => e
log("\tError: #{e.to_s} reading #{fout}", :level => 1)
log "Error: #{e.to_s} reading #{fout}", true
end
else
text = "#{FORMAT_HANDLERS[type]} #{fpath}"
@ -394,13 +380,13 @@ def add_or_update_index(databasepath, indexconf, project, repository, identifier
text = convert_to_text("#{$tempdir}/#{fname}", type) if File.exists?("#{$tempdir}/#{fname}") and !bstr.nil?
File.unlink("#{$tempdir}/#{fname}")
end
log "generated uri: #{uri}", :lebel => 1
log('Mime type text', :level => 1) if Redmine::MimeType.is_type?('text', path)
log("\t>Indexing: #{path}", :level => 1)
log "generated uri: #{uri}"
log('Mime type text') if Redmine::MimeType.is_type?('text', path)
log "Indexing: #{path}"
begin
itext = Tempfile.new('filetoindex.tmp', $tempdir)
itext.write("url=#{uri.to_s}\n")
if action != DELETE then
if action != DELETE
sdate = lastrev.time || Time.at(0).in_time_zone
itext.write("date=#{sdate.to_s}\n")
body = nil
@ -414,24 +400,25 @@ def add_or_update_index(databasepath, indexconf, project, repository, identifier
end
end
else
log "Path: #{path} should be deleted", :level => 1
log "Path: #{path} should be deleted"
end
itext.close
log "TEXT #{itext.path} generated", :level => 1
log "Index command: #{$scriptindex} -s #{$user_stem_lang} #{databasepath} #{indexconf.path} #{itext.path}", :level => 1
log "TEXT #{itext.path} generated"
log "Index command: #{$scriptindex} -s #{$user_stem_lang} #{databasepath} #{indexconf.path} #{itext.path}"
system_or_raise("#{$scriptindex} -s english #{databasepath} #{indexconf.path} #{itext.path}")
itext.unlink
log 'New doc added to xapian database'
rescue Exception => e
log "Text not indexed beacause an error #{e.message}"
log "Text not indexed beacause an error #{e.message}", true
end
end
def log(text, options={})
level = options[:level] || 0
dtext = Time.now.asctime.to_s + ": #{text}"
puts dtext unless level > $verbose
exit 1 if options[:exit]
def log(text, error = false)
if error
$stderr.puts text
elsif $verbose > 0
$stdout.puts text
end
end
def system_or_raise(command)
@ -442,102 +429,88 @@ def system_or_raise(command)
end
end
def find_project(prt)
scope = Project.active.has_module(:repository)
project = nil
project = scope.find_by_identifier(prt)
Rails.logger.debug "Project found: #{project}"
raise ActiveRecord::RecordNotFound unless project
rescue ActiveRecord::RecordNotFound
log("- ERROR project #{prt} not found", :level => 1)
@project = project
def find_project(prt)
project = Project.active.has_module(:repository).find_by_identifier(prt)
if project
log "Project found: #{project}"
else
log "Project #{prt} not found", true
end
@project = project
end
def create_dir(path)
begin
Dir.mkdir path
sleep 1
rescue SystemCallError
return 1
end
return 0
end
log("- Trying to load Redmine environment <<#{$environment}>>...", :level => 1)
log "Trying to load Redmine environment <<#{$environment}>>..."
begin
require $environment
rescue LoadError
puts "\n\tRedmine #{$environment} cannot be loaded!! Be sure the redmine installation directory is correct!\n"
puts "\tEdit script and correct path\n\n"
log "Redmine #{$environment} cannot be loaded!! Be sure the redmine installation directory is correct!", true
log 'Edit script and correct path', true
exit 1
end
include Rails.application.routes.url_helpers
log("- Redmine environment [RAILS_ENV=#{$env}] correctly loaded ...", :level => 1)
if $test
log('- Running in test mode ...')
end
log "Redmine environment [RAILS_ENV=#{$env}] correctly loaded ..."
# Indexing files
if not $onlyrepos then
if not File.exist?($omindex) then
log("- ERROR! #{$omindex} does not exist, exiting...")
unless $onlyrepos
unless File.exist?($omindex)
log "#{$omindex} does not exist, exiting...", true
exit 1
end
$stem_langs.each do | lang |
filespath = File.join($redmine_root, $files)
if not File.directory?(filespath) then
log("- ERROR accessing #{filespath}, exiting...")
unless File.directory?(filespath)
log "An error while accessing #{filespath}, exiting...", true
exit 1
end
dbpath = File.join($dbrootpath,lang)
if not File.directory?(dbpath)
log("- #{dbpath} does not exist, creating ...")
if not create_dir(dbpath) then
log("- ERROR! #{dbpath} can not be created!, exiting...")
databasepath = File.join($dbrootpath, lang)
unless File.directory?(databasepath)
log "#{databasepath} does not exist, creating ..."
begin
FileUtils.mkdir_p databasepath
rescue Exception => e
log e.message, true
exit 1
end
end
log("- Indexing files under #{filespath} with omindex stemming in #{lang} ...", :level => 1)
system_or_raise ("#{$omindex} -s #{lang} --db #{dbpath} #{filespath} --url / > /dev/null")
end
end
cmd = "#{$omindex} -s #{lang} --db #{databasepath} #{filespath} --url /"
cmd << ' -v' if $verbose > 0
log cmd
system_or_raise (cmd)
end
log('- Redmine files indexed ...', :level => 1)
log 'Redmine files indexed'
end
# Indexing repositories
if not $onlyfiles then
if not File.exist?($scriptindex) then
log("- ERROR! #{$scriptindex} does not exist, exiting...")
unless $onlyfiles
unless File.exist?($scriptindex)
log "#{$scriptindex} does not exist, exiting...", true
exit 1
end
databasepath = File.join($dbrootpath.rstrip, 'repodb')
log(databasepath)
if not File.directory?(databasepath)
log("- Db directory #{databasepath} does not exist, creating...")
databasepath = File.join($dbrootpath.rstrip, 'repodb')
unless File.directory?(databasepath)
log "Db directory #{databasepath} does not exist, creating..."
begin
Dir.mkdir(databasepath)
sleep 1
rescue SystemCallError
log("- ERROR! #{databasepath} can not be created!, exiting ...")
FileUtils.mkdir_p databasepath
rescue Exception => e
log e.message, true
exit 1
end
end
end
projects.each do |identifier|
$projects.each do |identifier|
begin
project = Project.active.has_module(:repository).where(:identifier => identifier).preload(:repository).first
raise ActiveRecord::RecordNotFound unless project
log("- Indexing repositories for #{project.name}...", :level => 1)
log "Indexing repositories for #{project.name}..."
repositories = project.repositories.select { |repository| repository.supports_cat? }
repositories.each do |repository|
delete_log(repository) if ($resetlog)
indexing(databasepath, project, repository)
end
rescue ActiveRecord::RecordNotFound
log("- WARNING project identifier #{identifier} not found or repository module not enabled, ignoring...", :level => 1)
Rails.logger.error "Project identifier #{identifier} not found"
log "Project identifier #{identifier} not found or repository module not enabled, ignoring..."
end
end
end

24
init.rb
View File

@ -4,7 +4,7 @@
#
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright (C) 2011-15 Karel Pičman <karel.picman@kontron.com>
# Copyright (C) 2011-16 Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -26,9 +26,9 @@ require 'zip'
Redmine::Plugin.register :redmine_dmsf do
name 'DMSF'
author 'Vit Jonas / Daniel Munn / Karel Picman'
author 'Vít Jonáš / Daniel Munn / Karel Pičman'
description 'Document Management System Features'
version '1.5.5'
version '1.5.6'
url 'http://www.redmine.org/plugins/dmsf'
author_url 'https://github.com/danmunn/redmine_dmsf/graphs/contributors'
@ -53,6 +53,9 @@ Redmine::Plugin.register :redmine_dmsf do
Redmine::Activity.register :dmsf_file_revision_accesses, :default => false
Redmine::Activity.register :dmsf_file_revisions
# Uncomment to remove the original Documents from searching (replaced with DMSF)
# Redmine::Search.available_search_types.delete('documents')
project_module :dmsf do
permission :view_dmsf_file_revision_accesses,
:read => true
@ -144,7 +147,20 @@ Redmine::Plugin.register :redmine_dmsf do
raise ArgumentError if args.length < 1 # Requires file id
file = DmsfFile.visible.find args[0].strip
if User.current && User.current.allowed_to?(:view_dmsf_files, file.project)
return file.description
return textilizable(file.description)
else
raise l(:notice_not_authorized)
end
end
desc "Wiki link to DMSF document's content preview:\n\n" +
"{{dmsft(file_id)}}\n\n" +
"_file_id_ can be found in the link for file/revision download."
macro :dmsft do |obj, args|
raise ArgumentError if args.length < 2 # Requires file id and lines number
file = DmsfFile.visible.find args[0].strip
if User.current && User.current.allowed_to?(:view_dmsf_files, file.project)
return file.preview(args[1].strip).gsub("\n", '<br/>').html_safe
else
raise l(:notice_not_authorized)
end

View File

@ -39,10 +39,10 @@ class DmsfZip
@zip.close if @zip
end
def add_file(file, root_path = nil)
def add_file(file, member, root_path = nil)
string_path = file.folder.nil? ? '' : "#{file.folder.dmsf_path_str}/"
string_path = string_path[(root_path.length + 1) .. string_path.length] if root_path
string_path += file.name
string_path = string_path[(root_path.length + 1) .. string_path.length] if root_path
string_path += file.formatted_name(member ? member.title_format : nil)
@zip_file.put_next_entry(string_path)
File.open(file.last_revision.disk_file, 'rb') do |f|
while (buffer = f.read(8192))
@ -52,12 +52,12 @@ class DmsfZip
@files << file
end
def add_folder(folder, root_path = nil)
def add_folder(folder, member, root_path = nil)
string_path = "#{folder.dmsf_path_str}/"
string_path = string_path[(root_path.length + 1) .. string_path.length] if root_path
@zip_file.put_next_entry(string_path)
folder.subfolders.visible.each { |subfolder| self.add_folder(subfolder, root_path) }
folder.files.visible.each { |file| self.add_file(file, root_path) }
folder.files.visible.each { |file| self.add_file(file, member, root_path) }
end
end

View File

@ -39,15 +39,23 @@ class DmsfConvertDocuments
dry = options[:dry] ? options[:dry] == 'true' : false
replace = options[:invalid] ? options[:invalid] == 'replace' : false
projects = options[:project] ? [Project.find(options[:project])] : Project.find(:all)
projects = options[:project] ? [Project.find(options[:project])] : Project.active.to_a
projects.reject! {|project| project.module_enabled?('dmsf') }
projects.reject! {|project| !project.module_enabled?('documents') }
unless projects.nil? || projects.empty?
if projects
prjs = projects.reject {|project| project.module_enabled?('dmsf') }
diff = (projects - prjs)
if diff.count > 0
puts "Projects skipped due to already enabled module DMSF: #{diff.collect{|p| p.name }.join(' ,')}"
end
projects = prjs.reject {|project| !project.module_enabled?('documents') }
diff = (prjs - projects)
if diff.count > 0
puts "Projects skipped due to not enabled module Documents: #{diff.collect{|p| p.name }.join(' ,')}"
end
projects.each do |project|
puts "Processing project: #{project.identifier}"
puts "Processing project: #{project}"
project.enabled_module_names = (project.enabled_module_names << 'dmsf').uniq unless dry
project.save! unless dry
@ -55,22 +63,22 @@ class DmsfConvertDocuments
folders = []
project.documents.each do |document|
puts "Processing document: #{document.title}"
folder = DmsfFolder.new
folder.project = project
folder.user = (a = document.attachments.find(:first, :order => 'created_on ASC')) ? a.author : User.find(:first)
folder.project = project
folder.user = document.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author)
folder.title = document.title
folder.title.gsub!(/[\/\\\?":<>]/, '-') if replace
i = 1
suffix = ''
while folders.index{|f| f.title == (folder.title + suffix)}
i+=1
suffix = "_#{i}"
end
folder.title = folder.title + suffix
folder.description = document.description
@ -90,44 +98,44 @@ class DmsfConvertDocuments
next
end
end
folders << folder;
files = []
document.attachments.each do |attachment|
begin
file = DmsfFile.new
file.project = project
file.folder = folder
file.name = attachment.filename
i = 1
suffix = ""
suffix = ''
while files.index{|f| f.name == (DmsfFileRevision.remove_extension(file.name) + suffix + File.extname(file.name))}
i+=1
suffix = "_#{i}"
end
# Need to save file first to generate id for it in case of creation.
# File id is needed to properly generate revision disk filename
file.name = DmsfFileRevision.remove_extension(file.name) + suffix + File.extname(file.name)
unless File.exist?(attachment.diskfile)
puts "Creating file: #{attachment.filename} failed, attachment file #{attachment.diskfile} doesn't exist"
fail = true
next
end
if dry
file.id = attachment.id # Just to have an ID there
puts "Dry check file: #{file.name}"
if file.invalid?
file.errors.each {|e,msg| puts "#{e}: #{msg}"}
file.errors.each {|e, msg| puts "#{e}: #{msg}"}
end
else
file.save!
end
revision = DmsfFileRevision.new
revision.file = file
revision.name = file.name
@ -140,27 +148,27 @@ class DmsfConvertDocuments
revision.minor_version = 1
revision.comment = 'Converted from documents'
revision.mime_type = attachment.content_type
revision.disk_filename = revision.new_storage_filename
unless dry
FileUtils.cp(attachment.diskfile, revision.disk_file)
revision.size = File.size(revision.disk_file)
end
if dry
puts "Dry check revision: #{revision.title}"
if revision.invalid?
revision.errors.each {|e,msg| puts "#{e}: #{msg}"}
revision.errors.each {|e, msg| puts "#{e}: #{msg}"}
end
else
revision.save!
end
files << file
attachment.destroy unless dry
puts "Created file: #{file.name}" unless dry
rescue Exception => e
puts "Creating file: #{attachment.filename} failed"
@ -168,13 +176,13 @@ class DmsfConvertDocuments
fail = true
end
end
document.destroy unless dry || fail
end
project.enabled_module_names = project.enabled_module_names.reject {|mod| mod == 'documents'} unless dry || fail
project.save! unless dry
end
end
end
end