Tree view optimized for speed

This commit is contained in:
Karel Picman 2016-09-23 10:17:16 +02:00
parent 4d19f5b893
commit 70fcbb6ba2
12 changed files with 344 additions and 266 deletions

View File

@ -24,7 +24,7 @@ class DmsfController < ApplicationController
unloadable
before_filter :find_project
before_filter :authorize
before_filter :authorize, :except => [:expand_folder]
before_filter :find_folder, :except => [:new, :create, :edit_root, :save_root]
before_filter :find_parent, :only => [:new, :create]
before_filter :tree_view, :only => [:delete, :show]
@ -33,116 +33,22 @@ class DmsfController < ApplicationController
helper :all
def show
@folder_manipulation_allowed = User.current.allowed_to?(:folder_manipulation, @project)
@file_manipulation_allowed = User.current.allowed_to?(:file_manipulation, @project)
@file_delete_allowed = User.current.allowed_to?(:file_delete, @project)
@file_view_allowed = User.current.allowed_to?(:view_dmsf_files, @project)
@force_file_unlock_allowed = User.current.allowed_to?(:force_file_unlock, @project)
@workflows_available = DmsfWorkflow.where(['project_id = ? OR project_id IS NULL', @project.id]).exists?
@file_approval_allowed = User.current.allowed_to?(:file_approval, @project)
tag = params[:custom_field_id].present? && params[:custom_value].present?
@folder = nil if tag
if @tree_view
@locked_for_user = false
else
unless @folder
if tag
@subfolders = []
DmsfFolder.where(:project_id => @project.id).visible.each do |f|
f.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@subfolders << f
break
end
end
end
end
@files = []
DmsfFile.where(:project_id => @project.id).visible.each do |f|
r = f.last_revision
if r
r.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@files << f
break
end
end
end
end
end
@dir_links = []
DmsfLink.where(:project_id => @project.id, :target_type => DmsfFolder.model_name.to_s).visible.each do |l|
l.target_folder.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@dir_links << l
break
end
end
end
end
@file_links = []
DmsfLink.where(:project_id => @project.id, :target_type => DmsfFile.model_name.to_s).visible.each do |l|
r = l.target_file.last_revision if l.target_file
if r
r.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@file_links << l
break
end
end
end
end
end
@url_links = []
DmsfLink.where(:project_id => @project.id, :target_type => 'DmsfUrl').visible.each do |l|
r = l.target_file.last_revision if l.target_file
if r
r.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@file_links << l
break
end
end
end
end
end
else
@subfolders = @project.dmsf_folders.visible
@files = @project.dmsf_files.visible
@dir_links = @project.folder_links.visible
@file_links = @project.file_links.visible
@url_links = @project.url_links.visible
end
@locked_for_user = false
else
if @folder.deleted?
render_404
return
end
@subfolders = @folder.dmsf_folders.visible
@files = @folder.dmsf_files.visible
@dir_links = @folder.folder_links.visible
@file_links = @folder.file_links.visible
@url_links = @folder.url_links.visible
@locked_for_user = @folder.locked_for_user?
end
def expand_folder
@tree_view = true
get_display_params
@idnt = params[:idnt].present? ? params[:idnt].to_i + 1 : 0
@pos = params[:pos].present? ? params[:pos].to_f : 0.0
respond_to do |format|
format.js { render :action => 'dmsf_rows' }
end
end
@ajax_upload_size = Setting.plugin_redmine_dmsf['dmsf_max_ajax_upload_filesize'].present? ? Setting.plugin_redmine_dmsf['dmsf_max_ajax_upload_filesize'] : 100
# Trash
@trash_visible = @folder_manipulation_allowed && @file_manipulation_allowed &&
@file_delete_allowed && !@locked_for_user && !@folder
@trash_enabled = DmsfFolder.deleted.where(:project_id => @project.id).any? ||
DmsfFile.deleted.where(:project_id => @project.id).any? ||
DmsfLink.deleted.where(:project_id => @project.id).any?
def show
get_display_params
if @folder && @folder.deleted?
render_404
return
end
respond_to do |format|
format.html {
render :layout => !request.xhr?
@ -650,4 +556,113 @@ class DmsfController < ApplicationController
copy
end
end
private
def get_display_params
@folder_manipulation_allowed = User.current.allowed_to?(:folder_manipulation, @project)
@file_manipulation_allowed = User.current.allowed_to?(:file_manipulation, @project)
@file_delete_allowed = User.current.allowed_to?(:file_delete, @project)
@file_view_allowed = User.current.allowed_to?(:view_dmsf_files, @project)
@force_file_unlock_allowed = User.current.allowed_to?(:force_file_unlock, @project)
@workflows_available = DmsfWorkflow.where(['project_id = ? OR project_id IS NULL', @project.id]).exists?
@file_approval_allowed = User.current.allowed_to?(:file_approval, @project)
tag = params[:custom_field_id].present? && params[:custom_value].present?
@folder = nil if tag
if @tree_view
@locked_for_user = false
else
unless @folder
if tag
@subfolders = []
DmsfFolder.where(:project_id => @project.id).visible.each do |f|
f.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@subfolders << f
break
end
end
end
end
@files = []
DmsfFile.where(:project_id => @project.id).visible.each do |f|
r = f.last_revision
if r
r.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@files << f
break
end
end
end
end
end
@dir_links = []
DmsfLink.where(:project_id => @project.id, :target_type => DmsfFolder.model_name.to_s).visible.each do |l|
l.target_folder.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@dir_links << l
break
end
end
end
end
@file_links = []
DmsfLink.where(:project_id => @project.id, :target_type => DmsfFile.model_name.to_s).visible.each do |l|
r = l.target_file.last_revision if l.target_file
if r
r.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@file_links << l
break
end
end
end
end
end
@url_links = []
DmsfLink.where(:project_id => @project.id, :target_type => 'DmsfUrl').visible.each do |l|
r = l.target_file.last_revision if l.target_file
if r
r.custom_field_values.each do |v|
if v.custom_field_id == params[:custom_field_id].to_i
if v.custom_field.compare_values?(v.value, params[:custom_value])
@file_links << l
break
end
end
end
end
end
else
@subfolders = @project.dmsf_folders.visible
@files = @project.dmsf_files.visible
@dir_links = @project.folder_links.visible
@file_links = @project.file_links.visible
@url_links = @project.url_links.visible
end
@locked_for_user = false
else
@subfolders = @folder.dmsf_folders.visible
@files = @folder.dmsf_files.visible
@dir_links = @folder.folder_links.visible
@file_links = @folder.file_links.visible
@url_links = @folder.url_links.visible
@locked_for_user = @folder.locked_for_user?
end
end
@ajax_upload_size = Setting.plugin_redmine_dmsf['dmsf_max_ajax_upload_filesize'].present? ? Setting.plugin_redmine_dmsf['dmsf_max_ajax_upload_filesize'] : 100
# Trash
@trash_visible = @folder_manipulation_allowed && @file_manipulation_allowed &&
@file_delete_allowed && !@locked_for_user && !@folder
@trash_enabled = DmsfFolder.deleted.where(:project_id => @project.id).any? ||
DmsfFile.deleted.where(:project_id => @project.id).any? ||
DmsfLink.deleted.where(:project_id => @project.id).any?
end
end

View File

@ -57,20 +57,27 @@ module DmsfHelper
extension = File.extname(filename)
extension = extension[1, extension.length-1]
if File.exists?("#{File.dirname(__FILE__)}/../../assets/images/filetypes/#{extension}.png")
return "filetype-#{extension}";
"filetype-#{extension}";
else
return Redmine::MimeType.css_class_of(filename)
Redmine::MimeType.css_class_of(filename)
end
end
def plugin_asset_path(plugin, asset_type, source)
return "#{Redmine::Utils.relative_url_root}/plugin_assets/#{plugin}/#{asset_type}/#{source}"
"#{Redmine::Utils.relative_url_root}/plugin_assets/#{plugin}/#{asset_type}/#{source}"
end
def self.dmsf_tree(parent, obj, tree = nil)
tree ||= []
def json_url
if I18n.locale && !I18n.locale.to_s.match(/^en.*/)
"jquery.dataTables/#{I18n.locale.to_s.downcase}.json"
else
'jquery.dataTables/en.json'
end
end
def self.all_children_sorted(parent, pos, ident)
# Folders && files && links
nodes = obj.dmsf_folders.visible + obj.dmsf_links.visible + obj.dmsf_files.visible
nodes = parent.dmsf_folders.visible + parent.dmsf_links.visible + parent.dmsf_files.visible
# Alphabetical and type sort
nodes.sort! do |x, y|
if ((x.is_a?(DmsfFolder) || (x.is_a?(DmsfLink) && x.is_folder?)) &&
@ -83,22 +90,17 @@ module DmsfHelper
x.title.downcase <=> y.title.downcase
end
end
# Create the tree
nodes.each do |node|
local_parent = node.dmsf_folder
level = 0
while local_parent && (local_parent != parent)
level += 1
local_parent = local_parent.dmsf_folder
# Calculate position
step = 1.0 / (10 ** ident)
tree = []
i = 0
nodes.each do |x|
if x.is_a?(DmsfFolder) || (x.is_a?(DmsfLink) && x.is_folder?)
i += 1
tree << [x, pos + (step * i)]
else
tree << [x, pos + step + i]
end
position = tree.size
# Files of the same parent and on the same level have the same position
if position > 0 && tree[-1][1] == level &&
(tree[-1][0].is_a?(DmsfFile) || (tree[-1][0].is_a?(DmsfLink) && tree[-1][0].is_file?))
position = tree[-1][2]
end
tree << [node, level, position]
self.dmsf_tree(parent, node, tree) if node.is_a?(DmsfFolder)
end
tree
end

View File

@ -110,7 +110,7 @@
<% end %>
<% end %>
</td>
<td class="dmsf_invisible"><%= position %></td>
<td id="dmsf_position" class="dmsf_invisible"><%= position %></td>
<td class="dmsf_invisible">0</td>
<td class="dmsf_invisible"><%= subfolder.modified.to_i if subfolder %></td>
<td class="dmsf_invisible">0</td>

View File

@ -0,0 +1,96 @@
<% parent = @folder ? @folder : @project %>
<% @idnt = 0 unless @idnt %>
<% @pos = 0.0 unless @pos %>
<% DmsfHelper.all_children_sorted(parent, @pos, @idnt).each do |obj, position| %>
<% classes = "dmsf_tree idnt-#{@idnt}" %>
<% classes += " dmsf-#{cycle('odd', 'even')}" %>
<% if obj.is_a?(DmsfFolder) && ((obj.dmsf_folders.visible.count > 0) || (obj.dmsf_files.visible.count > 0) || (obj.dmsf_links.visible.count > 0)) %>
<% classes += ' idnt dmsf_collapsed dmsf-not-loaded' %>
<% id = "id='#{obj.id}span'".html_safe %>
<% onclick = "onclick=\"dmsfToggle('#{obj.id}','#{obj.id}span','#{escape_javascript(expand_folder_dmsf_path)}')\"" %>
<% else %>
<% classes += ' dmsf_child' %>
<% onclick = '' %>
<% end %>
<% parent = obj.dmsf_folder %>
<% while parent %>
<% classes += " #{parent.id}" %>
<% parent = parent.dmsf_folder %>
<% end %>
<% if obj.is_a? DmsfFolder %>
<tr <%= id %> class="dir <%= classes %>">
<%= render(:partial => 'dir',
:locals => {
:project => @project,
:subfolder => obj,
:link => nil,
:id => obj.id,
:name => 'subfolders[]',
:title => obj.title,
:onclick => onclick,
:position => position}) %>
</tr>
<% elsif obj.is_a?(DmsfLink) && (obj.target_type == 'DmsfFolder') %>
<% unless obj.target_project %>
<% Rails.logger.error "Error: dmsf_link id #{obj.id} has no target!" %>
<% next %>
<% end %>
<tr <%= id %> class="dmsf_gray <%= classes %>">
<%= render(:partial => 'dir',
:locals => {
:project => obj.target_project,
:subfolder => obj.target_folder,
:link => obj,
:id => obj.id,
:name => 'dir_links[]',
:title => obj.name,
:onclick => onclick,
:position => position}) %>
</tr>
<% elsif obj.is_a?(DmsfFile) %>
<% unless obj.last_revision %>
<% Rails.logger.error "Error: dmsf_file id #{obj.id} has no revision!" %>
<% next %>
<% end %>
<tr <%= id %> class="file <%= classes %>">
<%= render(:partial => 'file', :locals => {
:project => @project,
:file => obj,
:link => nil,
:id => obj.id,
:name => 'files[]',
:title => obj.title,
:onclick => onclick,
:position => position}) %>
</tr>
<% elsif obj.is_a?(DmsfLink) && (obj.target_type == 'DmsfFile') %>
<% unless obj.target_file.last_revision %>
<% Rails.logger.error "Error: dmsf_file id #{obj.target_id} has no revision!" %>
<% next %>
<% end %>
<tr <%= id %> class="dmsf_gray <%= classes %>">
<%= render(:partial => 'file', :locals => {
:project => obj.target_project,
:file => obj.target_file,
:link => obj,
:id => obj.id,
:name => 'file_links[]',
:title => obj.name,
:onclick => onclick,
:position => position}) %>
</tr>
<% elsif obj.is_a?(DmsfLink) && (obj.target_type == 'DmsfUrl') %>
<tr <%= id %> class="dmsf_gray <%= classes %>">
<%= render(:partial => 'url', :locals => {
:project => obj.target_project,
:file => obj.target_file,
:link => obj,
:id => obj.id,
:name => 'file_links[]',
:title => obj.name,
:onclick => onclick,
:position => position}) %>
</tr>
<% end %>
<% end %>

View File

@ -26,7 +26,7 @@
:title => l(:title_check_for_zip_download_or_email), :id => "file_#{id}") %></td>
<td class="dmsf_title">
<% if @tree_view %>
<span class='dmsf_expander' <%= onclick.html_safe %>></span>
<span class='dmsf_expander'></span>
<% end %>
<% file_view_url = url_for({:controller => :dmsf_files, :action => 'view', :id => file}) %>
<%= link_to(h(title),
@ -36,7 +36,6 @@
:title => h(file.last_revision.try(:tooltip)),
'data-downloadurl' => "#{file.last_revision.detect_content_type}:#{h(file.name)}:#{file_view_url}") %>
<div class="dmsf_filename" title="<%= l(:title_filename_for_download)%>"><%= h(link ? link.path : file.display_name) %></div>
<%= '</span>'.html_safe if @tree_view %>
</td>
<td class="dmsf_size"><%= number_to_human_size(file.last_revision.size) %></td>
<td class="dmsf_modified">

View File

@ -29,115 +29,17 @@
<th class ="dmsf_th"><%= l(:link_title) %></th>
<th class ="dmsf_th"><%= l(:link_size) %></th>
<th class ="dmsf_th"><%= l(:link_modified) %></th>
<th title="<%= l(:label_dmsf_version) %>" class ="dmsf_th"><%= l(:link_ver) %></th>
<th title="<%= l(:label_dmsf_version) %>" class="dmsf_th"><%= l(:link_ver) %></th>
<th class ="dmsf_th"><%= l(:link_workflow) %></th>
<th class ="dmsf_th"><%= l(:link_author) %></th>
<th class ="dmsf_th"></th>
<th class="dmsf_invisible"></th>
<th class="dmsf_invisible"></th>
<th class="dmsf_invisible"></th>
<th class="dmsf_invisible"></th>
<th class ="dmsf_th"><%# controls %></th>
<th class="dmsf_invisible"><%# position %></th>
<th class="dmsf_invisible"><%# size %></th>
<th class="dmsf_invisible"><%# updated %></th>
<th class="dmsf_invisible"><%# revision %></th>
</tr>
</thead>
<tbody>
<% parent = @folder ? @folder : @project %>
<% DmsfHelper.dmsf_tree(parent, parent).each do |obj, level, position| %>
<% classes = "dmsf_tree idnt-#{level}" %>
<% if obj.is_a?(DmsfFolder) && ((obj.dmsf_folders.visible.count > 0) || (obj.dmsf_files.visible.count > 0) || (obj.dmsf_links.visible.count > 0)) %>
<% classes += ' idnt dmsf_collapsed' %>
<% id = "id='#{obj.id}span'".html_safe %>
<% onclick = "onclick=\"dmsf_toggle('#{obj.id}','#{obj.id}span')\"" %>
<% else %>
<% classes += ' dmsf_child' %>
<% onclick = '' %>
<% end %>
<%if obj.dmsf_folder && obj.dmsf_folder != @folder %>
<% classes += ' dmsf_hidden' %>
<% else %>
<%# Force odd/even backgroung style for visible items %>
<% classes += " dmsf_#{cycle('odd', 'even')}" %>
<% end %>
<% parent = obj.dmsf_folder %>
<% while parent %>
<% classes += " #{parent.id}" %>
<% parent = parent.dmsf_folder %>
<% end %>
<% if obj.is_a? DmsfFolder %>
<tr <%= id %> class="dir <%= classes %>">
<%= render(:partial => 'dir',
:locals => {
:project => @project,
:subfolder => obj,
:link => nil,
:id => obj.id,
:name => 'subfolders[]',
:title => obj.title,
:onclick => onclick,
:position => position}) %>
</tr>
<% elsif obj.is_a?(DmsfLink) && (obj.target_type == 'DmsfFolder') %>
<% unless obj.target_project %>
<% Rails.logger.error "Error: dmsf_link id #{obj.id} has no target!" %>
<% next %>
<% end %>
<tr <%= id %> class="dmsf_gray <%= classes %>">
<%= render(:partial => 'dir',
:locals => {
:project => obj.target_project,
:subfolder => obj.target_folder,
:link => obj,
:id => obj.id,
:name => 'dir_links[]',
:title => obj.name,
:onclick => onclick,
:position => position}) %>
</tr>
<% elsif obj.is_a?(DmsfFile) %>
<% unless obj.last_revision %>
<% Rails.logger.error "Error: dmsf_file id #{obj.id} has no revision!" %>
<% next %>
<% end %>
<tr <%= id %> class="file <%= classes %>">
<%= render(:partial => 'file', :locals => {
:project => @project,
:file => obj,
:link => nil,
:id => obj.id,
:name => 'files[]',
:title => obj.title,
:onclick => onclick,
:position => position}) %>
</tr>
<% elsif obj.is_a?(DmsfLink) && (obj.target_type == 'DmsfFile') %>
<% unless obj.target_file.last_revision %>
<% Rails.logger.error "Error: dmsf_file id #{obj.target_id} has no revision!" %>
<% next %>
<% end %>
<tr <%= id %> class="dmsf_gray <%= classes %>">
<%= render(:partial => 'file', :locals => {
:project => obj.target_project,
:file => obj.target_file,
:link => obj,
:id => obj.id,
:name => 'file_links[]',
:title => obj.name,
:onclick => onclick,
:position => position}) %>
</tr>
<% elsif obj.is_a?(DmsfLink) && (obj.target_type == 'DmsfUrl') %>
<tr <%= id %> class="dmsf_gray <%= classes %>">
<%= render(:partial => 'url', :locals => {
:project => obj.target_project,
:file => obj.target_file,
:link => obj,
:id => obj.id,
:name => 'file_links[]',
:title => obj.name,
:onclick => onclick,
:position => position}) %>
</tr>
<% end %>
<% end %>
<%= render(:partial => 'dmsf/dmsf_rows') %>
</tbody>
</table>

View File

@ -0,0 +1,39 @@
// Store DMSF controls
var dmsfButtons = $('#dmsf_buttons')[0].outerHTML
var dmsfTag = $('#dmsf_tag')[0].outerHTML
var browserInfo = $('#browser_info').text();
// Destroy the original dataTable
$("#browser").dataTable().fnDestroy();
// Add rows
$('#<%= params[:row_id] %>').after('<%= escape_javascript(render(:partial => 'dmsf/dmsf_rows')) %>');
// Reinitialize the dataTable
$('#browser').dataTable({
'bJQueryUI': true,
'oLanguage': {
'sUrl': "<%= plugin_asset_path(:redmine_dmsf, 'javascripts', json_url) %>"
},
'bAutoWidth': false,
'bPaginate': false,
'aaSorting': [[1, 'asc']],
'aaSortingFixed': [[ 8, 'asc']],
'aoColumnDefs': [
{ 'bSearchable': false, 'aTargets': [0, 7, 8, 9, 10, 11] },
{ 'bSortable': false, 'aTargets': [0, 7] },
{ 'iDataSort': 9, 'aTargets': [ 2 ] },
{ 'iDataSort': 10, 'aTargets': [ 3 ] },
{ 'iDataSort': 11, 'aTargets': [ 4 ] }
],
'fnInitComplete': function() {
$(dmsfButtons).prependTo($('#browser_wrapper div.fg-toolbar')[0]);
$(dmsfTag).prependTo($('#browser_wrapper div.fg-toolbar')[0]);
},
'fnInfoCallback': function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) {
return browserInfo;
}
});
// Hot fix
$('#browser').attr('style', 'width: 100%');

