Zeitwerk autoload

This commit is contained in:
Karel Pičman 2022-05-17 09:05:37 +02:00
parent cc112e64c1
commit aa13e70cd7
25 changed files with 132 additions and 80 deletions

View File

@ -1,7 +1,7 @@
Redmine DMSF Plugin
===================
The current version of Redmine DMSF is **3.0.0**
The current version of Redmine DMSF is **3.0.1 devel**
[![pipeline status](https://gitlab.kontron.com/redmine-plugins/redmine_dmsf/badges/master/pipeline.svg)](https://gitlab.kontron.com/redmine-plugins/redmine_dmsf/pipelines/master/latest)
[![Support Ukraine Badge](https://bit.ly/support-ukraine-now)](https://github.com/support-ukraine/support-ukraine)
@ -241,7 +241,7 @@ You can either clone the master branch or download the latest zipped version. Be
`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 restart apache2`
7. You should configure the plugin via Redmine interface: Administration -> Plugins -> DMSF -> Configure.
7. You should configure the plugin via Redmine interface: Administration -> Plugins -> DMSF -> Configure. (You should check and then save the plugin's configuration after each upgrade.)
8. Don't forget to grant permissions for DMSF in Administration -> Roles and permissions
9. Assign DMSF permissions to appropriate roles.
10. There are a few rake tasks:

View File

@ -22,7 +22,11 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'zip'
require File.dirname(__FILE__) + '/lib/redmine_dmsf'
# All files in lib sub-folder are already loaded by Zeitwerk
if RedmineApp::Application.config.autoloader != :zeitwerk
require File.dirname(__FILE__) + '/lib/redmine_dmsf'
end
def dmsf_init
# Administration menu extension

View File

@ -648,8 +648,8 @@ class DmsfController < ApplicationController
recipients = DmsfMailer.deliver_files_deleted(@project, deleted_files)
if Setting.plugin_redmine_dmsf['dmsf_display_notified_recipients']
if recipients.any?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
to = recipients.collect{ |r| r.name }.first(Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i).join(', ')
to << ((recipients.count > Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i) ? ',...' : '.')
flash[:warning] = l(:warning_email_notifications, to: to)
end
end

View File

@ -167,8 +167,8 @@ class DmsfFilesController < ApplicationController
recipients = DmsfMailer.deliver_files_updated(@project, [@file])
if Setting.plugin_redmine_dmsf['dmsf_display_notified_recipients']
if recipients.any?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
to = recipients.collect{ |r| r.name }.first(Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i).join(', ')
to << ((recipients.count > Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i) ? ',...' : '.')
end
end
rescue => e
@ -203,8 +203,8 @@ class DmsfFilesController < ApplicationController
recipients = DmsfMailer.deliver_files_deleted(@project, [@file])
if Setting.plugin_redmine_dmsf['dmsf_display_notified_recipients']
if recipients.any?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
to = recipients.collect{ |r| r.name }.first(Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i).join(', ')
to << ((recipients.count > Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i) ? ',...' : '.')
flash[:warning] = l(:warning_email_notifications, to: to)
end
end

View File

@ -87,8 +87,8 @@ class DmsfWorkflowsController < ApplicationController
:text_email_to_see_history)
if Setting.plugin_redmine_dmsf['dmsf_display_notified_recipients']
unless recipients.blank?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
to = recipients.collect{ |r| r.name }.first(Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i).join(', ')
to << ((recipients.count > Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i) ? ',...' : '.')
flash[:warning] = l(:warning_email_notifications, to: to)
end
end
@ -110,8 +110,8 @@ class DmsfWorkflowsController < ApplicationController
action.note)
if Setting.plugin_redmine_dmsf['dmsf_display_notified_recipients']
unless recipients.blank?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
to = recipients.collect{ |r| r.name }.first(Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i).join(', ')
to << ((recipients.count > Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i) ? ',...' : '.')
flash[:warning] = l(:warning_email_notifications, to: to)
end
end
@ -176,8 +176,8 @@ class DmsfWorkflowsController < ApplicationController
recipients = recipients & DmsfMailer.get_notify_users(@project, revision.dmsf_file,
true)
unless recipients.empty?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
to = recipients.collect{ |r| r.name }.first(Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i).join(', ')
to << ((recipients.count > Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i) ? ',...' : '.')
flash[:warning] = l(:warning_email_notifications, to: to)
end
end

View File

@ -133,8 +133,8 @@ module DmsfUploadHelper
recipients = DmsfMailer.deliver_files_updated(project, files)
if Setting.plugin_redmine_dmsf['dmsf_display_notified_recipients']
unless recipients.empty?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
to = recipients.collect{ |r| r.name }.first(Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i).join(', ')
to << ((recipients.count > Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i) ? ',...' : '.')
controller.flash[:warning] = l(:warning_email_notifications, to: to) if controller
end
end

View File

@ -223,8 +223,8 @@ class DmsfWorkflow < ActiveRecord::Base
assignments.first&.dmsf_workflow_step)
if Setting.plugin_redmine_dmsf['dmsf_display_notified_recipients'] && controller
unless recipients.blank?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
to << ((recipients.count > DMSF_MAX_NOTIFICATION_RECEIVERS_INFO) ? ',...' : '.')
to = recipients.collect{ |r| r.name }.first(Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i).join(', ')
to << ((recipients.count > Setting.plugin_redmine_dmsf['dmsf_max_notification_receivers_info'].to_i) ? ',...' : '.')
controller.flash[:warning] = l(:warning_email_notifications, to: to)
end
end

View File

@ -34,6 +34,15 @@
</em>
</p>
<p>
<%= content_tag :label, l(:label_dmsf_max_notification_receivers_info) %>
<% @settings['dmsf_max_notification_receivers_info'] ||= 10 %>
<%= text_field_tag 'settings[dmsf_max_notification_receivers_info]', @settings['dmsf_max_notification_receivers_info'], size: 10 %>
<em class="info">
<%= l(:note_dmsf_max_notification_receivers_info) %> <%= l(:label_default) %>: 10
</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 %>

View File

@ -443,6 +443,9 @@ cs:
label_dmsf_new_top_level_document: Nový kořenový DMS dokument
label_dmsf_new_top_level_folder: Nová kořenová DMS složka
label_dmsf_max_notification_receivers_info: Maximální počet zobrazených příjemců notifikace
note_dmsf_max_notification_receivers_info: Omezí maximální počet zobrazených příjemců e-mailové notifikace
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -439,6 +439,9 @@ de:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: Von mir gesperrte Dokumente

View File

@ -443,6 +443,9 @@ en:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -443,6 +443,9 @@ es:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -443,6 +443,9 @@ fr:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -442,6 +442,9 @@ hu:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -443,6 +443,9 @@ it: # Italian strings thx 2 Matteo Arceci!
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -444,6 +444,9 @@ ja:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: 自分がロック中の文書

View File

@ -443,6 +443,9 @@ ko:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: 내 잠긴 파일

View File

@ -443,6 +443,9 @@ nl:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -443,6 +443,9 @@ pl:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -443,6 +443,9 @@ pt-BR:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -443,6 +443,9 @@ sl:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -442,6 +442,9 @@ zh-TW:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -443,6 +443,9 @@ zh:
label_dmsf_new_top_level_document: New top level DMS document
label_dmsf_new_top_level_folder: New top level DMS folder
label_dmsf_max_notification_receivers_info: Maximum notification receivers info
note_dmsf_max_notification_receivers_info: Limits maximum number of displayed email notification receivers.
easy_pages:
modules:
dmsf_locked_documents: My locked documents

View File

@ -61,7 +61,8 @@ Redmine::Plugin.register :redmine_dmsf do
'dmsf_webdav_use_project_names' => Redmine::Plugin.installed?(:easy_extensions) ? '1' : nil,
'dmsf_webdav_ignore_1b_file_for_authentication' => '1',
'dmsf_projects_as_subfolders' => nil,
'only_approval_zero_minor_version' => '0'
'only_approval_zero_minor_version' => '0',
'dmsf_max_notification_receivers_info' => 10
}
end

View File

@ -21,72 +21,65 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
DMSF_MAX_NOTIFICATION_RECEIVERS_INFO = 10
# DMSF libraries
# All files in lib sub-folder are already loaded by Zeitwerk
if RedmineApp::Application.config.autoloader != :zeitwerk
# Validators
require File.dirname(__FILE__) + '/../app/validators/dmsf_file_name_validator'
require File.dirname(__FILE__) + '/../app/validators/dmsf_max_file_size_validator'
require File.dirname(__FILE__) + '/../app/validators/dmsf_workflow_name_validator'
require File.dirname(__FILE__) + '/../app/validators/dmsf_url_validator'
require File.dirname(__FILE__) + '/../app/validators/dmsf_folder_parent_validator'
# Validators
require File.dirname(__FILE__) + '/../app/validators/dmsf_file_name_validator'
require File.dirname(__FILE__) + '/../app/validators/dmsf_max_file_size_validator'
require File.dirname(__FILE__) + '/../app/validators/dmsf_workflow_name_validator'
require File.dirname(__FILE__) + '/../app/validators/dmsf_url_validator'
require File.dirname(__FILE__) + '/../app/validators/dmsf_folder_parent_validator'
# Plugin's patches
require File.dirname(__FILE__) + '/redmine_dmsf/patches/projects_helper_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/project_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/user_preference_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/user_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/issue_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/role_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/queries_controller_patch'
# Plugin's patches
require File.dirname(__FILE__) + '/redmine_dmsf/patches/projects_helper_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/project_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/user_preference_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/user_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/issue_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/role_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/queries_controller_patch'
# redmine_resources depends on redmine_contact and redmine_contacts is alphabetically sorted before redmine_dmsf
# in the plugin list.
if Redmine::Plugin.installed?(:redmine_contacts) && !Redmine::Plugin.installed?(:easy_extensions)
require File.dirname(__FILE__) + '/redmine_dmsf/patches/notifiable_ru_patch'
else
require File.dirname(__FILE__) + '/redmine_dmsf/patches/notifiable_patch'
end
# redmine_resources depends on redmine_contact and redmine_contacts is alphabetically sorted before redmine_dmsf
# in the plugin list.
if Redmine::Plugin.installed?(:redmine_contacts) && !Redmine::Plugin.installed?(:easy_extensions)
require File.dirname(__FILE__) + '/redmine_dmsf/patches/notifiable_ru_patch'
else
require File.dirname(__FILE__) + '/redmine_dmsf/patches/notifiable_patch'
end
if defined?(EasyExtensions)
require File.dirname(__FILE__) + '/redmine_dmsf/patches/easy_crm_case_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/attachable_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/easy_crm_cases_controller_patch.rb'
end
if defined?(EasyExtensions)
require File.dirname(__FILE__) + '/redmine_dmsf/patches/easy_crm_case_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/attachable_patch'
require File.dirname(__FILE__) + '/redmine_dmsf/patches/easy_crm_cases_controller_patch.rb'
end
# Load up classes that make up our WebDAV solution ontop of Dav4rack
require File.dirname(__FILE__) + '/dav4rack'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/custom_middleware'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/base_resource'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/dmsf_resource'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/index_resource'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/project_resource'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/resource_proxy'
# Load up classes that make up our WebDAV solution ontop of Dav4rack
require File.dirname(__FILE__) + '/dav4rack'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/custom_middleware'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/base_resource'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/dmsf_resource'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/index_resource'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/project_resource'
require File.dirname(__FILE__) + '/redmine_dmsf/webdav/resource_proxy'
# Errors
require File.dirname(__FILE__) + '/redmine_dmsf/errors/dmsf_access_error'
require File.dirname(__FILE__) + '/redmine_dmsf/errors/dmsf_email_max_file_size_error'
require File.dirname(__FILE__) + '/redmine_dmsf/errors/dmsf_file_not_found_error'
require File.dirname(__FILE__) + '/redmine_dmsf/errors/dmsf_lock_error'
require File.dirname(__FILE__) + '/redmine_dmsf/errors/dmsf_zip_max_files_error'
# Errors
require File.dirname(__FILE__) + '/redmine_dmsf/errors/dmsf_access_error'
require File.dirname(__FILE__) + '/redmine_dmsf/errors/dmsf_email_max_file_size_error'
require File.dirname(__FILE__) + '/redmine_dmsf/errors/dmsf_file_not_found_error'
require File.dirname(__FILE__) + '/redmine_dmsf/errors/dmsf_lock_error'
require File.dirname(__FILE__) + '/redmine_dmsf/errors/dmsf_zip_max_files_error'
# Hooks
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/controllers/search_controller_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/controllers/issues_controller_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/views/view_projects_form_hook'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/views/base_view_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/views/issue_view_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/views/custom_field_view_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/views/search_view_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/helpers/issues_helper_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/helpers/search_helper_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/helpers/project_helper_hooks'
# Hooks
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/controllers/search_controller_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/controllers/issues_controller_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/views/view_projects_form_hook'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/views/base_view_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/views/issue_view_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/views/custom_field_view_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/views/search_view_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/helpers/issues_helper_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/helpers/search_helper_hooks'
require File.dirname(__FILE__) + '/redmine_dmsf/hooks/helpers/project_helper_hooks'
# Macros
require File.dirname(__FILE__) + '/redmine_dmsf/macros'
end
# Macros
require File.dirname(__FILE__) + '/redmine_dmsf/macros'