Rework SelectObjectStore API interaction to pinia stores.

This commit is contained in:
John Chilton
2024-02-15 14:16:38 -05:00
parent c94997719d
commit c0cd6ad214
4 changed files with 70 additions and 33 deletions
+2
View File
@@ -77,6 +77,8 @@ export type DCObject = components["schemas"]["DCObject"];
export type DatasetCollectionAttributes = components["schemas"]["DatasetCollectionAttributesResult"];
export type ConcreteObjectStoreModel = components["schemas"]["ConcreteObjectStoreModel"];
/**
* A SubCollection is a DatasetCollectionElement of type `dataset_collection`
* with additional information to simplify its handling.
@@ -1,8 +1,8 @@
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { storeToRefs } from "pinia";
import { computed, ref } from "vue";
import { getSelectableObjectStores } from "@/api/objectStores";
import { errorMessageAsString } from "@/utils/simple-error";
import { useObjectStoreStore } from "@/stores/objectStoreStore";
import LoadingSpan from "@/components/LoadingSpan.vue";
import DescribeObjectStore from "@/components/ObjectStore/DescribeObjectStore.vue";
@@ -22,13 +22,13 @@ const props = withDefaults(defineProps<SelectObjectStoreProps>(), {
parentError: null,
});
const loading = ref(true);
const error = ref(props.parentError);
const popoverProps = {
placement: "rightbottom",
boundary: "window", // don't warp the popover to squeeze it into this modal
};
const objectStores = ref<Array<object>>([]);
const store = useObjectStoreStore();
const { isLoading, loadErrorMessage, selectableObjectStores } = storeToRefs(store);
const loadingObjectStoreInfoMessage = ref("Loading object store information");
const whyIsSelectionPreferredText = ref(`
@@ -40,28 +40,6 @@ click on the info icon in the history panel to view information about where it i
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";
@@ -74,6 +52,10 @@ const emit = defineEmits<{
(e: "onSubmit", id: string | null): void;
}>();
const error = computed(() => {
return props.parentError || loadErrorMessage.value;
});
async function handleSubmit(preferredObjectStoreId: string) {
emit("onSubmit", preferredObjectStoreId);
}
@@ -81,7 +63,7 @@ async function handleSubmit(preferredObjectStoreId: string) {
<template>
<div>
<LoadingSpan v-if="loading" :message="loadingObjectStoreInfoMessage" />
<LoadingSpan v-if="isLoading" :message="loadingObjectStoreInfoMessage" />
<div v-else>
<b-alert v-if="error" variant="danger" class="object-store-selection-error" show>
{{ error }}
@@ -98,7 +80,7 @@ async function handleSubmit(preferredObjectStoreId: string) {
><i>{{ defaultOptionTitle | localize }}</i></b-button
>
<b-button
v-for="object_store in objectStores"
v-for="object_store in selectableObjectStores"
:id="`preferred-object-store-button-${object_store.object_store_id}`"
:key="object_store.object_store_id"
:variant="variant(object_store.object_store_id)"
@@ -125,7 +107,7 @@ async function handleSubmit(preferredObjectStoreId: string) {
<span v-localize>{{ defaultOptionDescription }}</span>
</b-popover>
<b-popover
v-for="object_store in objectStores"
v-for="object_store in selectableObjectStores"
:key="object_store.object_store_id"
:target="`preferred-object-store-button-${object_store.object_store_id}`"
triggers="hover"
@@ -1,13 +1,28 @@
import { createTestingPinia } from "@pinia/testing";
import { getSelectableObjectStores } from "@/api/objectStores";
jest.mock("@/api/objectStores");
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 },
{
object_store_id: "object_store_1",
badges: [],
quota: { enabled: false },
private: false,
name: "Object Store 1",
},
{
object_store_id: "object_store_2",
badges: [],
quota: { enabled: false },
private: false,
name: "Object Store 2",
},
];
export function setupSelectableMock() {
createTestingPinia();
const mockGetObjectStores = getSelectableObjectStores as jest.MockedFunction<typeof getSelectableObjectStores>;
mockGetObjectStores.mockResolvedValue(OBJECT_STORES);
}
+38
View File
@@ -0,0 +1,38 @@
import { defineStore } from "pinia";
import { computed, ref } from "vue";
import { ConcreteObjectStoreModel } from "@/api";
import { getSelectableObjectStores } from "@/api/objectStores";
import { errorMessageAsString } from "@/utils/simple-error";
export const useObjectStoreStore = defineStore("objectStoreStore", () => {
const selectableObjectStores = ref<ConcreteObjectStoreModel[] | null>(null);
const loadErrorMessage = ref<string | null>(null);
const isLoading = ref(false);
const isLoaded = computed(() => selectableObjectStores.value != null);
async function loadObjectStores() {
if (!isLoaded.value && !isLoading.value) {
isLoading.value = true;
try {
const data = await getSelectableObjectStores();
selectableObjectStores.value = data;
} catch (err) {
const errorMessage = `Error loading Galaxy object stores: ${errorMessageAsString(err)}`;
loadErrorMessage.value = errorMessage;
console.error("Error loading Galaxy object stores", err);
} finally {
isLoading.value = false;
}
}
}
loadObjectStores();
return {
isLoaded,
isLoading,
loadErrorMessage,
selectableObjectStores,
};
});