mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #13104 from itisAliRH/back-button-in-file-source-navigation
Add Back button in file source navigation and ftp helper text
This commit is contained in:
@@ -9,6 +9,7 @@ import axios from "axios";
|
||||
import BootstrapVue from "bootstrap-vue";
|
||||
|
||||
import {
|
||||
ftpId,
|
||||
rootId,
|
||||
directoryId,
|
||||
subDirectoryId,
|
||||
@@ -19,6 +20,7 @@ import {
|
||||
directory2RecursiveResponse,
|
||||
directory1Response,
|
||||
subsubdirectoryResponse,
|
||||
someErrorText,
|
||||
} from "./testingData";
|
||||
import { selectionStates } from "components/SelectionDialog/selectionStates";
|
||||
|
||||
@@ -44,6 +46,11 @@ const initComponent = async (props) => {
|
||||
axiosMock.onGet(path).reply(200, response);
|
||||
}
|
||||
|
||||
axiosMock.onGet("/api/remote_files?target=gxfiles://empty-dir").reply(404, {
|
||||
err_msg: someErrorText,
|
||||
err_code: 404,
|
||||
});
|
||||
|
||||
const wrapper = shallowMount(FilesDialog, {
|
||||
localVue,
|
||||
propsData: props,
|
||||
@@ -193,6 +200,43 @@ describe("FilesDialog, file mode", () => {
|
||||
const rootNode = utils.getRenderedDirectory(rootId);
|
||||
expect(rootNode._rowVariant).toBe(selectionStates.selected);
|
||||
});
|
||||
|
||||
it("should show ftp helper only in ftp directory", async () => {
|
||||
// open some other directory than ftp
|
||||
await utils.open_root_folder();
|
||||
// check that ftp helper is not visible
|
||||
expect(wrapper.vm.showFTPHelper).toBe(false);
|
||||
expect(wrapper.find("#helper").exists()).toBe(false);
|
||||
// back to root folder
|
||||
await utils.navigateBack();
|
||||
|
||||
// open ftp directory
|
||||
await utils.openDirectory(ftpId);
|
||||
// check that ftp helper is visible
|
||||
expect(wrapper.vm.showFTPHelper).toBe(true);
|
||||
expect(wrapper.find("#helper").exists()).toBe(true);
|
||||
});
|
||||
|
||||
it("should show loading error and can return back", async () => {
|
||||
expect(wrapper.vm.errorMessage).toBeNull();
|
||||
|
||||
// open directory with error
|
||||
await utils.openDirectory("empty-dir");
|
||||
// assert that error message is set and showed
|
||||
expect(wrapper.vm.errorMessage).toBe(someErrorText);
|
||||
expect(wrapper.html()).toContain(someErrorText);
|
||||
|
||||
// assert that OK button is disabled
|
||||
expect(wrapper.vm.hasValue).toBe(false);
|
||||
|
||||
// back to the root folder
|
||||
await wrapper.find("#back-btn").trigger("click");
|
||||
await flushPromises();
|
||||
expect(wrapper.vm.items.length).toBe(rootResponse.length);
|
||||
|
||||
// assert that OK button is disabled
|
||||
expect(wrapper.vm.hasValue).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("FilesDialog, directory mode", () => {
|
||||
@@ -238,6 +282,27 @@ describe("FilesDialog, directory mode", () => {
|
||||
//should close modal
|
||||
expect(wrapper.vm.modalShow).toBe(false);
|
||||
});
|
||||
|
||||
it("should show loading error and can return back", async () => {
|
||||
expect(wrapper.vm.errorMessage).toBeNull();
|
||||
|
||||
// open directory with error
|
||||
await utils.openDirectory("empty-dir");
|
||||
// assert that error message is set and showed
|
||||
expect(wrapper.vm.errorMessage).toBe(someErrorText);
|
||||
expect(wrapper.html()).toContain(someErrorText);
|
||||
|
||||
// assert that OK button is disabled
|
||||
expect(wrapper.vm.hasValue).toBe(false);
|
||||
|
||||
// back to the root folder
|
||||
await wrapper.find("#back-btn").trigger("click");
|
||||
await flushPromises();
|
||||
expect(wrapper.vm.items.length).toBe(rootResponse.length);
|
||||
|
||||
// assert that OK button is disabled
|
||||
expect(wrapper.vm.hasValue).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
/** Util methods **/
|
||||
|
||||
@@ -3,10 +3,24 @@
|
||||
:error-message="errorMessage"
|
||||
:options-show="optionsShow"
|
||||
:modal-show="modalShow"
|
||||
:hide-modal="() => (modalShow = false)">
|
||||
:hide-modal="() => (modalShow = false)"
|
||||
:back-func="load"
|
||||
:undo-show="undoShow">
|
||||
<template v-slot:search>
|
||||
<data-dialog-search v-model="filter" />
|
||||
</template>
|
||||
<template v-slot:helper>
|
||||
<b-alert v-if="showFTPHelper" id="helper" variant="info" show>
|
||||
This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at
|
||||
<strong>{{ ftpUploadSite }}</strong> using your Galaxy credentials. For help visit the
|
||||
<a href="https://galaxyproject.org/ftp-upload/" target="_blank">tutorial</a>.
|
||||
<span v-if="oidcEnabled"
|
||||
><br />If you are signed-in to Galaxy using a third-party identity and you
|
||||
<strong>do not have a Galaxy password</strong> please use the reset password option in the login
|
||||
form with your email to create a password for your account.</span
|
||||
>
|
||||
</b-alert>
|
||||
</template>
|
||||
<template v-slot:options>
|
||||
<data-dialog-table
|
||||
v-if="optionsShow"
|
||||
@@ -43,6 +57,7 @@
|
||||
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
import { getGalaxyInstance } from "../../app";
|
||||
import SelectionDialogMixin from "components/SelectionDialog/SelectionDialogMixin";
|
||||
import { selectionStates } from "components/SelectionDialog/selectionStates";
|
||||
import { UrlTracker } from "components/DataDialog/utilities";
|
||||
@@ -89,7 +104,10 @@ export default {
|
||||
showDetails: true,
|
||||
isBusy: false,
|
||||
currentDirectory: undefined,
|
||||
showFTPHelper: false,
|
||||
selectAllIcon: selectionStates.unselected,
|
||||
ftpUploadSite: getGalaxyInstance()?.config?.ftp_upload_site,
|
||||
oidcEnabled: getGalaxyInstance()?.config?.enable_oidc,
|
||||
};
|
||||
},
|
||||
created: function () {
|
||||
@@ -258,10 +276,12 @@ export default {
|
||||
/** Performs server request to retrieve data records **/
|
||||
load: function (record) {
|
||||
this.currentDirectory = this.urlTracker.getUrl(record);
|
||||
this.showFTPHelper = record?.url === "gxftp://";
|
||||
this.filter = null;
|
||||
this.optionsShow = false;
|
||||
this.undoShow = !this.urlTracker.atRoot();
|
||||
if (this.urlTracker.atRoot()) {
|
||||
if (this.urlTracker.atRoot() || this.errorMessage) {
|
||||
this.errorMessage = null;
|
||||
this.services
|
||||
.getFileSources()
|
||||
.then((items) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export const ftpId = "_ftp";
|
||||
export const rootId = "pdb-gzip";
|
||||
export const directoryId = "gxfiles://pdb-gzip/directory1";
|
||||
export const subDirectoryId = "gxfiles://pdb-gzip/directory1/subdirectory1";
|
||||
@@ -24,6 +25,16 @@ export const rootResponse = [
|
||||
requires_roles: null,
|
||||
requires_groups: null,
|
||||
},
|
||||
{
|
||||
id: "empty-dir",
|
||||
type: "posix",
|
||||
uri_root: "gxfiles://empty-dir",
|
||||
label: "Empty Directory",
|
||||
doc: "Empty Directory",
|
||||
writable: true,
|
||||
requires_roles: null,
|
||||
requires_groups: null,
|
||||
},
|
||||
];
|
||||
|
||||
export const pdbResponse = [
|
||||
@@ -172,3 +183,5 @@ export const subsubdirectoryResponse = [
|
||||
path: "directory1/subdirectory1/subsubdirectory",
|
||||
},
|
||||
];
|
||||
|
||||
export const someErrorText = "some error text";
|
||||
|
||||
@@ -1,24 +1,31 @@
|
||||
<template>
|
||||
<b-modal
|
||||
modal-class="selection-dialog-modal"
|
||||
v-if="modalShow"
|
||||
visible
|
||||
ok-only
|
||||
ok-title="Close"
|
||||
:static="modalStatic"
|
||||
@hide="hideModal">
|
||||
<b-modal modal-class="selection-dialog-modal" v-if="modalShow" visible :static="modalStatic" @hide="hideModal">
|
||||
<template v-slot:modal-header>
|
||||
<slot name="search"> </slot>
|
||||
</template>
|
||||
<slot name="helper"> </slot>
|
||||
<b-alert v-if="errorMessage" variant="danger" show v-html="errorMessage" />
|
||||
<div v-else>
|
||||
<slot name="options" v-if="optionsShow"> </slot>
|
||||
<div v-else><span class="fa fa-spinner fa-spin" /> <span>Please wait...</span></div>
|
||||
</div>
|
||||
<template v-if="!errorMessage" v-slot:modal-footer>
|
||||
<template v-slot:modal-footer>
|
||||
<div class="w-100">
|
||||
<slot name="buttons"> </slot>
|
||||
<b-btn size="sm" class="float-right selection-dialog-modal-cancel" @click="hideModal"> Cancel </b-btn>
|
||||
<div v-if="!errorMessage">
|
||||
<slot name="buttons"> </slot>
|
||||
<b-btn size="sm" class="float-right selection-dialog-modal-cancel" @click="hideModal">
|
||||
Cancel
|
||||
</b-btn>
|
||||
</div>
|
||||
<div v-else>
|
||||
<b-btn id="back-btn" size="sm" class="float-left" v-if="undoShow" @click="backFunc">
|
||||
<font-awesome-icon :icon="['fas', 'caret-left']" />
|
||||
Back
|
||||
</b-btn>
|
||||
<b-btn size="sm" class="float-right" variant="primary" id="close-btn" @click="hideModal">
|
||||
Close
|
||||
</b-btn>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</b-modal>
|
||||
@@ -27,6 +34,7 @@
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
import BootstrapVue from "bootstrap-vue";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
|
||||
Vue.use(BootstrapVue);
|
||||
|
||||
@@ -56,6 +64,18 @@ export default {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
backFunc: {
|
||||
type: Function,
|
||||
required: false,
|
||||
default: () => {},
|
||||
},
|
||||
undoShow: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
FontAwesomeIcon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user