diff --git a/js/app.js b/js/app.js index 73b5945..d1f5eb9 100644 --- a/js/app.js +++ b/js/app.js @@ -26,7 +26,6 @@ import {igvxhr} from "../node_modules/igv-utils/src/index.js" import * as GoogleAuth from '../node_modules/google-utils/src/googleAuth.js' import makeDraggable from "./widgets/utils/draggable.js" import AlertSingleton from "./widgets/alertSingleton.js" -import {createSessionWidgets} from "./widgets/sessionWidgets.js" import { updateTrackMenusWithTrackConfigurations, createTrackWidgetsWithTrackRegistry, @@ -48,6 +47,7 @@ import GtexUtils from "./gtexUtils.js" import version from "./version.js" import {createCircularViewResizeModal} from "./circularViewResizeModal.js" import {createLoadDropdown} from "./widgets/loadWidget.js" +import {createSessionLoadSaveDropdown} from "./widgets/sessionLoadSaveWidget.js" document.addEventListener("DOMContentLoaded", async (event) => await main(document.getElementById('igv-app-container'), igvwebConfig)) @@ -60,6 +60,8 @@ let svgSaveImageModal let pngSaveImageModal let roiURLModal let sampleInfoURLModal +let sessionURLModal +let sessionSaveModal async function main(container, config) { @@ -233,8 +235,6 @@ async function initializationHelper(browser, container, options) { $('div#igv-session-dropdown-menu > :nth-child(2)').after(googleDriveDropdownItem('igv-app-dropdown-google-drive-session-file-button')) - const $igvMain = $('#igv-main') - const genomeFileLoadConfig = { localFileInput: document.getElementById('igv-app-dropdown-local-genome-file-input'), @@ -277,7 +277,7 @@ async function initializationHelper(browser, container, options) { localFileInput: document.getElementById('igv-app-sample-info-dropdown-local-track-file-input'), initializeDropbox, dropboxButton: options.dropboxAPIKey ? document.getElementById('igv-app-dropdown-dropbox-sample-info-file-button') : undefined, - googleEnabled: googleEnabled, + googleEnabled, googleDriveButton: document.getElementById('igv-app-dropdown-google-drive-sample-info-file-button'), urlModalId: 'igv-app-sample-info-from-url-modal', urlModalTitle: 'Sample Info', @@ -303,7 +303,7 @@ async function initializationHelper(browser, container, options) { localFileInput: document.getElementById('igv-app-roi-dropdown-local-track-file-input'), initializeDropbox, dropboxButton: options.dropboxAPIKey ? document.getElementById('igv-app-dropdown-dropbox-roi-file-button') : undefined, - googleEnabled: googleEnabled, + googleEnabled, googleDriveButton: document.getElementById('igv-app-dropdown-google-drive-roi-file-button'), urlModalId: 'igv-app-roi-from-url-modal', urlModalTitle: 'ROI', @@ -333,17 +333,21 @@ async function initializationHelper(browser, container, options) { } - createSessionWidgets($igvMain, - 'igv-webapp', - 'igv-app-dropdown-local-session-file-input', + const sessionDropdownConfig = { + igvMain: document.getElementById('igv-main'), + localFileInput: document.getElementById('igv-app-dropdown-local-session-file-input'), initializeDropbox, - options.dropboxAPIKey ? 'igv-app-dropdown-dropbox-session-file-button' : undefined, - 'igv-app-dropdown-google-drive-session-file-button', - 'igv-app-session-url-modal', - 'igv-app-session-save-modal', + dropboxButton: options.dropboxAPIKey ? document.getElementById('igv-app-dropdown-dropbox-session-file-button') : undefined, googleEnabled, - sessionLoader, - sessionSaver) + googleDriveButton: document.getElementById('igv-app-dropdown-google-drive-session-file-button'), + urlModalId: 'igv-app-session-url-modal', + urlModalTitle: 'Session', + saveModalId: 'igv-app-session-save-modal', + loadHandler: sessionLoader, + saveHandler: sessionSaver + }; + + ({ sessionURLModal, sessionSaveModal } = createSessionLoadSaveDropdown(sessionDropdownConfig)) svgSaveImageModal = new bootstrap.Modal(document.getElementById('igv-app-svg-save-modal')) createSaveImageWidget({ browser, saveModal: svgSaveImageModal, imageType: 'svg' }) diff --git a/js/widgets/sessionFileLoad.js b/js/widgets/sessionFileLoad.js deleted file mode 100644 index a07cf14..0000000 --- a/js/widgets/sessionFileLoad.js +++ /dev/null @@ -1,24 +0,0 @@ -import FileLoad from "./fileLoad.js" - -class SessionFileLoad extends FileLoad { - - constructor({localFileInput, initializeDropbox, dropboxButton, googleEnabled, googleDriveButton, loadHandler}) { - super({localFileInput, initializeDropbox, dropboxButton, googleEnabled, googleDriveButton}) - this.loadHandler = loadHandler - } - - async loadPaths(paths) { - - const path = paths[0] - - try { - this.loadHandler({url: path}) - - } catch (e) { - throw new Error('Session file did not load' + e.message) - } - }; - -} - -export default SessionFileLoad diff --git a/js/widgets/sessionLoadSaveWidget.js b/js/widgets/sessionLoadSaveWidget.js new file mode 100644 index 0000000..19dca45 --- /dev/null +++ b/js/widgets/sessionLoadSaveWidget.js @@ -0,0 +1,122 @@ +import {FileUtils} from '../../node_modules/igv-utils/src/index.js' +import {createLoadDropdown} from "./loadWidget.js" + +function createSessionLoadSaveDropdown({ igvMain, + localFileInput, + initializeDropbox, + dropboxButton, + googleEnabled, + googleDriveButton, + urlModalId, + urlModalTitle, + saveModalId, + loadHandler, + saveHandler }) { + + const urlLoadModal = createLoadDropdown({ igvMain, + localFileInput, + initializeDropbox, + dropboxButton, + googleEnabled, + googleDriveButton, + urlModalId, + urlModalTitle, + loadHandler }) + + + const saveModal = configureSaveSessionModal(igvMain, 'igv-webapp', saveHandler, saveModalId) + + return { urlLoadModal, saveModal } +} + +function configureSaveSessionModal(igvMain, prefix, saveHandler, saveModalId) { + + const html = + ``; + + + const fragment = document.createRange().createContextualFragment(html) + const modalElement = fragment.firstChild + + igvMain.appendChild(modalElement) + + const modal = new bootstrap.Modal(modalElement) + + const inputElement = modalElement.querySelector('input') + const $input = $(inputElement) + + modalElement.addEventListener('show.bs.modal', () => inputElement.value = `${prefix}-session.json`) + + const okHandler = () => { + + const extensions = new Set(['json', 'xml']) + + let filename = $input.val() + + if (undefined === filename || '' === filename) { + filename = $input.attr('placeholder') + } else if (false === extensions.has(FileUtils.getExtension(filename))) { + filename = filename + '.json' + } + + const json = saveHandler() + + if (json) { + const jsonString = JSON.stringify(json, null, '\t') + const data = URL.createObjectURL(new Blob([jsonString], {type: "application/octet-stream"})) + FileUtils.download(filename, data) + } + + modal.hide() + } + + const okElement = modalElement.querySelector('.modal-footer button:nth-child(2)') + okElement.addEventListener('click', () => okHandler()) + + inputElement.addEventListener('keyup', e => { + // enter key + if (13 === e.keyCode) { + okHandler() + } + }) + + return modal +} + + +export { createSessionLoadSaveDropdown } diff --git a/js/widgets/sessionWidgets.js b/js/widgets/sessionWidgets.js deleted file mode 100644 index ea52b24..0000000 --- a/js/widgets/sessionWidgets.js +++ /dev/null @@ -1,154 +0,0 @@ -import {FileUtils} from '../../node_modules/igv-utils/src/index.js' -import FileLoadManager from './fileLoadManager.js' -import FileLoadWidget from './fileLoadWidget.js' -import SessionFileLoad from "./sessionFileLoad.js" -import {createURLModalElement} from './urlModal.js' -import * as Utils from './utils.js' - -let fileLoadWidget -let sessionWidgetModal -let saveSessionModal -function createSessionWidgets($rootContainer, - prefix, - localFileInputId, - initializeDropbox, - dropboxButtonId, - googleDriveButtonId, - urlModalId, - sessionSaveModalId, - googleEnabled, - loadHandler, - JSONProvider) { - - const urlModalElement = createURLModalElement(urlModalId, 'Session URL') - $rootContainer.get(0).appendChild(urlModalElement) - - if (!googleEnabled) { - $(`#${googleDriveButtonId}`).parent().hide() - } - - const fileLoadWidgetConfig = - { - widgetParent: urlModalElement.querySelector('.modal-body'), - dataTitle: 'Session', - indexTitle: undefined, - mode: 'url', - fileLoadManager: new FileLoadManager(), - dataOnly: true, - doURL: undefined - } - - fileLoadWidget = new FileLoadWidget(fileLoadWidgetConfig) - - const sessionFileLoadConfig = - { - localFileInput: document.querySelector(`#${localFileInputId}`), - initializeDropbox, - dropboxButton: dropboxButtonId ? document.querySelector(`#${dropboxButtonId}`) : undefined, - googleEnabled, - googleDriveButton: document.querySelector(`#${googleDriveButtonId}`), - loadHandler - } - - const sessionFileLoad = new SessionFileLoad(sessionFileLoadConfig) - - sessionWidgetModal = new bootstrap.Modal(urlModalElement) - Utils.configureModal(fileLoadWidget, sessionWidgetModal, async fileLoadWidget => { - await sessionFileLoad.loadPaths(fileLoadWidget.retrievePaths()) - return true - }) - - saveSessionModal = configureSaveSessionModal($rootContainer, prefix, JSONProvider, sessionSaveModalId) - -} - -function configureSaveSessionModal($rootContainer, prefix, JSONProvider, sessionSaveModalId) { - - const html = - ``; - - - const fragment = document.createRange().createContextualFragment(html) - const modalElement = fragment.firstChild - - $rootContainer.get(0).appendChild(modalElement) - - const modal = new bootstrap.Modal(modalElement) - - const inputElement = modalElement.querySelector('input') - const $input = $(inputElement) - - modalElement.addEventListener('show.bs.modal', () => $input.val(`${prefix}-session.json`)) - - const okHandler = () => { - - const extensions = new Set(['json', 'xml']) - - let filename = $input.val() - - if (undefined === filename || '' === filename) { - filename = $input.attr('placeholder') - } else if (false === extensions.has(FileUtils.getExtension(filename))) { - filename = filename + '.json' - } - - const json = JSONProvider() - - if (json) { - const jsonString = JSON.stringify(json, null, '\t') - const data = URL.createObjectURL(new Blob([jsonString], {type: "application/octet-stream"})) - FileUtils.download(filename, data) - } - - modal.hide() - } - - const okElement = modalElement.querySelector('.modal-footer button:nth-child(2)') - okElement.addEventListener('click', () => okHandler()) - - inputElement.addEventListener('keyup', e => { - // enter key - if (13 === e.keyCode) { - okHandler() - } - }) - - return modal -} - -export {createSessionWidgets}