12479: Merge branch 'master' into 12479-wb-structured-vocabulary
authorLucas Di Pentima <ldipentima@veritasgenetics.com>
Mon, 8 Jan 2018 14:44:38 +0000 (11:44 -0300)
committerLucas Di Pentima <ldipentima@veritasgenetics.com>
Mon, 8 Jan 2018 17:40:44 +0000 (14:40 -0300)
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <ldipentima@veritasgenetics.com>

15 files changed:
apps/workbench/app/assets/javascripts/application.js
apps/workbench/app/assets/javascripts/components/edit_tags.js [new file with mode: 0644]
apps/workbench/app/assets/javascripts/edit_collection_tags.js [deleted file]
apps/workbench/app/assets/javascripts/mithril_mount.js
apps/workbench/app/assets/javascripts/models/session_db.js
apps/workbench/app/assets/stylesheets/application.css.scss
apps/workbench/app/controllers/collections_controller.rb
apps/workbench/app/views/collections/_show_tag_rows.html.erb [deleted file]
apps/workbench/app/views/collections/_show_tags.html.erb
apps/workbench/app/views/collections/save_tags.js.erb [deleted file]
apps/workbench/app/views/collections/tags.js.erb [deleted file]
apps/workbench/npm_packages
apps/workbench/public/vocabulary-example.json [new file with mode: 0644]
apps/workbench/test/controllers/collections_controller_test.rb
apps/workbench/test/integration/collections_test.rb

index bba2f9dcc044b8b20b42e12cac8c62af5c4846f4..184c14b9ba239cfa9aa254c6c209f12823aa604d 100644 (file)
@@ -33,6 +33,9 @@
 //= require jquery.number.min
 //= require npm-dependencies
 //= require mithril/stream/stream
+//= require microplugin
+//= require sifter
+//= require selectize
 //= require_tree .
 
 Es6ObjectAssign.polyfill()