View File

@ -85,7 +85,7 @@
<%= form_tag({:action => :entries_operation, :id => @project, :folder_id => @folder}, :method => :post,
:class => 'dmsf_entries', :id => 'entries_form') do %>
<%= hidden_field_tag('action') %>
<div class="dmsf_controls" style="float: left">
<div id="dmsf_buttons" class="dmsf_controls" style="float: left">
<%= submit_tag(l(:button_download), :title => l(:title_download_checked), :name => 'download_entries') if @file_view_allowed %>
<%= submit_tag(l(:field_mail), :title => l(:title_send_checked_by_email), :name => 'email_entries') if (@file_view_allowed && User.current.allowed_to?(:email_documents, @project)) %>
<% if @file_delete_allowed%>
@ -94,7 +94,7 @@
</div>
<% values = @folder ? @folder.custom_field_values : @parent ? @parent.custom_field_values : DmsfFolder.new(:project => @project).custom_field_values %>
<% unless values.empty? %>
<div class="dmsf_controls" style="float: right">
<div id="dmsf_tag" class="dmsf_controls" style="float: right">
<%= custom_field_tag_with_label(
:dmsf_folder,
CustomValue.new(:custom_field_id => params[:custom_field_id].present? ? params[:custom_field_id] : values.first.custom_field_id, :value => params[:custom_value])) %>
@ -127,11 +127,6 @@
});
</script>
<%
sUrl = 'jquery.dataTables/en.json'
sUrl = "jquery.dataTables/#{I18n.locale.to_s.downcase}.json" if I18n.locale && !I18n.locale.to_s.match(/^en.*/)
%>
<% content_for :header_tags do %>
<%= javascript_include_tag 'bowser.min.js', :plugin => 'redmine_dmsf' %>
<%= stylesheet_link_tag 'jquery.dataTables/jquery-ui.dataTables.css', :plugin => 'redmine_dmsf' %>
@ -142,7 +137,7 @@
$('#browser').dataTable({
'bJQueryUI': true,
'oLanguage': {
'sUrl': "<%= plugin_asset_path(:redmine_dmsf, 'javascripts', sUrl) %>"
'sUrl': "<%= plugin_asset_path(:redmine_dmsf, 'javascripts', json_url) %>"
},
'bAutoWidth': false,
'bPaginate': false,
@ -156,7 +151,8 @@
{ 'iDataSort': 11, 'aTargets': [ 4 ] }
],
'fnInitComplete': function() {
jQuery('div.dmsf_controls').prependTo(jQuery('#browser_wrapper div.fg-toolbar')[0]);
$('#dmsf_buttons').prependTo($('#browser_wrapper div.fg-toolbar')[0]);
$('#dmsf_tag').prependTo($('#browser_wrapper div.fg-toolbar')[0]);
},
'fnInfoCallback': function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) {
<% if @tree_view %>

View File

@ -152,11 +152,6 @@
});
</script>
<%
sUrl = "jquery.dataTables/#{I18n.locale.to_s.downcase}.json"
sUrl = 'jquery.dataTables/en.json' unless File.exist?(sUrl)
%>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'jquery.dataTables/jquery-ui.dataTables.css', :plugin => 'redmine_dmsf' %>
<%= javascript_include_tag 'jquery.dataTables/jquery.dataTables.min.js', :plugin => 'redmine_dmsf' %>
@ -166,7 +161,7 @@
$('#browser').dataTable({
'bJQueryUI': true,
'oLanguage': {
'sUrl': "<%= plugin_asset_path(:redmine_dmsf, 'javascripts', sUrl) %>"
'sUrl': "<%= plugin_asset_path(:redmine_dmsf, 'javascripts', json_url) %>"
},
'bAutoWidth': false,
'bPaginate': false,
@ -180,7 +175,7 @@
{ 'iDataSort': 11, 'aTargets': [ 4 ] }
],
'fnInitComplete': function() {
jQuery('div.dmsf_controls').prependTo(jQuery('#browser_wrapper div.fg-toolbar')[0]);
$('div.dmsf_controls').prependTo($('#browser_wrapper div.fg-toolbar')[0]);
},
'fnInfoCallback': function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) {
return "<%= l(:label_number_of_folders)%>: <%= @subfolders.count + @dir_links.count %>, <%= l(:label_number_of_documents)%>: <%= @files.count + @file_links.count + @url_links.count %>";

View File

@ -85,7 +85,7 @@
multipart: true,
// Enable ability to drag'n'drop files onto the widget (currently only HTML5 supports that)
dragdrop: true,
multipart_params : {authenticity_token : jQuery('input[name=authenticity_token]').val()},
multipart_params : { authenticity_token : $('input[name=authenticity_token]').val() },
// Rename files by clicking on their titles
rename: true,
@ -134,11 +134,11 @@
pluploader.trigger('QueueChanged');
}
}
if(pluploader.total.uploaded == pluploader.files.length) jQuery('#uploadform').submit();
if(pluploader.total.uploaded == pluploader.files.length) $('#uploadform').submit();
else if((pluploader.total.uploaded + pluploader.total.failed) == pluploader.files.length) setTimeout(function() {$('#uploadform').submit();}, 2000);
else dmsfFileFieldCount++;
return true;
});
}
</script>
<% end %>
<% end %>

