[ARVADOS] updated: 5aac4c685edaa685c255dcf79aefde46c267e6d7

git at public.curoverse.com git at public.curoverse.com
Wed May 21 20:21:26 EDT 2014


Summary of changes:
 .../app/assets/javascripts/select_modal.js         | 39 ++++++++++++++++++++++
 .../app/assets/stylesheets/select_modal.css.scss   |  3 ++
 .../app/controllers/application_controller.rb      | 14 ++++----
 .../app/controllers/folders_controller.rb          | 18 +++++++---
 apps/workbench/app/models/arvados_base.rb          |  4 +++
 apps/workbench/app/views/folders/_choose.html.erb  | 35 +++++++++++++++++++
 apps/workbench/app/views/folders/_choose.js.erb    |  8 +++++
 .../app/views/folders/_show_folders.html.erb       | 14 +++++---
 apps/workbench/app/views/folders/show.html.erb     | 35 +++++++++++++++----
 .../app/views/layouts/application.html.erb         |  1 +
 apps/workbench/config/routes.rb                    |  1 +
 apps/workbench/test/integration/folders_test.rb    | 39 ++++++++++++++++++++--
 services/api/app/models/group.rb                   | 16 +++++++++
 13 files changed, 203 insertions(+), 24 deletions(-)
 create mode 100644 apps/workbench/app/assets/javascripts/select_modal.js
 create mode 100644 apps/workbench/app/assets/stylesheets/select_modal.css.scss
 create mode 100644 apps/workbench/app/views/folders/_choose.html.erb
 create mode 100644 apps/workbench/app/views/folders/_choose.js.erb

       via  5aac4c685edaa685c255dcf79aefde46c267e6d7 (commit)
       via  8ab98660dfc1973cced8b1deed355336cf4c5e64 (commit)
       via  540dbe405430bc8d58a07cfff141b4b4bc9811c1 (commit)
      from  8f20c1723c0614fabedb2c2468932d9245a1fc86 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 5aac4c685edaa685c255dcf79aefde46c267e6d7
Author: Tom Clegg <tom at curoverse.com>
Date:   Wed May 21 20:21:16 2014 -0400

    2760: Add test case.

diff --git a/apps/workbench/test/integration/folders_test.rb b/apps/workbench/test/integration/folders_test.rb
index 3039786..7518d3c 100644
--- a/apps/workbench/test/integration/folders_test.rb
+++ b/apps/workbench/test/integration/folders_test.rb
@@ -3,9 +3,11 @@ require 'selenium-webdriver'
 require 'headless'
 
 class FoldersTest < ActionDispatch::IntegrationTest
+  setup do
+    Capybara.current_driver = Capybara.javascript_driver
+  end
 
   test 'Find a folder and edit its description' do
-    Capybara.current_driver = Capybara.javascript_driver
     visit page_with_token 'active', '/'
     find('nav a', text: 'Folders').click
     find('.arv-folder-list a,button', text: 'A Folder').
@@ -24,7 +26,6 @@ class FoldersTest < ActionDispatch::IntegrationTest
   end
 
   test 'Add a new name, then edit it, without creating a duplicate' do
-    Capybara.current_driver = Capybara.javascript_driver
     folder_uuid = api_fixture('groups')['afolder']['uuid']
     specimen_uuid = api_fixture('specimens')['owned_by_afolder_with_no_name_link']['uuid']
     visit page_with_token 'active', '/folders/' + folder_uuid
@@ -45,4 +46,38 @@ class FoldersTest < ActionDispatch::IntegrationTest
     end
   end
 