diff --git a/apps/workbench/app/assets/javascripts/components/edit_tags.js b/apps/workbench/app/assets/javascripts/components/edit_tags.js
new file mode 100644 (file)
index 0000000..fa3f13e
--- /dev/null
@@ -0,0 +1,286 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+window.SimpleInput = {
+    view: function(vnode) {
+        return m("input.form-control", {
+            style: {
+                width: '100%',
+            },
+            type: 'text',
+            placeholder: vnode.attrs.placeholder,
+            value: vnode.attrs.value,
+            onchange: function() {
+                console.log(this.value)
+                if (this.value != '') {
+                    vnode.attrs.value(this.value)
+                }
+            },
+        }, vnode.attrs.value)
+    },
+    oncreate: function(vnode) {
+        if (vnode.attrs.setFocus) {
+            vnode.dom.focus()
+        }
+    }
+}
+
+window.SelectOrAutocomplete = {
+    onFocus: function(vnode) {
+        // Allow the user to edit an already entered value by removing it
+        // and filling the input field with the same text
+        activeSelect = vnode.state.selectized[0].selectize
+        value = activeSelect.getValue()
+        if (value.length > 0) {
+            activeSelect.clear(silent = true)
+            activeSelect.setTextboxValue(value)
+        }
+    },
+    view: function(vnode) {
+        return m("input", {
+            style: {
+                width: '100%'
+            },
+            type: 'text',
+            value: vnode.attrs.value
+        }, vnode.attrs.value)
+    },
+    oncreate: function(vnode) {
+        vnode.state.selectized = $(vnode.dom).selectize({
+            labelField: 'value',
+            valueField: 'value',
+            searchField: 'value',
+            sortField: 'value',
+            persist: false,
+            hideSelected: true,
+            openOnFocus: false,
+            createOnBlur: true,
+            maxItems: 1,
+            placeholder: vnode.attrs.placeholder,
+            create: vnode.attrs.create ? function(input) {
+                return {value: input}
+            } : false,
+            items: [vnode.attrs.value()],
+            options: vnode.attrs.options.map(function(option) {
+                return {value: option}
+            }),
+            onChange: function(val) {
+                if (val != '') {
+                    vnode.attrs.value(val)
+                }
+            },
+            onFocus: function() {
+                vnode.state.onFocus(vnode)
+            }
+        })
+        if (vnode.attrs.setFocus) {
+            vnode.state.selectized[0].selectize.focus()
+        }
+    }
+}
+
+window.TagEditorRow = {
+    view: function(vnode) {
+        var nameOpts = Object.keys(vnode.attrs.vocabulary().tags)
+        var valueOpts = []
+        var inputComponent = SelectOrAutocomplete
+        if (nameOpts.length === 0) {
+            // If there's not vocabulary defined, switch to a simple input field
+            inputComponent = SimpleInput
+        } else {
+            // Name options list
+            if (vnode.attrs.name() != '' && !(vnode.attrs.name() in vnode.attrs.vocabulary().tags)) {
+                nameOpts.push(vnode.attrs.name())
+            }
+            // Value options list
+            if (vnode.attrs.name() in vnode.attrs.vocabulary().tags &&
+                'values' in vnode.attrs.vocabulary().tags[vnode.attrs.name()]) {
+                    valueOpts = vnode.attrs.vocabulary().tags[vnode.attrs.name()].values
+            }
+            if (vnode.attrs.value() != '') {
+                valueOpts.push(vnode.attrs.value())
+            }
+        }
+        return m("tr", [
+            // Erase tag
+            m("td", [
+                vnode.attrs.editMode &&
+                m('div.text-center', m('a.btn.btn-default.btn-sm', {
+                    style: {
+                        align: 'center'
+                    },
+                    onclick: function(e) { vnode.attrs.removeTag() }
+                }, m('i.fa.fa-fw.fa-trash-o')))
+            ]),
+            // Tag name
+            m("td", [
+                vnode.attrs.editMode ?
+                m("div", {key: 'name-'+vnode.attrs.name()},[
+                    m(inputComponent, {
+                        options: nameOpts,
+                        value: vnode.attrs.name,
+                        // Allow any tag name unless "strict" is set to true.
+                        create: !vnode.attrs.vocabulary().strict,
+                        placeholder: 'new tag',
+                        // Focus on tag name field when adding a new tag that's
+                        // not the first one.
+                        setFocus: vnode.attrs.name() === ''
+                    })
+                ])
+                : vnode.attrs.name
+            ]),
+            // Tag value
+            m("td", [
+                vnode.attrs.editMode ?
+                m("div", {key: 'value-'+vnode.attrs.name()}, [
+                    m(inputComponent, {
+                        options: valueOpts,
+                        value: vnode.attrs.value,
+                        placeholder: 'new value',
+                        // Allow any value on tags not listed on the vocabulary.
+                        // Allow any value on tags without values, or the ones
+                        // that aren't explicitly declared to be strict.
+                        create: !(vnode.attrs.name() in vnode.attrs.vocabulary().tags)
+                            || !vnode.attrs.vocabulary().tags[vnode.attrs.name()].values
+                            || vnode.attrs.vocabulary().tags[vnode.attrs.name()].values.length === 0
+                            || !vnode.attrs.vocabulary().tags[vnode.attrs.name()].strict,
+                        // Focus on tag value field when new tag name is set
+                        setFocus: vnode.attrs.name() !== '' && vnode.attrs.value() === ''
+                    })
+                ])
+                : vnode.attrs.value
+            ])
+        ])
+    }
+}
+
+window.TagEditorTable = {
+    view: function(vnode) {
+        return m("table.table.table-condensed.table-justforlayout", [
+            m("colgroup", [
+                m("col", {width:"5%"}),
+                m("col", {width:"25%"}),
+                m("col", {width:"70%"}),
+            ]),
+            m("thead", [
+                m("tr", [
+                    m("th"),
+                    m("th", "Key"),
+                    m("th", "Value"),
+                ])
+            ]),
+            m("tbody", [
+                vnode.attrs.tags.length > 0
+                ? vnode.attrs.tags.map(function(tag, idx) {
+                    return m(TagEditorRow, {
+                        key: idx,
+                        removeTag: function() {
+                            vnode.attrs.tags.splice(idx, 1)
+                            vnode.attrs.dirty(true)
+                        },
+                        editMode: vnode.attrs.editMode,
+                        name: tag.name,
+                        value: tag.value,
+                        vocabulary: vnode.attrs.vocabulary
+                    })
+                })
+                : m("tr", m("td[colspan=3]", m("center","loading tags...")))
+            ]),
+        ])
+    }
+}
+
+window.TagEditorApp = {
+    appendTag: function(vnode, name, value) {
+        var tag = {name: m.stream(name), value: m.stream(value)}
+        vnode.state.tags.push(tag)
+        // Set dirty flag when any of name/value changes to non empty string
+        tag.name.map(function(v) {
+            if (v !== '') {
+                vnode.state.dirty(true)
+            }
+        })
+        tag.value.map(function(v) {
+            if (v !== '') {
+                vnode.state.dirty(true)
+            }
+        })
+        tag.name.map(m.redraw)
+    },
+    oninit: function(vnode) {
+        vnode.state.sessionDB = new SessionDB()
+        // Get vocabulary
+        vnode.state.vocabulary = m.stream({"strict":false, "tags":{}})
+        m.request('/vocabulary.json').then(vnode.state.vocabulary)
+        vnode.state.editMode = vnode.attrs.targetEditable
+        vnode.state.tags = []
+        vnode.state.dirty = m.stream(false)
+        vnode.state.dirty.map(m.redraw)
+        vnode.state.objPath = '/arvados/v1/'+vnode.attrs.targetController+'/'+vnode.attrs.targetUuid
+        // Get tags
+        vnode.state.sessionDB.request(
+            vnode.state.sessionDB.loadLocal(),
+            '/arvados/v1/'+vnode.attrs.targetController,
+            {
+                data: {
+                    filters: JSON.stringify([['uuid', '=', vnode.attrs.targetUuid]]),
+                    select: JSON.stringify(['properties'])
+                },
+            }).then(function(obj) {
+                if (obj.items.length == 1) {
+                    o = obj.items[0]
+                    Object.keys(o.properties).forEach(function(k) {
+                        vnode.state.appendTag(vnode, k, o.properties[k])
+                    })
+                    // Data synced with server, so dirty state should be false
+                    vnode.state.dirty(false)
+                    // Add new tag row when the last one is completed
+                    vnode.state.dirty.map(function() {
+                        if (!vnode.state.editMode) { return }
+                        lastTag = vnode.state.tags.slice(-1).pop()
+                        if (lastTag === undefined || (lastTag.name() !== '' && lastTag.value() !== '')) {
+                            vnode.state.appendTag(vnode, '', '')
+                        }
+                    })
+                }
+            }
+        )
+    },
+    view: function(vnode) {
+        return [
+            vnode.state.editMode &&
+            m("div.pull-left", [
+                m("a.btn.btn-primary.btn-sm"+(vnode.state.dirty() ? '' : '.disabled'), {
+                    style: {
+                        margin: '10px 0px'
+                    },
+                    onclick: function(e) {
+                        var tags = {}
+                        vnode.state.tags.forEach(function(t) {
+                            if (t.name() != '' && t.value() != '') {
+                                tags[t.name()] = t.value()
+                            }
+                        })
+                        vnode.state.sessionDB.request(
+                            vnode.state.sessionDB.loadLocal(),
+                            vnode.state.objPath, {
+                                method: "PUT",
+                                data: {properties: JSON.stringify(tags)}
+                            }
+                        ).then(function(v) {
+                            vnode.state.dirty(false)
+                        })
+                    }
+                }, vnode.state.dirty() ? ' Save changes ' : ' Saved ')
+            ]),
+            // Tags table
+            m(TagEditorTable, {
+                editMode: vnode.state.editMode,
+                tags: vnode.state.tags,
+                vocabulary: vnode.state.vocabulary,
+                dirty: vnode.state.dirty
+            })
+        ]
+    },
+}
\ No newline at end of file
diff --git a/apps/workbench/app/assets/javascripts/edit_collection_tags.js b/apps/workbench/app/assets/javascripts/edit_collection_tags.js
deleted file mode 100644 (file)
index e1c1515..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-jQuery(function($){
-  $(document).
-    on('click', '.collection-tag-save, .collection-tag-cancel', function(event) {
-        $('.edit-collection-tags').removeClass('disabled');
-        $('#edit-collection-tags').attr("title", "Edit tags");
-        $('.collection-tag-add').addClass('hide');
-        $('.collection-tag-remove').addClass('hide');
-        $('.collection-tag-save').addClass('hide');
-        $('.collection-tag-cancel').addClass('hide');
-        $('.collection-tag-field').prop("contenteditable", false);
-    }).
-    on('click', '.edit-collection-tags', function(event) {
-        $('.edit-collection-tags').addClass('disabled');
-        $('#edit-collection-tags').attr("title", "");
-        $('.collection-tag-add').removeClass('hide');
-        $('.collection-tag-remove').removeClass('hide');
-        $('.collection-tag-save').removeClass('hide');
-        $('.collection-tag-cancel').removeClass('hide');
-        $('.collection-tag-field').prop("contenteditable", true);
-        $('div').remove('.collection-tags-status-label');
-    }).
-    on('click', '.collection-tag-save', function(event) {
-      var tag_data = {};
-      var has_tags = false;
-
-      var $tags = $(".collection-tags-table");
-      $tags.find('tr').each(function (i, el) {
-        var $tds = $(this).find('td');
-        var $key = $tds.eq(1).text();
-        if ($key && $key.trim().length > 0) {
-          has_tags = true;
-          tag_data[$key.trim()] = $tds.eq(2).text().trim();
-        }
-      });
-
-      var to_send;
-      if (has_tags == false) {
-        to_send = {tag_data: "empty"}
-      } else {
-        to_send = {tag_data: tag_data}
-      }
-
-      $.ajax($(location).attr('pathname')+'/save_tags', {
-          type: 'POST',
-          data: to_send
-      }).success(function(data, status, jqxhr) {
-        $('.collection-tags-status').append('<div class="collection-tags-status-label alert alert-success"><p class="contain-align-left">Saved successfully.</p></div>');
-      }).fail(function(jqxhr, status, error) {
-        $('.collection-tags-status').append('<div class="collection-tags-status-label alert alert-danger"><p class="contain-align-left">We are sorry. There was an error saving tags. Please try again.</p></div>');
-      });
-    }).
-    on('click', '.collection-tag-cancel', function(event) {
-      $.ajax($(location).attr('pathname')+'/tags', {
-          type: 'GET'
-      });
-    }).
-    on('click', '.collection-tag-remove', function(event) {
-      $(this).parents('tr').detach();
-    }).
-    on('click', '.collection-tag-add', function(event) {
-      var $collection_tags = $(this).closest('.collection-tags-container');
-      var $clone = $collection_tags.find('tr.hide').clone(true).removeClass('hide');
-      $collection_tags.find('table').append($clone);
-    }).
-    on('keypress', '.collection-tag-field', function(event){
-      return event.which != 13;
-    });
-});
index f4689b51d7ebfc265476dfa3e0b748ac33b62b94..7995ffea6ab8a69dd97030bef774de3599dfe5e6 100644 (file)
@@ -4,6 +4,7 @@
 
 $(document).on('ready arv:pane:loaded', function() {
     $('[data-mount-mithril]').each(function() {
-        m.mount(this, window[$(this).data('mount-mithril')])
+        var data = $(this).data()
+        m.mount(this, {view: function () {return m(window[data.mountMithril], data)}})
     })
 })
