diff --git a/client/.babelrc b/client/.babelrc
deleted file mode 100644
index f9d881a541d..00000000000
--- a/client/.babelrc
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presets": [
- [
- "@babel/preset-env",
- {
- "modules": false
- }
- ]
- ],
- "plugins": ["transform-vue-template", "@babel/plugin-syntax-dynamic-import"],
- "ignore": ["i18n.js", "utils/localization.js", "nls/*"]
-}
diff --git a/client/galaxy/scripts/bundleEntries.js b/client/galaxy/scripts/bundleEntries.js
index c630dbb4dfc..f25b8f383f7 100644
--- a/client/galaxy/scripts/bundleEntries.js
+++ b/client/galaxy/scripts/bundleEntries.js
@@ -96,7 +96,7 @@ export let chartUtilities = {
export { initMasthead } from "components/Masthead/initMasthead";
export { panelManagement } from "onload/globalInits/panelManagement";
-export { init_tag_click_function } from "ui/autocom_tagging";
+export { mountTaggingComponent } from "components/Tags";
// Used in common.mako
-export { default as store } from "store";
+export { default as store } from "storemodern";
diff --git a/client/galaxy/scripts/components/Tags/GalaxyTags.test.js b/client/galaxy/scripts/components/Tags/GalaxyTags.test.js
new file mode 100644
index 00000000000..00dd607daae
--- /dev/null
+++ b/client/galaxy/scripts/components/Tags/GalaxyTags.test.js
@@ -0,0 +1,51 @@
+import { mount, createLocalVue } from "@vue/test-utils";
+import GalaxyTags from "./GalaxyTags";
+import _l from "utils/localization";
+
+let localVue = createLocalVue();
+localVue.filter("localize", value => _l(value));
+
+describe("Tags/GalaxyTags.vue", () => {
+ const testTags = ["abc", "def", "ghi"];
+
+ let wrapper, emitted;
+
+ beforeEach(function() {
+ wrapper = mount(GalaxyTags, { localVue });
+ wrapper.setProps({
+ value: testTags
+ });
+ emitted = wrapper.emitted();
+ });
+
+ it("should render a div for each tag", () => {
+ let tags = wrapper.findAll(".ti-tag-center");
+ assert(tags.length == testTags.length, "Wrong number of tags");
+ for (let i = 0; i < testTags.length; i++) {
+ assert(tags.at(i).is("div"), "button not a div");
+ assert(tags.at(i).text() == testTags[i], "rendered tag label doesn't match test data");
+ }
+ });
+
+ it("should emit a click event when the tag is clicked", () => {
+ let tags = wrapper.findAll(".ti-tag-center > div");
+ tags.at(0).trigger("click");
+ assert(emitted["tag-click"], "click event not detected");
+ assert(emitted["tag-click"].length == 1, "wrong event count");
+ });
+
+ it("should emit a tag model payload when tag is clicked", () => {
+ let tags = wrapper.findAll(".ti-tag-center > div");
+ tags.at(0).trigger("click");
+ let firstEvent = emitted["tag-click"][0];
+ let firstArg = firstEvent[0];
+ assert((firstArg.text = testTags[0]), "returned tag model doesn't match test data");
+ });
+
+ it("should change intermal model representation when new tag list assigned", async () => {
+ assert(wrapper.vm.tagModels.length == 3);
+ let newTags = ["floob", "clown", "hoohah", "doodoo"];
+ wrapper.setProps({ value: newTags });
+ assert(wrapper.vm.tagModels.length == newTags.length);
+ });
+});
diff --git a/client/galaxy/scripts/components/Tags/GalaxyTags.usage.txt b/client/galaxy/scripts/components/Tags/GalaxyTags.usage.txt
new file mode 100644
index 00000000000..f603be6b1c5
--- /dev/null
+++ b/client/galaxy/scripts/components/Tags/GalaxyTags.usage.txt
@@ -0,0 +1,70 @@
+GalaxyTags.vue
+
+Configurable tag component. Needed to do some minor event/property remapping
+to make the 3rd party component suit the interface I wanted to expose. This
+component is used like a glorified form input with v-model. Set v-model
+to the array of selected tags.
+
+Props:
+ "value":
+ Standard vue property that is assigned when v-model="tags" is set.
+ No need to set it directly, just use v-model="tags"
+ autoCompleteItems:
+ An array of autocomplete items for the current tag text. You can capture
+ changes to the tag being entered in the tag-input-changed event and reset
+ this property as required
+
+Events:
+ "input" (standard v-model update event, Not used directly):
+ Emits when list of tags change
+ before-adding-tag({ tag, addTag })
+ Hook allowing user the chance to do an operation before
+ commiting a tag to the list
+ before-deleting-tag({ tag, deleteTag })
+ Hook allowing consumer to do somehting before removing
+ a tag from the displayed list.
+ tag-click:
+ When the central name display of the tag is clicked, can
+ assign a handler from the consuming environment
+ tag-input-changed:
+ As user is typing a new tag, the text gets emitted here.
+
+Usage:
+
+
+
+ ...
+
+ methods: {
+
+ // tag is only added when addTag(tag) is called
+ beforeAddingTag({ tag, addTag }) {
+ saveTagToServer().then(() => addTag(tag));
+ },
+
+ // tag is deleted when deleteTag(tag) is called
+ beforeDeletingTag({ tag, deleteTag }) {
+ deleteTagFromServer().then(() => deleteTag(tag));
+ },
+
+ // do a database lookup to generate viable options and
+ // set on the property that's passed to the component to
+ // do a little autocomplete dropdown
+ tagTextChanged(txt) {
+ generateAutocompleteOptions(txt).then((newOptions) => {
+ this.autocompleteItems = newOptions;
+ })
+ },
+
+ // any appropriate click handler (update search, etc.)
+ tagClick(tag) {
+ // do something with the tag data
+ }
+ }
diff --git a/client/galaxy/scripts/components/Tags/GalaxyTags.vue b/client/galaxy/scripts/components/Tags/GalaxyTags.vue
new file mode 100644
index 00000000000..7a88f6364c3
--- /dev/null
+++ b/client/galaxy/scripts/components/Tags/GalaxyTags.vue
@@ -0,0 +1,193 @@
+
+
-
- ## Build buttons for current tags.
- %for tag in tags:
- <%
- ## Handle both Tag and ItemTagAssociation objects.
- if isinstance( tag, Tag ):
- tag_name = tag.name
- tag_value = None
- elif isinstance( tag, ItemTagAssociation ):
- tag_name = tag.user_tname
- tag_value = tag.user_value
-
- ## Convert tag name, value to unicode.
- if isinstance( tag_name, six.binary_type ):
- tag_name = unicodify( escape( tag_name ) )
- if tag_value:
- tag_value = unicodify( escape( tag_value ) )
- if tag_value:
- tag_str = tag_name + ":" + tag_value
- else:
- tag_str = tag_name
- %>
-
- ${tag_str | h}
- %if editable:
-
- %endif
-
- %endfor
-
- ## Add tag input field. If element is in form, tag input is a textarea; otherwise element is a input type=text.
- %if editable:
- %if in_form:
-
- %else:
-
- %endif
- ## Add "add tag" button.
- %if render_add_tag_button:
-
- %endif
- %endif
-
-
-%def>
-
-## Render tool tagging elements
-<%def name="render_tool_tagging_elements()">
- <%
- elt_id = int ( floor ( random() * six.MAXSIZE ) )
- tags = trans.app.tag_handler.get_tool_tags()
- %>
- ${self.render_tagging_element_html(elt_id=elt_id, \
- tags=tags, \
- editable=False, \
- use_toggle_link=False )}
-
-%def>
-
-## Render community tagging element.
-<%def name="render_community_tagging_element(tagged_item=None, elt_context=None, use_toggle_link=False, tag_click_fn='default_tag_click_fn')">
- ## Build HTML.
- <%
- elt_id = int ( floor ( random() * six.MAXSIZE ) )
+ controller_name = get_controller_name(tagged_item)
+ click_url = h.url_for( controller='/' + controller_name , action='list_published')
community_tags = trans.app.tag_handler.get_community_tags( item=tagged_item, limit=5 )
+
+ ## Having trouble converting list of tags into a plain array, this just
+ ## just plucks out the name
+ community_tag_names = []
+ for tag in community_tags:
+ community_tag_names.append(escape(tag.name))
%>
- ${self.render_tagging_element_html(elt_id=elt_id, \
- tags=community_tags, \
- use_toggle_link=use_toggle_link, \
- editable=False, tag_type="community")}
+
+
- ## Set up tag click function.
%def>
-## Render individual tagging element.
-<%def name="render_individual_tagging_element(user=None, tagged_item=None, elt_context=None, use_toggle_link=True, in_form=False, input_size='15', tag_click_fn='default_tag_click_fn', get_toggle_link_text_fn='default_get_toggle_link_text_fn', editable=True, render_add_tag_button=True)">
- ## Useful attributes.
+<%def name="render_individual_tagging_element(
+ user=None,
+ tagged_item=None,
+ elt_context=None,
+ use_toggle_link=True,
+ tag_click_fn='default_tag_click_fn',
+ get_toggle_link_text_fn='default_get_toggle_link_text_fn',
+ editable=True)">
+
<%
- # Useful ids.
tagged_item_id = str( trans.security.encode_id ( tagged_item.id ) )
- elt_id = int ( floor ( random() * six.MAXSIZE ) )
-
- # Get list of user's item tags. TODO: implement owner_tags for all taggable objects and use here.
item_tags = [ tag for tag in tagged_item.tags if ( tag.user == user ) ]
+
+ item_tag_names = []
+ for ta in item_tags:
+ item_tag_names.append(escape(ta.tag.name))
%>
- ## Build HTML.
- <%
- if len(item_tags) > 3:
- # If item has more than 3 tags show a link to see tags instead of displaying them all
- use_toggle_link = True
- else:
- use_toggle_link = False
- %>
- ${self.render_tagging_element_html(elt_id=elt_id, tags=item_tags, editable=editable, use_toggle_link=use_toggle_link, input_size=input_size, in_form=in_form, render_add_tag_button=render_add_tag_button)}
+
- ## Build script that augments tags using progressive javascript.
- ## Use style to hide/display the tag area.
-
-
-
%def>
<%def name="community_tag_js( controller_name )">
+## TODO: Note that this function no longer has anything to do with community
+## tags. the ratings code and tagging initialization were previously co-mingled
+## in here. Will remove this script when we write the ratings components
+
## set up comminity tag and rating handling - used for page start up / set up
## controller_name: the model controller for the item being tagged - generally gotten with get_controller_name( item )