diff --git a/client/src/components/Workflow/Invocations.test.js b/client/src/components/Workflow/Invocations.test.js index f273d0a1729..7f40f14e053 100644 --- a/client/src/components/Workflow/Invocations.test.js +++ b/client/src/components/Workflow/Invocations.test.js @@ -73,12 +73,12 @@ describe("Invocations.vue with invocation", () => { expect(rows.length).toBe(1); const row = rows[0]; const columns = row.findAll("td"); - expect(columns.at(0).text()).toBe("workflow name"); - expect(columns.at(1).text()).toBe("history name"); - expect(columns.at(2).text()).toBe(moment.utc(invocationData.create_time).fromNow()); - expect(columns.at(3).text()).toBe(moment.utc(invocationData.update_time).fromNow()); - expect(columns.at(4).text()).toBe("scheduled"); - expect(columns.at(5).text()).toBe(""); + expect(columns.at(1).text()).toBe("workflow name"); + expect(columns.at(2).text()).toBe("history name"); + expect(columns.at(3).text()).toBe(moment.utc(invocationData.create_time).fromNow()); + expect(columns.at(4).text()).toBe(moment.utc(invocationData.update_time).fromNow()); + expect(columns.at(5).text()).toBe("scheduled"); + expect(columns.at(6).text()).toBe(""); }); it("toggles detail rendering", async () => { diff --git a/client/src/components/Workflow/Invocations.vue b/client/src/components/Workflow/Invocations.vue index ee35740bba1..9c1ee0bc82d 100644 --- a/client/src/components/Workflow/Invocations.vue +++ b/client/src/components/Workflow/Invocations.vue @@ -20,7 +20,8 @@ striped caption-top :busy="loading" - fixed> + fixed + class="invocations-table"> @@ -31,25 +32,39 @@ @invocation-cancelled="$emit('reload-invocations')" /> - + - {{ getWorkflowNameByInstanceId(data.item.workflow_id) }} - + v-b-tooltip.hover.top + title="Show Invocation Details" + class="btn-sm fa fa-chevron-down toggle-invocation-details" + v-if="!data.detailsShowing" + @click.stop="swapRowDetails(data)" /> + + + + + + {{ getWorkflowNameByInstanceId(data.item.workflow_id) }} + + - - {{ getHistoryNameById(data.item.history_id) }} - + + + {{ getHistoryNameById(data.item.history_id) }} + + @@ -94,12 +109,13 @@ export default { }, data() { const fields = [ - { key: "workflow_id", label: "Workflow" }, - { key: "history_id", label: "History" }, - { key: "create_time", label: "Invoked" }, - { key: "update_time", label: "Updated" }, - { key: "state" }, - { key: "execute", label: "" }, + { key: "expand", label: "", class: "col-button" }, + { key: "workflow_id", label: "Workflow", class: "col-name" }, + { key: "history_id", label: "History", class: "col-history" }, + { key: "create_time", label: "Invoked", class: "col-small" }, + { key: "update_time", label: "Updated", class: "col-small" }, + { key: "state", class: "col-small" }, + { key: "execute", label: "", class: "col-button" }, ]; return { invocationItemsModel: [], @@ -145,3 +161,25 @@ export default { }, }; + diff --git a/lib/galaxy/model/tags.py b/lib/galaxy/model/tags.py index 4e3f0d2069a..6f77c1459ac 100644 --- a/lib/galaxy/model/tags.py +++ b/lib/galaxy/model/tags.py @@ -2,6 +2,8 @@ import logging import re from typing import Dict, List, Optional, Tuple +from sqlalchemy.exc import IntegrityError +from sqlalchemy.orm import sessionmaker from sqlalchemy.sql import select from sqlalchemy.sql.expression import func @@ -245,7 +247,18 @@ class TagHandler: return self.sa_session.query(galaxy.model.Tag).filter_by(name=tag_name).first() def _create_tag_instance(self, tag_name): - return galaxy.model.Tag(type=0, name=tag_name) + # For good performance caller should first check if there's already an appropriate tag + Session = sessionmaker(self.sa_session.bind) + tag = galaxy.model.Tag(type=0, name=tag_name) + with Session() as separate_session: + separate_session.add(tag) + try: + separate_session.commit() + separate_session.flush() + except IntegrityError: + # tag already exists, get from database + separate_session.rollback() + return self._get_tag(tag_name) def _get_or_create_tag(self, tag_str): """Get or create a Tag object from a tag string.""" diff --git a/test/unit/app/managers/test_TagHandler.py b/test/unit/app/managers/test_TagHandler.py index 7839be7d019..118edddfaa6 100644 --- a/test/unit/app/managers/test_TagHandler.py +++ b/test/unit/app/managers/test_TagHandler.py @@ -100,6 +100,12 @@ class TagHandlerTestCase(BaseTestCase): self.tag_handler.delete_item_tags(user=self.user, item=hda) self.assertEqual(hda.tags, []) + def test_unique_constraint_applied(self): + tag_name = 'abc' + tag = self.tag_handler._create_tag_instance(tag_name) + same_tag = self.tag_handler._create_tag_instance(tag_name) + assert tag.id == same_tag.id + def test_item_has_tag(self): hda = self._create_vanilla_hda() tags = ['tag1']