From 7d93f386d725232ca3345f5be7ae63492596a6f5 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Wed, 13 Jul 2022 13:05:12 +0200 Subject: [PATCH 01/69] Add href links to some history item actions This will allow to right click and open the action in a new tab or window. --- .../History/Content/ContentItem.vue | 33 +++++++++++++++---- .../History/Content/ContentOptions.vue | 7 ++-- .../Content/Dataset/DatasetActions.vue | 25 ++++++++++---- .../Content/Dataset/DatasetDetails.vue | 7 +++- 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/client/src/components/History/Content/ContentItem.vue b/client/src/components/History/Content/ContentItem.vue index 049f11f36ca..f8b4f8bc533 100644 --- a/client/src/components/History/Content/ContentItem.vue +++ b/client/src/components/History/Content/ContentItem.vue @@ -53,6 +53,7 @@ :is-history-item="isHistoryItem" :is-visible="item.visible" :state="state" + :item-urls="itemUrls" @delete="$emit('delete')" @display="onDisplay" @edit="onEdit" @@ -81,6 +82,7 @@ v-if="expandDataset" :dataset="item" :show-highlight="isHistoryItem" + :item-urls="itemUrls" @edit="onEdit" @toggleHighlights="toggleHighlights" /> @@ -99,9 +101,12 @@ import { JobStateSummary } from "./Collection/JobStateSummary"; import { library } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { faArrowCircleUp, faMinusCircle, faCheckCircle } from "@fortawesome/free-solid-svg-icons"; +import { getAppRoot } from "onload/loadConfig"; library.add(faArrowCircleUp, faMinusCircle, faCheckCircle); +const root = getAppRoot(); + export default { components: { CollectionDescription, @@ -165,6 +170,25 @@ export default { tagsDisabled() { return !this.expandDataset || !this.isHistoryItem; }, + isCollection() { + return "collection_type" in this.item; + }, + itemUrls() { + const id = this.item.id; + if (this.isCollection) { + return { + edit: `${root}collection/edit/${id}`, + }; + } + return { + display: `${root}datasets/${id}/display/?preview=True`, + edit: `${root}datasets/edit?dataset_id=${id}`, + showDetails: `${root}datasets/${id}/details`, + reportError: `${root}datasets/error?dataset_id=${id}`, + rerun: `${root}tool_runner/rerun?id=${id}`, + visualize: `visualizations?dataset_id=${id}`, + }; + }, }, methods: { onClick() { @@ -175,8 +199,7 @@ export default { } }, onDisplay() { - const url = `datasets/${this.item.id}/display/?preview=True`; - iframeAdd({ path: url, title: this.name }); + iframeAdd({ path: this.itemUrls.display, title: this.name }); }, onDragStart(evt) { evt.dataTransfer.dropEffect = "move"; @@ -184,11 +207,7 @@ export default { evt.dataTransfer.setData("text", JSON.stringify([this.item])); }, onEdit() { - if (this.item.collection_type) { - backboneRoute(`collection/edit/${this.item.id}`); - } else { - backboneRoute("datasets/edit", { dataset_id: this.item.id }); - } + backboneRoute(this.itemUrls.edit); }, onTags(newTags) { this.$emit("tag-change", this.item, newTags); diff --git a/client/src/components/History/Content/ContentOptions.vue b/client/src/components/History/Content/ContentOptions.vue index b24d51f1dc7..0e25a4eb405 100644 --- a/client/src/components/History/Content/ContentOptions.vue +++ b/client/src/components/History/Content/ContentOptions.vue @@ -7,7 +7,8 @@ class="px-1" size="sm" variant="link" - @click.stop="$emit('display')"> + :href="itemUrls.display" + @click.prevent.stop="$emit('display')"> + :href="itemUrls.edit" + @click.prevent.stop="$emit('edit')">
- + @@ -21,7 +28,8 @@ title="Dataset Details" size="sm" variant="link" - @click.stop="onInfo"> + :href="itemUrls.showDetails" + @click.prevent.stop="onInfo"> + :href="itemUrls.rerun" + @click.prevent.stop="onRerun"> + :href="itemUrls.visualize" + @click.prevent.stop="onVisualize"> {{ result.misc_info }}
- +
             
         
@@ -94,6 +98,7 @@ export default {
     props: {
         dataset: { type: Object, required: true },
         showHighlight: { type: Boolean, default: false },
+        itemUrls: { type: Object, required: true },
     },
     computed: {
         stateText() {

From 1e75d85fd4ca2a35dfa0081840125a2d725600e6 Mon Sep 17 00:00:00 2001
From: John Davis 
Date: Wed, 13 Jul 2022 15:40:42 -0400
Subject: [PATCH 02/69] Prevent accessing LegacyScripts.database before
 processing script args

---
 lib/galaxy/model/migrations/scripts.py          | 11 +++++++++--
 test/unit/data/model/migrations/test_scripts.py | 12 ++++++++++++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/lib/galaxy/model/migrations/scripts.py b/lib/galaxy/model/migrations/scripts.py
index b23c6af7bc9..487e0b744ce 100644
--- a/lib/galaxy/model/migrations/scripts.py
+++ b/lib/galaxy/model/migrations/scripts.py
@@ -120,7 +120,13 @@ class LegacyScripts:
     def __init__(self, argv: List[str], cwd: Optional[str] = None) -> None:
         self.argv = argv
         self.cwd = cwd or os.getcwd()
-        self.database = self.DEFAULT_DB_ARG
+        self._database = None  # Do not assign default value: `None` means we don't know yet.
+
+    @property
+    def database(self):
+        if self._database is None:
+            raise LegacyScriptsException("Attempt to access identifier of database before processing the script arguments")
+        return self._database
 
     def run(self) -> None:
         """
@@ -147,8 +153,9 @@ class LegacyScripts:
         If last argument is a valid database name, pop and assign it; otherwise assign default.
         """
         arg = self.argv[-1]
+        self._database = self.DEFAULT_DB_ARG
         if arg in ["galaxy", "install"]:
-            self.database = self.argv.pop()
+            self._database = self.argv.pop()
 
     def rename_config_argument(self) -> None:
         """
diff --git a/test/unit/data/model/migrations/test_scripts.py b/test/unit/data/model/migrations/test_scripts.py
index 216bc6a5efe..5fc28b73346 100644
--- a/test/unit/data/model/migrations/test_scripts.py
+++ b/test/unit/data/model/migrations/test_scripts.py
@@ -145,3 +145,15 @@ class TestLegacyScripts:
         argv = ["caller", "--alembic-config", "path-to-alembic", "downgrade"]
         with pytest.raises(LegacyScriptsException):
             LegacyScripts(argv).convert_args()
+
+    def test_access_database_id(self):
+        db = "galaxy"
+        argv = ["caller", "--alembic-config", "path-to-alembic", "upgrade", db]
+        ls = LegacyScripts(argv)
+        ls.run()
+        assert ls.database == db
+
+    def test_access_database_id_before_processing_script_args_raises_error(self):
+        argv = ["caller", "--alembic-config", "path-to-alembic", "upgrade"]
+        with pytest.raises(LegacyScriptsException):
+            LegacyScripts(argv).database

From def882932d152a6f4d868d6e1a67e730b7550f9e Mon Sep 17 00:00:00 2001
From: John Davis 
Date: Wed, 13 Jul 2022 16:10:58 -0400
Subject: [PATCH 03/69] Add verify_db_is_initialized function; tests

---
 lib/galaxy/model/migrations/scripts.py        | 54 ++++++++++++++++++-
 .../data/model/migrations/test_scripts.py     | 15 ++++++
 2 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/lib/galaxy/model/migrations/scripts.py b/lib/galaxy/model/migrations/scripts.py
index 487e0b744ce..491f8f1ce6f 100644
--- a/lib/galaxy/model/migrations/scripts.py
+++ b/lib/galaxy/model/migrations/scripts.py
@@ -14,7 +14,10 @@ from alembic.script import ScriptDirectory
 from sqlalchemy import create_engine
 from sqlalchemy.engine import Engine
 
-from galaxy.model.database_utils import is_one_database
+from galaxy.model.database_utils import (
+    database_exists,
+    is_one_database,
+)
 from galaxy.model.migrations import (
     AlembicManager,
     DatabaseConfig,
@@ -38,6 +41,51 @@ GXY_CONFIG_PREFIX = "GALAXY_CONFIG_"
 TSI_CONFIG_PREFIX = "GALAXY_INSTALL_CONFIG_"
 
 
+class DatabaseDoesNotExistError(Exception):
+    def __init__(self, db_url: str) -> None:
+        super().__init__(
+            f"""The database at {db_url} does not exist. You must
+            create and initialize the database before running this script. You
+            can do so by (a) running `create_db.sh`; or by (b) starting Galaxy,
+            in which case Galaxy will create and initialize the database
+            automatically."""
+        )
+
+
+class DatabaseNotInitializedError(Exception):
+    def __init__(self, db_url: str) -> None:
+        super().__init__(
+            f"""The database at {db_url} is empty. You must
+            initialize the database before running this script. You can do so by
+            (a) running `create_db.sh`; or by (b) starting Galaxy, in which case
+            Galaxy will initialize the database automatically."""
+        )
+
+
+def verify_database_is_initialized(db_url: str) -> None:
+    """
+    Intended for use by scripts that run database migrations (manage_db.sh,
+    run_alembic.sh). Those scripts are meant to run on a database that has been
+    initialized with the appropriate metadata (e.g. galaxy or install model).
+
+    This function will raise an error if the database does not exist or has not
+    been initialized*.
+
+    *NOTE: this function cannot determine whether a database has been properly
+    initialized; it can only tell when a database has *not* been initialized.
+    """
+    if not database_exists(db_url):
+        raise DatabaseDoesNotExistError(db_url)
+
+    engine = create_engine(db_url)
+    try:
+        db_state = DatabaseStateCache(engine=engine)
+        if db_state.is_database_empty() or db_state.contains_only_kombu_tables():
+            raise DatabaseNotInitializedError(db_url)
+    finally:
+        engine.dispose()
+
+
 def get_configuration(argv: List[str], cwd: str) -> Tuple[DatabaseConfig, DatabaseConfig, bool]:
     """
     Return a 3-item-tuple with configuration values used for managing databases.
@@ -125,7 +173,9 @@ class LegacyScripts:
     @property
     def database(self):
         if self._database is None:
-            raise LegacyScriptsException("Attempt to access identifier of database before processing the script arguments")
+            raise LegacyScriptsException(
+                "Attempt to access identifier of database before processing the script arguments"
+            )
         return self._database
 
     def run(self) -> None:
diff --git a/test/unit/data/model/migrations/test_scripts.py b/test/unit/data/model/migrations/test_scripts.py
index 5fc28b73346..0472b7503a7 100644
--- a/test/unit/data/model/migrations/test_scripts.py
+++ b/test/unit/data/model/migrations/test_scripts.py
@@ -1,8 +1,13 @@
+import random
+
 import pytest
 
 from galaxy.model.migrations.scripts import (
+    DatabaseDoesNotExistError,
+    DatabaseNotInitializedError,
     LegacyScripts,
     LegacyScriptsException,
+    verify_database_is_initialized,
 )
 
 
@@ -157,3 +162,13 @@ class TestLegacyScripts:
         argv = ["caller", "--alembic-config", "path-to-alembic", "upgrade"]
         with pytest.raises(LegacyScriptsException):
             LegacyScripts(argv).database
+
+    def test_verify_database_is_init_raises_error_if_no_database(self):
+        nonexistant_path = str(random.random())[2:]
+        db_url = f"sqlite:////{nonexistant_path}"
+        with pytest.raises(DatabaseDoesNotExistError):
+            verify_database_is_initialized(db_url)
+
+    def test_verify_database_is_init_raises_error_if_database_not_initialized(self, sqlite_memory_url):
+        with pytest.raises(DatabaseNotInitializedError):
+            verify_database_is_initialized(sqlite_memory_url)

From af81f2a01d9685a967b2ccc89eed34b637e0ccc7 Mon Sep 17 00:00:00 2001
From: John Davis 
Date: Wed, 13 Jul 2022 16:38:11 -0400
Subject: [PATCH 04/69] Verify db initialization before running upgrade script

---
 lib/galaxy/model/migrations/scripts.py | 6 ++++++
 scripts/manage_db_adapter.py           | 3 +++
 2 files changed, 9 insertions(+)

diff --git a/lib/galaxy/model/migrations/scripts.py b/lib/galaxy/model/migrations/scripts.py
index 491f8f1ce6f..c25b88d0080 100644
--- a/lib/galaxy/model/migrations/scripts.py
+++ b/lib/galaxy/model/migrations/scripts.py
@@ -253,6 +253,12 @@ class LegacyScripts:
                 elif self.database == "install":
                     self.argv.append("tsi@head")
 
+    def get_db_url(self):
+        if self.database in ["galaxy", self.DEFAULT_DB_ARG]:
+            return self.gxy_url
+        elif self.database == "install":
+            return self.tsi_url
+
     def _rename_arg(self, old_name, new_name) -> None:
         pos = self.argv.index(old_name)
         self.argv[pos] = new_name
diff --git a/scripts/manage_db_adapter.py b/scripts/manage_db_adapter.py
index d4be4f14127..f19974486e8 100644
--- a/scripts/manage_db_adapter.py
+++ b/scripts/manage_db_adapter.py
@@ -25,12 +25,15 @@ sys.path.insert(1, os.path.abspath(os.path.join(os.path.dirname(__file__), os.pa
 from galaxy.model.migrations.scripts import (
     invoke_alembic,
     LegacyScripts,
+    verify_database_is_initialized,
 )
 
 
 def run():
     ls = LegacyScripts(sys.argv, os.getcwd())
     ls.run()
+    db_url = ls.get_db_url()
+    verify_database_is_initialized(db_url)
     invoke_alembic()
 
 

From 2d19565986a3f64a17dfe3949e50bf701412468b Mon Sep 17 00:00:00 2001
From: John Davis 
Date: Wed, 13 Jul 2022 16:43:19 -0400
Subject: [PATCH 05/69] Fix mypy

---
 lib/galaxy/model/migrations/scripts.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/galaxy/model/migrations/scripts.py b/lib/galaxy/model/migrations/scripts.py
index c25b88d0080..54f0ad774e1 100644
--- a/lib/galaxy/model/migrations/scripts.py
+++ b/lib/galaxy/model/migrations/scripts.py
@@ -168,7 +168,7 @@ class LegacyScripts:
     def __init__(self, argv: List[str], cwd: Optional[str] = None) -> None:
         self.argv = argv
         self.cwd = cwd or os.getcwd()
-        self._database = None  # Do not assign default value: `None` means we don't know yet.
+        self._database: Optional[str] = None  # Do not assign default value: `None` means we don't know yet.
 
     @property
     def database(self):

From 1638dc0210c9a04d6cab9d5823694efa2377d95b Mon Sep 17 00:00:00 2001
From: davelopez <46503462+davelopez@users.noreply.github.com>
Date: Thu, 14 Jul 2022 11:41:20 +0200
Subject: [PATCH 06/69] Add HREF to dataset download

---
 .../History/Content/Dataset/DatasetDownload.vue        | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/client/src/components/History/Content/Dataset/DatasetDownload.vue b/client/src/components/History/Content/Dataset/DatasetDownload.vue
index b0288e1d69f..14455e47d8e 100644
--- a/client/src/components/History/Content/Dataset/DatasetDownload.vue
+++ b/client/src/components/History/Content/Dataset/DatasetDownload.vue
@@ -14,12 +14,15 @@
         
-         Download Dataset 
+        
+            Download Dataset
+        
         
+            :href="metaDownloadUrl + metaFile.file_type"
+            @click.prevent.stop="onDownload(metaDownloadUrl, metaFile.file_type)">
             Download {{ metaFile.file_type }}
         
     
@@ -29,7 +32,8 @@
         title="Download"
         size="sm"
         variant="link"
-        @click.stop="onDownload(downloadUrl)">
+        :href="downloadUrl"
+        @click.prevent.stop="onDownload(downloadUrl)">
         
     
 

From d642ce34c8bdae5819c643648dfedc1efa665a6b Mon Sep 17 00:00:00 2001
From: Matthias Bernt 
Date: Thu, 14 Jul 2022 14:19:40 +0200
Subject: [PATCH 07/69] fix `startswith` attribute of ``

as documented in the xsd

in addition fix https://github.com/galaxyproject/galaxy/issues/14324,
i.e. document the `separator` attribute of options

also doc that only 1MB is used and lines starting with `#` are always
ignored
---
 lib/galaxy/tool_util/xsd/galaxy.xsd           | 15 +++++--
 .../tools/parameters/dynamic_options.py       |  2 +-
 .../tools/options_from_metadata_file.xml      | 39 ++++++++++++------
 test/functional/tools/samples_tool_conf.xml   |  1 +
 .../tools/select_from_csvdataset.xml          | 40 +++++++++++++++++++
 5 files changed, 80 insertions(+), 17 deletions(-)
 create mode 100644 test/functional/tools/select_from_csvdataset.xml

diff --git a/lib/galaxy/tool_util/xsd/galaxy.xsd b/lib/galaxy/tool_util/xsd/galaxy.xsd
index 5fa1fd5813a..7f32306bdde 100644
--- a/lib/galaxy/tool_util/xsd/galaxy.xsd
+++ b/lib/galaxy/tool_util/xsd/galaxy.xsd
@@ -3937,7 +3937,7 @@ exclusively use ``filter``s to populate options.
 * ``from_dataset`` - The options for the select list are dynamically obtained
   from input dataset selected for the tool from the current history.
 * ``from_file`` - The options for the select list are dynamically obtained from
-  a file. This mechanis is discourage in favor of the more generic
+  a file. This mechanism is discouraged in favor of the more generic
   ``from_data_table``.
 * ``from_parameter`` - The options for the select list are dynamically obtained
   from a parameter.
@@ -4013,6 +4013,10 @@ Starting from Galaxy v21.01, ``meta_file_key`` can be used together with
 medadata file that the ``meta_file_key`` implies, instead of the dataset
 itself.
 
+Note that in any case only the first mega byte of the referred dataset (or file)
+is considered. Lines starting with ``#`` are ignored. By using the ``startswith``
+attribute also lines starting with other strings can be ignored.
+
 ```xml
 
 
@@ -4087,7 +4091,7 @@ used to generate dynamic options.
     
     
       
-        Determine options from the dataset given in the referred input parameter. If 'meta_file_key' is given, the options are determined from the data in the metadata file of the input.
+        Determine options from (the first MB of) the dataset given in the referred input parameter. If 'meta_file_key' is given, the options are determined from (the first MB of) the data in the metadata file of the input.
       
     
     
@@ -4117,7 +4121,7 @@ used to generate dynamic options.
     
     
       
-        Ignore lines starting with the given character.
+        Ignore lines starting with the given string.
       
     
     
@@ -4125,6 +4129,11 @@ used to generate dynamic options.
         Works with from_dataset only. See [docs](#from-dataset)
       
     
+    
+      
+        Split tabular data with this character (default is tab)
+      
+    
   
   
     
diff --git a/lib/galaxy/tools/parameters/dynamic_options.py b/lib/galaxy/tools/parameters/dynamic_options.py
index 6eaac75fad4..803d54349f6 100644
--- a/lib/galaxy/tools/parameters/dynamic_options.py
+++ b/lib/galaxy/tools/parameters/dynamic_options.py
@@ -645,7 +645,7 @@ class DynamicOptions:
         rval = []
         field_count = None
         for line in reader:
-            if line.startswith('#') or (self.line_startswith and not line.startswith(self.line_startswith)):
+            if line.startswith("#") or (self.line_startswith and line.startswith(self.line_startswith)):
                 continue
             line = line.rstrip("\n\r")
             if line:
diff --git a/test/functional/tools/options_from_metadata_file.xml b/test/functional/tools/options_from_metadata_file.xml
index 23347ebf938..c29f422e7bd 100644
--- a/test/functional/tools/options_from_metadata_file.xml
+++ b/test/functional/tools/options_from_metadata_file.xml
@@ -1,19 +1,30 @@
 
    '${output}';
+echo '${species_comma}' >> '${output}';
 echo '${species_2}' >> '${output}'
   ]]>
   
     
+    
     
-        
-            
-            
+        
+          
+          
         
     
-    
+    
+    
+        
+          
+          
+        
+    
+    
+    
     
-        
+        
             
             
             
@@ -21,23 +32,25 @@ echo '${species_2}' >> '${output}'
     
   
   
-    
+    
   
   
     
-      
-      
+      
+      
+      
       
         
-          
-          
+          
+          
         
       
-      
+      
       
         
-          
-          
+          
+          
+          
         
       
     
diff --git a/test/functional/tools/samples_tool_conf.xml b/test/functional/tools/samples_tool_conf.xml
index 4c6ea5df1d6..be536e1c005 100644
--- a/test/functional/tools/samples_tool_conf.xml
+++ b/test/functional/tools/samples_tool_conf.xml
@@ -53,6 +53,7 @@
   
   
   
+  
   
   
   
diff --git a/test/functional/tools/select_from_csvdataset.xml b/test/functional/tools/select_from_csvdataset.xml
new file mode 100644
index 00000000000..6ca646a1db3
--- /dev/null
+++ b/test/functional/tools/select_from_csvdataset.xml
@@ -0,0 +1,40 @@
+
+    Create dynamic options from CSV data sets
+     '$output'
+    ]]>
+    
+        
+        
+            
+                
+                
+                
+            
+        
+    
+
+    
+        
+    
+
+    
+        
+        
+            
+            
+            
+                
+                        
+                
+            
+        
+        
+        
+            
+            
+        
+    
+    
+    
+
\ No newline at end of file

From 9feebb88cb4ad82aaf90d9b5b03b3925c00b8e5a Mon Sep 17 00:00:00 2001
From: davelopez <46503462+davelopez@users.noreply.github.com>
Date: Thu, 14 Jul 2022 12:54:58 +0200
Subject: [PATCH 08/69] Fix tours selectors

The buttons are now considered links so better use the class to select them since it will be less prone to change than the title.
---
 .../components/History/Content/ContentOptions.vue   | 10 +++++-----
 client/src/utils/navigation/navigation.yml          |  5 ++---
 config/plugins/tours/core.galaxy_ui.yaml            | 12 ++++++------
 config/plugins/tours/core.history.yaml              | 13 ++++++-------
 config/plugins/tours/core.windows.yaml              |  2 +-
 5 files changed, 20 insertions(+), 22 deletions(-)

diff --git a/client/src/components/History/Content/ContentOptions.vue b/client/src/components/History/Content/ContentOptions.vue
index 0e25a4eb405..52be3890cb9 100644
--- a/client/src/components/History/Content/ContentOptions.vue
+++ b/client/src/components/History/Content/ContentOptions.vue
@@ -4,7 +4,7 @@
             v-if="isDataset"
             :disabled="displayDisabled"
             :title="displayButtonTitle"
-            class="px-1"
+            class="display-btn px-1"
             size="sm"
             variant="link"
             :href="itemUrls.display"
@@ -15,7 +15,7 @@
             v-if="isHistoryItem"
             :disabled="editDisabled"
             :title="editButtonTitle"
-            class="px-1"
+            class="edit-btn px-1"
             size="sm"
             variant="link"
             :href="itemUrls.edit"
@@ -24,7 +24,7 @@
         
         
         
         
Date: Thu, 14 Jul 2022 23:30:11 +0200
Subject: [PATCH 09/69] Update
 test/functional/tools/options_from_metadata_file.xml

Co-authored-by: Nicola Soranzo 
---
 test/functional/tools/options_from_metadata_file.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/functional/tools/options_from_metadata_file.xml b/test/functional/tools/options_from_metadata_file.xml
index c29f422e7bd..e15e1a1a4e5 100644
--- a/test/functional/tools/options_from_metadata_file.xml
+++ b/test/functional/tools/options_from_metadata_file.xml
@@ -38,7 +38,7 @@ echo '${species_2}' >> '${output}'
     
       
       
-      
+      
       
         
           

From fe06eea75d6b28e088a7b0c7d13dddb5062a63a7 Mon Sep 17 00:00:00 2001
From: Matthias Bernt 
Date: Fri, 15 Jul 2022 10:49:12 +0200
Subject: [PATCH 10/69] fix test output

---
 test/functional/tools/options_from_metadata_file.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/functional/tools/options_from_metadata_file.xml b/test/functional/tools/options_from_metadata_file.xml
index e15e1a1a4e5..87e1863bbb8 100644
--- a/test/functional/tools/options_from_metadata_file.xml
+++ b/test/functional/tools/options_from_metadata_file.xml
@@ -38,7 +38,7 @@ echo '${species_2}' >> '${output}'
     
       
       
-      
+      
       
         
           

From 23f190bd2400b49d7676055037eef0ecbea5fe86 Mon Sep 17 00:00:00 2001
From: davelopez <46503462+davelopez@users.noreply.github.com>
Date: Fri, 15 Jul 2022 13:18:38 +0200
Subject: [PATCH 11/69] Fix history item action URLs with prefix

Declare relative URLs only and then prefix the root when necessary.
---
 .../History/Content/ContentItem.vue           | 16 ++++++--------
 .../History/Content/ContentOptions.vue        | 11 ++++++++--
 .../Content/Dataset/DatasetActions.vue        | 22 ++++++++++++++-----
 3 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/client/src/components/History/Content/ContentItem.vue b/client/src/components/History/Content/ContentItem.vue
index f8b4f8bc533..ba7a9be6227 100644
--- a/client/src/components/History/Content/ContentItem.vue
+++ b/client/src/components/History/Content/ContentItem.vue
@@ -101,12 +101,9 @@ import { JobStateSummary } from "./Collection/JobStateSummary";
 import { library } from "@fortawesome/fontawesome-svg-core";
 import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
 import { faArrowCircleUp, faMinusCircle, faCheckCircle } from "@fortawesome/free-solid-svg-icons";
-import { getAppRoot } from "onload/loadConfig";
 
 library.add(faArrowCircleUp, faMinusCircle, faCheckCircle);
 
-const root = getAppRoot();
-
 export default {
     components: {
         CollectionDescription,
@@ -173,19 +170,20 @@ export default {
         isCollection() {
             return "collection_type" in this.item;
         },
+        /** Relative URLs for history item actions */
         itemUrls() {
             const id = this.item.id;
             if (this.isCollection) {
                 return {
-                    edit: `${root}collection/edit/${id}`,
+                    edit: `collection/edit/${id}`,
                 };
             }
             return {
-                display: `${root}datasets/${id}/display/?preview=True`,
-                edit: `${root}datasets/edit?dataset_id=${id}`,
-                showDetails: `${root}datasets/${id}/details`,
-                reportError: `${root}datasets/error?dataset_id=${id}`,
-                rerun: `${root}tool_runner/rerun?id=${id}`,
+                display: `datasets/${id}/display/?preview=True`,
+                edit: `datasets/edit?dataset_id=${id}`,
+                showDetails: `datasets/${id}/details`,
+                reportError: `datasets/error?dataset_id=${id}`,
+                rerun: `tool_runner/rerun?id=${id}`,
                 visualize: `visualizations?dataset_id=${id}`,
             };
         },
diff --git a/client/src/components/History/Content/ContentOptions.vue b/client/src/components/History/Content/ContentOptions.vue
index 52be3890cb9..4c708261858 100644
--- a/client/src/components/History/Content/ContentOptions.vue
+++ b/client/src/components/History/Content/ContentOptions.vue
@@ -7,7 +7,7 @@
             class="display-btn px-1"
             size="sm"
             variant="link"
-            :href="itemUrls.display"
+            :href="displayUrl"
             @click.prevent.stop="$emit('display')">
             
         
@@ -18,7 +18,7 @@
             class="edit-btn px-1"
             size="sm"
             variant="link"
-            :href="itemUrls.edit"
+            :href="editUrl"
             @click.prevent.stop="$emit('edit')">
             
         
@@ -53,6 +53,7 @@
 
 
 
diff --git a/client/src/components/History/Content/Dataset/DatasetActions.vue b/client/src/components/History/Content/Dataset/DatasetActions.vue
index a140fae183f..95dd7f7f86c 100644
--- a/client/src/components/History/Content/Dataset/DatasetActions.vue
+++ b/client/src/components/History/Content/Dataset/DatasetActions.vue
@@ -8,7 +8,7 @@
                     title="Error"
                     size="sm"
                     variant="link"
-                    :href="itemUrls.reportError"
+                    :href="reportErrorUrl"
                     @click.prevent.stop="onError">
                     
                 
@@ -28,7 +28,7 @@
                     title="Dataset Details"
                     size="sm"
                     variant="link"
-                    :href="itemUrls.showDetails"
+                    :href="showDetailsUrl"
                     @click.prevent.stop="onInfo">
                     
                 
@@ -38,7 +38,7 @@
                     title="Run Job Again"
                     size="sm"
                     variant="link"
-                    :href="itemUrls.rerun"
+                    :href="rerunUrl"
                     @click.prevent.stop="onRerun">
                     
                 
@@ -48,7 +48,7 @@
                     title="Visualize"
                     size="sm"
                     variant="link"
-                    :href="itemUrls.visualize"
+                    :href="visualizeUrl"
                     @click.prevent.stop="onVisualize">
                     
                 
@@ -72,7 +72,7 @@