mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
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:
@@ -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 || ""}`);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user