import { computed, type Ref, ref } from "vue"; import { GalaxyApi } from "@/api"; import type { Instance, PluginStatus, TemplateSummary } from "@/api/configTemplates"; import type { buildInstanceRoutingComposable } from "@/components/ConfigTemplates/routing"; import { errorMessageAsString } from "@/utils/simple-error"; import { createFormDataToPayload, createTemplateForm, editFormDataToPayload, editTemplateForm, type FormEntry, pluginStatusToErrorMessage, upgradeForm, upgradeFormDataToPayload, } from "./formUtil"; import ActionSummary from "./ActionSummary.vue"; import ConfigurationTestSummaryModal from "@/components/ConfigTemplates/ConfigurationTestSummaryModal.vue"; import InstanceForm from "@/components/ConfigTemplates/InstanceForm.vue"; type InstanceRoutingComposableType = ReturnType; export function useConfigurationTesting() { const testRunning = ref(false); const testResults = ref(undefined); return { testRunning, testResults, }; } type CreateTestUrl = "/api/object_store_instances/test" | "/api/file_source_instances/test"; type CreateUrl = "/api/object_store_instances" | "/api/file_source_instances"; export function useConfigurationTemplateCreation( what: string, template: Ref, uuid: Ref, testUrl: CreateTestUrl, createUrl: CreateUrl, onCreate: (result: R) => unknown, ) { const error = ref(null); const { testRunning, testResults } = useConfigurationTesting(); async function onSubmit(formData: any) { const payload = createFormDataToPayload(template.value, formData); if (uuid.value) { payload.uuid = uuid.value; } let pluginStatus: PluginStatus; try { testRunning.value = true; const { data, error: testRequestError } = await GalaxyApi().POST(testUrl, { body: payload, }); if (testRequestError) { error.value = "Failed to verify configuration: " + errorMessageAsString(testRequestError); return; } else { pluginStatus = data; testResults.value = pluginStatus; } } catch (e) { error.value = "Failed to verify configuration: " + errorMessageAsString(e); return; } finally { testRunning.value = false; } if (pluginStatus) { const testError = pluginStatusToErrorMessage(pluginStatus); if (testError) { error.value = testError; return; } } try { const { data: userObject, error: createRequestError } = await GalaxyApi().POST(createUrl, { body: payload, }); if (createRequestError) { error.value = errorMessageAsString(createRequestError); } else { onCreate(userObject as R); } } catch (e) { error.value = errorMessageAsString(e); return; } } const inputs = computed(() => { return createTemplateForm(template.value, what); }); const submitTitle = "Create"; const loadingMessage = `Loading ${what} template and instance information`; return { ActionSummary, error, inputs, InstanceForm, onSubmit, submitTitle, loadingMessage, testRunning, testResults, }; } type TestInstanceUrl = "/api/file_source_instances/{uuid}/test" | "/api/object_store_instances/{uuid}/test"; export function useInstanceTesting(testUrl: TestInstanceUrl) { const showTestResults = ref(false); const testResults = ref(undefined); const testingError = ref(undefined); async function test(instance: R) { testResults.value = undefined; testingError.value = undefined; showTestResults.value = true; try { const { data, error } = await GalaxyApi().GET(testUrl, { params: { path: { uuid: instance.uuid } }, }); const pluginStatus = data; const testRequestError = error; if (testRequestError) { testingError.value = errorMessageAsString(testRequestError); } else { testResults.value = pluginStatus; } } catch (e) { testingError.value = errorMessageAsString(e); } } return { ConfigurationTestSummaryModal, showTestResults, testResults, testingError, test, }; } type TestUpdateUrl = "/api/object_store_instances/{uuid}/test" | "/api/file_source_instances/{uuid}/test"; type UpdateUrl = "/api/object_store_instances/{uuid}" | "/api/file_source_instances/{uuid}"; export function useConfigurationTemplateEdit( what: string, instance: Ref, template: Ref, testUpdateUrl: TestUpdateUrl, updateUrl: UpdateUrl, useRouting: InstanceRoutingComposableType, /** * Callback to be called when the object store is updated. * By default, no action is taken. */ onUpdated: (result: R) => void = (__: R) => {}, ) { const { testRunning, testResults } = useConfigurationTesting(); const showForceActionButton = ref(false); const { goToIndex } = useRouting(); async function onUpdate(objectStore: R) { onUpdated(objectStore); const message = `Updated ${what} ${objectStore.name}`; goToIndex({ message }); } const inputs = computed | undefined>(() => { const realizedInstance = instance.value; const realizedTemplate = template.value; if (!realizedInstance || !realizedTemplate) { return undefined; } return editTemplateForm(realizedTemplate, what, realizedInstance); }); const error = ref(null); const hasSecrets = computed(() => instance.value?.secrets && instance.value?.secrets.length > 0); const submitTitle = "Update Settings"; const loadingMessage = `Loading ${what} template and instance information`; async function onSubmit(formData: any) { if (template.value && instance.value) { const payload = editFormDataToPayload(template.value, formData); let pluginStatus; try { testRunning.value = true; showForceActionButton.value = false; const { data: pluginStatus, error: testRequestError } = await GalaxyApi().POST(testUpdateUrl, { params: { path: { uuid: instance.value.uuid } }, body: payload, }); if (testRequestError) { error.value = errorMessageAsString(testRequestError); showForceActionButton.value = true; } testResults.value = pluginStatus; } catch (e) { error.value = errorMessageAsString(e); showForceActionButton.value = true; return; } finally { testRunning.value = false; } if (pluginStatus) { const testError = pluginStatusToErrorMessage(pluginStatus); if (testError) { error.value = testError; showForceActionButton.value = true; return; } } try { const { data, error: updateRequestError } = await GalaxyApi().PUT(updateUrl, { params: { path: { uuid: instance.value.uuid } }, body: payload, }); if (updateRequestError) { error.value = errorMessageAsString(updateRequestError); } else { await onUpdate(data as R); } } catch (e) { error.value = errorMessageAsString(e); return; } } } async function onForceSubmit(formData: any) { if (template.value && instance.value) { const payload = editFormDataToPayload(template.value, formData); try { const { data, error: updateRequestError } = await GalaxyApi().PUT(updateUrl, { params: { path: { uuid: instance.value.uuid } }, body: payload, }); if (updateRequestError) { error.value = errorMessageAsString(updateRequestError); } else { await onUpdate(data as R); } } catch (e) { error.value = errorMessageAsString(e); return; } } } return { error, ActionSummary, inputs, InstanceForm, hasSecrets, loadingMessage, onForceSubmit, onSubmit, showForceActionButton, submitTitle, testResults, testRunning, }; } export function useConfigurationTemplateUpgrade( what: string, instance: Ref, template: Ref, testUpdateUrl: TestUpdateUrl, updateUrl: UpdateUrl, useRouting: InstanceRoutingComposableType, ) { const { goToIndex } = useRouting(); async function onUpgrade(objectStore: R) { const message = `Upgraded ${what} ${objectStore.name}`; goToIndex({ message }); } const error = ref(null); const { testRunning, testResults } = useConfigurationTesting(); const showForceActionButton = ref(false); const submitTitle = "Upgrade Configuration"; const loadingMessage = `Loading latest ${what} template and instance information`; const inputs = computed | undefined>(() => { const realizedInstance = instance.value; const realizedLatestTemplate = template.value; if (!realizedInstance || !realizedLatestTemplate) { return undefined; } const form = upgradeForm(realizedLatestTemplate, realizedInstance); return form; }); async function onSubmit(formData: any) { if (!instance.value || !template.value) { return; } const payload = upgradeFormDataToPayload(template.value, formData); let pluginStatus; try { testRunning.value = true; showForceActionButton.value = false; const { data: pluginStatus, error: testRequestError } = await GalaxyApi().POST(testUpdateUrl, { params: { path: { uuid: instance.value.uuid } }, body: payload, }); if (testRequestError) { error.value = errorMessageAsString(testRequestError); showForceActionButton.value = true; return; } else { testResults.value = pluginStatus; } } catch (e) { showForceActionButton.value = true; error.value = errorMessageAsString(e); return; } finally { testRunning.value = false; } if (pluginStatus) { const testError = pluginStatusToErrorMessage(pluginStatus); if (testError) { error.value = testError; showForceActionButton.value = true; return; } } try { const { data, error: updateRequestError } = await GalaxyApi().PUT(updateUrl, { params: { path: { uuid: instance.value.uuid } }, body: payload, }); if (updateRequestError) { error.value = errorMessageAsString(updateRequestError); } else { await onUpgrade(data as R); } } catch (e) { error.value = errorMessageAsString(e); return; } } async function onForceSubmit(formData: any) { const payload = upgradeFormDataToPayload(template.value, formData); try { const { data, error: updateRequestError } = await GalaxyApi().PUT(updateUrl, { params: { path: { uuid: instance.value.uuid } }, body: payload, }); if (updateRequestError) { error.value = errorMessageAsString(updateRequestError); } else { await onUpgrade(data as R); } } catch (e) { error.value = errorMessageAsString(e); return; } } return { error, ActionSummary, inputs, InstanceForm, loadingMessage, onForceSubmit, onSubmit, submitTitle, showForceActionButton, testResults, testRunning, }; }