Merge pull request #17806 from jmchilton/respect_user_os_selection

[24.0] Allow admin to sharpen language about selected object stores.
This commit is contained in:
Martin Cech
2024-03-26 17:47:32 +01:00
committed by GitHub
14 changed files with 152 additions and 26 deletions
@@ -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(() => {
<BModal
v-model="showPreferredObjectStoreModal"
title="History Preferred Storage Location"
:title="storageLocationTitle"
modal-class="history-preferred-object-store-modal"
title-tag="h3"
size="sm"
@@ -2,8 +2,12 @@
import { BPopover } from "bootstrap-vue";
import { computed } from "vue";
import { useStorageLocationConfiguration } from "@/composables/storageLocation";
import ShowSelectedObjectStore from "@/components/ObjectStore/ShowSelectedObjectStore.vue";
const { isOnlyPreference } = useStorageLocationConfiguration();
interface Props {
historyId: string;
historyPreferredObjectStoreId?: string;
@@ -19,28 +23,40 @@ const preferredObjectStoreId = computed(() => {
}
return id;
});
const title = computed(() => {
if (isOnlyPreference.value) {
return "Preferred Storage Location";
} else {
return "Storage Location";
}
});
</script>
<template>
<BPopover :target="`history-storage-${historyId}`" triggers="hover" placement="bottomleft" boundary="window">
<template v-slot:title>Preferred Storage Location</template>
<template v-slot:title>{{ title }}</template>
<div class="popover-wide">
<p>
<b
>This option only affects new datasets created in this history. Existing history datasets will
remain at their current storage location.</b
>
</p>
<p v-if="historyPreferredObjectStoreId" class="history-preferred-object-store-inherited">
This storage location has been set at the history level.
</p>
<p v-else class="history-preferred-object-store-not-inherited">
This storage location has been inherited from your user preferences (set in User -> Preferences ->
Preferred Storage Location). If that option is updated, this history will target that new default.
This storage location has been inherited from your user preferences (set in
<router-link to="/user">User -> Preferences</router-link> -> {{ title }}). If that option is updated,
this history will target that new default.
</p>
<ShowSelectedObjectStore
v-if="preferredObjectStoreId"
:preferred-object-store-id="preferredObjectStoreId"
for-what="Galaxy will default to storing this history's datasets in " />
<div v-localize>
Change preferred storage location by clicking on the storage button in the history panel.
</div>
</div>
</BPopover>
</template>
@@ -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<SelectObjectStoreProps>(), {
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
<b-alert v-if="error" variant="danger" class="object-store-selection-error" show>
{{ error }}
</b-alert>
<b-row>
<b-row align-h="center">
<b-col cols="7">
<b-button-group vertical size="lg" style="width: 100%">
<b-button
@@ -85,7 +87,7 @@ async function handleSubmit(preferredObjectStore: ConcreteObjectStoreModel | nul
@click="handleSubmit(objectStore)" />
</b-button-group>
</b-col>
<b-col cols="5">
<b-col v-if="isOnlyPreference" cols="5">
<p v-localize style="float: right">
{{ whyIsSelectionPreferredText }}
</p>
@@ -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 || ""}`);
},
},
};
+11 -1
View File
@@ -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
</ToolTargetPreferredObjectStorePopover>
<b-modal
v-model="showPreferredObjectStoreModal"
title="Tool Execution Preferred Storage Location"
:title="storageLocationModalTitle"
modal-class="tool-preferred-object-store-modal"
title-tag="h3"
size="sm"
@@ -3,8 +3,9 @@
<template v-slot:title>{{ title }}</template>
<div class="popover-wide">
<p v-if="toolPreferredObjectStoreId">
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.
</p>
<ShowSelectedObjectStore
v-if="toolPreferredObjectStoreId"
@@ -15,7 +16,8 @@
No selection has been made for this tool execution. Defaults from history, user, or Galaxy will be used.
</div>
<div v-localize>
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.
</div>
</div>
</b-popover>
@@ -7,17 +7,17 @@
v-b-modal.modal-select-preferred-object-store
class="preferred-storage"
href="javascript:void(0)"
><b v-localize>Preferred Storage Location</b></a
><b v-localize>{{ title }}</b></a
>
<div v-localize class="form-text text-muted">
Select a preferred storage location for the outputs of new jobs.
Select a {{ preferredOrEmptyString }} storage location for the outputs of new jobs.
</div>
<BModal
id="modal-select-preferred-object-store"
ref="modal"
v-model="showModal"
centered
title="Preferred Storage Location"
:title="title"
:title-tag="titleTag"
hide-footer
static
@@ -40,10 +40,13 @@
import axios from "axios";
import { BModal, BRow, VBModal } from "bootstrap-vue";
import SelectObjectStore from "components/ObjectStore/SelectObjectStore";
import { mapState } from "pinia";
import { prependPath } from "utils/redirect";
import { errorMessageAsString } from "utils/simple-error";
import Vue from "vue";
import { useConfigStore } from "@/stores/configurationStore";
Vue.use(VBModal);
export default {
@@ -76,6 +79,19 @@ export default {
"Selecting this will reset Galaxy to default behaviors configured by your Galaxy administrator.",
};
},
computed: {
...mapState(useConfigStore, ["config"]),
preferredOrEmptyString() {
if (this.config?.object_store_always_respect_user_selection) {
return "";
} else {
return "Preferred";
}
},
title() {
return `${this.preferredOrEmptyString} Storage Location`;
},
},
methods: {
resetModal() {},
async handleSubmit(preferredObjectStoreId) {
@@ -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(),
});
}
@@ -12,11 +12,7 @@
:title-suffix="suffixPrimary"
:invocation-preferred-object-store-id="selectedObjectStoreId">
</WorkflowTargetPreferredObjectStorePopover>
<b-modal
v-model="showPreferredObjectStoreModal"
title="Invocation Preferred Storage Location"
v-bind="modalProps"
hide-footer>
<b-modal v-model="showPreferredObjectStoreModal" :title="primaryModalTitle" v-bind="modalProps" hide-footer>
<WorkflowSelectPreferredObjectStore
:invocation-preferred-object-store-id="selectedObjectStoreId"
@updated="onUpdate" />
@@ -37,7 +33,7 @@
</WorkflowTargetPreferredObjectStorePopover>
<b-modal
v-model="showIntermediatePreferredObjectStoreModal"
title="Invocation Preferred Storage Location (Intermediate Datasets)"
:title="intermediateModalTitle"
v-bind="modalProps"
hide-footer>
<WorkflowSelectPreferredObjectStore
@@ -48,6 +44,10 @@
</template>
<script>
import { mapState } from "pinia";
import { useConfigStore } from "@/stores/configurationStore";
import WorkflowSelectPreferredObjectStore from "./WorkflowSelectPreferredObjectStore";
import WorkflowTargetPreferredObjectStorePopover from "./WorkflowTargetPreferredObjectStorePopover";
@@ -79,6 +79,20 @@ export default {
};
},
computed: {
...mapState(useConfigStore, ["config"]),
preferredOrEmptyString() {
if (this.config?.object_store_always_respect_user_selection) {
return "";
} else {
return "Preferred";
}
},
primaryModalTitle() {
return `Invocation ${this.preferredOrEmptyString} Storage Location`;
},
intermediateModalTitle() {
return `Invocation {{ preferredOrEmptyString }} Storage Location (Intermediate Datasets)`;
},
suffixPrimary() {
if (this.splitObjectStore) {
return ` (Workflow Output Datasets)`;
@@ -9,11 +9,12 @@
for-what="Galaxy will default to storing this tool run's output in">
</ShowSelectedObjectStore>
<div v-else>
No selection has been made for this worklfow invocation. Defaults from history, user, or Galaxy will be
No selection has been made for this workflow invocation. Defaults from history, user, or Galaxy will be
used.
</div>
<div v-localize>
Change preferred storage location by clicking on the storage button in the worklfow run header.
Change {{ preferredOrEmptyString }} storage location by clicking on the storage button in the worklfow
run header.
</div>
</div>
</b-popover>
+15
View File
@@ -0,0 +1,15 @@
import { computed } from "vue";
import { useConfig } from "./config";
export function useStorageLocationConfiguration() {
const { config } = useConfig();
const isOnlyPreference = computed(() => {
return !config.value || !config.value?.object_store_always_respect_user_selection;
});
return {
isOnlyPreference,
};
}
+14
View File
@@ -1521,6 +1521,20 @@
:Type: int
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``object_store_always_respect_user_selection``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:Description:
Set this to true to indicate in the UI that a user's object store
selection isn't simply a "preference" that job destinations often
respect but in fact will always be respected. This should be set
to true to simplify the UI as long as job destinations never
override 'object_store_id's for a jobs.
:Default: ``false``
:Type: bool
~~~~~~~~~~~~~~~~~~~~~~~~~
``object_store_store_by``
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1094,6 +1094,16 @@ mapping:
Default cache size for caching object stores if cache not configured for
that object store entry.
object_store_always_respect_user_selection:
type: bool
default: false
required: false
desc: |
Set this to true to indicate in the UI that a user's object store selection
isn't simply a "preference" that job destinations often respect but in fact
will always be respected. This should be set to true to simplify the UI as
long as job destinations never override 'object_store_id's for a jobs.
object_store_store_by:
type: str
required: false
+1
View File
@@ -213,6 +213,7 @@ class ConfigSerializer(base.ModelSerializer):
),
"object_store_allows_id_selection": lambda item, key, **context: object_store.object_store_allows_id_selection(),
"object_store_ids_allowing_selection": lambda item, key, **context: object_store.object_store_ids_allowing_selection(),
"object_store_always_respect_user_selection": _use_config,
"user_activation_on": _use_config,
"user_library_import_dir_available": lambda item, key, **context: bool(item.get("user_library_import_dir")),
"welcome_directory": _use_config,