2872: Rearrange folder index. Show collection tags and files in folder view.
authorTom Clegg <tom@curoverse.com>
Sun, 1 Jun 2014 21:27:15 +0000 (17:27 -0400)
committerTom Clegg <tom@curoverse.com>
Sun, 1 Jun 2014 21:27:15 +0000 (17:27 -0400)
18 files changed:
apps/workbench/app/assets/javascripts/editable.js
apps/workbench/app/assets/stylesheets/application.css.scss
apps/workbench/app/assets/stylesheets/folders.css.scss
apps/workbench/app/controllers/application_controller.rb
apps/workbench/app/helpers/application_helper.rb
apps/workbench/app/models/arvados_base.rb
apps/workbench/app/views/application/_content.html.erb
apps/workbench/app/views/application/_content_layout.html.erb
apps/workbench/app/views/application/_show_object_button.html.erb
apps/workbench/app/views/application/_show_object_description_cell.html.erb [new file with mode: 0644]
apps/workbench/app/views/collections/_show_object_description_cell.html.erb [new file with mode: 0644]
apps/workbench/app/views/folders/_index_folders.html.erb [new file with mode: 0644]
apps/workbench/app/views/folders/_show_contents.html.erb
apps/workbench/app/views/folders/_show_contents_rows.html.erb
apps/workbench/app/views/folders/_show_folders.html.erb [deleted file]
apps/workbench/app/views/folders/index.html.erb [new file with mode: 0644]
apps/workbench/app/views/layouts/application.html.erb
apps/workbench/app/views/pipeline_instances/_show_components.html.erb

