diff --git a/client/src/api/schema/schema.ts b/client/src/api/schema/schema.ts index 8865c361e282..cb7b0dc21217 100644 --- a/client/src/api/schema/schema.ts +++ b/client/src/api/schema/schema.ts @@ -6656,19 +6656,38 @@ export interface components { * This model is based on the Discourse API response for the search endpoint. */ HelpForumSearchResponse: { - /** Categories */ - categories: components["schemas"]["HelpForumCategory"][] | null; - grouped_search_result: components["schemas"]["HelpForumGroupedSearchResult"] | null; - /** Groups */ - groups: components["schemas"]["HelpForumGroup"][] | null; - /** Posts */ - posts: components["schemas"]["HelpForumPost"][] | null; - /** Tags */ - tags: components["schemas"]["HelpForumTag"][] | null; - /** Topics */ - topics: components["schemas"]["HelpForumTopic"][] | null; - /** Users */ - users: components["schemas"]["HelpForumUser"][] | null; + /** + * Categories + * @description The list of categories returned by the search. + */ + categories?: components["schemas"]["HelpForumCategory"][] | null; + /** @description The grouped search result. */ + grouped_search_result?: components["schemas"]["HelpForumGroupedSearchResult"] | null; + /** + * Groups + * @description The list of groups returned by the search. + */ + groups?: components["schemas"]["HelpForumGroup"][] | null; + /** + * Posts + * @description The list of posts returned by the search. + */ + posts?: components["schemas"]["HelpForumPost"][]; + /** + * Tags + * @description The list of tags returned by the search. + */ + tags?: components["schemas"]["HelpForumTag"][] | null; + /** + * Topics + * @description The list of topics returned by the search. + */ + topics?: components["schemas"]["HelpForumTopic"][]; + /** + * Users + * @description The list of users returned by the search. + */ + users?: components["schemas"]["HelpForumUser"][] | null; }; /** * HelpForumTag @@ -6696,7 +6715,7 @@ export interface components { * Bookmarked * @description Whether the topic is bookmarked. */ - bookmarked: boolean | null; + bookmarked?: boolean | null; /** * Bumped * @description Whether the topic was bumped. @@ -6751,7 +6770,7 @@ export interface components { * Liked * @description Whether the topic is liked. */ - liked: boolean | null; + liked?: boolean | null; /** * Pinned * @description Whether the topic is pinned. @@ -6781,7 +6800,7 @@ export interface components { * Tags Descriptions * @description The descriptions of the tags of the topic. */ - tags_descriptions: Record | null; + tags_descriptions?: Record | null; /** * Title * @description The title of the topic. @@ -6791,7 +6810,7 @@ export interface components { * Unpinned * @description Whether the topic is unpinned. */ - unpinned: boolean | null; + unpinned?: boolean | null; /** * Unseen * @description Whether the topic is unseen. diff --git a/client/src/components/History/Content/Dataset/DatasetDetails.vue b/client/src/components/History/Content/Dataset/DatasetDetails.vue index 23c1138714f5..5cf6b2880e1d 100644 --- a/client/src/components/History/Content/Dataset/DatasetDetails.vue +++ b/client/src/components/History/Content/Dataset/DatasetDetails.vue @@ -8,6 +8,7 @@ import { useDatasetStore } from "@/stores/datasetStore"; import { type ItemUrls } from "."; import DatasetActions from "./DatasetActions.vue"; +import DatasetMiscInfo from "./DatasetMiscInfo.vue"; const datasetStore = useDatasetStore(); @@ -56,9 +57,7 @@ function toggleHighlights() { result.genome_build }} -
- {{ result.misc_info }} -
+ +import { computed, ref, watch } from "vue"; + +interface Props { + miscInfo: string; +} + +const showErrorHelp = ref(false); +const sharingError = ref(false); + +// old sharable error: Attempted to create shared output datasets in objectstore with sharing disabled +// new sharable error: Job attempted to create sharable output datasets in a storage location with sharing disabled +const sharingErrorRex: RegExp = /with sharing disabled/g; +const knownErrors = [{ regex: sharingErrorRex, modalRef: sharingError }]; + +const props = defineProps(); + +const fixable = computed(() => { + return knownErrors.some((error) => error.modalRef.value); +}); + +function checkForKnownErrors() { + for (const knownError of knownErrors) { + const regex = knownError.regex; + if (props.miscInfo.match(regex)) { + knownError.modalRef.value = true; + } + } +} + +watch(props, checkForKnownErrors, { immediate: true }); + +function showHelp() { + showErrorHelp.value = true; +} + + + diff --git a/client/src/components/History/CurrentHistory/HistoryCounter.vue b/client/src/components/History/CurrentHistory/HistoryCounter.vue index df3f0a1d0e0f..98efa0bf11b8 100644 --- a/client/src/components/History/CurrentHistory/HistoryCounter.vue +++ b/client/src/components/History/CurrentHistory/HistoryCounter.vue @@ -12,6 +12,7 @@ import { useRouter } from "vue-router/composables"; import type { HistorySummary } from "@/api"; import { HistoryFilters } from "@/components/History/HistoryFilters.js"; import { useConfig } from "@/composables/config"; +import { useStorageLocationConfiguration } from "@/composables/storageLocation"; import { useUserStore } from "@/stores/userStore"; import { useDetailedHistory } from "./usesDetailedHistory"; @@ -19,6 +20,8 @@ import { useDetailedHistory } from "./usesDetailedHistory"; import PreferredStorePopover from "./PreferredStorePopover.vue"; import SelectPreferredStore from "./SelectPreferredStore.vue"; +const { isOnlyPreference } = useStorageLocationConfiguration(); + library.add(faDatabase, faEyeSlash, faHdd, faMapMarker, faSync, faTrash); const props = withDefaults( @@ -54,6 +57,14 @@ const historyPreferredObjectStoreId = ref(props.history.preferred_object_store_i const niceHistorySize = computed(() => prettyBytes(historySize.value)); +const storageLocationTitle = computed(() => { + if (isOnlyPreference.value) { + return "History Preferred Storage Location"; + } else { + return "History Storage Location"; + } +}); + function onDashboard() { router.push({ name: "HistoryOverviewInAnalysis", params: { historyId: props.history.id } }); } @@ -206,7 +217,7 @@ onMounted(() => { { } return id; }); + +const title = computed(() => { + if (isOnlyPreference.value) { + return "Preferred Storage Location"; + } else { + return "Storage Location"; + } +}); diff --git a/client/src/components/ObjectStore/SelectObjectStore.vue b/client/src/components/ObjectStore/SelectObjectStore.vue index def41a60ff4d..1aa6287a6a07 100644 --- a/client/src/components/ObjectStore/SelectObjectStore.vue +++ b/client/src/components/ObjectStore/SelectObjectStore.vue @@ -3,6 +3,7 @@ import { storeToRefs } from "pinia"; import { computed, ref } from "vue"; import { ConcreteObjectStoreModel } from "@/api"; +import { useStorageLocationConfiguration } from "@/composables/storageLocation"; import { useObjectStoreStore } from "@/stores/objectStoreStore"; import ObjectStoreSelectButton from "./ObjectStoreSelectButton.vue"; @@ -25,6 +26,7 @@ const props = withDefaults(defineProps(), { const store = useObjectStoreStore(); const { isLoading, loadErrorMessage, selectableObjectStores } = storeToRefs(store); +const { isOnlyPreference } = useStorageLocationConfiguration(); const loadingObjectStoreInfoMessage = ref("Loading storage location information"); const whyIsSelectionPreferredText = ref(` @@ -64,7 +66,7 @@ async function handleSubmit(preferredObjectStore: ConcreteObjectStoreModel | nul {{ error }} - + - +

{{ whyIsSelectionPreferredText }}

diff --git a/client/src/components/ObjectStore/showTargetPopoverMixin.js b/client/src/components/ObjectStore/showTargetPopoverMixin.js index 66c68f4bfd5e..61f19c279871 100644 --- a/client/src/components/ObjectStore/showTargetPopoverMixin.js +++ b/client/src/components/ObjectStore/showTargetPopoverMixin.js @@ -1,3 +1,7 @@ +import { mapState } from "pinia"; + +import { useConfigStore } from "@/stores/configurationStore"; + import ShowSelectedObjectStore from "./ShowSelectedObjectStore"; export default { @@ -11,8 +15,16 @@ export default { }, }, computed: { + ...mapState(useConfigStore, ["config"]), + preferredOrEmptyString() { + if (this.config?.object_store_always_respect_user_selection) { + return ""; + } else { + return "Preferred"; + } + }, title() { - return this.l(`Preferred Target Storage Location ${this.titleSuffix || ""}`); + return this.l(`${this.preferredOrEmptyString} Target Storage Location ${this.titleSuffix || ""}`); }, }, }; diff --git a/client/src/components/Tool/ToolCard.vue b/client/src/components/Tool/ToolCard.vue index f1df26492a1a..d28e4d46ad96 100644 --- a/client/src/components/Tool/ToolCard.vue +++ b/client/src/components/Tool/ToolCard.vue @@ -7,6 +7,7 @@ import { getAppRoot } from "onload/loadConfig"; import { storeToRefs } from "pinia"; import { computed, ref, watch } from "vue"; +import { useStorageLocationConfiguration } from "@/composables/storageLocation"; import { useConfigStore } from "@/stores/configurationStore"; import { useUserStore } from "@/stores/userStore"; @@ -83,12 +84,21 @@ function onSetError(e) { errorText.value = e; } +const { isOnlyPreference } = useStorageLocationConfiguration(); const { currentUser, isAnonymous } = storeToRefs(useUserStore()); const { isLoaded: isConfigLoaded, config } = storeToRefs(useConfigStore()); const hasUser = computed(() => !isAnonymous.value); const versions = computed(() => props.options.versions); const showVersions = computed(() => props.options.versions?.length > 1); +const storageLocationModalTitle = computed(() => { + if (isOnlyPreference.value) { + return "Tool Execution Preferred Storage Location"; + } else { + return "Tool Execution Storage Location"; + } +}); + const root = computed(() => getAppRoot()); const showPreferredObjectStoreModal = ref(false); const toolPreferredObjectStoreId = ref(props.preferredObjectStoreId); @@ -148,7 +158,7 @@ const showHelpForum = computed(() => isConfigLoaded.value && config.value.enable topics.value.length > 0); const root = ref(null); -const query = computed(() => `tags:${props.toolId}+${toolHelpTag} status:solved`); +const shortToolId = computed(() => getShortToolId(props.toolId)); +const query = computed(() => `tags:${shortToolId.value}+${toolHelpTag} status:solved`); onMounted(async () => { const response = await helpFetcher({ query: query.value }); @@ -49,7 +51,7 @@ function blurbForTopic(topicId: number): string { const { createNewTopicUrl, searchTopicUrl } = useHelpURLs({ title: computed(() => props.toolName), - tags: computed(() => [props.toolId, toolHelpTag]), + tags: computed(() => [shortToolId.value, toolHelpTag]), query, }); diff --git a/client/src/components/Tool/ToolTargetPreferredObjectStorePopover.vue b/client/src/components/Tool/ToolTargetPreferredObjectStorePopover.vue index a88e5214335d..26dc9b790b7f 100644 --- a/client/src/components/Tool/ToolTargetPreferredObjectStorePopover.vue +++ b/client/src/components/Tool/ToolTargetPreferredObjectStorePopover.vue @@ -3,8 +3,9 @@

- Preferred storage location has been set at the tool level, by default history or user preferences will - be used and if those are not set Galaxy will pick an administrator-configured default. + The {{ preferredOrEmptyString }} storage location has been set at the tool level, by default history or + user preferences will be used and if those are not set Galaxy will pick an administrator-configured + default.

- Change preferred storage location by clicking on the storage button in the tool header. + Change {{ preferredOrEmptyString }} storage location by clicking on the storage button in the tool + header.
diff --git a/client/src/components/ToolRecommendation.vue b/client/src/components/ToolRecommendation.vue index bf3e4f891bb8..7df9be1a2660 100644 --- a/client/src/components/ToolRecommendation.vue +++ b/client/src/components/ToolRecommendation.vue @@ -22,6 +22,8 @@ import { getCompatibleRecommendations } from "components/Workflow/Editor/modules import * as d3 from "d3"; import { getAppRoot } from "onload/loadConfig"; +import { getShortToolId } from "@/utils/tool"; + export default { props: { toolId: { @@ -38,12 +40,7 @@ export default { }, computed: { getToolId() { - let toolId = this.toolId || ""; - if (toolId.indexOf("/") > 0) { - const toolIdSlash = toolId.split("/"); - toolId = toolIdSlash[toolIdSlash.length - 2]; - } - return toolId; + return getShortToolId(this.toolId ?? ""); }, }, created() { diff --git a/client/src/components/User/UserPreferredObjectStore.vue b/client/src/components/User/UserPreferredObjectStore.vue index e2c056ddae66..c51ab8b8b60f 100644 --- a/client/src/components/User/UserPreferredObjectStore.vue +++ b/client/src/components/User/UserPreferredObjectStore.vue @@ -7,17 +7,17 @@ v-b-modal.modal-select-preferred-object-store class="preferred-storage" href="javascript:void(0)" - >Preferred Storage Location{{ title }}
- Select a preferred storage location for the outputs of new jobs. + Select a {{ preferredOrEmptyString }} storage location for the outputs of new jobs.
-1) { - const toolIdSlash = toolId.split("/"); - toolId = toolIdSlash[toolIdSlash.length - 2]; - } - return toolId; + return getShortToolId(toolId ?? ""); }, getWorkflowPath(currentNodeId) { const steps = {}; diff --git a/client/src/components/Workflow/Run/WorkflowStorageConfiguration.test.js b/client/src/components/Workflow/Run/WorkflowStorageConfiguration.test.js index 02ee504ddeed..876578e709c0 100644 --- a/client/src/components/Workflow/Run/WorkflowStorageConfiguration.test.js +++ b/client/src/components/Workflow/Run/WorkflowStorageConfiguration.test.js @@ -1,3 +1,4 @@ +import { createTestingPinia } from "@pinia/testing"; import { mount } from "@vue/test-utils"; import { findViaNavigation, getLocalVue } from "tests/jest/helpers"; import { ROOT_COMPONENT } from "utils/navigation"; @@ -18,6 +19,7 @@ describe("WorkflowStorageConfiguration.vue", () => { wrapper = mount(WorkflowStorageConfiguration, { propsData, localVue, + pinia: createTestingPinia(), }); } diff --git a/client/src/components/Workflow/Run/WorkflowStorageConfiguration.vue b/client/src/components/Workflow/Run/WorkflowStorageConfiguration.vue index d6d9b03ea557..d67dc2b5a191 100644 --- a/client/src/components/Workflow/Run/WorkflowStorageConfiguration.vue +++ b/client/src/components/Workflow/Run/WorkflowStorageConfiguration.vue @@ -12,11 +12,7 @@ :title-suffix="suffixPrimary" :invocation-preferred-object-store-id="selectedObjectStoreId"> - + @@ -37,7 +33,7 @@