Skip to content

Commit

Permalink
Merge pull request #15654 from jmchilton/object_store_ui_followup
Browse files Browse the repository at this point in the history
Follow up on object store selection PR.
  • Loading branch information
jmchilton authored Mar 3, 2023
2 parents 18e5c81 + 9964d4d commit 92270af
Show file tree
Hide file tree
Showing 18 changed files with 564 additions and 313 deletions.
34 changes: 21 additions & 13 deletions client/src/components/History/CurrentHistory/HistoryCounter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,25 @@
<span>{{ historySize | niceFileSize }}</span>
</b-button>
<b-button-group>
<b-button
:id="`history-storage-${history.id}`"
variant="link"
size="sm"
class="rounded-0 text-decoration-none"
@click="showPreferredObjectStoreModal = true">
<icon icon="hdd" />
</b-button>
<PreferredStorePopover
:history-id="history.id"
:history-preferred-object-store-id="historyPreferredObjectStoreId"
:user="user">
</PreferredStorePopover>
<ConfigProvider v-slot="{ config }">
<b-button
v-if="config && config.object_store_allows_id_selection"
:id="`history-storage-${history.id}`"
variant="link"
size="sm"
class="rounded-0 text-decoration-none"
@click="showPreferredObjectStoreModal = true">
<icon icon="hdd" />
</b-button>
</ConfigProvider>
<ConfigProvider v-slot="{ config }">
<PreferredStorePopover
v-if="config && config.object_store_allows_id_selection"
:history-id="history.id"
:history-preferred-object-store-id="historyPreferredObjectStoreId"
:user="user">
</PreferredStorePopover>
</ConfigProvider>
<b-button-group>
<b-button
v-b-tooltip.hover
Expand Down Expand Up @@ -90,11 +96,13 @@ import prettyBytes from "pretty-bytes";
import { formatDistanceToNowStrict } from "date-fns";
import { usesDetailedHistoryMixin } from "./usesDetailedHistoryMixin.js";
import CurrentUser from "components/providers/CurrentUser";
import ConfigProvider from "components/providers/ConfigProvider";
import PreferredStorePopover from "./PreferredStorePopover";
import SelectPreferredStore from "./SelectPreferredStore";
export default {
components: {
ConfigProvider,
CurrentUser,
PreferredStorePopover,
SelectPreferredStore,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { mount } from "@vue/test-utils";
import { getLocalVue } from "tests/jest/helpers";
import SelectPreferredStore from "./SelectPreferredStore";
import { setupSelectableMock } from "../../ObjectStore/mockServices";
setupSelectableMock();

import axios from "axios";
import MockAdapter from "axios-mock-adapter";
import flushPromises from "flush-promises";

import SelectPreferredStore from "./SelectPreferredStore.vue";

const localVue = getLocalVue(true);

const TEST_HISTORY_ID = "myTestHistoryId";
Expand All @@ -22,19 +26,15 @@ function mountComponent() {
return wrapper;
}

import { ROOT_COMPONENT } from "utils/navigation";
import { ROOT_COMPONENT } from "@/utils/navigation";

const OBJECT_STORES = [
{ object_store_id: "object_store_1", badges: [], quota: { enabled: false } },
{ object_store_id: "object_store_2", badges: [], quota: { enabled: false } },
];
const PREFERENCES = ROOT_COMPONENT.preferences;

describe("SelectPreferredStore.vue", () => {
let axiosMock;

beforeEach(async () => {
axiosMock = new MockAdapter(axios);
axiosMock.onGet("/api/object_store?selectable=true").reply(200, OBJECT_STORES);
});

afterEach(async () => {
Expand All @@ -44,10 +44,10 @@ describe("SelectPreferredStore.vue", () => {
it("updates object store to default on selection null", async () => {
const wrapper = mountComponent();
await flushPromises();
const els = wrapper.findAll(ROOT_COMPONENT.preferences.object_store_selection.option_buttons.selector);
const els = wrapper.findAll(PREFERENCES.object_store_selection.option_buttons.selector);
expect(els.length).toBe(3);
const galaxyDefaultOption = wrapper.find(
ROOT_COMPONENT.preferences.object_store_selection.option_button({ object_store_id: "__null__" }).selector
PREFERENCES.object_store_selection.option_button({ object_store_id: "__null__" }).selector
);
expect(galaxyDefaultOption.exists()).toBeTruthy();
axiosMock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,27 @@ export default {
selectedObjectStoreId: selectedObjectStoreId,
newDatasetsDescription: "New dataset outputs from tools and workflows executed in this history",
popoverPlacement: "left",
galaxySelectionDefalutTitle: "Use Galaxy Defaults",
galaxySelectionDefalutDescription:
galaxySelectionDefaultTitle: "Use Galaxy Defaults",
galaxySelectionDefaultDescription:
"Selecting this will reset Galaxy to default behaviors configured by your Galaxy administrator.",
userSelectionDefalutTitle: "Use Your User Preference Defaults",
userSelectionDefalutDescription:
userSelectionDefaultTitle: "Use Your User Preference Defaults",
userSelectionDefaultDescription:
"Selecting this will cause the history to not set a default and to fallback to your user preference defined default.",
};
},
computed: {
defaultOptionTitle() {
if (this.userPreferredObjectStoreId) {
return this.userSelectionDefalutTitle;
return this.userSelectionDefaultTitle;
} else {
return this.galaxySelectionDefalutTitle;
return this.galaxySelectionDefaultTitle;
}
},
defaultOptionDescription() {
if (this.userPreferredObjectStoreId) {
return this.userSelectionDefalutDescription;
return this.userSelectionDefaultDescription;
} else {
return this.galaxySelectionDefalutDescription;
return this.galaxySelectionDefaultDescription;
}
},
},
Expand Down
180 changes: 86 additions & 94 deletions client/src/components/ObjectStore/SelectObjectStore.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,89 @@
<script lang="ts" setup>
import { ref, watch, onMounted } from "vue";
import LoadingSpan from "@/components/LoadingSpan.vue";
import DescribeObjectStore from "@/components/ObjectStore/DescribeObjectStore.vue";
import { errorMessageAsString } from "@/utils/simple-error";
import ObjectStoreBadges from "@/components/ObjectStore/ObjectStoreBadges.vue";
import ProvidedQuotaSourceUsageBar from "@/components/User/DiskUsage/Quota/ProvidedQuotaSourceUsageBar.vue";
import { getSelectableObjectStores } from "./services";
const props = defineProps({
selectedObjectStoreId: {
type: String,
default: null,
},
defaultOptionTitle: {
// "Use Your User Preference Defaults"
type: String,
required: true,
},
defaultOptionDescription: {
// "Selecting this will cause the history to not set a default and to fallback to your user preference defined default."
type: String,
required: true,
},
forWhat: {
type: String,
required: true,
},
parentError: {
type: String,
default: null,
},
});
const loading = ref(true);
const error = ref(props.parentError);
const popoverPlacement = "left";
const objectStores = ref<Array<object>>([]);
const loadingObjectStoreInfoMessage = ref("Loading object store information");
const whyIsSelectionPreferredText = ref(`
Selecting this will reset Galaxy to default behaviors configured by your Galaxy administrator.
Select a preferred object store for new datasets. This is should be thought of as a preferred
object store because depending the job and workflow configuration execution configuration of
this Galaxy instance - a different object store may be selected. After a dataset is created,
click on the info icon in the history panel to view information about where it is stored. If it
is not stored in the correct place, contact your Galaxy administrator for more information.
`);
watch(
() => props.parentError,
() => {
error.value = props.parentError;
}
);
function handleError(e: unknown) {
const errorMessage = errorMessageAsString(e);
error.value = errorMessage;
}
onMounted(async () => {
try {
const data = await getSelectableObjectStores();
objectStores.value = data;
loading.value = false;
} catch (e) {
handleError(e);
}
});
function variant(objectStoreId: string) {
if (props.selectedObjectStoreId == objectStoreId) {
return "outline-primary";
} else {
return "outline-info";
}
}
const emit = defineEmits(["onSubmit"]);
async function handleSubmit(preferredObjectStoreId: string) {
emit("onSubmit", preferredObjectStoreId);
}
</script>

<template>
<div>
<loading-span v-if="loading" :message="loadingObjectStoreInfoMessage" />
Expand Down Expand Up @@ -55,97 +141,3 @@
</div>
</div>
</template>

<script>
import axios from "axios";
import { prependPath } from "utils/redirect";
import LoadingSpan from "components/LoadingSpan";
import DescribeObjectStore from "components/ObjectStore/DescribeObjectStore";
import { errorMessageAsString } from "utils/simple-error";
import ObjectStoreBadges from "components/ObjectStore/ObjectStoreBadges";
import ProvidedQuotaSourceUsageBar from "components/User/DiskUsage/Quota/ProvidedQuotaSourceUsageBar";
export default {
components: {
LoadingSpan,
DescribeObjectStore,
ObjectStoreBadges,
ProvidedQuotaSourceUsageBar,
},
props: {
selectedObjectStoreId: {
type: String,
default: null,
},
defaultOptionTitle: {
// "Use Your User Preference Defaults"
type: String,
required: true,
},
defaultOptionDescription: {
// "Selecting this will cause the history to not set a default and to fallback to your user preference defined default."
type: String,
required: true,
},
forWhat: {
type: String,
required: true,
},
parentError: {
type: String,
default: null,
},
},
data() {
return {
loading: true,
error: this.parentError,
popoverPlacement: "left",
objectStores: [],
loadingObjectStoreInfoMessage: "Loading object store information",
galaxySelectionDefalutTitle: "Use Galaxy Defaults",
galaxySelectionDefalutDescription:
"Selecting this will reset Galaxy to default behaviors configured by your Galaxy administrator.",
whyIsSelectionPreferredText: `
Selecting this will reset Galaxy to default behaviors configured by your Galaxy administrator.
Select a preferred object store for new datasets. This is should be thought of as a preferred
object store because depending the job and workflow configuration execution configuration of
this Galaxy instance - a different object store may be selected. After a dataset is created,
click on the info icon in the history panel to view information about where it is stored. If it
is not stored in the correct place, contact your Galaxy adminstrator for more information.
`,
};
},
watch: {
parentError() {
this.error = this.parentError;
},
},
async mounted() {
const url = prependPath("api/object_store?selectable=true");
try {
const { data } = await axios.get(url);
this.objectStores = data;
this.loading = false;
} catch (e) {
this.handleError(e);
}
},
methods: {
handleError(e) {
const errorMessage = errorMessageAsString(e);
this.error = errorMessage;
},
variant(objectStoreId) {
if (this.selectedObjectStoreId == objectStoreId) {
return "outline-primary";
} else {
return "outline-info";
}
},
async handleSubmit(preferredObjectStoreId) {
this.$emit("onSubmit", preferredObjectStoreId);
},
},
};
</script>
12 changes: 12 additions & 0 deletions client/src/components/ObjectStore/mockServices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { getSelectableObjectStores } from "./services";
jest.mock("./services");

const OBJECT_STORES = [
{ object_store_id: "object_store_1", badges: [], quota: { enabled: false }, private: false },
{ object_store_id: "object_store_2", badges: [], quota: { enabled: false }, private: false },
];

export function setupSelectableMock() {
const mockGetObjectStores = getSelectableObjectStores as jest.MockedFunction<typeof getSelectableObjectStores>;
mockGetObjectStores.mockResolvedValue(OBJECT_STORES);
}
8 changes: 8 additions & 0 deletions client/src/components/ObjectStore/services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { fetcher } from "@/schema/fetcher";

const getObjectStores = fetcher.path("/api/object_store").method("get").create();

export async function getSelectableObjectStores() {
const { data } = await getObjectStores({ selectable: true });
return data;
}
2 changes: 1 addition & 1 deletion client/src/components/Tool/ToolCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ function onUpdatePreferredObjectStoreId(selectedToolPreferredObjectStoreId) {
size="sm"
class="float-right"
@click="onShowObjectStoreSelect">
<span class="fa fa-database" />
<span class="fa fa-hdd" />
</b-button>
<ToolTargetPreferredObjectStorePopover
v-if="allowObjectStoreSelection"
Expand Down
Loading

0 comments on commit 92270af

Please sign in to comment.