index a32eb7e548f06e6404d32586bb702484d89036f3..093a671acd10799eadf1c651e96b706f6b751141 100644 (file)
@@ -41,10 +41,9 @@ $.fn.editable.defaults.validate = function (value) {
 
 $(document).
     on('ready ajax:complete', function() {
-        $('#editable-submit').click(function() {
-            console.log($(this));
-        });
         $('.editable').
+            not('.editable-done-setup').
+            addClass('editable-done-setup').
             editable({
                 success: function(response, newValue) {
                     // If we just created a new object, stash its UUID
@@ -77,10 +76,13 @@ $(document).
             });
     }).
     on('ready ajax:complete', function() {
-        $("[data-toggle~='x-editable']").click(function(e) {
-            e.stopPropagation();
-            $($(this).attr('data-toggle-selector')).editable('toggle');
-        });
+        $("[data-toggle~='x-editable']").
+            not('.editable-done-setup').
+            addClass('editable-done-setup').
+            click(function(e) {
+                e.stopPropagation();
+                $($(this).attr('data-toggle-selector')).editable('toggle');
+            });
     });
 
 $.fn.editabletypes.text.defaults.tpl = '<input type="text" name="editable-text">'
index 7d76f5aafb762bd7b6c03b7d1362ec5c4df909ec..75080a0bbdf9d58a694b9216fbbb29b91b269fe8 100644 (file)
@@ -47,6 +47,7 @@ table.table-justforlayout {
     font-size: .8em;
     color: #888;
 }
+.arvados-filename,
 .arvados-uuid {
     font-size: .8em;
     font-family: monospace;
@@ -184,6 +185,7 @@ div#wrapper {
 }
 .arv-description-in-table {
   max-height: 3.5em;
+  overflow-x: hidden;
   overflow-y: hidden;
 }
 .arv-description-in-table:hover {
index 163c188623118999755181197d371794c1993596..aa5f14cfaaa4d2f90ac67da097a4f642fda88dde 100644 (file)
@@ -6,3 +6,7 @@
 .arv-folder-list > .row.folder:hover {
     background: #d9edf7;
 }
+div.scroll-20em {
+    height: 20em;
+    overflow-y: scroll;
+}
index 97ef55aa1a0918533f9b478643a6174805d160b2..3ed440ff6c85bb354712afbb30ff3fa51a17c99a 100644 (file)
@@ -144,7 +144,7 @@ class ApplicationController < ActionController::Base
   end
 
   def update
-    @updates ||= params[@object.class.to_s.underscore.singularize.to_sym]
+    @updates ||= params[@object.resource_param_name.to_sym]
     @updates.keys.each do |attr|
       if @object.send(attr).is_a? Hash
         if @updates[attr].is_a? String
index 117f808d02cf78b6916747dceab0c662a83cd9c4..dc97251132ea106493ead45ff7e290e5c6746a0e 100644 (file)
@@ -212,7 +212,8 @@ module ApplicationHelper
       end
     end
 
-    if !object.attribute_editable?(attr, :ever) or
+    if !object or
+        !object.attribute_editable?(attr, :ever) or
         (!object.editable? and
          !object.owner_uuid.in?(my_folders.collect(&:uuid)))
       return link_to_if_arvados_object attrvalue
@@ -349,6 +350,15 @@ module ApplicationHelper
     end
   end
 
+  def render_controller_partial partial, opts
+    cname = opts.delete :controller_name
+    begin
+      render opts.merge(partial: "#{cname}/#{partial}")
+    rescue ActionView::MissingTemplate
+      render opts.merge(partial: "application/#{partial}")
+    end
+  end
+    
   def fa_icon_class_for_object object
     case object.class.to_s.to_sym
     when :User
@@ -365,6 +375,22 @@ module ApplicationHelper
       'fa-clipboard'
     when :Human
       'fa-male'
+    when :VirtualMachine
+      'fa-terminal'
+    when :Repository
+      'fa-code-fork'
+    when :Link
+      'fa-arrows-h'
+    when :User
+      'fa-user'
+    when :Node
+      'fa-cloud'
+    when :KeepService
+      'fa-exchange'
+    when :KeepDisk
+      'fa-hdd-o'
+    else
+      'fa-cube'
     end
   end
 end
index cb457014aa56218fd3c07f240a7156ee551aeab7..e8b4cafd6ac930039edadbfe58f967e62167309e 100644 (file)
@@ -348,6 +348,10 @@ class ArvadosBase < ActiveRecord::Base
     resource_class
   end
 
+  def resource_param_name
+    self.class.to_s.underscore
+  end
+
   def friendly_link_name
     (name if self.respond_to? :name) || default_name
   end
@@ -364,6 +368,14 @@ class ArvadosBase < ActiveRecord::Base
     self.to_s.underscore.humanize
   end
 
+  def controller
+    (self.class.to_s.pluralize + 'Controller').constantize
+  end
+
+  def controller_name
+    self.class.to_s.tableize
+  end
+
   # Placeholder for name when name is missing or empty
   def default_name
     if self.respond_to? :name
index 32c053f645fb7012275816c3f7ffe3cc4396a37b..b41da15c2fb9e7767e0056e53bbcd0526f655a41 100644 (file)
@@ -1,3 +1,24 @@
+<% content_for :content_top do %>
+  <% if @object and not @object.is_a?(Group) and @object.class.goes_in_folders? and @object.owner_uuid == current_user.uuid %>
+    <div class="pull-right" style="width: 40%">
+      <div class="alert alert-warning alert-dismissable">
+        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
+        <strong>Hey.</strong> This <%= @object.class_for_display.downcase %> belongs to your account, but it's not in any of your folders. If you want it to be easy to find in the future, you should move it to a folder.<br />
+        <%= button_to(choose_folders_path(
+                   title: 'Move to...',
+                   editable: true,
+                   action_name: 'Move',
+                   action_href: url_for(action: :update),
+                   action_method: 'patch',
+                   action_data: {selection_param: @object.resource_param_name+'[owner_uuid]', success: 'page-refresh'}.to_json),
+                  { class: "btn btn-primary btn-sm", remote: true, method: 'get' }) do %>
+          <i class="fa fa-fw fa-folder"></i> Choose a folder...
+        <% end %>
+      </div>
+    </div>
+  <% end %>
+<% end %>
+
 <% content_for :tab_panes do %>
 
 <% comparable = controller.respond_to? :compare %>
index 1bc0b855b4a520171de8c1e8b1c350b7b9ec82e9..426a497a605111eb8e56e1c60e114b2dda393f17 100644 (file)
@@ -1,4 +1,5 @@
 <%= content_for :content_top %>
+<br clear="all" />
 <div class="pull-right">
   <%= content_for :tab_line_buttons %>
 </div>
index 157ae49c25f4631b99eb791dd51beebba42abe2f..17e9737f091658a87d580747c4d413aac3d5f4a6 100644 (file)
@@ -1,3 +1,12 @@
 <% htmloptions = {class: ''}.merge(htmloptions || {})
    htmloptions[:class] += " btn-#{size}" rescue nil %>
-<%= link_to_if_arvados_object object, { link_text: raw('<i class="glyphicon glyphicon-zoom-in"></i>') }, { data: {toggle: 'tooltip', placement: 'top'}, title: 'show', class: 'btn btn-default btn-nodecorate ' + htmloptions[:class] } %>
+<%= link_to_if_arvados_object object, {
+      link_text: raw('<i class="fa fa-fw ' + fa_icon_class_for_object(object) + '"></i>')
+    }, {
+      data: {
+        toggle: 'tooltip',
+        placement: 'top'
+      },
+      title: 'show',
+      class: 'btn btn-default btn-nodecorate ' + htmloptions[:class]
+    } %>
diff --git a/apps/workbench/app/views/application/_show_object_description_cell.html.erb b/apps/workbench/app/views/application/_show_object_description_cell.html.erb
new file mode 100644 (file)
index 0000000..7ad3f0e
--- /dev/null
@@ -0,0 +1,2 @@
+<%= object.content_summary %>
+
diff --git a/apps/workbench/app/views/collections/_show_object_description_cell.html.erb b/apps/workbench/app/views/collections/_show_object_description_cell.html.erb
new file mode 100644 (file)
index 0000000..0b3352b
--- /dev/null
@@ -0,0 +1,14 @@
+<div class="nowrap">
+  <div>
+    <% Link.filter([['link_class','=','tag'],['head_uuid','=',object.uuid]]).collect(&:name).each do |tagname| %>
+      <span class="label label-info"><%= tagname %></span>
+    <% end %>
+  </div>
+  <span class="deemphasize">
+    Files (<%= human_readable_bytes_html(object.total_bytes) %>):
+  </span><span class="arvados-filename">
+    <% object.files.each do |path, file, size| %>
+      <%= file %>
+    <% end %>
+  </span>
+</div>
diff --git a/apps/workbench/app/views/folders/_index_folders.html.erb b/apps/workbench/app/views/folders/_index_folders.html.erb
new file mode 100644 (file)
index 0000000..734e0f4
--- /dev/null
@@ -0,0 +1,31 @@
+<div class="container-fluid arv-folder-list">
+  <% tree.each do |foldernode| %>
+    <% rowtype = foldernode[:object].class %>
+    <% next if rowtype != Group and !show_root_node %>
+    <div class="<%= 'folder' if rowtype == Group %> row">
+      <div class="col-md-12" style="padding-left: <%= foldernode[:depth] - (show_root_node ? 0 : 1) %>em;">
+        <% if show_root_node and rowtype == String %>
+          <i class="fa fa-fw fa-folder-open-o"></i>
+          <%= foldernode[:object] %>
+        <% elsif show_root_node and rowtype == User %>
+          <% if foldernode[:object].uuid == current_user.andand.uuid %>
+            <i class="fa fa-fw fa-folder-open-o"></i>
+            My Folders
+          <% else %>
+            <i class="fa fa-fw fa-folder-o"></i>
+            <%= foldernode[:object].friendly_link_name %>
+          <% end %>
+        <% elsif rowtype == Group %>
+          <i class="fa fa-fw fa-folder-o"></i>
+          <% opts = {} %>
+          <% opts[:title] = foldernode[:object].description %>
+          <% opts[:'data-toggle'] = 'tooltip' %>
+          <% opts[:'data-placement'] = 'bottom' %>
+          <%= link_to foldernode[:object], opts do %>
+            <%= foldernode[:object].friendly_link_name %>
+          <% end %>
+        <% end %>
+      </div>
+    </div>
+  <% end %>
+</div>
index ce9f1b17cbbc600088917e18e1d3b13e811d7b4c..3a1193067e85aa9016955fab69985c0d5e9c09b8 100644 (file)
@@ -67,7 +67,7 @@
   </div>
 </div>
 
-<table class="table table-condensed arv-index arv-folder-contents">
+<table class="table table-condensed table-fixedlayout arv-index arv-folder-contents" style="overflow-x: hidden">
   <colgroup>
     <col width="40%" />
     <col width="60%" />
index c20bf27af5e490da96cf06f35d4f4e2160cae202..54e7ff60efb0af38f112f102acccfaed2a3bcbed 100644 (file)
@@ -6,21 +6,23 @@
       >
     <td>
       <% if folder.editable? %>
-        <%= link_to({action: 'remove_item', id: folder.uuid, item_uuid: ((name_link && name_link.uuid) || object.uuid)}, method: :delete, remote: true, data: {confirm: "Remove #{object.class_for_display.downcase} #{name_object.name rescue object.uuid} from this folder?", toggle: 'tooltip', placement: 'top'}, class: 'btn btn-xs btn-default btn-nodecorate', title: 'remove') do %>
+        <%= link_to({action: 'remove_item', id: folder.uuid, item_uuid: ((name_link && name_link.uuid) || object.uuid)}, method: :delete, remote: true, data: {confirm: "Remove #{object.class_for_display.downcase} #{name_object.name rescue object.uuid} from this folder?", toggle: 'tooltip', placement: 'top'}, class: 'btn btn-sm btn-default btn-nodecorate', title: 'remove') do %>
           <i class="fa fa-fw fa-ban"></i>
         <% end %>
       <% else %>
         <i class="fa fa-fw"></i><%# placeholder %>
       <% end %>
 
-      <%= render :partial => "show_object_button", :locals => {object: object, size: 'xs'} %>
-
-      <i class="fa fa-fw <%= fa_icon_class_for_object(object) %>"></i>
+      <%= render :partial => "show_object_button", :locals => {object: object, size: 'sm'} %>
 
       <%= render_editable_attribute name_object, 'name', nil %>
     </td>
-    <td>
-      <%= object.content_summary %>
+    <td class="arv-description-in-table">
+      <%= render_controller_partial(
+          'show_object_description_cell.html',
+          controller_name: object.controller_name,
+          locals: {object: object})
+          %>
     </td>
   </tr>
 <% end %>
diff --git a/apps/workbench/app/views/folders/_show_folders.html.erb b/apps/workbench/app/views/folders/_show_folders.html.erb
deleted file mode 100644 (file)
index 8c4f0d8..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<div class="container-fluid arv-folder-list">
-  <% [@my_folder_tree, @shared_folder_tree].each do |tree| %>
-    <% tree.each do |foldernode| %>
-      <% rowtype = foldernode[:object].class %>
-      <div class="<%= 'folder' if rowtype == Group %> row">
-        <div class="col-lg-4" style="padding-left: <%= 1 + foldernode[:depth] %>em;">
-          <% if rowtype == String %>
-            <i class="fa fa-fw fa-folder-open-o"></i>
-            <%= foldernode[:object] %>
-          <% elsif rowtype == User %>
-            <% if foldernode[:object].uuid == current_user.andand.uuid %>
-              <i class="fa fa-fw fa-folder-open-o"></i>
-              My Folders
-            <% else %>
-              <i class="fa fa-fw fa-folder-o"></i>
-              <%= foldernode[:object].friendly_link_name %>
-            <% end %>
-          <% else %>
-            <i class="fa fa-fw fa-folder-o"></i>
-            <%= link_to foldernode[:object] do %>
-              <%= foldernode[:object].friendly_link_name %>
-            <% end %>
-          <% end %>
-        </div>
-        <div class="col-lg-8 arv-description-in-table">
-          <% if rowtype == Group %>
-            <%= foldernode[:object].description %>
-          <% end %>
-        </div>
-      </div>
-    <% end %>
-  <% end %>
-</div>
diff --git a/apps/workbench/app/views/folders/index.html.erb b/apps/workbench/app/views/folders/index.html.erb
new file mode 100644 (file)
index 0000000..7666e54
--- /dev/null
@@ -0,0 +1,57 @@
+<% content_for :breadcrumbs do %>
+<li class="nav-separator"><span class="glyphicon glyphicon-arrow-right"></span></li>
+<li><a href="#">Home</a></li>
+<% end %>
+
+<div class="container-fluid">
+  <div class="row">
+    <div class="col-sm-6">
+      <% if my_folders.empty? %>
+        <div class="panel panel-info">
+          <div class="panel-heading">
+            <h3 class="panel-title">
+              Welcome to <b><%= Rails.configuration.site_name %></b>.
+            </h3>
+          </div>
+          <div class="panel-body">
+            <img src="/favicon.ico" class="pull-right" alt="" style="opacity: 0.3"/>
+            <p>
+              This site runs Arvados, the open source biomedical analysis platform. <a href="https://arvados.org" target="_blank">Learn more&hellip;</a>
+            </p>
+            <p>
+              <b>To get started,</b> create a folder using the "Add new folder" button below.
+            </p>
+          </div>
+        </div>
+      <% end %>
+      <div class="panel panel-default">
+        <div class="panel-heading">
+          <div class="pull-right">
+            <%= button_to folders_path(method: 'post'), class: 'btn btn-xs btn-primary' do %>
+              <i class="fa fa-fw fa-plus"></i>
+              Add new folder
+            <% end %>
+          </div>
+          <h3 class="panel-title">
+            My folders
+          </h3>
+        </div>
+        <div class="panel-body scroll-20em">
+          <%= render partial: 'index_folders', locals: {tree: @my_folder_tree, show_root_node: false} %>
+        </div>
+      </div>
+    </div>
+    <div class="col-sm-6">
+      <div class="panel panel-default">
+        <div class="panel-heading">
+          <h3 class="panel-title">
+            Shared folders
+          </h3>
+        </div>
+        <div class="panel-body scroll-20em">
+          <%= render partial: 'index_folders', locals: {tree: @shared_folder_tree, show_root_node: false} %>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
index 0ec08ccb726b3df3e8c40574467d3bef8aca3d5e..631595fb0920237eeed4b94b4368e9a718e8aa27 100644 (file)
                 <span class="glyphicon glyphicon-cog"></span><span class="caret"></span>
               </a>
               <ul class="dropdown-menu" role="menu">
-                <li role="presentation" class="dropdown-header">System objects</li>
+                <li role="presentation" class="dropdown-header">
+                  <i class="fa fa-lg fa-fw"></i>
+                  System tools
+                </li>
                 <li role="presentation" class="divider"></li>
                 <li role="presentation"><a href="/repositories">
                     <i class="fa fa-lg fa-code-fork fa-fw"></i> Repositories
index b08e0b888acfea1198768f27ff3950c9a79ffd7e..b8f94d5c14aa7a983f1e0b425e9b33650b6764d9 100644 (file)
@@ -9,10 +9,9 @@
     <%= render_editable_attribute @object, 'name', nil %>
   </h2>
   <% if template %>
-  <h4>
-    From template:
+  <blockquote><span class="deemphasize">From template:</span><br />
     <%= link_to_if_arvados_object template, friendly_name: true %>
-  </h4>
+  </blockquote>
   <% end %>
 <% end %>