+  test 'Create a folder and move it into a different folder' do
+    visit page_with_token 'active', '/folders'
+    find('input[value="Add a new folder"]').click
+
+    within('.panel', text: 'New folder') do
+      find('.panel-title span', text: 'New folder').click
+      find('.editable-input input').set('Folder 1234')
+      find('.glyphicon-ok').click
+    end
+    wait_for_ajax
+
+    visit '/folders'
+    find('input[value="Add a new folder"]').click
+    within('.panel', text: 'New folder') do
+      find('.panel-title span', text: 'New folder').click
+      find('.editable-input input').set('Folder 5678')
+      find('.glyphicon-ok').click
+    end
+    wait_for_ajax
+
+    find('input[value="Move to..."]').click
+    find('.selectable', text: 'Folder 1234').click
+    find('a,button', text: 'Move').click
+    wait_for_ajax
+
+    # Wait for the page to refresh and show the new parent folder in
+    # the Permissions panel:
+    find('.panel', text: 'Folder 1234')
+
+    assert(find('.panel', text: 'Permissions inherited from').
+           all('*', text: 'Folder 1234').any?,
+           "Folder 5678 should now be inside folder 1234")
+  end
+
 end

commit 8ab98660dfc1973cced8b1deed355336cf4c5e64
Author: Tom Clegg <tom at curoverse.com>
Date:   Wed May 21 20:20:54 2014 -0400

    2760: Refresh permission cache after changing group uuid or owner_uuid.

diff --git a/services/api/app/models/group.rb b/services/api/app/models/group.rb
index f055716..d380244 100644
--- a/services/api/app/models/group.rb
+++ b/services/api/app/models/group.rb
@@ -5,6 +5,8 @@ class Group < ArvadosModel
   include KindAndEtag
   include CommonApiTemplate
   include CanBeAnOwner
+  after_create :invalidate_permissions_cache
+  after_update :maybe_invalidate_permissions_cache
 
   api_accessible :user, extend: :common do |t|
     t.add :name
@@ -12,4 +14,18 @@ class Group < ArvadosModel
     t.add :description
     t.add :writable_by
   end
+
+  def maybe_invalidate_permissions_cache
+    if uuid_changed? or owner_uuid_changed?
+      # This can change users' permissions on other groups as well as
+      # this one.
+      invalidate_permissions_cache
+    end
+  end
+
+  def invalidate_permissions_cache
+    # Ensure a new group can be accessed by the appropriate users
+    # immediately after being created.
+    User.invalidate_permissions_cache
+  end
 end

commit 540dbe405430bc8d58a07cfff141b4b4bc9811c1
Author: Tom Clegg <tom at curoverse.com>
Date:   Wed May 21 19:17:53 2014 -0400

    2760: Add "move to a different folder" button to folders#show.

diff --git a/apps/workbench/app/assets/javascripts/select_modal.js b/apps/workbench/app/assets/javascripts/select_modal.js
new file mode 100644
index 0000000..85d97c9
--- /dev/null
+++ b/apps/workbench/app/assets/javascripts/select_modal.js
@@ -0,0 +1,39 @@
+$(document).on('click', '.selectable', function() {
+    var $this = $(this);
+    if (!$this.hasClass('multiple')) {
+        $this.closest('.selectable-container').
+            find('.selectable').
+            removeClass('active');
+    }
+    $this.toggleClass('active');
+}).on('click', '.modal button[data-action-href]', function() {
+    var selection = [];
+    var data = {};
+    var $modal = $(this).closest('.modal');
+    $modal.find('.modal-error').removeClass('hide').hide();
+    $modal.find('.selectable.active[data-object-uuid]').each(function() {
+        selection.push($(this).attr('data-object-uuid'));
+    });
+    data[$(this).data('action-data').selection_param] = selection[0];
+    $.ajax($(this).attr('data-action-href'),
+           {dataType: 'json',
+            type: $(this).attr('data-method'),
+            data: data,
+            context: {modal: $modal}}).
+        fail(function(jqxhr, status, error) {
+            if (jqxhr.readyState == 0 || jqxhr.status == 0) {
+                message = "Cancelled."
+            } else if (jqxhr.responseJSON && jqxhr.responseJSON.errors) {
+                message = jqxhr.responseJSON.errors.join("; ");
+            } else {
+                message = "Request failed.";
+            }
+            this.modal.find('.modal-error').
+                html('<div class="alert alert-danger">' + message + '</div>').
+                show();
+        }).
+        success(function() {
+            this.modal.find('.modal-error').hide();
+            window.location.reload();
+        });
+});
diff --git a/apps/workbench/app/assets/stylesheets/select_modal.css.scss b/apps/workbench/app/assets/stylesheets/select_modal.css.scss
new file mode 100644
index 0000000..6fe5651
--- /dev/null
+++ b/apps/workbench/app/assets/stylesheets/select_modal.css.scss
@@ -0,0 +1,3 @@
+.selectable.active, .selectable:hover {
+    background: #d9edf7;
+}
diff --git a/apps/workbench/app/controllers/application_controller.rb b/apps/workbench/app/controllers/application_controller.rb
index 4d6008a..2b71eea 100644
--- a/apps/workbench/app/controllers/application_controller.rb
+++ b/apps/workbench/app/controllers/application_controller.rb
@@ -122,21 +122,21 @@ class ApplicationController < ActionController::Base
   end
 
   def update
