commit 2795213dda6cf376f90fb841caf36b9869b47e96
Author: choibk tag, the text is moved one column to the right by Redmin's CSS. A new line causes double new line.
+ text.gsub(' ', '')
+ .gsub(' <%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %>
+ <%= l(:text_dmsf_webdav_digest_reset) %>
+ <%= l(:label_no_data) %>
+ <%= label_tag 'dmsf_entries[target_project_id]', l(:field_target_project) %>
+ <%= select_tag 'dmsf_entries[target_project_id]',
+ project_tree_options_for_select(@projects, selected: @target_project) %>
+
+ <%= label_tag 'dmsf_entries[target_folder_id]', l(:field_target_folder) %><%= ' #' if @fast_links %>
+ <% if @fast_links %>
+ <%= text_field_tag 'dmsf_entries[target_folder_id]', '', required: true, max_length: 255 %>
+ <% else %>
+ <%= select_tag 'dmsf_entries[target_folder_id]', options_for_select(@folders, selected: @target_folder&.id) %>
+ <% end %>
+
+ <%= submit_tag l(:button_copy), id: 'copy_button', data: { cy: "button__copy--dmsf" } %>
+ <%# TODO: Lock and proper permissions %>
+ <% if User.current.allowed_to?(:folder_manipulation, @project) &&
+ User.current.allowed_to?(:file_manipulation, @project) %>
+ <%= submit_tag l(:button_move), id: 'move_button', data: { cy: "button__move--dmsf" } %>
+ <% end %>
+
+ <%= f.text_field :title, required: true %>
+
+ <%= f.text_area :description, rows: 8, class: 'wiki-edit dmsf-description' %>
+
+ <% dir = @folder.inherited_permissions_from %>
+ <% if dir %>
+ <%= label_tag '', l(:label_inherited_permissions) %>
+ <% @project_roles.each do |role| %>
+ <% checked = dir.permission_for_role(role) %>
+ <% if checked %>
+
+ <% end %>
+ <% end %>
+
+ <%= custom_field_tag_with_label :dmsf_folder, value %>
+ <%= f.text_area :dmsf_description, rows: 8, class: 'wiki-edit dmsf-description', label: l(:field_description) %>
+
+ <%= label_tag '', l(:label_email_from) %>
+ <%= text_field_tag 'email[from_disabled]', @email_params[:from], class: 'dmsf-full-width', disabled: true %>
+
+ <%= label_tag 'email[to]', l(:label_email_to) %>
+
+ <%= text_field_tag 'email[to]', @email_params[:to], class: 'dmsf-full-width', required: true %>
+ <%= link_to sprite_icon('add', l(:button_add)), add_email_dmsf_path(id: @project),
+ title: l(:label_email_address_add), class: 'icon icon-add', remote: true %>
+
+
+ <%= label_tag 'email[cc]', l(:label_email_cc) %>
+ <%= text_field_tag 'email[cc]', @email_params[:cc], class: 'dmsf-full-width' %>
+
+ <%= label_tag 'email[subject]', l(:label_email_subject) %>
+ <%= text_field_tag 'email[subject]', @email_params[:subject], class: 'dmsf-full-width' %>
+
+ <%= label_tag '', l(:label_email_documents) %>
+
+ <%= link_to 'Documents.zip', download_email_entries_path(id: @project, folder_id: @folder, entry: @email_params[:zipped_content]) %>
+ <%= l(:label_or) %>
+ <%= check_box_tag('email[links_only]', 1, RedmineDmsf.dmsf_documents_email_links_only?,
+ onchange: "$('#public_url').toggle($('#email_links_only').prop('checked'))")
+ %>
+ <%= l(:label_links_only) %>
+ <%= render partial: 'dmsf_public_urls/new' %>
+
+
+ <%= label_tag 'email[body]', l(:label_email_body) %>
+ <%= text_area_tag 'email[body]', @email_params['body'], rows: '20', class: 'dmsf-full-width wiki-edit' %>
+ <%= l(:info_file_locked) %>
+ <%= f.text_field(:title) %>
+
+ <%= f.text_field :name, label: l(:label_file) %>
+
+ <%= f.text_area :description, rows: 6, class: 'wiki-edit dmsf-description' %>
+
+ <%= render partial: 'dmsf_files/version_selector', locals: {
+ label_tag_name: 'version',
+ select_tag_name_patch: 'version_patch',
+ select_tag_name_minor: 'version_minor',
+ select_tag_name_major: 'version_major',
+ revision_or_upload: @file.last_revision } %>
+ <%= custom_field_tag_with_label(:dmsf_file_revision, value) %>
+ <%= label_tag 'file_upload', l(:label_new_content) %>
+
+ <%= render partial: 'dmsf_upload/form',
+ locals: { multiple: false, container: nil, awf: false } %>
+
+
+ <%= f.text_area :comment, rows: 2, label: l(:label_comment), class: 'wiki-edit dmsf-description' %>
+
+ <%= l(:menu_dmsf) %>
+ <%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %> DMS přidává následující makra: DMS fügt die folgenden integrierten Makros hinzu:
+ Document Management System “Features” - DMSF is a plugin for Redmine issue tracking system. It is aimed to
+ replace current Redmine's Documents module.
+
+ Redmine DMSF now comes bundled with WebDAV functionality: if switched on within plugin settings this will be
+ accessible from /dmsf/webdav.
+
+ Initial development was for Kontron AG R&D department and it is released as open source thanks to their
+ generosity.
+
+ Redmine Document Management System "Features" plugin is distributed under GNU General Public License v2 (GPL).
+
+ Redmine is a flexible project management web application, released under the terms of the GNU General Public
+ License v2 (GPL) at http://www.redmine.org
+
+ Further information about the GPL license can be found at
+
+ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html#SEC1
+ In this document the following syntax is used:
+ The following options related to DMS are available in My account:
+
+ In order to be DMS available, it is necessary to have checked the DMS module on the Modules tab.
+
+ Every project member is allowed to customize the DMS module behavior as follows:
+
+ Your DMS project's preferences
+
+ Notifications – Activated(default), Deactivated – If deactivated, you won't receive any email
+ notifications related to documents and vice versa.
+
+ Title format – File names of downloaded documents can be formated using following tags:
+
+ Fast links – If selected, you are expected to enter a document’s ID instead of selecting the document
+ from a pick list when creating a document link.
+
+ This feature provides a possibility to attach documents to issues. The new/edit issue form contains a
+ Drag&Drop area for uploading documents. It’s also possible to link existing documents using the button Link
+ from. Attached documents are stored in system folders visible from the user interface depending on
+ permissions.
+
+ Default query - You can select an existing query which will be default in DMS view.
+
+ Definition of approval workflows of the project.
+
+ This tab allows project managers to define approval workflows.
+
+ To create a new approval workflow click on the icon New approval workflowin the top left corner.
+ Then you are expected to enter a name of the new approval wokflow:
+ Now fill in a new workflow name and click on Create button. Optionally you can select an existing approval workflow to be copied.
+ Just created workflow appears on the workflow list. In order to change the workflow name or to define workflow
+ steps click on the workflow name. In our case on the text Basic.
+
+ Then workflow update form appears. In the top of the form you can update the workflow name. Edit the name there
+ and click on Save button.
+
+ Using the New step button you can choose one or more approvals and by clicking on AND
+ or OR button you will add a new approval step to the end or by choosing an existing step from
+ the list to an existing step.
+
+ Later on exiting approval steps can be removed, reordered or edited by clicking on corresponding icon next to
+ the step approvals.
+
+ The DMS module allows you to store all documentation relevant to a project at one place, sorted
+ into folders. You can switch on the Documents module by going to the project Settings → Modules tab. Check the check box in front of the DMS item, which is the Document Management System Feature.
+
+ The documents are stored in folders, which should have such a structure that provides an easy orientation within the topic.
+
+ You can create a new folder by clicking the green plus sign Create folder in the right upper corner. This
+ takes you to the following screen:
+
+ Type the new folder Title and click the Create button. You can add a description of the
+ folder. You can use various types of text formatting, such as headings, lists, links to web pages, documents
+ etc. If you need help with the text formatting, click the Helpb> tool button and you are provided
+ with a list of commands, including examples. Moreover, you can set folder's custom fields if any. Access to the
+ folder can be driven by selecting certain roles or particular users in Allow access only to section.
+
+ A new folder can be also created by copying an existing folder. Go to the folder you wish to create a
+ copy of, and click the Edit icon:
+
+ Or click on Edit item in the context menu next to the folder in the main view:
+
+ On the folder edit page choose Copy/Move from the context menu:
+
+ Select the Target project and Target folder. Click the Copy button.
+
+ In the new folder form or later in the edit form you can specify an extra folder permissions. By selecting roles
+ and members you can control access to the folder.
+
+ Only the selected roles or users will have access to the folder.
+
+ The editing tool uses the same form as is used for creating a new folder. You can change the folder's title,
+ description and permissions.
+
+ The list of folders can by ordered by any column. Just click on the column title and the list will be reordered by
+ the column's values. If you click the same title again the order will be reversed.
+
+ You can limit the view to certain folders and documents by defining filter rules. An empty filter for the title
+ is displayed by default. Additionally, you can add more filters using the pick list on the right side. In case
+ of a list of values you can combine multiple values.
+
+ There in Options you can specify visible columns.
+
+ Defined filters and options can be saved as custom queries for later usage.
+
+ Firstly, define filters and options. Then, save them as a custom query using the link Save custom query.
+
+ Defined custom queries can be then edited, cleared or deleted using corresponding commands:
+ Edit custom query, Clear and Delete custom query.
+
+ In My account you can select Default DMS query for your account.
+
+ To download or see a document just click its title.
+
+ Documents of display-able types such as PDF, PNG, JPG, ODT,... are displayed inline. If you want to download
+ them use the right mouse button's context menu of your browser and click on Save link as.
+
+ Multiple documents and folders can be downloaded at once. Select multiple items using check boxes on the left
+ side or using your mouse and <Shift> button. The open the conext menu using your mouse and click on
+ Download. Selected items will be zipped and offered for downloading.
+
+ Single or multiple documents can be sent by email. Select one or multiple document and choose Email
+ from the context menu.
+
+ In the email form fill in email recipients and optionally a body text and click Send.
+
+ By default, selected documents are zipped and attached to the email. If you select links only, the
+ documents won't be directly attached but linked into the email's body instead. If you use
+ Public URLs check box, the documents' links will be made public and will be valid for the specified
+ period of time.
+
+ Select single or multiple items and from the context menu choose Delete.
+
+ Click on the green plus icon New document in the top right of the main view. Then you can use the
+ Browse button or simple drag and drop files into the drop-able area. Multiple files (max 10) can be selected.
+
+ Recently uploaded files ar listed on the screen. You can delete them, if they were
+ selected by mistake using the trash bin icon. When done, click the Uplad button.
+
+ If you use [+] icon, you can specify document's details and then you can directly use Upload and commit button.
+ In that case the following commit screeen will be skipped and uploaded documents will be directly stored.
+
+ Once the new files are uploaded, corresponding documents are created. Here you can specify additional attributes
+ of the new documents. E.g. version and custom fields if any. When done, click again on Upload button.
+ Then the new documents are committed and your are redirected to the parent folder with the new documents.
+
+ Attributes or content of any document can be altered in the Edit from. Use the context menu and click
+ Edit. Each change means a new revision. Click on the plus button New Revision. Then you can
+ update any of the document's attribute and you can also upoad a new content using New content field.
+
+ The version of the document is automatically increased starting from 0.1. Major, minor and patch versions are
+ available. the rabge of each version varies from 0 to 999 and from A to Z.
+
+ When all required attributes are set, click Create button.
+
+ The same effect you can achieve by uploading an updated document to its original location. A new
+ revision of the same document is created automatically after uploading.
+
+ There is possible to create a link to another document or folder from the same or another folder of the same or
+ another project. Links behave as if operating directly on the target document or folder. It means for example
+ that if you download or email a link, the referenced file is sent to the user.
+
+ If the target document is going to be removed or moved the user will be warn about existing links and these
+ links will be automatically removed.
+
+ There is a command Link to in the context menu of a document or folder. After a click on that item a new
+ form New document link appears. The user is expected to choose a target project and folder as the
+ destination of the link just being created.
+
+ There is a command Link to in the context menu in the top right corner of the main view. After a click on
+ that item a new form New document link appears. The user is expected to choose a sorce project and folder
+ and optionaly document as the target of the link just being created.
+
+ Allow to create links to DMS objects.
+
+ Allow to create links to external objects using their URL.
+
+ Using the context menu you can trigger the following commands:
+
+ List of available commands might vary according to the document's state and user's parmissions.
+
+ Document's details are avaiable when you click on the Edit item in the context menu. A new form appears
+ then with a list of existing document's revisions. Each revision is represented by a box containg all attributes
+ related to the revision.
+
+ Except visible attributes, there is also a context menu in the top right corner of each revision's box containg
+ a command for displaying dowloading history - Download entries, downloading the particular revision -
+ Download and deleting the revision Delete. The Delete command is only available, if it is
+ not the last revision.
+
+ Each project with active DMS module, each folder or document ca be set as "watched". Watch/Unwatch
+ command is available from context menus. Watched items are marked with a yellow star.
+
+ You will reveive email notifications when watched items are updated, deleted or downloaded. The notifications
+ about downloads must be explicitely switched on in your user's profile.
+
+
+ If a project or folder is marked as watched, notifications are sent for all folders and documents under the
+ given project or folder.
+
+ Thanks to approval workflows we can applied an approval process on each document. Approval workflows can be
+ defined in the project's settings or in the administration.
+
+ The approval workflow state is indicated by workflow status in the Workflow column. The initial state is
+ empty. If you move your mouse cursor over the status text and the approval workflow hasn't been finished yet,
+ you will see a list of users who are expected to do an approval. If the workflow is in the stat of
+ Waiting for an approval and the approval steps have assigned names, you will see the name of the current
+ approval step.
+
+ You can check your open approval workflows on My Page Using the context menu you can approve documents
+ directly from there. If the command is missing, it means that you are not expected to do an approval in the
+ current approval step.
+
+ The process itself is clearly described on the diagram below.
+
+ And now step by step:
+
+
+ Assign an existing approval workflow to the selected document by clicking on Assignment. Then a
+ workflow assignment form appears:
+
+ All project's and global approval workflows are selectable. To manage approval workflows, see
+ Approval Workflow of Project settings. Select a workflow and click on Submit button.
+ The selected workflow is assigned to the document.
+
+ When the workflow is started, all approvers in particular steps are expected to do an approval. The
+ document is locked to prevent all changes.
+
+ If you are one of the approvers of the current approval step, you can do an approval by clicking on
+ Approval. Then the approval form appears:
+
+
+ You have three options here, either approve, reject or delegate the current approval step. In case of
+ rejection or delegation you are obliged to comment it in the text field Your note.... Only
+ members of the project are offered for delegation. Your decision will be confirmed by clicking the
+ Submit button.
+
+ Approved an rejected documents remain locked depending on the plugin’s settings.
+
+ All workflow approvals are stored and are available in the log window. You can open the window by clicking the
+ workflow status text:
+
+ Email notifications
+
+ Email notifications are sent according to the table as follows:
+
+ Retrieving/Reassigning of an approval workflow
+
+ In case of a wrong approval workflow assigning or a need to restart the workflow, just add a new empty revision
+ from the document details. Then you can assign a new approval workflow to the document. The approval workflow is
+ always related to the last document revision.
+
+ If documents or folders are deleted by a user, they are moved into the Trash bin only in fact and can be
+ restored again or definitively removed from the Trash bin.
+
+ The Trash bin is available from the main context menu.
+
+ The user interface of the trash bin is very similar to the documents view except available command. Only
+ commands for restoring and deleting are available.
+
+ Once a document or folder is deleted from the trash bin, there is no way back!
+
+ If you use Restore, the selected items are restored to their original position in DMS.
+
+ All changes related to a file revision and all downloads are recorded as activities. You can list any of them on
+ Activity tab.
+
+ The document module of the project can be mounted as a web folder. In a mounted folder is available a complete
+ document and folder structure. When a user does an operation such as download/upload a document or
+ creating a new folder it is automatically recorded in DMS and it has the same effect as the operation would be
+ done in the web interface of DMS.
+
+ A URL to mount has the following format:
+
+ https://[your domain]/dmsf/webdav/[project identifier]
+
+ You can mount mount all available documents using the following URL:
+
+ If you switch the authentication method to Basic in the plugin's settings, users are authenticated by their login and password that are sent from a client to the server as a text. From that reason it is not considered as secure.
+
+ It's the default authentication method. Users are authenticated using a digest that is auto-generated after a successful login to Redmine or they can reset it in their user's profile (My account). To log in from a client, they again use their login and password. Login is case-sensitive.
+
+ DMS exposes some of its data through a REST API. This API provides access and basic CRUD operations (create,
+ update, delete) for documents and folders. The API supports both XML and JSON formats.
+
+ Detailed description can be found here
+ togeather with a
+ sample shell scrit.
+
+ You can use DMS macros to link DMS documents and folders in Wiki formatted text. The wiki toolbar is extended
+ with a DMS button. The popup menu contains all available macros togeather with their description under the
+ Help command.
+ DMS adds the following builtin macros:
+ <%= radio_button_tag :external_link, 'false', true %> <%= l(:label_internal) %>
+ <% if @type == 'link_from' %>
+
+ <% else %>
+
+ <% end %>
+ <%= select_tag 'dmsf_link[target_project_id]',
+ project_tree_options_for_select(DmsfFile.allowed_target_projects_on_copy,
+ selected: @dmsf_link.target_project) %>
+ <%= javascript_tag do %>
+ $('#dmsf_link_target_project_id').change(function(){
+ $.ajax({
+ url: '<%= escape_javascript autocomplete_for_project_dmsf_link_path(@project, format: 'js') %>',
+ type: 'get',
+ data: $('#new_dmsf_link').serialize()
+ });
+ });
+ <% end %>
+
+ <% if @type == 'link_from' %>
+ <%= label_tag 'dmsf_link[target_folder_id]', l(:label_source_folder) %>
+ <% else %>
+
+ <% if @fast_links %>
+ <%= text_field_tag 'dmsf_link[target_folder_id]', '', required: true, max_length: 255 %>
+ <% end %>
+ <% end %>
+ <% if !@fast_links || (@type != 'link_to') %>
+ <%= select_tag 'dmsf_link[target_folder_id]',
+ folder_tree_options_for_select(DmsfFolder.directory_tree(@dmsf_link.target_project)) %>
+ <%= javascript_tag do %>
+ $('#dmsf_link_target_folder_id').change(function(){
+ $.ajax({
+ url: '<%= escape_javascript autocomplete_for_folder_dmsf_link_path(@project, format: 'js') %>',
+ type: 'get',
+ data: $('#new_dmsf_link').serialize()
+ });
+ });
+ <% end %>
+ <% end %>
+
+ <%= label_tag 'dmsf_link[target_file_id]', l(:field_target_file) %>
+ <% files = files_for_select(@dmsf_link.target_project.id) %>
+ <%= select_tag 'dmsf_link[target_file_id]', options_for_select(DmsfFolder.file_list(files)), required: modal %>
+
+ <%= f.text_field :external_url, required: false %>
+
+ <%= f.text_field :name, required: true, max_length: 255 %>
+
+ <%= h(file.dmsf_path_str) %> (<%= file.name %>)
+ <% if file.last_revision %>
+ , <%= number_to_human_size(file.last_revision.size) %>, <%= l(:label_dmsf_version) %> <%= file.last_revision.version %>
+ <% end %>
+
+ <%= h(file.dmsf_path_str) %> (<%= file.name %>)
+ <% if file.last_revision %>
+ , <%= number_to_human_size(file.last_revision.size) %>,
+ <%= l(:label_dmsf_version) %> <%= file.last_revision.version %>
+ <% end %>
+
+ <%= link_to h(file.dmsf_path_str), dmsf_file_url(file, download: '') %>
+ (<%= file.name %>),
+ <%= number_to_human_size(file.last_revision.size) %>,
+ <%= l(:label_dmsf_version) %> <%= file.last_revision.version %>,
+ <%= "#{file.last_revision.workflow_str(true)}," if file.last_revision.workflow_str(true) != l(:title_none) %>
+ <%= link_to l(:link_details, title: h(file.title)), dmsf_file_url(file) %>
+ <% if file.last_revision.comment.present? %>
+ <%= @user.name %>,
+ <%= @text1 %>
+
+ <%= @text2 %>
+ <% if @revision.dmsf_file.dmsf_folder %>
+ <%= link_to @revision.dmsf_file.dmsf_folder.title,
+ dmsf_folder_url(id: @revision.dmsf_file.project, folder_id: @revision.dmsf_file.dmsf_folder) %>
+ <% else %>
+ <%= link_to l(:link_documents), dmsf_folder_url(id: @revision.dmsf_file.project) %>
+ <% end %>.
+
+ <%= label_tag "committed_files[#{i}][title]", l(:label_title) %>
+ <%= text_field_tag "committed_files[#{i}][title]", upload.title, required: true %>
+
+ <%= label_tag "committed_files[#{i}][name]", l(:label_filename) %>
+ <%= text_field_tag "committed_files[#{i}][name]", upload.name, readonly: true %>
+
+ <%= label_tag "committed_files[#{i}][description]", l(:label_description) %>
+ <%= text_area_tag "committed_files[#{i}][description]", upload.description, rows: 6,
+ class: 'wiki-edit dmsf-description' %>
+
+ <%= render partial: 'dmsf_files/version_selector', locals: {
+ label_tag_name: "committed_files[#{i}][version]",
+ select_tag_name_patch: "committed_files[#{i}][version_patch]",
+ select_tag_name_minor: "committed_files[#{i}][version_minor]",
+ select_tag_name_major: "committed_files[#{i}][version_major]",
+ revision_or_upload: upload } %>
+
+ <%= label_tag "committed_files[#{i}][mime_type]", l(:label_mime) %>
+ <%= text_field_tag "committed_files[#{i}][mime_type]", h(upload.mime_type), readonly: true %>
+
+ <%= label_tag "committed_files[#{i}][human_size]", l(:label_size) %>
+ <%= text_field_tag "committed_files[#{i}][human_size]", number_to_human_size(upload.size), readonly: true %>
+ <%= custom_field_tag_with_label "committed_files[#{i}]", value %>
+ <%= label_tag "committed_files[#{i}][comment]", l(:label_comment) %>
+ <%= text_area_tag "committed_files[#{i}][comment]", upload.comment, rows: 2, class: 'wiki-edit dmsf-description' %>
+ <%= l(:info_file_locked) %>
+ <%= label_tag "committed_files[#{i}][title]", l(:label_title) %>
+ <%= text_field_tag "committed_files[#{i}][title]", upload.title, readonly: true %>
+
+ <%= label_tag "committed_files[#{i}][name]", l(:label_filename) %>
+ <%= text_field_tag "committed_files[#{i}][name]", upload.name, readonly: true %>
+
+ <%= label_tag "committed_files[#{i}][version]", l(:label_dmsf_version) %>
+ <%= text_field_tag "committed_files[#{i}][version]",
+ "#{DmsfUploadHelper::gui_version(upload.major_version)}.#{DmsfUploadHelper::gui_version(upload.minor_version)}",
+ readonly: true %>
+
+ <%= label_tag "committed_files[#{i}][mime_type]", l(:label_mime) %>
+ <%= text_field_tag "committed_files[#{i}][mime_type]", upload.mime_type, readonly: true %>
+
+ <%= label_tag "committed_files[#{i}][human_size]", l(:label_size) %>
+ <%= text_field_tag "committed_files[#{i}][human_size]", number_to_human_size(upload.size), readonly: true %>
+
+ <%= label_tag "committed_files[#{i}][#{value.custom_field.id}]", value.custom_field.name %>
+ <% value.value = nil if value.custom_field.dmsf_not_inheritable %>
+ <%= text_field_tag "committed_files[#{i}][#{value.custom_field.id}]", value.value, readonly: true %>
+
+
+
+
+
+ <%= label_tag 'workflow', "#{l(:link_workflow)}:" %>
+ <%= select_tag 'dmsf_workflow_id', dmsf_workflows_for_select(@project, nil)%>
+
+ <%= link_to sprite_icon('add', l(:label_dmsf_workflow_new)), new_dmsf_workflow_path(project_id: @project.id),
+ class: 'icon icon-add' %>
+
+ <% if revision %>
+ for providing an excellent IDE.
diff --git a/app/controllers/dmsf_context_menus_controller.rb b/app/controllers/dmsf_context_menus_controller.rb
new file mode 100644
index 00000000..0b76886c
--- /dev/null
+++ b/app/controllers/dmsf_context_menus_controller.rb
@@ -0,0 +1,158 @@
+# frozen_string_literal: true
+
+# Redmine plugin for Document Management System "Features"
+#
+# Karel Pičman
')
+ .gsub("\n\t", '
')
+ end
+
+ def render_document_content(dmsf_file, content)
+ if dmsf_file.markdown?
+ render partial: 'common/markup', locals: { markup_text_formatting: markdown_formatter, markup_text: content }
+ elsif dmsf_file.textile?
+ render partial: 'common/markup', locals: { markup_text_formatting: 'textile', markup_text: content }
+ else
+ render partial: 'common/file', locals: { content: content, filename: dmsf_file.name }
+ end
+ end
+end
diff --git a/app/helpers/dmsf_folder_permissions_helper.rb b/app/helpers/dmsf_folder_permissions_helper.rb
new file mode 100644
index 00000000..b58db0a8
--- /dev/null
+++ b/app/helpers/dmsf_folder_permissions_helper.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+# Redmine plugin for Document Management System "Features"
+#
+# Vít Jonáš <%= l(:label_email_address_add) %>
+
+<%= form_tag(append_email_dmsf_path(id: @project), remote: true, method: :post, id: 'new-user-form') do %>
+ <%= hidden_field_tag :project_id, @project.id %>
+
+ <% render_custom_field_values(@folder) do |custom_field, formatted| %>
+
+ <% end %>
+
+ <% if folder %>
+ <%= link_to l(:link_documents), dmsf_folder_path(id: @project) %>
+ <% folder.dmsf_path.each do |path_element| %>
+ /
+ <% if filename.blank? && (path_element == folder.dmsf_path.last) %>
+ <%= h(path_element.title) %>
+ <% else %>
+ <%= link_to h(path_element.title), dmsf_folder_path(id: @project, folder_id: path_element) %>
+ <% end %>
+ <% end %>
+ <% if folder.locked? && !(filename || title) %>
+ <%= content_tag('span', sprite_icon('unlock', nil, icon_only: true, size: '12'),
+ title: l(:title_locked_by_user, user: folder.locked_by)) %>
+ <% end %>
+ <% else %>
+ <% if @project %>
+ <%= link_to l(:link_documents), dmsf_folder_path(id: @project) %>
+ <% else %>
+ <%= l(:link_documents) %>
+ <% end %>
+ <% end %>
+ <% if filename %>
+ /
+ <%= h(filename) %>
+ <% end %>
+ <% if title %>
+ » <%= title %>
+ <% end %>
+
diff --git a/app/views/dmsf/_query_list.html.erb b/app/views/dmsf/_query_list.html.erb
new file mode 100644
index 00000000..0b5da808
--- /dev/null
+++ b/app/views/dmsf/_query_list.html.erb
@@ -0,0 +1,44 @@
+<%
+ # Redmine plugin for Document Management System "Features"
+ #
+ # Karel Pičman
+
+
+
+
+ <% query.inline_columns.each do |column| %>
+ <%= column_header(query, column, query_options) %>
+ <% end %>
+
+
+
+ <%= render partial: 'query_rows', locals: { query: query, dmsf_pages: dmsf_pages } %>
+
+
+ ">
+
+ <% query.inline_columns.each do |column| %>
+ <% classes = column.css_classes.to_s.dup %>
+ <% classes << ' dmsf-gray' if node.type.match?(/link$/) %>
+ <% classes << ' dmsf-system' if node.system %>
+ <%= content_tag 'td', column_content(column, node), class: classes %>
+ <% end %>
+
+<% end %>
+
+<% unless query.deleted || query&.project.nil? %>
+ <%= javascript_tag do %>
+ $(function() {
+ $("table.dmsf tr").removeClass("ui-draggable-dragging ui-droppable-active ui-droppable-hover ui-draggable-handle");
+ $(".dmsf-draggable").draggable({
+ helper: function(event, ui) {
+ var ret = $(this).clone();
+ var width = $(this)[0].offsetWidth;
+ var myHelper = [];
+ myHelper.push('
+ <% unless node.system %>
+ <%= link_to_context_menu %>
+ <% end %>
+
+ ');
+ myHelper.push(ret.html());
+ myHelper.push('
');
+ helper = myHelper.join('');
+ return helper;
+ },
+ axis: "y",
+ revert: "invalid"
+ });
+ $(".dmsf-droppable" ).droppable({
+ drop: function(event, ui) {
+ let handle = $(this);
+ let dragObjectId = ui.draggable.find("td").find("input").val()
+ let dropObjectId = handle.attr('id');
+ let data = {};
+ handle.addClass("ui-state-highlight ajax-loading")
+ data['dmsf_folder'] = { drag_id: dragObjectId, drop_id: dropObjectId};
+ $.ajax({
+ url: '<%= dmsf_folder_url(query.project) %>',
+ type: 'put',
+ dataType: 'script',
+ data: data,
+ error: function(jqXHR, textStatus, errorThrown){
+ alert(errorThrown);
+ ui.draggable.animate(ui.draggable.data("ui-draggable").originalPosition, "slow");
+ },
+ complete: function(jqXHR, textStatus, errorThrown){
+ handle.removeClass("ui-state-highlight ajax-loading")
+ if(textStatus == 'success'){
+ if(!handle.hasClass('dmsf-not-loaded')){
+ var m = handle.attr("id").match(/^(\d+)span$/);
+ if(m){
+ $('.' + m[1]).remove();
+ handle.removeClass("dmsf-expanded");
+ handle.addClass("dmsf-collapsed dmsf-not-loaded");
+ }
+ ui.draggable.remove();
+ }
+ window.location.reload();
+ }
+ }
+ });
+ }
+ });
+ });
+ <% end %>
+<% end %>
diff --git a/app/views/dmsf/_sidebar.html.erb b/app/views/dmsf/_sidebar.html.erb
new file mode 100644
index 00000000..332ddbea
--- /dev/null
+++ b/app/views/dmsf/_sidebar.html.erb
@@ -0,0 +1,20 @@
+<%
+ # Redmine plugin for Document Management System "Features"
+ #
+ # Vít Jonáš
+ <% users = dir.permissions_users %>
+ <% checkboxes = users_checkboxes(users, inherited: true) %>
+ <%= checkboxes %>
+
+ <% if checkboxes.present? %>
+
+ <% end %>
+ <% end %>
+ <%= label_tag '', l(:label_dmsf_permissions) %>
+ <% @project_roles.each do |role| %>
+ <% checked = @folder.permission_for_role(role) %>
+
+ <% end %>
+
+
+ <% users = @folder.permissions_users %>
+ <% checkboxes = users_checkboxes(users) %>
+ <%= checkboxes %>
+
+ <% if checkboxes.present? %>
+
+ <% end %>
+
+ <%= link_to sprite_icon('add', l(:label_search_for_watchers), size: 12),
+ new_dmsf_folder_permissions_path(project_id: @project, dmsf_folder_id: @folder),
+ remote: true,
+ method: :get %>
+
+ <%= l(:link_trash_bin) %>
+
+<%= form_tag(trash_dmsf_path(id: @project), method: :get, id: 'query_form', class: 'dmsf-query-form') do %>
+
+ <% if @dmsf_file %>
+ <%= render partial: 'file', locals: { project: @project, folder: @folder, dmsf_file: @dmsf_file,
+ dmsf_link: @dmsf_link, locked: @locked, unlockable: @unlockable,
+ allowed: @allowed, email_allowed: @email_allowed,
+ notifications: @notifications, preview: @preview, back_url: @back_url } %>
+ <% elsif @dmsf_folder %>
+ <%= render partial: 'folder', locals: { project: @project, folder: @folder, dmsf_folder: @dmsf_folder,
+ dmsf_link: @dmsf_link, locked: @locked, unlockable: @unlockable,
+ allowed: @allowed, email_allowed: @email_allowed, edit: false,
+ notifications: @notifications, back_url: @back_url } %>
+ <% elsif @dmsf_link %>
+ <%= render partial: 'url', locals: { dmsf_link: @dmsf_link, allowed: @allowed, back_url: @back_url } %>
+ <% elsif @dmsf_project %>
+ <%= render partial: 'project', locals: { dmsf_project: @dmsf_project, allowed: @allowed, back_url: @back_url } %>
+ <% else %>
+ <%= render partial: 'multiple', locals: { project: @project, folder: @folder, allowed: @allowed,
+ email_allowed: @email_allowed, back_url: @back_url } %>
+ <% end %>
+
+
+<%= javascript_tag do %>
+ $('#dmsf-cm-delete').click(function (event) {
+ $('#context-menu').hide();
+ });
+ $('#dmsf-cm-workflow').click(function (event) {
+ $('#context-menu').hide();
+ });
+<% end %>
diff --git a/app/views/dmsf_context_menus/trash.html.erb b/app/views/dmsf_context_menus/trash.html.erb
new file mode 100644
index 00000000..dd894cc6
--- /dev/null
+++ b/app/views/dmsf_context_menus/trash.html.erb
@@ -0,0 +1,38 @@
+<%
+ # Redmine plugin for Document Management System "Features"
+ #
+ # Karel Pičman
+ <% if @dmsf_file || @dmsf_link %>
+ <%= render(partial: 'file_trash', locals: { project: @project, folder: @folder, dmsf_file: @dmsf_file,
+ dmsf_link: @dmsf_link, allowed_delete: @allowed_delete,
+ allowed_restore: @allowed_restore }) %>
+ <% elsif @dmsf_folder %>
+ <%= render(partial: 'folder_trash', locals: { project: @project, folder: @folder, dmsf_folder: @dmsf_folder,
+ dmsf_link: @dmsf_link, allowed_delete: @allowed_delete,
+ allowed_restore: @allowed_restore }) %>
+ <% else %>
+ <%= render(partial: 'multiple_trash', locals: { project: @project, folder: @folder, allowed_delete: @allowed_delete,
+ allowed_restore: @allowed_restore }) %>
+ <% end %>
+
+<%= javascript_tag do %>
+ $('#dmsf-cm-delete').click(function (event) {
+ $('#context-menu').hide();
+ });
+<% end %>
diff --git a/app/views/dmsf_files/_file_new_revision.html.erb b/app/views/dmsf_files/_file_new_revision.html.erb
new file mode 100644
index 00000000..92b2f891
--- /dev/null
+++ b/app/views/dmsf_files/_file_new_revision.html.erb
@@ -0,0 +1,85 @@
+<%
+ # Redmine plugin for Document Management System "Features"
+ #
+ # Vít Jonáš
+ <% file_view_url = url_for({ controller: :dmsf_files, action: 'view', id: dmsf_file }) %>
+ <% icon_name = icon_for_mime_type(Redmine::MimeType.css_class_of(dmsf_file.name)) %>
+ <%= link_to sprite_icon(icon_name, h(link ? link.name : dmsf_file.title)),
+ file_view_url,
+ target: '_blank',
+ rel: 'noopener',
+ title: h(dmsf_file.last_revision.try(:tooltip)),
+ 'data-downloadurl' => "#{dmsf_file.last_revision.detect_content_type}:#{h(dmsf_file.name)}:#{file_view_url}" %>
+
+
+ (<%= number_to_human_size dmsf_file.last_revision.size %>)
+ <%= link_to '', view_dmsf_file_url(dmsf_file, download: dmsf_file.last_revision, disposition: 'attachment'),
+ title: l(:title_title_version_version_download, title: h(dmsf_file.last_revision.title),
+ version: dmsf_file.last_revision.version), class: 'icon icon-download dmsf-revision-action-button' %>
+
+
+ <%= dmsf_file.description unless dmsf_file.description.blank? %>
+
+
+
+
+<% # Command icons %>
+
+
+ <% # Details %>
+ <% if User.current.allowed_to? :file_manipulation, dmsf_file.project %>
+ <%= link_to sprite_icon('edit', ''), dmsf_file_path(id: dmsf_file, back_url: issue_path(@issue)),
+ title: l(:link_details, title: h(dmsf_file.last_revision.title)),
+ class: 'icon-only icon-edit' %>
+ <% else %>
+
+ <% end %>
+ <% # Email %>
+ <%= link_to sprite_icon('email', ''), entries_operations_dmsf_path(id: dmsf_file.project_id, email_entries: 'email',
+ ids: ["file-#{dmsf_file.id}"],
+ back_url: issue_path(@issue)),
+ method: :post, title: l(:heading_send_documents_by_email), class: 'icon-only icon-email-disabled' %>
+ <% # Lock %>
+ <% if !dmsf_file.locked? %>
+ <%= link_to sprite_icon('lock', ''), lock_dmsf_files_path(id: dmsf_file, back_url: issue_path(@issue)),
+ title: l(:title_lock_file), class: 'icon-only icon-lock' %>
+ <% elsif dmsf_file.unlockable? && (!dmsf_file.locked_for_user? || User.current.allowed_to?(:force_file_unlock, dmsf_file.project)) %>
+ <%= link_to sprite_icon('unlock', ''), unlock_dmsf_files_path(id: dmsf_file, back_url: issue_path(@issue)),
+ title: dmsf_file.locked_title, class: 'icon-only icon-unlock' %>
+ <% else %>
+ <%= content_tag('span', sprite_icon('unlock', ''), title: dmsf_file.locked_title) %>
+ <% end %>
+ <% if !dmsf_file.locked? %>
+ <% # Notifications %>
+ <% if dmsf_file.notification %>
+ <%= link_to sprite_icon('email', ''), notify_deactivate_dmsf_files_path(id: dmsf_file,
+ back_url: issue_path(@issue)),
+ title: l(:title_notifications_active_deactivate), class: 'icon-only icon-email' %>
+ <% else %>
+ <%= link_to sprite_icon('email-disabled', ''), notify_activate_dmsf_files_path(id: dmsf_file,
+ back_url: issue_path(@issue)),
+ title: l(:title_notifications_not_active_activate), class: 'icon-only icon-email-add' %>
+ <% end %>
+ <% else %>
+
+
+ <% end %>
+ <% # Delete %>
+ <% if @issue.attributes_editable? &&
+ ((link && User.current.allowed_to?(:file_manipulation, dmsf_file.project)) ||
+ (!link && User.current.allowed_to?(:file_delete, dmsf_file.project))) %>
+ <% url = if link
+ dmsf_link_path(link, commit: 'yes', back_url: issue_path(@issue))
+ else
+ dmsf_file_path(id: dmsf_file, commit: 'yes', back_url: issue_path(@issue))
+ end %>
+ <%= delete_link url, {}, '' %>
+ <% end %>
+ <% # Approval workflow %>
+ <% wf = DmsfWorkflow.find_by(id: dmsf_file.last_revision.dmsf_workflow_id) if dmsf_file.last_revision.dmsf_workflow_id %>
+ <%= render partial: 'dmsf_workflows/approval_workflow_button',
+ locals: { file: dmsf_file,
+ file_approval_allowed: User.current.allowed_to?(:file_approval, dmsf_file.project),
+ workflows_available: DmsfWorkflow.where(['project_id = ? OR project_id IS NULL', dmsf_file.project_id]).exists?,
+ project: dmsf_file.project, wf: wf, dmsf_link_id: nil, back_url: issue_path(@issue) } %>
+
+
diff --git a/app/views/dmsf_files/_links.html.erb b/app/views/dmsf_files/_links.html.erb
new file mode 100644
index 00000000..065348b2
--- /dev/null
+++ b/app/views/dmsf_files/_links.html.erb
@@ -0,0 +1,36 @@
+<%
+ # Redmine plugin for Document Management System "Features"
+ #
+ # Karel Pičman
+
+
+
+
+ <% query.inline_columns.each do |column| %>
+ <%= column_header query, column, query_options %>
+ <% end %>
+
+
+
+ <% query.accesses.each do |access| %>
+
+ <% query.inline_columns.each do |column| %>
+ <%= content_tag 'td', column_content(column, access), class: column.css_classes %>
+ <% end %>
+
+ <% end %>
+
+ <%= l(:heading_revisions) %>
+<% @file.dmsf_file_revisions.visible[@revision_pages.offset, @revision_pages.per_page].each do |revision| %>
+ <%= l(:label_dmsf_permissions) %>
+<%= form_tag(append_dmsf_folder_permissions_path, remote: true, method: :post, id: 'new-user-form') do %>
+ <%= hidden_field_tag :project_id, @project.id %>
+ Referenční dokumentace syntaxe DMS
+
+
+
+
+ID dokumentu nebo složky naleznete v jejích detailech.
+
+
+
\ No newline at end of file
diff --git a/app/views/dmsf_help/de/wiki_syntax.html b/app/views/dmsf_help/de/wiki_syntax.html
new file mode 100644
index 00000000..2016c9de
--- /dev/null
+++ b/app/views/dmsf_help/de/wiki_syntax.html
@@ -0,0 +1,48 @@
+
+
+
+
+{{dmsf(17)}} - odkaz na dokument #17{{dmsf(17, File)}} - odkaz na dokument #17 s textem "File"{{dmsf(17, File, 10)}} - odkaz na dokument #17 r10 s textem "File"{{dmsfd(17)}} - odkaz na detaily dokument #17{{dmsfdesc(17)}} - odkaz na popis dokumentu #17{{dmsff(5)}} - odkaz na složku #5{{dmsff(5, Folder)}} - odkaz na složku #5 s textem "Folder"{{dmsf_image(8)}} - vložený obrázek dokumentu #8 (dokument musí být obrázek typu JPEG, PNG,...){{dmsf_image(8, size=300)}}{{dmsf_image(8, size=640x480)}}{{dmsf_image(8, size=50%)}}{{dmsf_image(8, height=300)}}{{dmsf_image(8, width=300)}} - obrázek dokumentu #8 s nastavenou velikostí{{dmsftn(8)}} - náhled obrázku dokumentu #8{{dmsftn(8, size=300)}} - náhled obrázku dokumentu #8 s nastavenou velikostí{{dmsfw(8)}} - schvalovací proces dokumentu #8DMS Syntax Reference
+
+
+
+
+ID des Dokuments/Ordners man kann in sein Details finden.
+
+
+
\ No newline at end of file
diff --git a/app/views/dmsf_help/en/dmsf_help.html.erb b/app/views/dmsf_help/en/dmsf_help.html.erb
new file mode 100644
index 00000000..754e2846
--- /dev/null
+++ b/app/views/dmsf_help/en/dmsf_help.html.erb
@@ -0,0 +1,792 @@
+
+
+
+
+ {{dmsf(17)}} - Link zum Dokument #17{{dmsf(17, File)}} - Link zum Dokument #17 mit dem Text "File"{{dmsf(17, File, 10)}} - Link zum Dokument #17 r10 mit dem Text "File"{{dmsfd(17)}} - Link zu den Dokumentdetails #17{{dmsfdesc(17)}} - Link zur Beschreibung des Dokuments #17{{dmsff(5)}} - Link zum Ordner #5{{dmsff(5, Folder)}} - Link yum Ordner #5 mit dem Text "Folder"{{dmsf_image(8)}} - Bild des Dokuments #8 (der Dokumnt must eine Bilddatei wie JPEG, PNG,... sein{{dmsf_image(8, size=300)}}{{dmsf_image(8, size=640x480)}}{{dmsf_image(8, size=50%)}}{{dmsf_image(8, height=300)}}{{dmsf_image(8, width=300)}} - Bild des Dokuments #8 mit Benutzerdefinierte Größe{{dmsftn(8)}} - Miniaturansicht des Documents #8{{dmsftn(8, size=300)}} - Miniaturansicht des Documents #8 mit Benutzerdefinierte Größe{{dmsfw(8)}} - Workflowstatus des Dokuments #8DMSF User's guide
+
+CONTENTS
+
+ 2 Features
+ 3 My Account
+ 4 Project settings
+ 4.1 Modules
+ 4.2 DMS
+ 4.3 Approval workflows
+ 5 DMS module
+ 5.1 Documents management
+ 5.2 New folder
+ 5.3 Folder permissions
+ 5.4 List of folders
+ 5.5 Filtering
+ 5.6 Options
+ 5.7 Custom queries
+ 5.8 Download
+ 5.9 Email
+ 5.10 Delete
+ 5.11 Add documents
+ 5.12 Update documents
+ 5.13 Documents links
+ 5.14 List of documents
+ 5.15 Document's details
+ 5.16 Notifications
+ 8.17 Approval workflow
+ 5.18 Trash bin
+ 6 Activity module
+ 7 WebDAV
+ 8 REST API
+ 9 Wiki macros
+1 Introduction
+
+ Bold italics – links, click-able items
+ Bold – names of tabs, or fields you can fill in
+ Courier – commands
+ 2 Features
+
+
+3 My Account
+
+
+4 Project settings
+4.1 Modules
+ 4.2 DMS
+
+
+
+
+
+
+
4.3 Approval workflows
+
+
+
+
+
+
5 DMS module
+ 5.1 Documents management
+
+
5.2 New folder
+
+
+
+
+
+
5.3 Folder permissions
+
+
5.4 List of folders
+ Each line of the folder list contains:
+
+
+
+
5.5 Filtering
+
+
5.6 Options
+
+
5.7 Custom queries
+
+
5.8 Download
+
+
5.9 Email
+
+
5.10 Delete
+ 5.11 Add documents
+
+
+
5.12 Update documents
+
+
5.13 Documents links
+
+ Create a link to a document or folder in the current folder
+
+ Internal
+
+
5.14 List of documents
+ Each line of the document list contains:
+
+
+
+
+
+ 5.15 Document's details
+
+
5.16 Notifications
+ 5.17 Approval workflow
+
+
+
+ Approval workflow process
+
+
+
+
+
+
+
+
+
+
+
+ Event
+ Receiver
+
+
+ The approval workflow is started
+ All approvers of the first step
+
+
+ An approval workflow step is finished
+ All approvers of the next step and workflow owner
+
+
+ The document has been approved
+ All members of the project
+
+
+ The document has been rejected
+ All participants of the workflow and the workflow owner
+
+
+ An approval step has been delegated
+ The delegate
+
+
+
+ Due date has been reached
+ All approvers in the given step who haven't approved yet. These notifications are resent every working
+ day.
+ 5.18 Trash bin
+ 6 Activity module
+
+
7 WebDAV
+
+
Authentication
+ Basic
+ Digest
+ 8 REST API
+ 9 Wiki macros
+
+
DMS Syntax Reference
+
+
+
+
+The document/folder's ID can be found in it's details.
+
+
+
\ No newline at end of file
diff --git a/app/views/dmsf_links/_form.html.erb b/app/views/dmsf_links/_form.html.erb
new file mode 100644
index 00000000..a9001146
--- /dev/null
+++ b/app/views/dmsf_links/_form.html.erb
@@ -0,0 +1,151 @@
+<%
+ # Redmine plugin for Document Management System "Features"
+ #
+ # Karel Pičman {{dmsf(17)}} - link to document #17{{dmsf(17, File)}} - link to document #17 with the text "File"{{dmsf(17, File, 10)}} - link to document #17 r10 with the text "File"{{dmsfd(17)}} - link to the details of document #17{{dmsfdesc(17)}} - link to the description of document #17{{dmsff(5)}} - link to folder #5{{dmsff(5, Folder)}} - link to folder #5 with the text "Folder"{{dmsf_image(8)}} - inline picture of document #8; the document must be an image file such as JPEG, PNG,...{{dmsf_image(8, size=300)}}{{dmsf_image(8, size=640x480)}}{{dmsf_image(8, size=50%)}}{{dmsf_image(8, height=300)}}{{dmsf_image(8, width=300)}} - inline picture of document 8 with a custom size{{dmsftn(8)}} - thumbnail of document #8{{dmsftn(8, size=300)}} - thumbnail of document #8 with a custom size{{dmsfw(8)}} - approval workflow status of document #8<%= l(:title_create_link) %>
+
+<%= labelled_form_for @dmsf_link, remote: modal do |f| %>
+ <%= error_messages_for @dmsf_link %>
+ <%= f.hidden_field :project_id, value: @dmsf_link.project_id %>
+ <%= f.hidden_field :dmsf_folder_id, value: @dmsf_link.dmsf_folder_id if @dmsf_link.dmsf_folder_id %>
+ <%= f.hidden_field :type, value: @type %>
+ <%= f.hidden_field :dmsf_file_id, value: @dmsf_file_id %>
+ <%= f.hidden_field(:container, value: @container) if @container %>
+ <%= hidden_field_tag 'back_url', @back_url %>
+
+ <%= radio_button_tag :external_link, 'true', false %> <%= l(:label_external) %>
+
<%= h(file.last_revision.comment) %>
+ <% end %>
+
+ <%= link_to h(dir.dmsf_path_str), dmsf_folder_url(id: dir.project_id, folder_id: dir.id, only_path: false) %>
+
+ <% dir.dmsf_files.each do |file| %>
+ <% unless files.include?(file) %>
+ <% if @public_urls %>
+ <% dmsf_public_url = DmsfPublicUrl.new %>
+ <% dmsf_public_url.dmsf_file = file %>
+ <% dmsf_public_url.user = @author %>
+ <% dmsf_public_url.expire_at = @expired_at %>
+ <% dmsf_public_url.save %>
+ <%= link_to h(file.title), dmsf_public_urls_url(token: dmsf_public_url.token) %>
+ (<%= link_to h(file.name), dmsf_public_urls_url(token: dmsf_public_url.token) %>)
+ <% else %>
+ <%= link_to(h(file.title), dmsf_file_url(file)) %>
+ (<%= link_to(h(file.name), dmsf_file_url(file)) %>)
+ <% end %>
+
+ <% files << file %>
+ <% end %>
+ <% end %>
+ <% folders << dir %>
+ <% end %>
+ <% end %>
+ <% end %>
+ <% end %>
+ <% end %>
+ <% if @files.present? %>
+
+ <% JSON.parse(@files).each do |id| %>
+ <% file = DmsfFile.find_by_id id %>
+ <% if file && !files.include?(file) %>
+ <% if @public_urls %>
+ <% dmsf_public_url = DmsfPublicUrl.new %>
+ <% dmsf_public_url.dmsf_file = file %>
+ <% dmsf_public_url.user = @author %>
+ <% dmsf_public_url.expire_at = @expired_at %>
+ <% dmsf_public_url.save %>
+ <%= link_to h(file.title), dmsf_public_urls_url(token: dmsf_public_url.token) %>
+ (<%= link_to h(file.name), dmsf_public_urls_url(token: dmsf_public_url.token) %>)
+ <% else %>
+ <%= link_to h(file.title), dmsf_file_url(file) %>
+ (<%= link_to h(file.name), dmsf_file_url(file) %>)
+ <% end %>
+
+ <% files << file %>
+ <% end %>
+ <% end %>
+ <% end %>
+<% end %>
+
\ No newline at end of file
diff --git a/app/views/dmsf_mailer/send_documents.text.erb b/app/views/dmsf_mailer/send_documents.text.erb
new file mode 100644
index 00000000..4157c7c7
--- /dev/null
+++ b/app/views/dmsf_mailer/send_documents.text.erb
@@ -0,0 +1,71 @@
+<%
+ # Redmine plugin for Document Management System "Features"
+ #
+ # Vít Jonáš <%= l(:field_label_dmsf_workflow) %>
+
+<%= form_tag({ controller: 'dmsf_workflows', action: 'new_action'}, method: :post, id: 'new-action-form') do %>
+ <%= hidden_field_tag :dmsf_workflow_step_assignment_id, params[:dmsf_workflow_step_assignment_id] %>
+ <%= hidden_field_tag :dmsf_file_revision_id, params[:dmsf_file_revision_id] %>
+ <%= hidden_field_tag :back_url, params[:back_url] %>
+
+ <%= text_area_tag :note, '', placeholder: l(:message_dmsf_wokflow_note), style: 'width: 90%' %>
+
+ <%= text_field_tag 'user_search', nil %>
+ <%= javascript_tag "observeSearchfield('user_search', null, '#{escape_javascript autocomplete_for_user_dmsf_workflow_path(@dmsf_workflow, dmsf_workflow_step_assignment_id: params[:dmsf_workflow_step_assignment_id], dmsf_file_revision_id: params[:dmsf_file_revision_id])}')" %>
+ <%= l(:field_label_dmsf_workflow) %>
+<% remote = params[:dmsf_link_id] || params[:attachment_id] %>
+<%= form_tag({ controller: 'dmsf_workflows', action: 'assignment' }, method: :post, id: 'assignment-form',
+ remote: remote) do %>
+ <%= hidden_field_tag :dmsf_file_revision_id, params[:dmsf_file_revision_id] %>
+ <%= hidden_field_tag :dmsf_link_id, params[:dmsf_link_id] %>
+ <%= hidden_field_tag :attachment_id, params[:attachment_id] %>
+ <%= hidden_field_tag :back_url, params[:back_url] %>
+ <%= l(:title_dmsf_workflow_log) %>
+
+
+
+
+
+
+ <%= l(:label_dmsf_workflow_step) %>
+ <%= l(:label_user) %>
+ <%= l(:label_action) %>
+ <%= l(:link_workflow) %>
+ <%= l(:label_note) %>
+ <%= l(:label_date)%>
+
+
+
+
+
+
+ <%= DmsfWorkflowStepAction.workflow_str(0) %>
+
+
+
+
+
+
+ <%= link_to_user revision.dmsf_workflow_assigned_by_user if revision.dmsf_workflow_assigned_by_user %>
+ <%= DmsfWorkflowStepAction.action_str(DmsfWorkflowStepAction::ACTION_ASSIGN) %>
+ <%= DmsfWorkflowStepAction.workflow_str(DmsfWorkflowStepAction::ACTION_ASSIGN) %>
+
+ <%= format_time(revision.dmsf_workflow_assigned_at) if revision.dmsf_workflow_assigned_at %>
+
+
+ <%# SQLite3::SQLException: RIGHT and FULL OUTER JOINs are not currently supported %>
+ <%# sql = "SELECT c.action, c.note, c.created_at, c.author_id, a.user_id, s.step, s.name FROM dmsf_workflow_step_actions c RIGHT JOIN dmsf_workflow_step_assignments a ON a.id = c.dmsf_workflow_step_assignment_id RIGHT JOIN dmsf_workflow_steps s ON s.id = a.dmsf_workflow_step_id WHERE a.dmsf_file_revision_id = #{revision.id} ORDER BY s.step, s.id, c.action DESC, c.created_at" %>
+ <% sql = "SELECT c.action, c.note, c.created_at, c.author_id, a.user_id, s.step, s.name FROM dmsf_workflow_steps s LEFT OUTER JOIN dmsf_workflow_step_assignments a ON s.id = a.dmsf_workflow_step_id LEFT OUTER JOIN dmsf_workflow_step_actions c ON a.id = c.dmsf_workflow_step_assignment_id WHERE a.dmsf_file_revision_id = #{revision.id} ORDER BY s.step, s.id, c.action DESC, c.created_at" %>
+ <% result = DmsfWorkflowStep.connection.exec_query sql %>
+ <% last_step = 0 %>
+ <% result.each_with_index do |row, i| %>
+
+
+ <%= link_to_user revision.dmsf_workflow_started_by_user if revision.dmsf_workflow_started_by_user %>
+ <%= DmsfWorkflowStepAction.action_str(DmsfWorkflowStepAction::ACTION_START) %>
+ <%= DmsfWorkflowStepAction.workflow_str(DmsfWorkflowStepAction::ACTION_START) if revision.dmsf_workflow_started_by_user %>
+
+ <%= format_time(revision.dmsf_workflow_started_at) if revision.dmsf_workflow_started_at %>
+
+
+ <% end %>
+
+ <%= row['step'] unless row['step'] == last_step %>
+ <% last_step = row['step'] %>
+ <%= row['name'] %>
+ <%= link_to_user User.find_by(id: row['author_id'].present? ? row['author_id'] : row['user_id']) %>
+ <%= DmsfWorkflowStepAction.action_str(row['action']) %>
+
+ <% if (row['step'].to_i == @dmsf_workflow.dmsf_workflow_steps.last.step) && (revision.workflow == DmsfWorkflow::STATE_APPROVED) && (row['action'] != DmsfWorkflowStepAction::ACTION_DELEGATE) %>
+ <%= l(:title_approved) if row['created_at'].present? %>
+ <% else %>
+ <%= DmsfWorkflowStepAction.workflow_str(row['action']) %>
+ <% end %>
+
+ <%= row['note'] %>
+ <%= format_time(row['created_at']) if row['created_at'].present? %>
+
+ <%= link_to sprite_icon('add', l(:label_dmsf_workflow_new)), new_dmsf_workflow_path(project_id: @project&.id), + class: 'icon icon-add', data: { cy: "button__new--dmsf-workflow" } %> +
+<% else %> +| <%= l(:field_name) %> | ++ |
|---|---|
| <%= link_to(h(workflow.name), dmsf_workflow_path(workflow)) %> | ++ <% url = { controller: 'dmsf_workflows', action: 'update', id: workflow.id } %> + <% if workflow.locked? %> + <%= link_to sprite_icon('unlock', l(:button_unlock)), + url.merge(dmsf_workflow: { status: DmsfWorkflow::STATUS_ACTIVE }), method: :put, + class: 'icon icon-unlock' %> + <% else %> + <%= link_to sprite_icon('lock', l(:button_lock)), + url.merge(dmsf_workflow: { status: DmsfWorkflow::STATUS_LOCKED }), method: :put, + class: 'icon icon-lock' %> + <% end %> + <%= delete_link dmsf_workflow_path(workflow, back_url: @path) %> + | +
<%= l(:label_no_data) %>
+<% end %> + +<% unless @project %> + <%= pagination_links_full @workflow_pages %> +<% end %> diff --git a/app/views/dmsf_workflows/_new_step_modal.html.erb b/app/views/dmsf_workflows/_new_step_modal.html.erb new file mode 100644 index 00000000..eb629aee --- /dev/null +++ b/app/views/dmsf_workflows/_new_step_modal.html.erb @@ -0,0 +1,47 @@ +<% + # Redmine plugin for Document Management System "Features" + # + # Karel Pičman+ <%= f.text_field :name, required: true %> + <%= f.submit l(:button_save) %> +
++ <%= link_to sprite_icon('add', l(:dmsf_new_step_or_approver)), new_step_dmsf_workflow_path(@dmsf_workflow), + remote: true, class: 'icon icon-add' %> +
+ <% steps = @dmsf_workflow.dmsf_workflow_steps.collect{|s| s.step}.uniq %> + <% if steps.any? %> +| + | <%= l(:label_dmsf_workflow_step) %> | +<%= l(:label_dmsf_workflow_approval_plural) %> | ++ |
|---|---|---|---|
| <%= i %> | +
+ <%= @dmsf_workflow.dmsf_workflow_steps[index].name if index %>
+ ">
+ <%= form_for(@dmsf_workflow, url: update_step_dmsf_workflow_path(step: index), method: :put,
+ html: { id: "step-index-name-#{index}-form" }) do |f| %>
+ <%= hidden_field_tag :back_url, dmsf_workflow_path(@dmsf_workflow) %>
+ <%= f.text_field(:step_name, value: @dmsf_workflow.dmsf_workflow_steps[index].name,
+ id: "dmsf_workflow_step_name_#{index}") %>
+
+ + <%= submit_tag l(:button_change), class: 'small' %> + <%= link_to_function( + l(:button_cancel), + "$('#step-index-#{index}-name').show(); $('#step-index-#{index}-approvers').show(); $('#step-index-#{index}-name-form').hide(); $('#step-index-#{index}-approvers-form').hide();") + %> + + <% end %> + |
+
+
+ <% stps = @dmsf_workflow.dmsf_workflow_steps.order(operator: :desc).
+ collect{ |s| (s.step == i) ? s : nil }.compact %>
+ <% stps.each_with_index do |step, j| %>
+ <% if (j > 0) || (step.operator != DmsfWorkflowStep::OPERATOR_AND) %>
+ <%= step.soperator %>
+ <% end %>
+ <%= link_to_user step.user %>
+ <% end %>
+
+ ">
+ <%= form_for(@dmsf_workflow, url: update_step_dmsf_workflow_path(step: index), method: :put,
+ html: { id: "step-index-operator-#{index}-form"}) do |_| %>
+ <%= hidden_field_tag :back_url, dmsf_workflow_path(@dmsf_workflow) %>
+
+
+ <% stps.each do |step| %>
+
+
+
+
+ + + + <%= delete_link delete_step_dmsf_workflow_path(step: step.id) %> +
+ <%= select_tag "assignee[#{step.id}]",
+ principals_options_for_select(@approving_candidates | [step.user], step.user),
+ include_blank: false %>
+
+ <% end %>
+ + <%= submit_tag l(:button_change), class: 'small' %> + <%= link_to_function l(:button_cancel), + "$('#step-index-#{index}-name').show(); $('#step-index-#{index}-approvers').show(); $('#step-index-#{index}-name-form').hide(); $('#step-index-#{index}-approvers-form').hide();" + %> + + <% end %> + |
+ + <%= reorder_handle(@dmsf_workflow, url: url_for(action: 'edit', id: @dmsf_workflow, step: i) ) %> + <%= link_to_function sprite_icon('edit', l(:button_edit)), + "$('#step-index-#{index}-name').hide(); $('#step-index-#{index}-approvers').hide(); $('#step-index-#{index}-name-form').show(); $('#step-index-#{index}-approvers-form').show();", + class: 'icon icon-edit' %> + <%= delete_link edit_dmsf_workflow_path(@dmsf_workflow, step: i, + back_url: dmsf_workflow_path(@dmsf_workflow)) %> + | + <% end %> +
<%= l(:label_no_data) %>
+ <% end %> ++ <%= f.text_field :name, required: true %> +
++ <%= f.select :id, dmsf_all_workflows_for_select(params[:dmsf_workflow] ? params[:dmsf_workflow][:id] : nil), + label: l(:label_copy_workflow_from) %> +
++ <% options = [[l(:label_none), nil]] %> + <% options.concat DmsfQuery.only_public.where(project_id: nil).or(DmsfQuery.where(user_id: @user.id)). + pluck(:name, :id) %> + <%= pref_fields.select :default_dmsf_query, + options_for_select(options, selected: @user.pref.default_dmsf_query) %> +
+<%= pref_fields.check_box :receive_download_notification %>
+<% end %> +<% if RedmineDmsf.dmsf_webdav_authentication == 'Digest' %> ++ + <% token = Token.find_by(user_id: @user.id, action: 'dmsf_webdav_digest') %> + <% if token %> + <%= l(:label_dmsf_webdav_digest_created_on, distance_of_time_in_words(Time.now, token.created_on)) %> + (<%= link_to l(:button_reset), dmsf_digest_path, remote: true, id: 'webdav_digest_reset' %>) + <% else %> + <%= l(:label_missing_dmsf_webdav_digest) %> + (<%= link_to l(:button_add), dmsf_digest_path, remote: true, id: 'webdav_digest_reset' %>) + <% end %> +
+<% end %> diff --git a/app/views/hooks/redmine_dmsf/_view_projects_form.html.erb b/app/views/hooks/redmine_dmsf/_view_projects_form.html.erb new file mode 100644 index 00000000..986f358d --- /dev/null +++ b/app/views/hooks/redmine_dmsf/_view_projects_form.html.erb @@ -0,0 +1,41 @@ +<% + # Redmine plugin for Document Management System "Features" + # + # Vít Jonáš+ <% counts = @source_project.dmsf_count %> + + + +
+<% end %> diff --git a/app/views/layouts/_document.html.erb b/app/views/layouts/_document.html.erb new file mode 100644 index 00000000..8dc26804 --- /dev/null +++ b/app/views/layouts/_document.html.erb @@ -0,0 +1,46 @@ +<% + # Redmine plugin for Document Management System "Features" + # + # Karel Pičman| <%= l(:field_project) %> | +<%= l(:label_document) %>/<%= l(:field_folder) %> | +<%= l(:field_folder) %> | ++ |
|---|---|---|---|
| + <%= link_to_project folder.project %> + | ++ <%= link_to sprite_icon('folder', h(folder.title)), + dmsf_folder_path(id: folder.project, folder_id: folder), class: 'icon icon-folder' %> + | ++ <% if folder.dmsf_folder %> + <%= link_to h(folder.dmsf_folder.title), + dmsf_folder_path(id: folder.project, folder_id: folder.dmsf_folder) %> + <% else %> + <%= link_to l(:link_documents), dmsf_folder_path(id: folder.project) %> + <% end %> + | ++ <%= link_to_context_menu %> + | +
| + <%= link_to_project file.project %> + | ++ <% icon_name = icon_for_mime_type(Redmine::MimeType.css_class_of(file.name)) %> + <%= link_to sprite_icon(icon_name, h(file.title)), dmsf_file_path(id: file), class: 'icon icon-file' %> + | ++ <% if file.dmsf_folder %> + <%= link_to h(file.dmsf_folder.title), dmsf_folder_path(id: file.project, folder_id: file.dmsf_folder) %> + <% else %> + <%= link_to_if file.project, l(:link_documents), dmsf_folder_path(id: file.project) %> + <% end %> + | ++ <%= link_to_context_menu %> + | +
<%= l(:label_no_data) %>
+<% end %> diff --git a/app/views/my/blocks/_open_approvals.html.erb b/app/views/my/blocks/_open_approvals.html.erb new file mode 100644 index 00000000..d52e6d2a --- /dev/null +++ b/app/views/my/blocks/_open_approvals.html.erb @@ -0,0 +1,110 @@ +<% + # encoding: utf-8 + # + # Redmine plugin for Document Management System "Features" + # + # Karel Pičman| <%= l(:field_project) %> | +<%= l(:field_label_dmsf_workflow) %> | +<%= l(:field_status) %> | +<%= l(:label_document) %> | +<%= l(:field_folder) %> | ++ |
|---|---|---|---|---|---|
| + <% if assignment.dmsf_file_revision.dmsf_file.project %> + <%= link_to_project assignment.dmsf_file_revision.dmsf_file.project %> + <% end %> + | ++ <% if assignment.dmsf_workflow_step && assignment.dmsf_workflow_step.dmsf_workflow %> + <%= link_to h(assignment.dmsf_workflow_step.dmsf_workflow.name), + edit_dmsf_workflow_path(assignment.dmsf_workflow_step.dmsf_workflow) %> + <% end %> + | ++ <% if assignment.dmsf_workflow_step.dmsf_workflow %> + <%= link_to assignment.dmsf_file_revision.workflow_str(false), + log_dmsf_workflow_path( + project_id: assignment.dmsf_file_revision.dmsf_file.project_id, + id: assignment.dmsf_workflow_step.dmsf_workflow_id, + dmsf_file_revision_id: assignment.dmsf_file_revision_id), + title: assignment.dmsf_file_revision.workflow_tooltip, + remote: true %> + <% else %> + <%= assignment.dmsf_file_revision.workflow_str(false) %> + <% end %> + | ++ <% if assignment.dmsf_file_revision && assignment.dmsf_file_revision.dmsf_file %> + <%= link_to h(assignment.dmsf_file_revision.title), + dmsf_file_path(id: assignment.dmsf_file_revision.dmsf_file) %> + <% end %> + | ++ <% if assignment.dmsf_file_revision %> + <% if assignment.dmsf_file_revision.dmsf_file.dmsf_folder %> + <%= link_to h(assignment.dmsf_file_revision.dmsf_file.dmsf_folder.title), + dmsf_folder_path(id: assignment.dmsf_file_revision.dmsf_file.project, + folder_id: assignment.dmsf_file_revision.dmsf_file.dmsf_folder) %> + <% elsif assignment.dmsf_file_revision.dmsf_file.project %> + <%= link_to l(:link_documents), dmsf_folder_path(id: assignment.dmsf_file_revision.dmsf_file.project) %> + <% end %> + <% end %> + | ++ <%= link_to_context_menu %> + | +
<%= l(:label_no_data) %>
+<% end %> diff --git a/app/views/my/blocks/_watched_documents.html.erb b/app/views/my/blocks/_watched_documents.html.erb new file mode 100644 index 00000000..2bb9c4da --- /dev/null +++ b/app/views/my/blocks/_watched_documents.html.erb @@ -0,0 +1,118 @@ +<% + # encoding: utf-8 + # + # Redmine plugin for Document Management System "Features" + # + # Karel Pičman| <%= l(:field_project) %> | +<%= l(:label_document) %>/<%= l(:field_folder) %> | +<%= l(:field_folder) %> | ++ |
|---|---|---|---|
| + <%= link_to_project project %> + | ++ <%= link_to_project project, jump: 'dmsf', class: 'project' %> + | ++ | + <%= link_to_context_menu %> + | +
| + <%= link_to_project folder.project %> + | ++ <%= link_to sprite_icon('folder', h(folder.title)), + dmsf_folder_path(id: folder.project, folder_id: folder), class: 'icon icon-folder' %> + | ++ <% if folder.dmsf_folder %> + <%= link_to h(folder.dmsf_folder.title), dmsf_folder_path(id: folder.project, folder_id: + folder.dmsf_folder) %> + <% else %> + <%= link_to l(:link_documents), dmsf_folder_path(id: folder.project) %> + <% end %> + | ++ <%= link_to_context_menu %> + | +
| + <%= link_to_project(file.project) if file.project %> + | ++ <% icon_name = icon_for_mime_type(Redmine::MimeType.css_class_of(file.name)) %> + <%= link_to sprite_icon(icon_name, h(file.title)), dmsf_file_path(id: file), class: 'icon icon-file' %> + | ++ <% if file.dmsf_folder %> + <%= link_to h(file.dmsf_folder.title), dmsf_folder_path(id: file.project, folder_id: file.dmsf_folder) %> + <% else %> + <%= link_to l(:link_documents), dmsf_folder_path(id: file.project) %> + <% end %> + | ++ <%= link_to_context_menu %> + | +
<%= l(:label_no_data) %>
+<% end %> diff --git a/app/views/search/_container.html.erb b/app/views/search/_container.html.erb new file mode 100644 index 00000000..987bf0c9 --- /dev/null +++ b/app/views/search/_container.html.erb @@ -0,0 +1,28 @@ +<% + # Redmine plugin for Document Management System "Features" + # + # Karel Pičman
+ <%= content_tag(:label, l(:field_column_names)) %>
+ <% columns = DmsfFolder::AVAILABLE_COLUMNS.dup %>
+ <% columns.concat(extra_columns) if defined?(extra_columns) %>
+ <% index = columns.index(l(:field_project)) %>
+ <%# Move Project to the second position %>
+ <% if index %>
+ <% columns.insert(0, columns.delete_at(index)) %>
+ <% end %>
+ <% cfs = DmsfFileRevisionCustomField.visible.order(:position) %>
+ <% selected_columns = DmsfFolder::DEFAULT_COLUMNS if selected_columns.blank? %>
+ <% columns.each_with_index do |column, i| %>
+ <%= check_box_tag 'settings[dmsf_columns][]', column, selected_columns.include?(column), id: "dmsf_column_#{i}" %>
+ <%= l("label_column_#{column}").capitalize %>
+
+ <% end %>
+ <% columns = cfs.map{ |c| c.name }
+ columns.each_with_index do |column, i| %>
+ <%= check_box_tag 'settings[dmsf_columns][]', column, selected_columns.include?(column), id: "dmsf_column_#{i}" %>
+ <%= h column.capitalize %>
+
+ <% end %>
+
+ <%= content_tag :label, l(:label_maximum_files_download) %>
+ <%= text_field_tag 'settings[dmsf_max_file_download]', RedmineDmsf.dmsf_max_file_download, size: 10 %>
+
+ <%= l(:note_maximum_number_of_files_downloaded) %>
+ <%= l(:label_default) %>: 0
+
+
+ <%= content_tag :label, l(:label_dmsf_max_notification_receivers_info) %>
+ <%= text_field_tag 'settings[dmsf_max_notification_receivers_info]', RedmineDmsf.dmsf_max_notification_receivers_info,
+ size: 10 %>
+
+ <%= l(:note_dmsf_max_notification_receivers_info) %>
+ <%= l(:label_default) %>: 10
+
+
+ <%= content_tag :label, l(:label_maximum_email_filesize) %>
+ <%= text_field_tag 'settings[dmsf_max_email_filesize]', RedmineDmsf.dmsf_max_email_filesize, size: 10 %>
+
+ <%= l(:note_maximum_email_filesize) %>
+ <%= l(:label_default) %>: 0
+
+
+ <%= content_tag :label, l(:label_file_storage_directory) %> + <%= text_field_tag 'settings[dmsf_storage_directory]', RedmineDmsf.dmsf_storage_directory, size: 256 %> + + <%= l(:label_default) %>: files/dmsf + +
+<% unless File.exist?(DmsfFile.storage_path) %> + <% begin %> + <% FileUtils.mkdir_p DmsfFile.storage_path %> + <% rescue %> +<%= l(:error_file_storage_directory_does_not_exist) %>
+ <% end %> +<% end %> +<% testfilename = DmsfFile.storage_path.join('test.test') %> +<% if File.exist?(RedmineDmsf.dmsf_storage_directory) %> + <% begin %> + <% File.open(testfilename, 'wb') {} %> + <% rescue %> +<%= l(:error_file_can_not_be_created) %>
+ <% ensure %> + <% FileUtils.rm_f testfilename %> + <% end %> +<% end %> + +
+ <%= content_tag :label, l(:label_dmsf_office_bin) %>
+ <%= text_field_tag 'settings[office_bin]', RedmineDmsf.office_bin, size: 10 %>
+ <% unless RedmineDmsf::Preview.office_available? %>
+
+ <%= l(:note_dmsf_office_bin_not_available, RedmineDmsf.office_bin ||= 'libreoffice') %>
+
+ <% end %>
+
+ <%= l(:note_dmsf_office_bin) %>
+ <%= l(:label_default) %>: 'libreoffice'
+
+
+ <%= content_tag :label, l(:label_physical_file_delete) %> + <%= check_box_tag 'settings[dmsf_really_delete_files]', '1', RedmineDmsf.physical_file_delete? %> + + <%= l(:label_default)%>: <%= l(:general_text_No)%> + +
+ ++ <%= content_tag :label, l(:label_default_notifications) %> + <%= select_tag 'settings[dmsf_default_notifications]', + options_for_select([ + [l(:select_option_deactivated), '0'], + [l(:select_option_activated), '1']], + selected: RedmineDmsf.dmsf_default_notifications? ? '1' : '0') %> + + <%= l(:label_default) %>: <%= l(:select_option_deactivated) %> + +
+ +
+ <%= content_tag :label, l(:label_display_notified_recipients) %>
+ <%= select_tag 'settings[dmsf_display_notified_recipients]',
+ options_for_select([
+ [l(:select_option_deactivated), '0'],
+ [l(:select_option_activated), '1']],
+ selected: RedmineDmsf.dmsf_display_notified_recipients? ? '1' : '0') %>
+
+ <%= l(:note_display_notified_recipients) %>
+ <%= l(:label_default) %>: <%= l(:select_option_deactivated) %>
+
+
+ <%= content_tag :label, l(:label_title_format) %> + <%= text_field_tag 'settings[dmsf_global_title_format]', RedmineDmsf.dmsf_global_title_format, size: 10 %> + + <%= l(:text_title_format) %> + +
+ +
+ <%= content_tag :label, l(:label_act_as_attachable) %>
+ <%= check_box_tag 'settings[dmsf_act_as_attachable]', '1', RedmineDmsf.dmsf_act_as_attachable? %>
+
+ <%= l(:note_dmsf_act_as_attachable) %>
+ <%= l(:label_default) %>: <%= l(:general_text_No) %>
+
+
+ <%= content_tag :label, l(:label_dmsf_projects_as_subfolders) %>
+ <%= check_box_tag 'settings[dmsf_projects_as_subfolders]', '1', RedmineDmsf.dmsf_projects_as_subfolders? %>
+
+ <%= l(:note_dmsf_projects_as_subfolders) %>
+ <%= l(:label_default) %>: <%= l(:general_text_No) %>
+
+
+ <%= content_tag :label, l(:label_dmsf_global_menu_disabled) %>
+ <%= check_box_tag 'settings[dmsf_global_menu_disabled]', '1', RedmineDmsf.dmsf_global_menu_disabled? %>
+
+ <%= l(:note_dmsf_global_menu_disabled) %>
+ <%= l(:label_default) %>: <%= l(:general_text_No) %>
+
+
+ <%= content_tag :label, l(:label_empty_minor_version_by_default) %> + <%= check_box_tag 'settings[empty_minor_version_by_default]', '1', RedmineDmsf.empty_minor_version_by_default? %> + + <%= l(:label_default) %>: <%= l(:general_text_No) %> + +
+ ++ <%= content_tag :label, l(:label_remove_original_documents_module) %> + <%= check_box_tag 'settings[remove_original_documents_module]', '1', RedmineDmsf.remove_original_documents_module? %> + + <%= l(:label_default) %>: <%= l(:general_text_No) %> + +
+ ++ <%= content_tag :label, l(:label_default_query) %> + <% options = [[l(:label_none), nil]] %> + <% options.concat DmsfQuery.only_public.where(project_id: nil).pluck(:name, :id) %> + <%= select_tag 'settings[dmsf_default_query]', + options_for_select(options, selected: RedmineDmsf.dmsf_default_query) %> +
+ ++ <%= content_tag :label, l(:label_email_from_override) %> + <%= text_field_tag 'settings[dmsf_documents_email_from]', RedmineDmsf.dmsf_documents_email_from, size: 128 %> + + <%= l(:label_default) %>: <%= l(:text_email_from_override) %> + +
+ ++ <%= content_tag :label, l(:label_email_reply_to) %> + <%= text_field_tag 'settings[dmsf_documents_email_reply_to]', RedmineDmsf.dmsf_documents_email_reply_to, size: 128 %> + + <%= l(:label_default) %>: <%= "''" %> + +
+ ++ <%= content_tag :label, l(:label_links_only).capitalize %> + <%= check_box_tag 'settings[dmsf_documents_email_links_only]', '1', RedmineDmsf.dmsf_documents_email_links_only? %> + + <%= l(:label_default) %>: <%= l(:general_text_No) %> + +
+ +
+ <%= content_tag :label, l(:label_dmsf_keep_documents_locked) %>
+ <%= check_box_tag 'settings[dmsf_keep_documents_locked]', '1', RedmineDmsf.dmsf_keep_documents_locked? %>
+
+ <%= l(:note_dmsf_keep_documents_locked) %>
+ <%= l(:label_default)%>: <%= l(:general_text_No)%>
+
+
+ <%= content_tag(:label, l(:only_approval_zero_minor_version)) %>
+ <%= check_box_tag 'settings[only_approval_zero_minor_version]', '1', RedmineDmsf.only_approval_zero_minor_version? %>
+
+ <%= l(:only_approval_zero_minor_version) %>
<%= l(:label_default) %>: <%= l(:general_text_No)%>
+
+
+ <%= content_tag :label, l(:label_webdav) %>
+ <%= select_tag 'settings[dmsf_webdav]',
+ options_for_select([
+ [l(:select_option_deactivated), '0'],
+ [l(:select_option_activated), '1']],
+ selected: RedmineDmsf.dmsf_webdav? ? '1' : '0'),
+ onchange: "$('#dmsf_webdav_block').toggle()" %>
+
+ <%= l(:note_webdav, protocol: Setting.protocol, domain: Setting.host_name) %>
+ <%= l(:label_default) %>: <%= l(:select_option_deactivated) %>
+
+
+ <%= content_tag :label, l(:label_webdav_authentication) %>
+ <% auth_types = [%w[Basic Basic], %w[Digest Digest]] %>
+ <%= select_tag 'settings[dmsf_webdav_authentication]',
+ options_for_select(auth_types, RedmineDmsf.dmsf_webdav_authentication) %>
+
+ <%= l(:note_webdav_authentication) %>
+ <%= l(:label_default)%>: <%= auth_types[1][0] %>
+
+
+ <%= 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: RedmineDmsf.dmsf_webdav_strategy),
+ onchange: "$('#dmsf_webdav_ro_block').toggle()" %>
+
+ <%= l(:note_webdav_strategy) %>
+ <%= l(:label_default) %>: <%= l(:select_option_webdav_readonly) %>
+
+
+ <%= content_tag(:label, l(:label_webdav_ignore)) %> + <%= text_field_tag 'settings[dmsf_webdav_ignore]', RedmineDmsf.dmsf_webdav_ignore, size: 50 %> + + <%= l(:note_webdav_ignore) %> <%= l(:label_default) %>: ^(\._|\.DS_Store$|Thumbs.db$) + +
+
+ <%= content_tag(:label, l(:dmsf_webdav_ignore_1b_file_for_authentication)) %>
+ <%= check_box_tag 'settings[dmsf_webdav_ignore_1b_file_for_authentication]', '1',
+ RedmineDmsf.dmsf_webdav_ignore_1b_file_for_authentication? %>
+
+ <%= l(:dmsf_webdav_ignore_1b_file_for_authentication_info) %>
+ <%= l(:label_default) %>: <%= l(:general_text_Yes) %>
+
+
+ <%= content_tag :label, l(:label_webdav_disable_versioning) %>
+ <%= text_field_tag 'settings[dmsf_webdav_disable_versioning]', RedmineDmsf.dmsf_webdav_disable_versioning,
+ size: 50 %>
+
+ <%= l(:note_webdav_disable_versioning) %>
+ <%= l(:label_default) %>: ^\~\$|\.tmp$
+
+
+ <%= content_tag :label, l(:label_webdav_use_project_names) %>
+ <%= check_box_tag 'settings[dmsf_webdav_use_project_names]', '1', RedmineDmsf.dmsf_webdav_use_project_names? %>
+
+ <%= l(:note_webdav_use_project_names) %>
+ <%= l(:label_default)%>: <%= l(:general_text_No) %>
+
+
+ <%= content_tag :label, l(:label_index_database) %> + <%= text_field_tag 'settings[dmsf_index_database]', RedmineDmsf.dmsf_index_database, size: 50 %> + + <%= l(:label_default) %>: <%= File.expand_path('dmsf_index', Rails.root) %> + +
+ + <% stem_langs = %w(danish dutch english finnish french german hungarian italian norwegian portuguese romanian russian + spanish swedish turkish) %> + +
+ <%= content_tag :label, l(:label_stemming_language) %>
+ <%= select_tag 'settings[dmsf_stemming_lang]', options_for_select(stem_langs, RedmineDmsf.dmsf_stemming_lang) %>
+
+ <%= l(:note_possible_values) %>: <%= stem_langs.join(', ') %>.
+ <%= "#{l(:label_default)}: #{stem_langs[2]}" %>
+
+
+ <%= content_tag :label, l(:label_stem_strategy) %>
+ <%= radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_NONE',
+ RedmineDmsf.dmsf_stemming_strategy == 'STEM_NONE' %> <%= l(:option_stem_none) %>
+
+ <%= radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_SOME',
+ RedmineDmsf.dmsf_stemming_strategy == 'STEM_SOME' %> <%= l(:option_stem_some) %>
+
+ <%= radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_ALL',
+ RedmineDmsf.dmsf_stemming_strategy == 'STEM_ALL' %> <%= l(:option_stem_all) %>
+
+
+ <%= l(:text_stemming_info) %>
+
+
+ <%= content_tag :label, l(:label_enable_cjk_ngrams) %>
+ <%= check_box_tag 'settings[dmsf_enable_cjk_ngrams]', '1', RedmineDmsf.dmsf_enable_cjk_ngrams? %>
+
+ <%= l(:text_enable_cjk_ngrams) %>
+ <%= l(:label_default)%>: <%= l(:general_text_No) %>
+
+
<%= l(:warning_xapian_not_available) %>
+<% end %> diff --git a/assets/images/dmsf.png b/assets/images/dmsf.png new file mode 100644 index 00000000..0fbdbd04 Binary files /dev/null and b/assets/images/dmsf.png differ diff --git a/assets/javascripts/attachments_dmsf.js b/assets/javascripts/attachments_dmsf.js new file mode 100644 index 00000000..0e3fe97a --- /dev/null +++ b/assets/javascripts/attachments_dmsf.js @@ -0,0 +1,407 @@ +/* + Redmine plugin for Document Management System "Features" + + Karel Pičman| Name | +Size | Type | +Last Modified |
|---|
' + classes = +'inline' + html << "' + classes << ' dmsf_attachments_label' unless container&.new_record? + html << "' + html << '
' + if User.current.pref.dmsf_attachments_upload_choice == 'DMSF' + html << context[:hook_caller].javascript_tag( + "$('.attachments-container:not(.dmsf-uploader)').hide();" + ) + end + end + # Upload form + html << attach_documents_form(context, label: false) if allowed_to_attach_documents?(container) + html + end + + def view_issues_show_description_bottom(context = {}) + show_attached_documents context[:issue], context[:controller] + end + + def view_issues_show_attachments_table_bottom(context = {}) + show_attached_documents context[:container], context[:controller], context[:attachments] + end + + def view_issues_dms_attachments(context = {}) + 'yes' if get_links(context[:container]).any? + end + + def view_issues_show_thumbnails(context = {}) + show_thumbnails(context[:container], context[:controller]) + end + + def view_issues_dms_thumbnails(context = {}) + links = get_links(context[:container]) + return unless links.present? && Setting.thumbnails_enabled? + + images = links.pluck(0).select(&:image?) + 'yes' if images.any? + end + + def view_issues_edit_notes_bottom_style(context = {}) + if User.current.pref.dmsf_attachments_upload_choice == 'Attachments' || + !allowed_to_attach_documents?(context[:container]) + '' + else + 'display: none' + end + end + + private + + def allowed_to_attach_documents?(container) + return false unless container.respond_to?(:project) && container.respond_to?(:saved_dmsf_attachments) && + RedmineDmsf.dmsf_act_as_attachable? + + return false if container.project && (!User.current.allowed_to?(:file_manipulation, container.project) || + (container.project&.dmsf_act_as_attachable != Project::ATTACHABLE_DMS_AND_ATTACHMENTS)) + + true + end + + def get_links(container) + links = [] + if defined?(container.dmsf_files) && + User.current.allowed_to?(:view_dmsf_files, container.project) && + RedmineDmsf.dmsf_act_as_attachable? && + container.project.dmsf_act_as_attachable == Project::ATTACHABLE_DMS_AND_ATTACHMENTS + container.dmsf_files.each do |dmsf_file| + links << [dmsf_file, nil, dmsf_file.created_at] if dmsf_file.last_revision + end + container.dmsf_links.each do |dmsf_link| + dmsf_file = dmsf_link.target_file + links << [dmsf_file, dmsf_link, dmsf_link.created_at] if dmsf_file&.last_revision + end + # Sort by 'create_at' + links.sort_by! { |a| a[2] } + end + links + end + + def show_thumbnails(container, controller) + links = get_links(container) + return if links.blank? + + controller.send :render_to_string, { partial: 'dmsf_files/thumbnails', + locals: { links: links, + thumbnails: Setting.thumbnails_enabled?, + link_to: false } } + end + + def attach_documents_form(context, label: true) + return unless context.is_a?(Hash) && context[:container] + + # Add Dmsf upload form + container = context[:container] + return unless allowed_to_attach_documents?(container) + + html = +'' + html + end + + def show_attached_documents(container, controller, _attachments = nil) + # Add list of attached documents + links = get_links(container) + return if links.blank? + + controller.send :render_to_string, + { partial: 'dmsf_files/links', + locals: { links: links, thumbnails: Setting.thumbnails_enabled? } } + end + end + end + end +end diff --git a/lib/redmine_dmsf/hooks/views/mailer_view_hooks.rb b/lib/redmine_dmsf/hooks/views/mailer_view_hooks.rb new file mode 100644 index 00000000..2f3e22cc --- /dev/null +++ b/lib/redmine_dmsf/hooks/views/mailer_view_hooks.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +# Redmine plugin for Document Management System "Features" +# +# Karel Pičman| #{l(:field_name)} | +#{l(:field_filesize)} | +#{l(:field_type)} | +#{l(:link_modified)} | +
|---|