View File

@ -20,9 +20,9 @@
*/
/* Function to allow the projects to show up as a tree */
function dmsf_toggle(EL, PM)
function dmsfToggle(EL, PM, url)
{
var els = document.getElementsByTagName('tr');
var els = document.querySelectorAll('tr.dmsf_tree');
var elsLen = els.length;
var pattern = new RegExp("(^|\\s)" + EL + "(\\s|$)");
var cpattern = new RegExp('span');
@ -33,6 +33,14 @@ function dmsf_toggle(EL, PM)
var classid = new RegExp('junk');
var oddeventoggle = 0;
// Expand not yet loaded selected row
var selectedRow = document.getElementById(PM);
if(selectedRow.className.indexOf('dmsf-not-loaded') >= 0){
dmsfExpandRows(EL, selectedRow, url);
}
for(i = 0; i < elsLen; i++)
{
if(cpattern.test(els[i].id))
@ -61,7 +69,7 @@ function dmsf_toggle(EL, PM)
cnames = cnames.replace(/dmsf_hidden/g,'');
if(expand.test(document.getElementById(PM).className))
if(expand.test(selectedRow.className))
{
cnames += ' dmsf_hidden';
}
@ -100,18 +108,43 @@ function dmsf_toggle(EL, PM)
}
}
if (collapse.test(document.getElementById(PM).className))
if (collapse.test(selectedRow.className))
{
var cnames = document.getElementById(PM).className;
var cnames = selectedRow.className;
cnames = cnames.replace(/dmsf_collapsed/,'dmsf_expanded');
document.getElementById(PM).className = cnames;
selectedRow.className = cnames;
}
else
{
var cnames = document.getElementById(PM).className;
var cnames = selectedRow.className;
cnames = cnames.replace(/dmsf_expanded/,'dmsf_collapsed');
document.getElementById(PM).className = cnames;
selectedRow.className = cnames;
}
}
/* Add child rows */
function dmsfExpandRows(EL, parentRow, url) {
parentRow.className = parentRow.className.replace(/dmsf-not-loaded/, '');
var idnt = 0;
var result = parentRow.className.match(/idnt-(\d+)/);
if(result){
idnt = result[1];
}
var pos = $(parentRow).find('#dmsf_position').text();
return $.ajax({
url: url,
type: 'post',
data: {
folder_id: EL,
row_id: parentRow.id,
idnt: idnt,
pos: pos}
});
}

View File

@ -46,6 +46,7 @@ RedmineApp::Application.routes.draw do
get '/projects/:id/dmsf/edit/root', :controller => 'dmsf', :action => 'edit_root', :as => 'edit_root_dmsf'
get '/projects/:id/dmsf/trash', :controller => 'dmsf', :action => 'trash', :as => 'trash_dmsf'
get '/projects/:id/dmsf/restore', :controller => 'dmsf', :action => 'restore', :as => 'restore_dmsf'
post '/projects/:id/dmsf/expand_folder', :controller => 'dmsf', :action => 'expand_folder', :as => 'expand_folder_dmsf'
#
# dmsf_state controller