-    updates = params[@object.class.to_s.underscore.singularize.to_sym]
-    updates.keys.each do |attr|
+    @updates ||= params[@object.class.to_s.underscore.singularize.to_sym]
+    @updates.keys.each do |attr|
       if @object.send(attr).is_a? Hash
-        if updates[attr].is_a? String
-          updates[attr] = Oj.load updates[attr]
+        if @updates[attr].is_a? String
+          @updates[attr] = Oj.load @updates[attr]
         end
         if params[:merge] || params["merge_#{attr}".to_sym]
           # Merge provided Hash with current Hash, instead of
           # replacing.
-          updates[attr] = @object.send(attr).with_indifferent_access.
-            deep_merge(updates[attr].with_indifferent_access)
+          @updates[attr] = @object.send(attr).with_indifferent_access.
+            deep_merge(@updates[attr].with_indifferent_access)
         end
       end
     end
-    if @object.update_attributes updates
+    if @object.update_attributes @updates
       show
     else
       self.render_error status: 422
diff --git a/apps/workbench/app/controllers/folders_controller.rb b/apps/workbench/app/controllers/folders_controller.rb
index b87a94b..fe7c9d2 100644
--- a/apps/workbench/app/controllers/folders_controller.rb
+++ b/apps/workbench/app/controllers/folders_controller.rb
@@ -39,11 +39,11 @@ class FoldersController < ApplicationController
 
   def index
     @objects = Group.where(group_class: 'folder').order('name')
-    parent_of = {}
+    parent_of = {current_user.uuid => 'me'}
     @objects.each do |ob|
       parent_of[ob.uuid] = ob.owner_uuid
     end
-    children_of = {false => [], current_user.uuid => []}
+    children_of = {false => [], 'me' => [current_user]}
     @objects.each do |ob|
       if ob.owner_uuid != current_user.uuid and
           not parent_of.has_key? ob.owner_uuid
@@ -61,16 +61,21 @@ class FoldersController < ApplicationController
     end
     def sorted_paths tree, depth=0
       paths = []
-      tree.keys.sort_by { |ob| ob.name || 'New folder' }.each do |ob|
+      tree.keys.sort_by { |ob| ob.friendly_link_name }.each do |ob|
         paths << {object: ob, depth: depth}
         paths += sorted_paths tree[ob], depth+1
       end
       paths
     end
-    @my_folder_tree = sorted_paths buildtree(children_of, current_user.uuid)
+    @my_folder_tree = sorted_paths buildtree(children_of, 'me')
     @shared_folder_tree = sorted_paths buildtree(children_of, false)
   end
 