index ad9ad1878417370dfd75294e9bd9cecbe25880d1..a43cd79545b66ff47dda07f3097b3c8803a47262 100644 (file)
@@ -28,6 +28,17 @@ window.SessionDB = function() {
             })
             return sessions
         },
+        loadLocal: function() {
+            var sessions = db.loadActive()
+            var s = false
+            Object.values(sessions).forEach(function(session) {
+                if (session.isFromRails) {
+                    s = session
+                    return
+                }
+            })
+            return s
+        },
         save: function(k, v) {
             var sessions = db.loadAll()
             sessions[k] = v
@@ -134,10 +145,11 @@ window.SessionDB = function() {
             // Guess workbench.{apihostport} is a Workbench... unless
             // the host part of apihostport is an IPv4 or [IPv6]
             // address.
-            if (!session.baseURL.match('://(\\[|\\d+\\.\\d+\\.\\d+\\.\\d+[:/])'))
+            if (!session.baseURL.match('://(\\[|\\d+\\.\\d+\\.\\d+\\.\\d+[:/])')) {
                 var wbUrl = session.baseURL.replace('://', '://workbench.')
                 // Remove the trailing slash, if it's there.
                 return wbUrl.slice(-1) == '/' ? wbUrl.slice(0, -1) : wbUrl
+            }
             return null
         },
         // Return a m.stream that will get fulfilled with the
index 32d80255d9fd831d2ea7f3e55ec163e53f154f06..b0c0100161b0eb7e26dddfe74bda32443985c472 100644 (file)
@@ -16,6 +16,8 @@
  *= require bootstrap
  *= require bootstrap3-editable/bootstrap-editable
  *= require morris
+ *= require selectize
+ *= require selectize.default
  *= require_tree .
  */
 
index 5fcb2dc569ff6b2446c602dc26de61a069155ba2..0a7f22b95789edc163198fbf32ab55045317f298 100644 (file)
@@ -300,30 +300,6 @@ class CollectionsController < ApplicationController
     end
   end
 
-  def tags
-    render
-  end
-
-  def save_tags
-    tags_param = params['tag_data']
-    if tags_param
-      if tags_param.is_a?(String) && tags_param == "empty"
-        tags = {}
-      else
-        tags = tags_param
-      end
-    end
-
-    if tags
-      if @object.update_attributes properties: tags
-        @saved_tags = true
-        render
-      else
-        self.render_error status: 422
-      end
-    end
-  end
-
   protected
 
   def find_usable_token(token_list)
diff --git a/apps/workbench/app/views/collections/_show_tag_rows.html.erb b/apps/workbench/app/views/collections/_show_tag_rows.html.erb
deleted file mode 100644 (file)
index eb57913..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<%# Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: AGPL-3.0 %>
-
-<%
-  tags = object.properties
-%>
-      <% if tags.andand.is_a?(Hash) %>
-        <% tags.each do |k, v| %>
-          <tr class="collection-tag-<%=k%>">
-            <td>
-              <% if object.editable? %>
-                <i class="glyphicon glyphicon-remove collection-tag-remove hide" style="cursor: pointer;"></i>
-              <% end %>
-            </td>
-            <td class="collection-tag-field collection-tag-field-key">
-              <%= k %>
-            </td>
-            <td class="collection-tag-field collection-tag-field-value">
-              <%= v %>
-            </td>
-          </tr>
-        <% end %>
-      <% end %>
-
-      <% if @object.editable? %>
-        <!-- A hidden row to add new tag -->
-        <tr class="collection-tag-hidden hide">
-          <td>
-            <i class="glyphicon glyphicon-remove collection-tag-remove hide" style="cursor: pointer"></i>
-          </td>
-          <td class="collection-tag-field collection-tag-field-key"></td>
-          <td class="collection-tag-field collection-tag-field-value"></td>
-        </tr>
-      <% end %>
index afab5266e9c2e46dbe5c84425ba9f42b7f41f544..e3432d2d3f667e19ef7a934059b0915e5079844d 100644 (file)
@@ -2,51 +2,7 @@
 
 SPDX-License-Identifier: AGPL-3.0 %>
 
-<%
-  object = @object unless object
-%>
-
   <div class="collection-tags-container" style="padding-left:2em;padding-right:2em;">
-    <% if object.editable? %>
-      <p title="Edit tags" id="edit-collection-tags">
-        <a class="btn btn-primary edit-collection-tags">Edit</a>
-      </p>
-    <% end %>
-
-    <table class="table table-condensed table-fixedlayout collection-tags-table" border="1">
-      <colgroup>
-        <col width="5%" />
-        <col width="25%" />
-        <col width="70%" />
-      </colgroup>
-
-      <thead>
-        <tr>
-          <th></th>
-          <th>Key</th>
-          <th>Value</th>
-        </tr>
-      </thead>
-
-      <tbody class="collection-tag-rows">
-        <%= render partial: 'show_tag_rows', locals: {object: object} %>
-      </tbody>
-    </table>
-    <div>
-      <% if object.editable? %>
-        <div class="pull-left">
-          <a class="btn btn-primary btn-sm collection-tag-add hide"><i class="glyphicon glyphicon-plus"></i> Add new tag </a>
-        </div>
-        <div class="pull-right">
-          <%= link_to(save_tags_collection_path, {class: 'btn btn-sm btn-primary collection-tag-save hide', :remote => true, method: 'post', return_to: request.url}) do %>
-            Save
-          <% end %>
-          <%= link_to(tags_collection_path, {class: 'btn btn-sm btn-primary collection-tag-cancel hide', :remote => true, method: 'get', return_to: request.url}) do %>
-            Cancel
-          <% end %>
-        </div>
-
-        <div><div class="collection-tags-status"/></div></div>
-      <% end %>
-    </div>
+    <div data-mount-mithril="TagEditorApp" data-target-controller="<%= controller_name %>" data-target-uuid="<%= @object.uuid %>" data-target-editable="<%= @object.editable? %>"></div>
   </div>
\ No newline at end of file
diff --git a/apps/workbench/app/views/collections/save_tags.js.erb b/apps/workbench/app/views/collections/save_tags.js.erb
deleted file mode 100644 (file)
index 073db7d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<%# Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: AGPL-3.0 %>
-
-<% if @saved_tags %>
-$(".collection-tag-rows").html("<%= escape_javascript(render partial: 'show_tag_rows', locals: {object: @object}) %>");
-<% end %>
diff --git a/apps/workbench/app/views/collections/tags.js.erb b/apps/workbench/app/views/collections/tags.js.erb
deleted file mode 100644 (file)
index e2154d6..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<%# Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: AGPL-3.0 %>
-
-$(".collection-tag-rows").html("<%= escape_javascript(render partial: 'show_tag_rows', locals: {object: @object}) %>");
index 2d57573dfd53dc3ceb5b90dccfe3bef363081ecc..1aa2575508ae4f7f2959fcffe1d75a30dd0e5100 100644 (file)
@@ -6,6 +6,10 @@
 
 # Browserify is required.
 npm 'browserify', require: false
+npm 'jquery'
+npm 'microplugin'
+npm 'sifter'
+npm 'selectize'
 
 npm 'mithril'
 npm 'es6-object-assign'
diff --git a/apps/workbench/public/vocabulary-example.json b/apps/workbench/public/vocabulary-example.json
new file mode 100644 (file)
index 0000000..97bdaa1
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "strict": false,
+    "tags": {
+        "fruit": {
+            "values": ["pineapple", "tomato", "orange", "banana"],
+            "strict": true
+        },
+        "animal": {
+            "values": ["human", "dog", "elephant", "eagle"],
+            "strict": false
+        },
+        "color": {
+            "values": ["yellow", "red", "magenta", "green"],
+            "strict": false
+        },
+        "text tag": {}
+    }
+}
\ No newline at end of file
index 773a4f45714b515d664ec290ecb61e32bcca5695..abe7f6af453f1c72070251ba90a889407469097a 100644 (file)
@@ -728,64 +728,4 @@ class CollectionsControllerTest < ActionController::TestCase
     assert_response 422
     assert_includes json_response['errors'], 'Duplicate file path'
   end
