Skip to content

Commit

Permalink
Merge branch 'release_24.1' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
mvdbeek committed Sep 20, 2024
2 parents 1a29913 + 2bbae08 commit 7572e5c
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 36 deletions.
11 changes: 10 additions & 1 deletion client/src/api/schema/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33135,9 +33135,18 @@ export interface operations {
* `is:published`
* : Include only published workflows in the final result. Be sure the query parameter `show_published` is set to `true` if to include all published workflows and not just the requesting user's.
*
* `is:share_with_me`
* `is:importable`
* : Include only importable workflows in the final result.
*
* `is:deleted`
* : Include only deleted workflows in the final result.
*
* `is:shared_with_me`
* : Include only workflows shared with the requesting user. Be sure the query parameter `show_shared` is set to `true` if to include shared workflows.
*
* `is:bookmarked`
* : Include only workflows bookmarked by the requesting user.
*
* ## Free Text
*
* Free text search terms will be searched against the following attributes of the
Expand Down
7 changes: 7 additions & 0 deletions client/src/components/Workflow/List/WorkflowFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,13 @@ export function WorkflowFilters(activeList = "my") {
handler: equals("deleted", "deleted", toBool),
menuItem: true,
},
bookmarked: {
placeholder: "Bookmarked",
type: Boolean,
boolType: "is",
handler: equals("bookmarked", "bookmarked", toBool),
menuItem: true,
},
},
undefined,
false,
Expand Down
22 changes: 5 additions & 17 deletions client/src/components/Workflow/List/WorkflowList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ const overlay = ref(false);
const filterText = ref("");
const totalWorkflows = ref(0);
const showAdvanced = ref(false);
const showBookmarked = ref(false);
const listHeader = ref<any>(null);
const workflowsLoaded = ref<WorkflowsList>([]);
Expand All @@ -65,6 +64,7 @@ const searchPlaceHolder = computed(() => {
const published = computed(() => props.activeList === "published");
const sharedWithMe = computed(() => props.activeList === "shared_with_me");
const showDeleted = computed(() => filterText.value.includes("is:deleted"));
const showBookmarked = computed(() => filterText.value.includes("is:bookmarked"));
const currentPage = computed(() => Math.floor(offset.value / limit.value) + 1);
const view = computed(() => (userStore.preferredListViewMode as ListView) || "grid");
const sortDesc = computed(() => (listHeader.value && listHeader.value.sortDesc) ?? true);
Expand All @@ -91,17 +91,12 @@ function updateFilterValue(filterKey: string, newValue: any) {
filterText.value = workflowFilters.value.setFilterValue(currentFilterText, filterKey, newValue);
}
function toggleBookmarked(bookmarked?: boolean) {
showBookmarked.value = bookmarked ?? !showBookmarked.value;
}
function onToggleBookmarked() {
toggleBookmarked();
updateFilterValue("bookmarked", true);
}
function onToggleDeleted() {
updateFilterValue("deleted", true);
toggleBookmarked(false);
}
async function load(overlayLoading = false, silent = false) {
Expand Down Expand Up @@ -149,21 +144,15 @@ async function load(overlayLoading = false, silent = false) {
rethrowSimple(error);
}
let filteredWorkflows = showBookmarked.value
? filter(data, (workflow: any) => workflow.show_in_tool_panel)
: data;
let filteredWorkflows = data;
if (props.activeList === "my") {
filteredWorkflows = filter(filteredWorkflows, (w: any) => userStore.matchesCurrentUsername(w.owner));
}
workflowsLoaded.value = filteredWorkflows;
if (showBookmarked.value) {
totalWorkflows.value = filteredWorkflows.length;
} else {
totalWorkflows.value = parseInt(response.headers.get("Total_matches") || "0", 10) || 0;
}
totalWorkflows.value = parseInt(response.headers.get("Total_matches") || "0", 10) || 0;
} catch (e) {
Toast.error(`Failed to load workflows: ${e}`);
} finally {
Expand All @@ -189,7 +178,7 @@ function validatedFilterText() {
return workflowFilters.value.getFilterText(validFilters.value, true);
}
watch([filterText, sortBy, sortDesc, showBookmarked], async () => {
watch([filterText, sortBy, sortDesc], async () => {
offset.value = 0;
await load(true);
});
Expand Down Expand Up @@ -269,7 +258,6 @@ onMounted(() => {
size="sm"
:title="bookmarkButtonTitle"
:pressed="showBookmarked"
:disabled="showDeleted"
variant="outline-primary"
@click="onToggleBookmarked">
<FontAwesomeIcon :icon="faStar" fixed-width />
Expand Down
2 changes: 1 addition & 1 deletion config/plugins/visualizations/editor/templates/editor.mako
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@
const ajax_url = "${h.url_for( controller='/datasets', action='index')}/" + hda_id + "/display";
const data = httpGet(ajax_url);
document.getElementById("editor").innerHTML = data;
var editor = ace.edit("editor", {
mode: "ace/mode/powershell",
theme: "ace/theme/textmate"
});
editor.setValue(data, -1);
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion lib/galaxy/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ def admin_users(self):
@admin_users.setter
def admin_users(self, value):
self._admin_users = value
self.admin_users_list = listify(value)
self.admin_users_list = listify(value, do_strip=True)

def is_admin_user(self, user: Optional["User"]) -> bool:
"""Determine if the provided user is listed in `admin_users`."""
Expand Down
6 changes: 6 additions & 0 deletions lib/galaxy/managers/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,12 @@ def name_filter(term):
message = "Can only use tag is:shared_with_me if show_shared parameter also true."
raise exceptions.RequestParameterInvalidException(message)
stmt = stmt.where(StoredWorkflowUserShareAssociation.user == user)
elif q == "bookmarked":
stmt = (
stmt.join(model.StoredWorkflowMenuEntry)
.where(model.StoredWorkflowMenuEntry.stored_workflow_id == StoredWorkflow.id)
.where(model.StoredWorkflowMenuEntry.user_id == user.id)
)
elif isinstance(term, RawTextTerm):
tf = w_tag_filter(term.text, False)
alias = aliased(User)
Expand Down
9 changes: 5 additions & 4 deletions lib/galaxy/model/store/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -578,10 +578,11 @@ def handle_dataset_object_edit(dataset_instance, dataset_attrs):
self._attach_raw_id_if_editing(dataset_instance, dataset_attrs)

# Older style...
if "uuid" in dataset_attrs:
dataset_instance.dataset.uuid = dataset_attrs["uuid"]
if "dataset_uuid" in dataset_attrs:
dataset_instance.dataset.uuid = dataset_attrs["dataset_uuid"]
if self.import_options.allow_edit:
if "uuid" in dataset_attrs:
dataset_instance.dataset.uuid = dataset_attrs["uuid"]
if "dataset_uuid" in dataset_attrs:
dataset_instance.dataset.uuid = dataset_attrs["dataset_uuid"]

self._session_add(dataset_instance)

Expand Down
18 changes: 12 additions & 6 deletions lib/galaxy/model/store/discover.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,6 @@ def create_dataset(
)
self.persist_object(primary_data)

if init_from:
self.permission_provider.copy_dataset_permissions(init_from, primary_data)
primary_data.state = init_from.state
else:
self.permission_provider.set_default_hda_permissions(primary_data)
else:
ld = galaxy.model.LibraryDataset(folder=library_folder, name=name)
ldda = galaxy.model.LibraryDatasetDatasetAssociation(
Expand Down Expand Up @@ -208,6 +203,7 @@ def create_dataset(
filename=filename,
link_data=link_data,
output_name=output_name,
init_from=init_from,
)
else:
storage_callbacks.append(
Expand All @@ -218,11 +214,14 @@ def create_dataset(
filename=filename,
link_data=link_data,
output_name=output_name,
init_from=init_from,
)
)
return primary_data

def finalize_storage(self, primary_data, dataset_attributes, extra_files, filename, link_data, output_name):
def finalize_storage(
self, primary_data, dataset_attributes, extra_files, filename, link_data, output_name, init_from
):
if primary_data.dataset.purged:
# metadata won't be set, maybe we should do that, then purge ?
primary_data.dataset.file_size = 0
Expand All @@ -243,6 +242,13 @@ def finalize_storage(self, primary_data, dataset_attributes, extra_files, filena
else:
# We are sure there are no extra files, so optimize things that follow by settting total size also.
primary_data.set_size(no_extra_files=True)

if init_from:
self.permission_provider.copy_dataset_permissions(init_from, primary_data)
primary_data.state = init_from.state
else:
self.permission_provider.set_default_hda_permissions(primary_data)

# TODO: this might run set_meta after copying the file to the object store, which could be inefficient if job working directory is closer to the node.
self.set_datasets_metadata(datasets=[primary_data], datasets_attributes=[dataset_attributes])

Expand Down
14 changes: 13 additions & 1 deletion lib/galaxy/webapps/galaxy/api/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -858,9 +858,21 @@ def __get_stored_workflow(self, trans, workflow_id, **kwd):
"Include only published workflows in the final result. Be sure the query parameter `show_published` is set to `true` if to include all published workflows and not just the requesting user's.",
),
IndexQueryTag(
"is:share_with_me",
"is:importable",
"Include only importable workflows in the final result.",
),
IndexQueryTag(
"is:deleted",
"Include only deleted workflows in the final result.",
),
IndexQueryTag(
"is:shared_with_me",
"Include only workflows shared with the requesting user. Be sure the query parameter `show_shared` is set to `true` if to include shared workflows.",
),
IndexQueryTag(
"is:bookmarked",
"Include only workflows bookmarked by the requesting user.",
),
]

SearchQueryParam: Optional[str] = search_query_param(
Expand Down
3 changes: 2 additions & 1 deletion lib/galaxy/webapps/galaxy/controllers/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from galaxy.datatypes.sniff import guess_ext
from galaxy.exceptions import (
MessageException,
InsufficientPermissionsException,
RequestParameterInvalidException,
)
from galaxy.managers.hdas import (
Expand Down Expand Up @@ -106,7 +107,7 @@ def _check_dataset(self, trans, hda_id):
if not data:
raise web.httpexceptions.HTTPNotFound(f"Invalid reference dataset id: {str(hda_id)}.")
if not self._can_access_dataset(trans, data):
return trans.show_error_message("You are not allowed to access this dataset")
raise InsufficientPermissionsException("You are not allowed to access this dataset")
self.app.hda_manager.ensure_dataset_on_disk(trans, data)
return data

Expand Down
26 changes: 22 additions & 4 deletions test/integration/objectstore/test_jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
import os
import string

from galaxy_test.driver.integration_util import (
integration_module_instance,
integration_tool_runner,
)
from ._base import (
BaseObjectStoreIntegrationTestCase,
files_count,
)
from .test_selection_with_resource_parameters import DISTRIBUTED_OBJECT_STORE_CONFIG_TEMPLATE

DISTRIBUTED_OBJECT_STORE_CONFIG_TEMPLATE = string.Template(
HIERARCHICAL_OBJECT_STORE_CONFIG_TEMPLATE = string.Template(
"""<?xml version="1.0"?>
<object_store type="hierarchical">
<backends>
Expand Down Expand Up @@ -39,7 +44,20 @@
TEST_INPUT_FILES_CONTENT = "1 2 3"


class TestObjectStoreJobsIntegration(BaseObjectStoreIntegrationTestCase):
class TestDistributedObjectStore(BaseObjectStoreIntegrationTestCase):
@classmethod
def handle_galaxy_config_kwds(cls, config):
super().handle_galaxy_config_kwds(config)
config["metadata_strategy"] = "directory"
config["object_store_store_by"] = "uuid"
cls._configure_object_store(DISTRIBUTED_OBJECT_STORE_CONFIG_TEMPLATE, config)


instance = integration_module_instance(TestDistributedObjectStore)
test_tools = integration_tool_runner(["all_output_types"])


class TestObjectStoreJobsIntegration(TestDistributedObjectStore):
# setup by _configure_object_store
files1_path: str
files2_path: str
Expand All @@ -48,7 +66,7 @@ class TestObjectStoreJobsIntegration(BaseObjectStoreIntegrationTestCase):
@classmethod
def handle_galaxy_config_kwds(cls, config):
super().handle_galaxy_config_kwds(config)
cls._configure_object_store(DISTRIBUTED_OBJECT_STORE_CONFIG_TEMPLATE, config)
cls._configure_object_store(HIERARCHICAL_OBJECT_STORE_CONFIG_TEMPLATE, config)

def setUp(self):
super().setUp()
Expand All @@ -68,7 +86,7 @@ def setUp(self):
def test_files_count_and_content_in_each_objectstore_backend(self):
"""
According to the ObjectStore configuration given in the
`DISTRIBUTED_OBJECT_STORE_CONFIG_TEMPLATE` variable, datasets
`HIERARCHICAL_OBJECT_STORE_CONFIG_TEMPLATE` variable, datasets
can be stored on three backends, named:
- primary/files1;
- primary/files2;
Expand Down
1 change: 1 addition & 0 deletions test/integration/test_extended_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"collection_creates_dynamic_nested_from_json_elements",
"implicit_conversion",
"environment_variables",
"all_output_types",
]


Expand Down

0 comments on commit 7572e5c

Please sign in to comment.