+  def choose
+    index
+    render partial: 'choose'
+  end
+
   def show
     @objects = @object.contents include_linked: true
     @share_links = Link.filter([['head_uuid', '=', @object.uuid],
@@ -100,4 +105,9 @@ class FoldersController < ApplicationController
     @new_resource_attrs[:name] ||= 'New folder'
     super
   end
+
+  def update
+    @updates = params['folder']
+    super
+  end
 end
diff --git a/apps/workbench/app/models/arvados_base.rb b/apps/workbench/app/models/arvados_base.rb
index 1ad0230..00e4dc1 100644
--- a/apps/workbench/app/models/arvados_base.rb
+++ b/apps/workbench/app/models/arvados_base.rb
@@ -351,6 +351,10 @@ class ArvadosBase < ActiveRecord::Base
     friendly_link_name
   end
 
+  def owner
+    ArvadosBase.find(owner_uuid) rescue nil
+  end
+
   protected
 
   def forget_uuid!
diff --git a/apps/workbench/app/views/folders/_choose.html.erb b/apps/workbench/app/views/folders/_choose.html.erb
new file mode 100644
index 0000000..d0fa73b
--- /dev/null
+++ b/apps/workbench/app/views/folders/_choose.html.erb
@@ -0,0 +1,35 @@
+<div class="modal">
+  <div class="modal-dialog">
+    <div class="modal-content">
+
+      <div class="modal-header">
+        <button type="button" class="close" onClick="reset_form()" data-dismiss="modal" aria-hidden="true">×</button>
+        <h4 class="modal-title"><%= params[:title] || 'Choose folder' %></h4>
+      </div>
+
+      <div class="modal-body">
+        <div class="container-fluid arv-folder-list selectable-container" style="height: 15em; overflow-y: scroll">
+          <% [[@my_folder_tree, 'My folders'],
+             [@shared_folder_tree, 'Shared with me']].each do |tree, label| %>
+            <div class="row">
+              <i class="fa fa-fw fa-folder-open-o"></i> <%= label %>
+            </div>
+            <% tree.each do |foldernode| %>
+              <div class="<%= 'selectable' if !params[:editable] || foldernode[:object].editable? %> folder row" style="padding-left: <%= 1 + foldernode[:depth] %>em;" data-object-uuid="<%= foldernode[:object].uuid %>">
+                <i class="fa fa-fw fa-folder-o"></i>
+                <%= foldernode[:object].friendly_link_name || 'New folder' %>
+              </div>
+            <% end %>
+          <% end %>
+        </div>
+      </div>
+
+      <div class="modal-footer">
+        <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Cancel</button>
+        <button class="btn btn-primary" aria-hidden="true"><%= params[:action_name] || 'Select' %></button>
+        <div class="modal-error hide" style="text-align: left; margin-top: 1em;">
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/apps/workbench/app/views/folders/_choose.js.erb b/apps/workbench/app/views/folders/_choose.js.erb
new file mode 100644
index 0000000..4ecd072
--- /dev/null
+++ b/apps/workbench/app/views/folders/_choose.js.erb
@@ -0,0 +1,8 @@
+$('body > .modal-container').html("<%= escape_javascript(render partial: 'choose.html') %>");
+$('body > .modal-container .modal').modal('show');
+$('body > .modal-container .modal .modal-footer .btn-primary').
+    addClass('<%= j params[:action_class] %>').
+    attr('data-action-href', '<%= j params[:action_href] %>').
+    attr('data-method', '<%= j params[:action_method] %>').
+    data('action-data', <%= raw params[:action_data] %>);
+$(document).trigger('ajax:complete');
diff --git a/apps/workbench/app/views/folders/_show_folders.html.erb b/apps/workbench/app/views/folders/_show_folders.html.erb
index f2dd1c0..e0c010d 100644
--- a/apps/workbench/app/views/folders/_show_folders.html.erb
+++ b/apps/workbench/app/views/folders/_show_folders.html.erb
@@ -7,12 +7,16 @@
     <% tree.each do |foldernode| %>
       <div class="folder row" style="padding-left: <%= 1 + foldernode[:depth] %>em;">
         <i class="fa fa-fw fa-folder-o"></i>
-        <%= link_to foldernode[:object] do %>
-          <%= foldernode[:object].name || 'New folder' %>
+        <% if foldernode[:object].class == User %>
+          <%= foldernode[:object].friendly_link_name %>
+        <% else %>
+          <%= link_to foldernode[:object] do %>
+            <%= foldernode[:object].friendly_link_name %>
+          <% end %>
+          <div class="pull-right">
+            <%= render partial: 'delete_object_button', locals: {object: foldernode[:object]} %>
+          </div>
         <% end %>
-        <div class="pull-right">
-          <%= render partial: 'delete_object_button', locals: {object: foldernode[:object]} %>
-        </div>
       </div>
     <% end %>
   <% end %>
diff --git a/apps/workbench/app/views/folders/show.html.erb b/apps/workbench/app/views/folders/show.html.erb
index 9a7fccf..ebf504e 100644
--- a/apps/workbench/app/views/folders/show.html.erb
+++ b/apps/workbench/app/views/folders/show.html.erb
@@ -62,14 +62,37 @@
         <input type="text" class="form-control" placeholder="Search"/>
         -->
         <div style="height:0.5em;"></div>
-        <p>Owner: <%= link_to_if_arvados_object @object.owner_uuid, friendly_name: true %></p>
-        <% if @share_links.any? %>
-        <p>Shared with:
-          <% @share_links.andand.each do |link| %>
-          <br /><%= link_to_if_arvados_object link.tail_uuid, friendly_name: true %>
+        <% if @object.owner %>
+          <p>Permissions inherited from:
+            <br />
+            <% if User == resource_class_for_uuid(@object.owner_uuid) %>
+              <i class="fa fa-fw fa-user"></i>
+            <% else %>
+              <i class="fa fa-fw fa-folder"></i>
+            <% end %>
+            <%= link_to_if_arvados_object @object.owner_uuid, friendly_name: true %>
+            <%= button_to('Move to...',
+                choose_folders_path(
+                 title: 'Move to...',
+                 editable: true,
+                 action_name: 'Move',
+                 action_href: folder_path(@object.uuid),
+                 action_method: 'put',
+                 action_data: {selection_param: 'folder[owner_uuid]'}.to_json),
+                { class: "btn btn-default btn-xs arv-move-to-folder", remote: true, method: 'get' }) %>
+          </p>
+          <hr />
+        <% end %>
+        <p>
+          <% if not @share_links.any? %>
+            <span class="deemphasize">(No additional permissions)</span>
+          <% else %>
+            Also shared with:
+            <% @share_links.andand.each do |link| %>
+              <br /><%= link_to_if_arvados_object link.tail_uuid, friendly_name: true %>
+            <% end %>
           <% end %>
         </p>
-        <% end %>
       </div>
     </div>
   </div>
diff --git a/apps/workbench/app/views/layouts/application.html.erb b/apps/workbench/app/views/layouts/application.html.erb
index 4560885..6db1886 100644
--- a/apps/workbench/app/views/layouts/application.html.erb
+++ b/apps/workbench/app/views/layouts/application.html.erb
@@ -243,5 +243,6 @@
   <%= yield :footer_js %>
   <% end %>
 
+<div class="modal-container"></div>
 </body>
 </html>
diff --git a/apps/workbench/config/routes.rb b/apps/workbench/config/routes.rb
index e0c93ec..efd5beb 100644
--- a/apps/workbench/config/routes.rb
+++ b/apps/workbench/config/routes.rb
@@ -46,6 +46,7 @@ ArvadosWorkbench::Application.routes.draw do
   get '/collections/:uuid/*file' => 'collections#show_file', :format => false
   resources :folders do
     match 'remove/:item_uuid', on: :member, via: :delete, action: :remove_item
+    get 'choose', on: :collection
   end
 
   post 'actions' => 'actions#post'

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list