-
-  [
-    [:active, true],
-    [:spectator, false],
-  ].each do |user, editable|
-    test "tags tab #{editable ? 'shows' : 'does not show'} edit button to #{user}" do
-      use_token user
-
-      get :tags, {
-        id: api_fixture('collections')['collection_with_tags_owned_by_active']['uuid'],
-        format: :js,
-      }, session_for(user)
-
-      assert_response :success
-
-      found = 0
-      response.body.scan /<i[^>]+>/ do |remove_icon|
-        remove_icon.scan(/\ collection-tag-remove(.*?)\"/).each do |i,|
-          found += 1
-        end
-      end
-
-      if editable
-        assert_equal(3, found)  # two from the tags + 1 from the hidden "add tag" row
-      else
-        assert_equal(0, found)
-      end
-    end
-  end
-
-  test "save_tags and verify that 'other' properties are retained" do
-    use_token :active
-
-    collection = api_fixture('collections')['collection_with_tags_owned_by_active']
-
-    new_tags = {"new_tag1" => "new_tag1_value",
-                "new_tag2" => "new_tag2_value"}
-
-    post :save_tags, {
-      id: collection['uuid'],
-      tag_data: new_tags,
-      format: :js,
-    }, session_for(:active)
-
-    assert_response :success
-    assert_equal true, response.body.include?("new_tag1")
-    assert_equal true, response.body.include?("new_tag1_value")
-    assert_equal true, response.body.include?("new_tag2")
-    assert_equal true, response.body.include?("new_tag2_value")
-    assert_equal false, response.body.include?("existing tag 1")
-    assert_equal false, response.body.include?("value for existing tag 1")
-
-    updated_tags = Collection.find(collection['uuid']).properties
-    assert_equal true, updated_tags.keys.include?(:'new_tag1')
-    assert_equal new_tags['new_tag1'], updated_tags[:'new_tag1']
-    assert_equal true, updated_tags.keys.include?(:'new_tag2')
-    assert_equal new_tags['new_tag2'], updated_tags[:'new_tag2']
-    assert_equal false, updated_tags.keys.include?(:'existing tag 1')
-    assert_equal false, updated_tags.keys.include?(:'existing tag 2')
-  end
 end
index 71cfe38abfda32b2d5b5ce943ecdbf26f46ff52b..443130a4a92c60cd6a46a4f4ca749d9712a5a7f9 100644 (file)
@@ -434,88 +434,4 @@ class CollectionsTest < ActionDispatch::IntegrationTest
     first('.lock-collection-btn').click
     accept_alert
   end
-
-  test "collection tags tab" do
-    visit page_with_token('active', '/collections/zzzzz-4zz18-bv31uwvy3neko21')
-
-    click_link 'Tags'
-    wait_for_ajax
-
-    # verify initial state
-    assert_selector 'a', text: 'Edit'
-    assert_no_selector 'a', text: 'Add new tag'
-    assert_no_selector 'a', text: 'Save'
-    assert_no_selector 'a', text: 'Cancel'
-
-    # Verify controls in edit mode
-    first('.edit-collection-tags').click
-    assert_selector 'a.disabled', text: 'Edit'
-    assert_selector 'a', text: 'Add new tag'
-    assert_selector 'a', text: 'Save'
-    assert_selector 'a', text: 'Cancel'
-
-    # add two tags
-    first('.glyphicon-plus').click
-    first('.collection-tag-field-key').click
-    first('.collection-tag-field-key').set('key 1')
-    first('.collection-tag-field-value').click
-    first('.collection-tag-field-value').set('value 1')
-
-    first('.glyphicon-plus').click
-    editable_key_fields = page.all('.collection-tag-field-key')
-    editable_key_fields[1].click
-    editable_key_fields[1].set('key 2')
-    editable_val_fields = page.all('.collection-tag-field-value')
-    editable_val_fields[1].click
-    editable_val_fields[1].set('value 2')
-
-    click_on 'Save'
-    wait_for_ajax
-
-    # added tags; verify
-    assert_text 'key 1'
-    assert_text 'value 1'
-    assert_text 'key 2'
-    assert_text 'value 2'
-    assert_selector 'a', text: 'Edit'
-    assert_no_selector 'a', text: 'Save'
-
-    # remove first tag
-    first('.edit-collection-tags').click
-    assert_not_nil first('.glyphicon-remove')
-    first('.glyphicon-remove').click
-    click_on 'Save'
-    wait_for_ajax
-
-    assert_text 'key 2'
-    assert_text 'value 2'
-    assert_no_text 'key 1'
-    assert_no_text 'value 1'
-    assert_selector 'a', text: 'Edit'
-
-    # Click on cancel and verify
-    first('.edit-collection-tags').click
-    first('.collection-tag-field-key').click
-    first('.collection-tag-field-key').set('this key wont stick')
-    first('.collection-tag-field-value').click
-    first('.collection-tag-field-value').set('this value wont stick')
-
-    click_on 'Cancel'
-    wait_for_ajax
-
-    assert_text 'key 2'
-    assert_text 'value 2'
-    assert_no_text 'this key wont stick'
-    assert_no_text 'this value wont stick'
-
-    # remove all tags
-    first('.edit-collection-tags').click
-    first('.glyphicon-remove').click
-    click_on 'Save'
-    wait_for_ajax
-
-    assert_selector 'a', text: 'Edit'
-    assert_no_text 'key 2'
-    assert_no_text 'value 2'
-  end
 end