[ARVADOS] created: 036b3b0ddb515f1f4f4588bfe1ea7e010dfd6bd4
git at public.curoverse.com
git at public.curoverse.com
Tue May 13 17:31:51 EDT 2014
at 036b3b0ddb515f1f4f4588bfe1ea7e010dfd6bd4 (commit)
commit 036b3b0ddb515f1f4f4588bfe1ea7e010dfd6bd4
Author: Brett Smith <brett at curoverse.com>
Date: Tue May 13 17:31:29 2014 -0400
2753: Workbench renders "0 bytes" for empty file sizes.
diff --git a/apps/workbench/app/helpers/application_helper.rb b/apps/workbench/app/helpers/application_helper.rb
index dbb05d6..022a313 100644
--- a/apps/workbench/app/helpers/application_helper.rb
+++ b/apps/workbench/app/helpers/application_helper.rb
@@ -17,6 +17,7 @@ module ApplicationHelper
def human_readable_bytes_html(n)
return h(n) unless n.is_a? Fixnum
+ return "0 bytes" if (n == 0)
orders = {
1 => "bytes",
commit cf117cf537c8da637c3e74f232cc97352ca98f16
Author: Brett Smith <brett at curoverse.com>
Date: Tue May 13 13:15:30 2014 -0400
2753: Workbench shows Collection files in a tree.
diff --git a/apps/workbench/Gemfile b/apps/workbench/Gemfile
index bcbe3ef..4d1eb29 100644
--- a/apps/workbench/Gemfile
+++ b/apps/workbench/Gemfile
@@ -37,6 +37,7 @@ group :test do
end
gem 'jquery-rails'
+gem 'jstree-rails', :git => 'git://github.com/xinlangzi/jstree-rails.git'
gem 'bootstrap-sass', '~> 3.1.0'
gem 'bootstrap-x-editable-rails'
diff --git a/apps/workbench/Gemfile.lock b/apps/workbench/Gemfile.lock
index 8e74832..676bde1 100644
--- a/apps/workbench/Gemfile.lock
+++ b/apps/workbench/Gemfile.lock
@@ -1,3 +1,10 @@
+GIT
+ remote: git://github.com/xinlangzi/jstree-rails.git
+ revision: bdf08b19a7fba167e8cdf7db57669a54dedd9bf3
+ specs:
+ jstree-rails (1.0.0)
+ rails (>= 3.2)
+
GEM
remote: https://rubygems.org/
specs:
@@ -194,6 +201,7 @@ DEPENDENCIES
headless
httpclient
jquery-rails
+ jstree-rails!
less
less-rails
multi_json
diff --git a/apps/workbench/app/assets/javascripts/application.js b/apps/workbench/app/assets/javascripts/application.js
index d66cb92..01239c2 100644
--- a/apps/workbench/app/assets/javascripts/application.js
+++ b/apps/workbench/app/assets/javascripts/application.js
@@ -12,6 +12,7 @@
//
//= require jquery
//= require jquery_ujs
+//= require jstree
//= require bootstrap
//= require bootstrap/dropdown
//= require bootstrap/tab
diff --git a/apps/workbench/app/assets/stylesheets/application.css.scss b/apps/workbench/app/assets/stylesheets/application.css.scss
index 51c96d7..6fc8cd0 100644
--- a/apps/workbench/app/assets/stylesheets/application.css.scss
+++ b/apps/workbench/app/assets/stylesheets/application.css.scss
@@ -9,6 +9,7 @@
* compiled file, but it's generally better to create a new file per style scope.
*
*= require_self
+ *= require jstree-themes/default/style
*= require bootstrap
*= require bootstrap3-editable/bootstrap-editable
*= require_tree .
diff --git a/apps/workbench/app/views/collections/_show_files.html.erb b/apps/workbench/app/views/collections/_show_files.html.erb
index 4b63162..827cb01 100644
--- a/apps/workbench/app/views/collections/_show_files.html.erb
+++ b/apps/workbench/app/views/collections/_show_files.html.erb
@@ -2,9 +2,55 @@
.file-list-inline-image {
width: 50%;
height: auto;
+ margin: auto auto;
+}
+
+div#collection_files {
+ width: 49%;
+ float: left;
+ overflow: auto;
+}
+
+i.jstree-icon {
+ font-style: normal;
+}
+
+div#collections_file_pane {
+ width: 50%;
+ float: right;
+}
+
+div#collections_file_pane h3 {
+ margin: 0;
+}
+
+.collections_file_size {
+ margin-top: 0em;
+ font-style: italic;
}
<% end %>
+<% content_for :js do %>
+$(function () {
+$("div#collection_files")
+.on("activate_node.jstree", function(event, data) {
+ if (data.instance.is_leaf(data.node)) {
+ var file_info = $("div[title=\"" + data.node.li_attr.title + "\"]").html();
+ $("div#collections_file_pane").html(file_info);
+ } else {
+ data.instance.toggle_node(data.node);
+ }
+})
+.jstree({
+ "core": {
+ "themes": {"stripes": true},
+ "multiple": false
+ },
+ "plugins": ["wholerow"],
+});
+});
+<% end %>
+
<% content_for :tab_line_buttons do %>
<div class="row">
<div class="col-md-6"></div>
@@ -17,59 +63,59 @@
</div>
<% end %>
-<table class="table table-condensed table-fixedlayout">
- <colgroup>
- <col width="4%" />
- <col width="35%" />
- <col width="40%" />
- <col width="15%" />
- <col width="10%" />
- </colgroup>
- <thead>
- <tr>
- <th></th>
- <th>path</th>
- <th>file</th>
- <th style="text-align:right">size</th>
- <th>d/l</th>
- </tr>
- </thead><tbody>
- <% if @object then @object.files.sort_by{|f|[f[0],f[1]]}.each do |file| %>
- <% file_path = CollectionsHelper::file_path file %>
- <tr>
- <td>
- <%= check_box_tag 'uuids[]', @object.uuid+'/'+file_path, false, {
- :class => 'persistent-selection',
- :friendly_type => "File",
- :friendly_name => "#{@object.uuid}/#{file_path}",
- :href => "#{url_for controller: 'collections', action: 'show', id: @object.uuid }/#{file_path}",
- :title => "Click to add this item to your selection list"
- } %>
- </td>
- <td>
- <%= file[0] %>
- </td>
-
- <td>
- <%= link_to (if CollectionsHelper::is_image file[1]
- image_tag "#{url_for @object}/#{file_path}", class: "file-list-inline-image"
- else
- file[1]
- end),
- {controller: 'collections', action: 'show_file', uuid: @object.uuid, file: file_path, size: file[2], disposition: 'inline'},
- {title: file_path} %>
- </td>
-
- <td style="text-align:right">
- <%= raw(human_readable_bytes_html(file[2])) %>
- </td>
-
- <td>
- <div style="display:inline-block">
- <%= link_to raw('<i class="glyphicon glyphicon-download-alt"></i>'), {controller: 'collections', action: 'show_file', uuid: @object.uuid, file: file_path, size: file[2], disposition: 'attachment'}, {class: 'btn btn-info btn-sm', title: 'Download'} %>
- </div>
- </td>
- </tr>
- <% end; end %>
- </tbody>
-</table>
+<% file_tree = @object.andand.files_tree %>
+<% if file_tree.nil? or file_tree.empty? %>
+ <p>This collection is empty.</p>
+<% else %>
+ <div id="collection_files"><ul>
+ <% dirstack = ["."] %>
+ <% file_tree.each do |dirname, filename, size| %>
+ <% while dirstack.any? and (dirstack.last != dirname) %>
+ <% dirstack.pop %></ul></li>
+ <% end %>
+ <% if size.nil? # This is a subdirectory. %>
+ <% dirstack.push(File.join(dirname, filename)) %>
+ <li data-jstree='{"icon": "fa-folder"}' class="jstree-open"><%= filename %><ul>
+ <% else %>
+ <% data = {'icon' => (CollectionsHelper::is_image(filename) ? 'fa-bar-chart-o' : 'fa-file') } %>
+ <li data-jstree='<%= data.to_json %>'
+ title="<%= CollectionsHelper::file_path([dirname, filename]) %>"><%= filename %></li>
+ <% end %>
+ <% end %>
+ </ul></div>
+ <div id="collections_file_pane">Select a file to view more information.</div>
+ <% file_tree.reject { |data| data.last.nil? }.each do |dirname, filename, size| %>
+ <% file_path = CollectionsHelper::file_path([dirname, filename])
+ link_params = {controller: 'collections',
+ action: 'show_file',
+ uuid: @object.uuid,
+ file: file_path,
+ size: size} %>
+ <div title="<%= file_path %>" style="display: none;">
+ <h3><%= file_path %></h3>
+ <p class="collections_file_size"><%= raw(human_readable_bytes_html(size)) %></p>
+ <%= link_to("View", link_params.merge(disposition: 'inline'),
+ {class: "btn btn-primary"}) %>
+ <%= link_to("Download", link_params.merge(disposition: 'attachment'),
+ {class: "btn btn-primary"}) %>
+ <p>
+ <%= check_box_tag 'uuids[]', "#{@object.uuid}/#{file_path}", false, {
+ :class => 'persistent-selection',
+ :friendly_type => "File",
+ :friendly_name => "#{@object.uuid}/#{file_path}",
+ :href => url_for(controller: 'collections', action: 'show_file',
+ uuid: @object.uuid, file: file_path),
+ :title => "Include this file in your selections",
+ } %>
+ Include this file in your selections
+ </p>
+ <% if CollectionsHelper::is_image(filename) %>
+ <div style="text-align: center;">
+ <%= link_to(image_tag("#{url_for @object}/#{file_path}", class: "file-list-inline-image"),
+ link_params.merge(disposition: 'inline'),
+ {title: file_path}) %>
+ </div>
+ <% end %>
+ </div>
+ <% end %>
+<% end %>
commit 04ed028ca994d24046175331e3bbe74dc734118d
Author: Brett Smith <brett at curoverse.com>
Date: Mon May 12 17:29:55 2014 -0400
2753: Add Workbench Collection#files_tree.
diff --git a/apps/workbench/app/models/collection.rb b/apps/workbench/app/models/collection.rb
index a63bf90..20da7ec 100644
--- a/apps/workbench/app/models/collection.rb
+++ b/apps/workbench/app/models/collection.rb
@@ -22,6 +22,27 @@ class Collection < ArvadosBase
end
end
+ def files_tree
+ tree = files.group_by { |file_spec| File.split(file_spec.first) }
+ # Fill in entries for empty directories.
+ tree.keys.map { |basedir, _| File.split(basedir) }.each do |splitdir|
+ until tree.include?(splitdir)
+ tree[splitdir] = []
+ splitdir = File.split(splitdir.first)
+ end
+ end
+ dir_to_tree = lambda do |dirname|
+ # First list subdirectories, with their files inside.
+ subnodes = tree.keys.select { |bd, td| (bd == dirname) and (td != '.') }
+ .sort.flat_map do |parts|
+ [parts + [nil]] + dir_to_tree.call(File.join(parts))
+ end
+ # Then extend that list with files in this directory.
+ subnodes + tree[File.split(dirname)]
+ end
+ dir_to_tree.call('.')
+ end
+
def attribute_editable?(attr)
false
end
diff --git a/apps/workbench/test/unit/collection_test.rb b/apps/workbench/test/unit/collection_test.rb
index bbfc983..512ad47 100644
--- a/apps/workbench/test/unit/collection_test.rb
+++ b/apps/workbench/test/unit/collection_test.rb
@@ -13,4 +13,31 @@ class CollectionTest < ActiveSupport::TestCase
assert_equal false, Collection.is_empty_blob_locator?(x)
end
end
+
+ def get_files_tree(coll_name)
+ use_token :admin
+ Collection.find(api_fixture('collections')[coll_name]['uuid']).files_tree
+ end
+
+ test "easy files_tree" do
+ files_in = lambda do |dirname|
+ (1..3).map { |n| [dirname, "file#{n}", 0] }
+ end
+ assert_equal([['.', 'dir1', nil], ['./dir1', 'subdir', nil]] +
+ files_in['./dir1/subdir'] + files_in['./dir1'] +
+ [['.', 'dir2', nil]] + files_in['./dir2'] + files_in['.'],
+ get_files_tree('multilevel_collection_1'),
+ "Collection file tree was malformed")
+ end
+
+ test "files_tree with files deep in subdirectories" do
+ # This test makes sure files_tree generates synthetic directory entries.
+ # The manifest doesn't list directories with no files.
+ assert_equal([['.', 'dir1', nil], ['./dir1', 'sub1', nil],
+ ['./dir1/sub1', 'a', 0], ['./dir1/sub1', 'b', 0],
+ ['.', 'dir2', nil], ['./dir2', 'sub2', nil],
+ ['./dir2/sub2', 'c', 0], ['./dir2/sub2', 'd', 0]],
+ get_files_tree('multilevel_collection_2'),
+ "Collection file tree was malformed")
+ end
end
diff --git a/services/api/test/fixtures/collections.yml b/services/api/test/fixtures/collections.yml
index ce05d18..26f5f48 100644
--- a/services/api/test/fixtures/collections.yml
+++ b/services/api/test/fixtures/collections.yml
@@ -37,3 +37,24 @@ baz_file:
modified_at: 2014-02-03T17:22:54Z
updated_at: 2014-02-03T17:22:54Z
manifest_text: ". 73feffa4b7f6bb68e44cf984c85f6e88+3 0:3:baz\n"
+
+multilevel_collection_1:
+ uuid: 1fd08fc162a5c6413070a8bd0bffc818+150
+ owner_uuid: qr1hi-tpzed-000000000000000
+ created_at: 2014-02-03T17:22:54Z
+ modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
+ modified_by_user_uuid: zzzzz-tpzed-d9tiejq69daie8f
+ modified_at: 2014-02-03T17:22:54Z
+ updated_at: 2014-02-03T17:22:54Z
+ manifest_text: ". 0:0:file1 0:0:file2 0:0:file3\n./dir1 0:0:file1 0:0:file2 0:0:file3\n./dir1/subdir 0:0:file1 0:0:file2 0:0:file3\n./dir2 0:0:file1 0:0:file2 0:0:file3\n"
+
+multilevel_collection_2:
+ # All of this collection's files are deep in subdirectories.
+ uuid: 80cf6dd2cf079dd13f272ec4245cb4a8+48
+ owner_uuid: qr1hi-tpzed-000000000000000
+ created_at: 2014-02-03T17:22:54Z
+ modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
+ modified_by_user_uuid: zzzzz-tpzed-d9tiejq69daie8f
+ modified_at: 2014-02-03T17:22:54Z
+ updated_at: 2014-02-03T17:22:54Z
+ manifest_text: "./dir1/sub1 0:0:a 0:0:b\n./dir2/sub2 0:0:c 0:0:d\n"
commit b519a95d758587ba82a1d9b5ffaa0d84292f7aaa
Author: Brett Smith <brett at curoverse.com>
Date: Mon May 12 11:21:12 2014 -0400
2753: Add tests for CollectionsHelper.file_path.
diff --git a/apps/workbench/test/unit/helpers/collections_helper_test.rb b/apps/workbench/test/unit/helpers/collections_helper_test.rb
index 16a85d9..56d23c5 100644
--- a/apps/workbench/test/unit/helpers/collections_helper_test.rb
+++ b/apps/workbench/test/unit/helpers/collections_helper_test.rb
@@ -1,4 +1,12 @@
require 'test_helper'
class CollectionsHelperTest < ActionView::TestCase
+ test "file_path generates short names" do
+ assert_equal('foo', CollectionsHelper.file_path(['.', 'foo', 0]),
+ "wrong result for filename in collection root")
+ assert_equal('foo/bar', CollectionsHelper.file_path(['foo', 'bar', 0]),
+ "wrong result for filename in directory without leading .")
+ assert_equal('foo/bar', CollectionsHelper.file_path(['./foo', 'bar', 0]),
+ "wrong result for filename in directory with leading .")
+ end
end
commit a73dca721e2d1cf3c83a40c2d23e0f45d2beee82
Author: Brett Smith <brett at curoverse.com>
Date: Mon May 12 10:37:55 2014 -0400
2753: Make Collection filenames with existing helper.
This is pure refactoring to make the code more consistent.
diff --git a/apps/workbench/app/controllers/collections_controller.rb b/apps/workbench/app/controllers/collections_controller.rb
index 4178e38..0fef60d 100644
--- a/apps/workbench/app/controllers/collections_controller.rb
+++ b/apps/workbench/app/controllers/collections_controller.rb
@@ -210,12 +210,9 @@ class CollectionsController < ApplicationController
end
def file_in_collection?(collection, filename)
- def normalized_path(part_list)
- File.join(part_list).sub(%r{^\./}, '')
- end
- target = normalized_path([filename])
+ target = CollectionsHelper.file_path(File.split(filename))
collection.files.each do |file_spec|
- return true if (normalized_path(file_spec[0, 2]) == target)
+ return true if (CollectionsHelper.file_path(file_spec) == target)
end
false
end
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list