mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Place specialized upload button in the tool form.
This commit is contained in:
@@ -23,6 +23,10 @@
|
||||
<div class="fa fa-caret-left mr-1" />
|
||||
Back
|
||||
</b-btn>
|
||||
<b-btn size="sm" class="float-left mr-1" @click="newUpload">
|
||||
<div class="fa fa-upload ml-1" />
|
||||
Upload
|
||||
</b-btn>
|
||||
<b-btn
|
||||
v-if="multiple"
|
||||
size="sm"
|
||||
@@ -44,6 +48,7 @@ import SelectionDialogMixin from "components/SelectionDialog/SelectionDialogMixi
|
||||
import { UrlTracker } from "./utilities";
|
||||
import { Model } from "./model";
|
||||
import { Services } from "./services";
|
||||
import { mountUploadModal } from "components/Upload";
|
||||
|
||||
Vue.use(BootstrapVue);
|
||||
|
||||
@@ -125,6 +130,16 @@ export default {
|
||||
this.load(record.url);
|
||||
}
|
||||
},
|
||||
newUpload: function () {
|
||||
const propsData = {
|
||||
multiple: this.multiple,
|
||||
format: this.format,
|
||||
callback: this.callback,
|
||||
modalShow: true,
|
||||
};
|
||||
mountUploadModal(propsData);
|
||||
this.modalShow = false;
|
||||
},
|
||||
/** Called when selection is complete, values are formatted and parsed to external callback **/
|
||||
finalize: function () {
|
||||
const results = this.model.finalize();
|
||||
|
||||
@@ -20,7 +20,9 @@ describe("Datatypes/index.js", () => {
|
||||
axiosMock.onGet(`/api/datatypes/types_and_mapping`).reply(200, typesAndMappingResponse);
|
||||
await getDatatypesMapper().then((mapper) => {
|
||||
expect(mapper.isSubType("txt", "data")).to.equals(true);
|
||||
expect(mapper.isSubType("txt", "txt")).to.equals(true);
|
||||
expect(mapper.isSubType("data", "txt")).to.equals(false);
|
||||
expect(mapper.isSubTypeOfAny("data", ["txt", "data"])).to.equals(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,4 +10,8 @@ export class DatatypesMapperModel {
|
||||
parent = mapping.ext_to_class_name[parent];
|
||||
return mapping.class_to_classes[child] && parent in mapping.class_to_classes[child];
|
||||
}
|
||||
|
||||
isSubTypeOfAny(child, parents) {
|
||||
return parents.some((parent) => this.isSubType(child, parent));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
</select2>
|
||||
</template>
|
||||
<template v-slot:buttons>
|
||||
<b-button ref="btnClose" class="ui-button-default" id="btn-close" @click="app.hide()">
|
||||
<b-button ref="btnClose" class="ui-button-default" id="btn-close" @click="app.dismiss()">
|
||||
{{ btnCloseTitle }}
|
||||
</b-button>
|
||||
<b-button
|
||||
@@ -139,6 +139,7 @@ export default {
|
||||
listExtensions: [],
|
||||
listGenomes: [],
|
||||
running: false,
|
||||
multiple: true, // needed for uploadbox stuff - always allow multiple uploads for collections
|
||||
counterAnnounce: 0,
|
||||
counterSuccess: 0,
|
||||
counterError: 0,
|
||||
@@ -158,7 +159,7 @@ export default {
|
||||
btnBuildTitle: _l("Build"),
|
||||
btnStopTitle: _l("Pause"),
|
||||
btnResetTitle: _l("Reset"),
|
||||
btnCloseTitle: _l("Close"),
|
||||
btnCloseTitle: this.app.callback ? _l("Cancel") : _l("Close"),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</select2>
|
||||
</template>
|
||||
<template v-slot:buttons>
|
||||
<b-button ref="btnClose" class="ui-button-default" @click="app.hide()">
|
||||
<b-button ref="btnClose" class="ui-button-default" @click="app.dismiss()">
|
||||
{{ btnCloseTitle }}
|
||||
</b-button>
|
||||
<b-button
|
||||
@@ -74,7 +74,7 @@ export default {
|
||||
showHelper: true,
|
||||
btnResetTitle: _l("Reset"),
|
||||
btnStartTitle: _l("Start"),
|
||||
btnCloseTitle: _l("Close"),
|
||||
btnCloseTitle: this.app.callback ? _l("Cancel") : _l("Close"),
|
||||
readyStart: false,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</select2>
|
||||
</template>
|
||||
<template v-slot:buttons>
|
||||
<b-button ref="btnClose" class="ui-button-default" id="btn-close" @click="app.hide()">
|
||||
<b-button ref="btnClose" class="ui-button-default" id="btn-close" @click="app.dismiss()">
|
||||
{{ btnCloseTitle }}
|
||||
</b-button>
|
||||
<b-button
|
||||
@@ -55,6 +55,16 @@
|
||||
>
|
||||
{{ btnStopTitle }}
|
||||
</b-button>
|
||||
<b-button
|
||||
ref="btnBuild"
|
||||
class="ui-button-default"
|
||||
id="btn-build"
|
||||
@click="_eventSelect"
|
||||
:disabled="!enableBuild"
|
||||
:variant="enableBuild ? 'primary' : ''"
|
||||
>
|
||||
{{ btnSelectTitle }}
|
||||
</b-button>
|
||||
<b-button
|
||||
ref="btnStart"
|
||||
class="ui-button-default"
|
||||
@@ -111,6 +121,12 @@ Vue.use(BootstrapVue);
|
||||
|
||||
export default {
|
||||
mixins: [UploadBoxMixin],
|
||||
props: {
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
topInfo: "",
|
||||
@@ -118,6 +134,7 @@ export default {
|
||||
showHelper: true,
|
||||
extension: this.app.defaultExtension,
|
||||
genome: this.app.defaultGenome,
|
||||
callback: this.app.callback,
|
||||
listExtensions: [],
|
||||
listGenomes: [],
|
||||
running: false,
|
||||
@@ -129,6 +146,7 @@ export default {
|
||||
uploadSize: 0,
|
||||
uploadCompleted: 0,
|
||||
enableReset: false,
|
||||
enableBuild: false,
|
||||
enableStart: false,
|
||||
enableSources: false,
|
||||
btnLocalTitle: _l("Choose local files"),
|
||||
@@ -136,7 +154,8 @@ export default {
|
||||
btnStartTitle: _l("Start"),
|
||||
btnStopTitle: _l("Pause"),
|
||||
btnResetTitle: _l("Reset"),
|
||||
btnCloseTitle: _l("Close"),
|
||||
btnCloseTitle: this.app.callback ? _l("Cancel") : _l("Close"),
|
||||
btnSelectTitle: _l("Select"),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
@@ -149,6 +168,7 @@ export default {
|
||||
// file upload
|
||||
this.initUploadbox({
|
||||
url: this.app.uploadPath,
|
||||
multiple: this.multiple,
|
||||
announce: (index, file) => {
|
||||
this._eventAnnounce(index, file);
|
||||
},
|
||||
@@ -200,6 +220,17 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
_eventSelect: function () {
|
||||
const models = this.getUploadedModels();
|
||||
const asDict = models.map((model) => {
|
||||
return {
|
||||
id: model.attributes.id, // model.id has datatype prefix
|
||||
src: model.src,
|
||||
};
|
||||
});
|
||||
this.callback(asDict);
|
||||
this.app.cancel();
|
||||
},
|
||||
_newUploadModelProps: function (index, file) {
|
||||
return {
|
||||
id: index,
|
||||
@@ -213,8 +244,9 @@ export default {
|
||||
|
||||
/** Success */
|
||||
_eventSuccess: function (index, message) {
|
||||
var hids = _.pluck(message["outputs"], "hid");
|
||||
var it = this.collection.get(index);
|
||||
it.set({ percentage: 100, status: "success" });
|
||||
it.set({ percentage: 100, status: "success", hids: hids });
|
||||
this._updateStateForSuccess(it);
|
||||
},
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
></textarea>
|
||||
</span>
|
||||
<template v-slot:buttons>
|
||||
<b-button ref="btnClose" class="ui-button-default" id="btn-close" @click="app.hide()">
|
||||
<b-button ref="btnClose" class="ui-button-default" id="btn-close" @click="app.dismiss()">
|
||||
{{ btnCloseTitle }}
|
||||
</b-button>
|
||||
<b-button
|
||||
@@ -103,7 +103,7 @@ export default {
|
||||
selectionType: "paste",
|
||||
btnBuildTitle: _l("Build"),
|
||||
btnResetTitle: _l("Reset"),
|
||||
btnCloseTitle: _l("Close"),
|
||||
btnCloseTitle: this.app.callback ? _l("Cancel") : _l("Close"),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
||||
@@ -102,15 +102,15 @@ export default {
|
||||
},
|
||||
_updateStateForCounters: function () {
|
||||
this.setTopInfoBasedOnCounters();
|
||||
this.enableReset =
|
||||
this.counterRunning == 0 && this.counterAnnounce + this.counterSuccess + this.counterError > 0;
|
||||
const counterNonRunning = this.counterAnnounce + this.counterSuccess + this.counterError;
|
||||
this.enableReset = this.counterRunning == 0 && counterNonRunning > 0;
|
||||
this.enableStart = this.counterRunning == 0 && this.counterAnnounce > 0;
|
||||
this.enableBuild =
|
||||
this.counterRunning == 0 &&
|
||||
this.counterAnnounce == 0 &&
|
||||
this.counterSuccess > 0 &&
|
||||
this.counterError == 0;
|
||||
this.enableSources = this.counterRunning == 0;
|
||||
this.enableSources = this.counterRunning == 0 && (this.multiple || counterNonRunning == 0);
|
||||
var show_table = this.counterAnnounce + this.counterSuccess + this.counterError > 0;
|
||||
this.showHelper = !show_table;
|
||||
},
|
||||
@@ -259,7 +259,7 @@ export default {
|
||||
return $(this.$refs.uploadTable);
|
||||
},
|
||||
extensionDetails(extension) {
|
||||
return findExtension(this.listExtensions, extension);
|
||||
return findExtension(this.effectiveExtensions, extension);
|
||||
},
|
||||
initExtensionInfo() {
|
||||
$(this.$refs.footerExtensionInfo)
|
||||
@@ -283,7 +283,7 @@ export default {
|
||||
this.collection = new UploadModel.Collection();
|
||||
},
|
||||
initAppProperties() {
|
||||
this.listExtensions = this.app.listExtensions;
|
||||
this.listExtensions = this.app.effectiveExtensions;
|
||||
this.listGenomes = this.app.listGenomes;
|
||||
this.ftpUploadSite = this.app.currentFtp();
|
||||
this.fileSourcesConfigured = this.app.fileSourcesConfigured;
|
||||
|
||||
@@ -6,23 +6,25 @@
|
||||
modal-class="ui-modal"
|
||||
dialog-class="upload-dialog"
|
||||
body-class="upload-dialog-body"
|
||||
ref="modal"
|
||||
no-enforce-focus
|
||||
hide-footer
|
||||
:id="id"
|
||||
>
|
||||
<template v-slot:modal-header>
|
||||
<h4 class="title" tabindex="0">{{ title }}</h4>
|
||||
</template>
|
||||
<b-tabs v-if="ready">
|
||||
<b-tab title="Regular" id="regular" button-id="tab-title-link-regular">
|
||||
<default :app="this" :lazy-load-max="50" />
|
||||
<b-tab title="Regular" id="regular" button-id="tab-title-link-regular" v-if="showRegular">
|
||||
<default :app="this" :lazy-load-max="50" :multiple="multiple" />
|
||||
</b-tab>
|
||||
<b-tab title="Composite" id="composite" button-id="tab-title-link-composite">
|
||||
<b-tab title="Composite" id="composite" button-id="tab-title-link-composite" v-if="showComposite">
|
||||
<composite :app="this" />
|
||||
</b-tab>
|
||||
<b-tab title="Collection" id="collection" button-id="tab-title-link-collection">
|
||||
<b-tab title="Collection" id="collection" button-id="tab-title-link-collection" v-if="showCollection">
|
||||
<collection :app="this" />
|
||||
</b-tab>
|
||||
<b-tab title="Rule-based" id="rule-based" button-id="tab-title-link-rule-based">
|
||||
<b-tab title="Rule-based" id="rule-based" button-id="tab-title-link-rule-based" v-if="showRules">
|
||||
<rules-input :app="this" />
|
||||
</b-tab>
|
||||
</b-tabs>
|
||||
@@ -40,6 +42,7 @@ import Vue from "vue";
|
||||
import BootstrapVue from "bootstrap-vue";
|
||||
import { getGalaxyInstance } from "app";
|
||||
import UploadUtils from "mvc/upload/upload-utils";
|
||||
import { getDatatypesMapper } from "components/Datatypes";
|
||||
import Composite from "./Composite";
|
||||
import Collection from "./Collection";
|
||||
import Default from "./Default";
|
||||
@@ -93,6 +96,20 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
formats: {
|
||||
type: Array,
|
||||
default: null,
|
||||
},
|
||||
multiple: {
|
||||
// Restrict the forms to a single dataset upload if false
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
callback: {
|
||||
// Return uploads when done if supplied.
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
auto: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
@@ -102,6 +119,7 @@ export default {
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
id: "",
|
||||
title: _l("Download from web or upload from disk"),
|
||||
historyAvailable: false,
|
||||
currentUser: null,
|
||||
@@ -109,6 +127,8 @@ export default {
|
||||
listExtensions: [],
|
||||
genomesSet: false,
|
||||
extensionsSet: false,
|
||||
datatypesMapper: null,
|
||||
datatypesMapperReady: true,
|
||||
};
|
||||
},
|
||||
created: function () {
|
||||
@@ -138,11 +158,67 @@ export default {
|
||||
}, this.defaultGenome);
|
||||
|
||||
this.initStateWhenHistoryReady();
|
||||
if (this.formats !== null) {
|
||||
this.datatypesMapperReady = false;
|
||||
getDatatypesMapper().then((datatypesMapper) => {
|
||||
this.datatypesMapper = datatypesMapper;
|
||||
this.datatypesMapperReady = true;
|
||||
});
|
||||
} else {
|
||||
this.datatypesMapperReady = true;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
ready() {
|
||||
return this.genomesSet && this.extensionsSet && this.historyAvailable;
|
||||
return this.genomesSet && this.extensionsSet && this.historyAvailable && this.datatypesMapperReady;
|
||||
},
|
||||
unrestricted() {
|
||||
return this.formats === null && this.multiple;
|
||||
},
|
||||
effectiveExtensions() {
|
||||
if (this.formats === null || !this.datatypesMapperReady) {
|
||||
return this.listExtensions;
|
||||
}
|
||||
const effectiveExtensions = [];
|
||||
this.listExtensions.forEach((extension) => {
|
||||
if (extension && extension.id == "auto") {
|
||||
effectiveExtensions.push(extension);
|
||||
} else if (this.datatypesMapper.isSubTypeOfAny(extension.id, this.formats)) {
|
||||
effectiveExtensions.push(extension);
|
||||
}
|
||||
});
|
||||
return effectiveExtensions;
|
||||
},
|
||||
formatRestricted() {
|
||||
return this.formats !== null;
|
||||
},
|
||||
showComposite() {
|
||||
if (!this.formatRestricted) {
|
||||
return true;
|
||||
}
|
||||
return this.effectiveExtensions.some((extension) => !!extension.composite_files);
|
||||
},
|
||||
showRegular() {
|
||||
if (!this.formatRestricted) {
|
||||
return true;
|
||||
}
|
||||
return this.effectiveExtensions.some((extension) => !extension.composite_files);
|
||||
},
|
||||
showCollection() {
|
||||
if (this.unrestricted) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
showRules() {
|
||||
if (this.unrestricted) {
|
||||
return true;
|
||||
}
|
||||
return this.multiple;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.id = String(this._uid);
|
||||
},
|
||||
methods: {
|
||||
show() {
|
||||
@@ -152,6 +228,21 @@ export default {
|
||||
hide() {
|
||||
this.modalShow = false;
|
||||
},
|
||||
cancel() {
|
||||
this.hide();
|
||||
this.$nextTick(() => {
|
||||
this.$bvModal.hide(this.id, "cancel");
|
||||
this.$destroy();
|
||||
});
|
||||
},
|
||||
dismiss() {
|
||||
// hide or cancel based on whether this is a singleton
|
||||
if (this.callback) {
|
||||
this.cancel();
|
||||
} else {
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
initStateWhenHistoryReady() {
|
||||
const Galaxy = getGalaxyInstance();
|
||||
if (!Galaxy.currHistoryPanel || !Galaxy.currHistoryPanel.model) {
|
||||
@@ -245,12 +336,4 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.upload-dialog {
|
||||
width: 900px;
|
||||
}
|
||||
.upload-dialog-body {
|
||||
height: 500px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
<style></style>
|
||||
|
||||
@@ -4,3 +4,5 @@
|
||||
export { default as UploadModal } from "./UploadModal";
|
||||
|
||||
export { initializeUploadDefaults } from "./config";
|
||||
|
||||
export { mount as mountUploadModal } from "./mount";
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import Vue from "vue";
|
||||
import UploadModal from "./UploadModal";
|
||||
import { initializeUploadDefaults } from "./config";
|
||||
|
||||
export function mount(propsData = {}) {
|
||||
propsData = initializeUploadDefaults(propsData);
|
||||
const instance = Vue.extend(UploadModal);
|
||||
const vm = document.createElement("div");
|
||||
document.getElementsByTagName("body")[0].appendChild(vm);
|
||||
new instance({
|
||||
propsData: propsData,
|
||||
}).$mount(vm);
|
||||
}
|
||||
@@ -10,7 +10,7 @@ export function mountWithApp(component, options = {}, propsData_ = {}) {
|
||||
return "ftp://localhost";
|
||||
},
|
||||
model: new Backbone.Model(),
|
||||
listExtensions: [
|
||||
effectiveExtensions: [
|
||||
{ id: "ab1", text: "ab1", description: "A binary sequence file in 'ab1' format with a '.ab1'" },
|
||||
{
|
||||
id: "affybatch",
|
||||
|
||||
@@ -272,8 +272,10 @@ const View = Backbone.View.extend({
|
||||
});
|
||||
if (cnf.src == "hda") {
|
||||
this.button_dialog.show();
|
||||
this.upload_dialog.show();
|
||||
} else {
|
||||
this.button_dialog.hide();
|
||||
this.upload_dialog.hide();
|
||||
}
|
||||
this.button_type.value(i);
|
||||
} else {
|
||||
@@ -306,7 +308,8 @@ const View = Backbone.View.extend({
|
||||
|
||||
// prepare extension component of error message
|
||||
const data = self.model.get("data");
|
||||
const extensions = Utils.textify(this.model.get("extensions"));
|
||||
const formats = this.model.get("extensions");
|
||||
const extensions = Utils.textify(formats);
|
||||
const src_labels = this.model.get("src_labels");
|
||||
|
||||
// build radio button for data selectors
|
||||
@@ -362,14 +365,38 @@ const View = Backbone.View.extend({
|
||||
},
|
||||
});
|
||||
|
||||
// build data dialog button
|
||||
this.upload_dialog = new Ui.Button({
|
||||
icon: "fa-upload",
|
||||
tooltip: "Upload Dataset",
|
||||
onclick: () => {
|
||||
const current = this.model.get("current");
|
||||
const cnf = this.config[current];
|
||||
// model doesn't have format yet unfortunately, need to get through to here.
|
||||
galaxy.data.dialog(
|
||||
(response) => {
|
||||
this._handleDropValues(response, false);
|
||||
},
|
||||
{
|
||||
multiple: cnf.multiple,
|
||||
formats: formats,
|
||||
new: true,
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// append views
|
||||
const $fields = $("<div/>").addClass("overflow-auto w-100 py-2 py-lg-0 pr-lg-2 ");
|
||||
this.$el
|
||||
.empty()
|
||||
.addClass("d-flex flex-row flex-wrap flex-lg-nowrap")
|
||||
.append($("<div/>").append(this.button_type.$el))
|
||||
.append($fields)
|
||||
.append($("<div/>").append(this.button_dialog.$el));
|
||||
.append($fields);
|
||||
if (galaxy.config.enable_upload_from_form_button) {
|
||||
this.$el.append($("<div style='margin-right: 5px;' />").append(this.upload_dialog.$el));
|
||||
}
|
||||
this.$el.append($("<div/>").append(this.button_dialog.$el));
|
||||
_.each(this.fields, (field) => {
|
||||
$fields.append(field.$el);
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import DataDialog from "components/DataDialog/DataDialog.vue";
|
||||
import { FilesDialog } from "components/FilesDialog";
|
||||
import WorkflowDialog from "components/SelectionDialog/WorkflowDialog.vue";
|
||||
import DatasetCollectionDialog from "components/SelectionDialog/DatasetCollectionDialog.vue";
|
||||
import { mountUploadModal } from "components/Upload";
|
||||
import { getGalaxyInstance } from "app";
|
||||
import { getAppRoot } from "onload/loadConfig";
|
||||
|
||||
@@ -44,7 +45,12 @@ export function dialog(callback, options = {}) {
|
||||
root: galaxy.root,
|
||||
host: host,
|
||||
});
|
||||
_mountSelectionDialog(DataDialog, options);
|
||||
if (options.new) {
|
||||
options.modalShow = true;
|
||||
mountUploadModal(options);
|
||||
} else {
|
||||
_mountSelectionDialog(DataDialog, options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -300,6 +300,7 @@ import { getAppRoot } from "onload/loadConfig";
|
||||
alert(m);
|
||||
},
|
||||
complete: () => {},
|
||||
multiple: true,
|
||||
},
|
||||
options
|
||||
);
|
||||
@@ -320,7 +321,7 @@ import { getAppRoot } from "onload/loadConfig";
|
||||
|
||||
// element
|
||||
var uploadinput = $(this).uploadinput({
|
||||
multiple: true,
|
||||
multiple: opts.multiple,
|
||||
onchange: (files) => {
|
||||
_.each(files, (file) => {
|
||||
file.chunk_mode = true;
|
||||
|
||||
@@ -316,6 +316,15 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.upload-dialog {
|
||||
width: 900px;
|
||||
}
|
||||
|
||||
.upload-dialog-body {
|
||||
height: 500px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// ==== Masthead ====
|
||||
#masthead {
|
||||
@extend .p-0;
|
||||
|
||||
@@ -105,6 +105,7 @@ class ConfigSerializer(base.ModelSerializer):
|
||||
'python' : _defaults_to((sys.version_info.major, sys.version_info.minor)),
|
||||
'select_type_workflow_threshold' : _use_config,
|
||||
'file_sources_configured' : lambda config, key, **context: self.app.file_sources.custom_sources_configured,
|
||||
'enable_upload_from_form_button' : _use_config,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2158,6 +2158,15 @@ mapping:
|
||||
When using LDAP for authentication, allow administrators to pre-populate users
|
||||
using an additional form on 'Create new user'
|
||||
|
||||
enable_upload_from_form_button:
|
||||
type: bool
|
||||
default: false
|
||||
required: false
|
||||
desc: |
|
||||
If enabled, add another button to tool form data inputs that allow uploading
|
||||
data from the tool form in fewer clicks (at the expense of making the form more
|
||||
complicated).
|
||||
|
||||
allow_user_dataset_purge:
|
||||
type: bool
|
||||
default: true
|
||||
|
||||
Reference in New Issue
Block a user