From 55c249b701be412ca5ebaaa5e431d575c8a04389 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Thu, 10 Apr 2025 11:33:16 -0400 Subject: [PATCH] Decompose dependencies around utils/data.js to avoid circular dependencies. --- client/src/app/galaxy.js | 15 +++- .../src/components/FilesDialog/FilesInput.vue | 2 +- client/src/components/Upload/CompositeRow.vue | 2 +- client/src/components/Upload/DefaultBox.vue | 2 +- client/src/components/Upload/RulesInput.vue | 2 +- client/src/utils/data.js | 71 ++----------------- client/src/utils/dataModalUtils.js | 34 +++++++++ client/src/utils/dataModals.js | 27 +++++++ 8 files changed, 84 insertions(+), 71 deletions(-) create mode 100644 client/src/utils/dataModalUtils.js create mode 100644 client/src/utils/dataModals.js diff --git a/client/src/app/galaxy.js b/client/src/app/galaxy.js index 5c24ff710d9..656f9162394 100644 --- a/client/src/app/galaxy.js +++ b/client/src/app/galaxy.js @@ -55,8 +55,19 @@ GalaxyApp.prototype._init = function (options, bootstrapped) { /* These shouldn't probably be here, but they need to be right now for * compatibility with external plugins */ this.data = {}; - this.data.create = create; - this.data.dialog = dialog; + + const galaxy = this; + + const createWithGalaxyProvided = (...args) => { + return create(galaxy, ...args); + }; + + const dialogWithGalaxyProvided = (...args) => { + return dialog(galaxy, ...args); + }; + + this.data.create = createWithGalaxyProvided; + this.data.dialog = dialogWithGalaxyProvided; return this; }; diff --git a/client/src/components/FilesDialog/FilesInput.vue b/client/src/components/FilesDialog/FilesInput.vue index 965eaab51f5..0d6551493b1 100644 --- a/client/src/components/FilesDialog/FilesInput.vue +++ b/client/src/components/FilesDialog/FilesInput.vue @@ -3,7 +3,7 @@ import { BFormInput } from "bootstrap-vue"; import { computed } from "vue"; import { type FileSourceBrowsingMode, type FilterFileSourcesOptions } from "@/api/remoteFiles"; -import { filesDialog } from "@/utils/data"; +import { filesDialog } from "@/utils/dataModals"; import { type SelectionItem } from "../SelectionDialog/selectionTypes"; diff --git a/client/src/components/Upload/CompositeRow.vue b/client/src/components/Upload/CompositeRow.vue index 3f2db691768..4c706739e3e 100644 --- a/client/src/components/Upload/CompositeRow.vue +++ b/client/src/components/Upload/CompositeRow.vue @@ -3,7 +3,7 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faCheck, faEdit, faExclamation, faFolderOpen, faLaptop } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { BDropdown, BDropdownItem } from "bootstrap-vue"; -import { filesDialog } from "utils/data"; +import { filesDialog } from "utils/dataModals"; import { bytesToString } from "utils/utils"; import { computed, ref } from "vue"; diff --git a/client/src/components/Upload/DefaultBox.vue b/client/src/components/Upload/DefaultBox.vue index eb875fb8c30..39a7efd7980 100644 --- a/client/src/components/Upload/DefaultBox.vue +++ b/client/src/components/Upload/DefaultBox.vue @@ -7,7 +7,7 @@ import Vue, { computed, type Ref, ref } from "vue"; import type { HDASummary } from "@/api"; import { monitorUploadedHistoryItems } from "@/composables/monitorUploadedHistoryItems"; import type { DbKey, ExtensionDetails } from "@/composables/uploadConfigurations"; -import { filesDialog } from "@/utils/data"; +import { filesDialog } from "@/utils/dataModals"; import { UploadQueue } from "@/utils/upload-queue.js"; import type { CollectionType } from "../History/adapters/buildCollectionModal"; diff --git a/client/src/components/Upload/RulesInput.vue b/client/src/components/Upload/RulesInput.vue index ed36d963657..729820057e8 100644 --- a/client/src/components/Upload/RulesInput.vue +++ b/client/src/components/Upload/RulesInput.vue @@ -5,7 +5,7 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { getGalaxyInstance } from "app"; import { BAlert, BButton } from "bootstrap-vue"; import { getRemoteEntries, getRemoteEntriesAt } from "components/Upload/utils"; -import { filesDialog } from "utils/data"; +import { filesDialog } from "utils/dataModals"; import { urlData } from "utils/url"; import { computed, ref } from "vue"; diff --git a/client/src/utils/data.js b/client/src/utils/data.js index 68ae2fe8a46..12b2e0120d5 100644 --- a/client/src/utils/data.js +++ b/client/src/utils/data.js @@ -1,46 +1,19 @@ -import { getGalaxyInstance } from "app"; -import axios from "axios"; -import { FilesDialog } from "components/FilesDialog"; import { useGlobalUploadModal } from "composables/globalUploadModal"; -import $ from "jquery"; -import { getAppRoot } from "onload/loadConfig"; -import Vue from "vue"; import { uploadPayload } from "@/utils/upload-payload.js"; import { uploadSubmit } from "@/utils/upload-submit.js"; import { startWatchingHistory } from "@/watch/watchHistory"; -import DataDialog from "components/DataDialog/DataDialog.vue"; -import DatasetCollectionDialog from "components/SelectionDialog/DatasetCollectionDialog.vue"; +import { getCurrentGalaxyHistory, mountSelectionDialog } from "./dataModalUtils"; -// This should be moved more centrally (though still hanging off Galaxy for -// external use?), and populated from the store; just using this as a temporary -// interface. -export async function getCurrentGalaxyHistory() { - const galaxy = getGalaxyInstance(); - if (galaxy.currHistoryPanel && galaxy.currHistoryPanel.model.id) { - // TODO: use central store for this. - return galaxy.currHistoryPanel.model.id; - } else { - // Otherwise manually fetch the current history json and use that id. - return axios - .get(`${getAppRoot()}history/current_history_json`) - .then((response) => { - return response.data.id; - }) - .catch((err) => { - console.error("Error fetching current user history:", err); - return null; - }); - } -} +import DataDialog from "components/DataDialog/DataDialog.vue"; /** * Opens a modal dialog for data selection * @param {function} callback - Result function called with selection */ -export function dialog(callback, options = {}) { - getCurrentGalaxyHistory().then((history_id) => { +export function dialog(galaxy, callback, options = {}) { + getCurrentGalaxyHistory(galaxy).then((history_id) => { Object.assign(options, { callback: callback, history: history_id, @@ -49,48 +22,16 @@ export function dialog(callback, options = {}) { const { openGlobalUploadModal } = useGlobalUploadModal(); openGlobalUploadModal(options); } else { - _mountSelectionDialog(DataDialog, options); + mountSelectionDialog(DataDialog, options); } }); } -/** - * Opens a modal dialog for dataset collection selection - * @param {function} callback - Result function called with selection - */ -export function datasetCollectionDialog(callback, options = {}) { - getCurrentGalaxyHistory().then((history_id) => { - Object.assign(options, { - callback: callback, - history: history_id, - }); - _mountSelectionDialog(DatasetCollectionDialog, options); - }); -} - -export function filesDialog(callback, options = {}) { - Object.assign(options, { - callback: callback, - }); - _mountSelectionDialog(FilesDialog, options); -} - -function _mountSelectionDialog(clazz, options) { - const instance = Vue.extend(clazz); - const vm = document.createElement("div"); - $("body").append(vm); - new instance({ - propsData: options, - }).$mount(vm); -} - /** * Creates a history dataset by submitting an upload request * TODO: This should live somewhere else. */ -export function create(options) { - const galaxy = getGalaxyInstance(); - +export function create(galaxy, options) { async function getHistory() { if (!options.history_id) { return getCurrentGalaxyHistory(); diff --git a/client/src/utils/dataModalUtils.js b/client/src/utils/dataModalUtils.js new file mode 100644 index 00000000000..be14700b70d --- /dev/null +++ b/client/src/utils/dataModalUtils.js @@ -0,0 +1,34 @@ +import axios from "axios"; +import $ from "jquery"; +import { getAppRoot } from "onload/loadConfig"; +import Vue from "vue"; + +// This should be moved more centrally (though still hanging off Galaxy for +// external use?), and populated from the store; just using this as a temporary +// interface. +export async function getCurrentGalaxyHistory(galaxy) { + if (galaxy.currHistoryPanel && galaxy.currHistoryPanel.model.id) { + // TODO: use central store for this. + return galaxy.currHistoryPanel.model.id; + } else { + // Otherwise manually fetch the current history json and use that id. + return axios + .get(`${getAppRoot()}history/current_history_json`) + .then((response) => { + return response.data.id; + }) + .catch((err) => { + console.error("Error fetching current user history:", err); + return null; + }); + } +} + +export function mountSelectionDialog(clazz, options) { + const instance = Vue.extend(clazz); + const vm = document.createElement("div"); + $("body").append(vm); + new instance({ + propsData: options, + }).$mount(vm); +} diff --git a/client/src/utils/dataModals.js b/client/src/utils/dataModals.js new file mode 100644 index 00000000000..f3cb5b0d030 --- /dev/null +++ b/client/src/utils/dataModals.js @@ -0,0 +1,27 @@ +import { getGalaxyInstance } from "app"; +import { FilesDialog } from "components/FilesDialog"; + +import { getCurrentGalaxyHistory, mountSelectionDialog } from "./dataModalUtils"; + +import DatasetCollectionDialog from "components/SelectionDialog/DatasetCollectionDialog.vue"; + +/** + * Opens a modal dialog for dataset collection selection + * @param {function} callback - Result function called with selection + */ +export function datasetCollectionDialog(callback, options = {}) { + getCurrentGalaxyHistory(getGalaxyInstance()).then((history_id) => { + Object.assign(options, { + callback: callback, + history: history_id, + }); + mountSelectionDialog(DatasetCollectionDialog, options); + }); +} + +export function filesDialog(callback, options = {}) { + Object.assign(options, { + callback: callback, + }); + mountSelectionDialog(FilesDialog, options); +}