Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow rule based operations on existing collections. #5819

Merged
merged 9 commits into from
Apr 25, 2018
320 changes: 212 additions & 108 deletions client/galaxy/scripts/components/RuleCollectionBuilder.vue

Large diffs are not rendered by default.

119 changes: 119 additions & 0 deletions client/galaxy/scripts/components/RulesDisplay.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<template>
<div>
<ol class="rules">
<rule-display-preview
v-for="(rule, index) in rules"
v-bind:rule="rule"
v-bind:index="index"
v-bind:key="index"
:col-headers="columnData.colHeadersPerRule[index]" />
<identifier-display-preview v-for="(map, index) in mapping"
v-bind="map"
v-bind:index="index"
v-bind:key="map.type"
:col-headers="colHeaders" />
</ol>
</div>
</template>
<script>
import RuleDefs from "mvc/rules/rule-definitions";
import _l from "utils/localization";

// read-only variants of the components for displaying these rules and mappings in builder widget.
const RuleDisplayPreview = {
template: `
<li class="rule">
<span class="rule-display">{{ title }}
</span>
<span class="rule-warning" v-if="rule.warn">
{{ rule.warn }}
</span>
<span class="rule-error" v-if="rule.error">
<span class="alert-message">{{ rule.error }}</span>
</span>
</li>
`,
props: {
rule: {
required: true,
type: Object
},
colHeaders: {
type: Array,
required: false
}
},
computed: {
title() {
const ruleType = this.rule.type;
return RuleDefs.RULES[ruleType].display(this.rule, this.colHeaders);
}
},
methods: {}
};

const IdentifierDisplayPreview = {
template: `
<li class="rule" :title="help">
Set {{ columnsLabel }} as {{ typeDisplay }}
</li>
`,
props: {
type: {
type: String,
required: true
},
columns: {
required: true
},
colHeaders: {
type: Array,
required: true
}
},
computed: {
typeDisplay() {
return RuleDefs.MAPPING_TARGETS[this.type].label;
},
help() {
return RuleDefs.MAPPING_TARGETS[this.type].help || "";
},
columnsLabel() {
return RuleDefs.columnDisplay(this.columns, this.colHeaders);
}
}
};

export default {
data: function() {
return {};
},
computed: {
mapping: function() {
return this.inputRules ? this.inputRules.mapping : [];
},
rules: function() {
return this.inputRules ? this.inputRules.rules : [];
},
columnData: function() {
const colHeadersPerRule = [];
const hotData = RuleDefs.applyRules([], [], [], this.rules, colHeadersPerRule);
return { colHeadersPerRule: colHeadersPerRule, columns: hotData.columns };
},
colHeaders: function() {
const columns = this.columnData.columns;
return RuleDefs.colHeadersFor([], columns);
}
},
props: {
inputRules: {
required: false,
type: Object
}
},
components: {
RuleDisplayPreview,
IdentifierDisplayPreview
}
};
</script>
47 changes: 16 additions & 31 deletions client/galaxy/scripts/mocha/tests/rules_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,44 +11,29 @@ function applyRules(rules, data, sources) {
columns.push("new");
}
}
for (var ruleIndex in rules) {
const rule = rules[ruleIndex];
rule.error = null;
rule.warn = null;

var ruleType = rule.type;
const ruleDef = RULES[ruleType];
const res = ruleDef.apply(rule, data, sources, columns);
if (res.error) {
throw res.error;
} else {
if (res.warn) {
rule.warn = res.warn;
}
data = res.data || data;
sources = res.sources || sources;
columns = res.columns || columns;
}
}
return { data, sources, columns };
return RuleDefs.applyRules(data, sources, columns, rules);
}

function itShouldConform(specTestCase, i) {
it("should pass conformance test case " + i, function() {
chai.assert.property(specTestCase, "rules");
chai.assert.property(specTestCase, "initial");
chai.assert.property(specTestCase, "final");
if (specTestCase.initial) {
chai.assert.property(specTestCase, "final");

const rules = specTestCase.rules;
const initial = specTestCase.initial;
const expectedFinal = specTestCase.final;
const rules = specTestCase.rules;
const initial = specTestCase.initial;
const expectedFinal = specTestCase.final;

const final = applyRules(rules, initial.data, initial.sources);
const finalData = final.data;
const finalSources = final.sources;
chai.assert.deepEqual(finalData, expectedFinal.data);
if (expectedFinal.sources !== undefined) {
chai.assert.deepEqual(finalSources, expectedFinal.sources);
const final = applyRules(rules, initial.data, initial.sources);
const finalData = final.data;
const finalSources = final.sources;
chai.assert.deepEqual(finalData, expectedFinal.data);
if (expectedFinal.sources !== undefined) {
chai.assert.deepEqual(finalSources, expectedFinal.sources);
}
} else {
chai.assert(specTestCase.error);
// TODO: test these...
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,8 @@ var ruleBasedCollectionCreatorModal = function _ruleBasedCollectionCreatorModal(
let title;
if (importType == "datasets") {
title = _l("Build Rules for Uploading Datasets");
} else if (elementsType == "collection_contents") {
title = _l("Build Rules for Applying to Existing Collection");
} else if (elementsType == "datasets" || elementsType == "library_datasets") {
title = _l("Build Rules for Creating Collection(s)");
} else {
Expand All @@ -1090,7 +1092,9 @@ var ruleBasedCollectionCreatorModal = function _ruleBasedCollectionCreatorModal(
creationFn: options.creationFn,
oncancel: options.oncancel,
oncreate: options.oncreate,
defaultHideSourceItems: options.defaultHideSourceItems
defaultHideSourceItems: options.defaultHideSourceItems,
saveRulesFn: options.saveRulesFn,
initialRules: options.initialRules
}
}).$mount(vm);
return deferred;
Expand Down Expand Up @@ -1128,7 +1132,8 @@ function createListCollection(contents, defaultHideSourceItems) {

function createCollectionViaRules(selection, defaultHideSourceItems) {
let elements, elementsType, importType;
if (!selection.selectionType) {
const selectionType = selection.selectionType;
if (!selectionType) {
// Have HDAs from the history panel.
elements = selection.toJSON();
elementsType = "datasets";
Expand Down
13 changes: 11 additions & 2 deletions client/galaxy/scripts/mvc/form/form-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,13 @@ export default Backbone.View.extend({
// render visibility
this.$el[this.model.get("hidden") ? "hide" : "show"]();
// render preview view for collapsed fields
// allow at least newlines to render properly after escape
const html = _.escape(this.model.get("text_value")).replace(/\n/g, "<br />");
this.$preview[
(this.field.collapsed && this.model.get("collapsible_preview")) || this.model.get("disabled")
? "show"
: "hide"
]().html(_.escape(this.model.get("text_value")));
]().html(html);
// render error messages
var error_text = this.model.get("error_text");
this.$error[error_text ? "show" : "hide"]();
Expand All @@ -106,7 +108,14 @@ export default Backbone.View.extend({
style: this.model.get("style")
});
// render collapsible options
if (!this.model.get("disabled") && this.model.get("collapsible_value") !== undefined) {
const workflowRuntimeCompatible =
this.field.workflowRuntimeCompatible === undefined ? true : this.field.workflowRuntimeCompatible;
if (
workflowRuntimeCompatible &&
!this.model.get("disabled") &&
this.model.get("collapsible_value") !== undefined
) {
console.log(this.field);
var collapsible_state = this.field.collapsed ? "enable" : "disable";
this.$title_text.hide();
this.$collapsible.show();
Expand Down
11 changes: 10 additions & 1 deletion client/galaxy/scripts/mvc/form/form-parameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import SelectContent from "mvc/ui/ui-select-content";
import SelectLibrary from "mvc/ui/ui-select-library";
import SelectFtp from "mvc/ui/ui-select-ftp";
import SelectGenomeSpace from "mvc/ui/ui-select-genomespace";
import RulesEdit from "mvc/ui/ui-rules-edit";
import ColorPicker from "mvc/ui/ui-color-picker";
// create form view
export default Backbone.Model.extend({
Expand All @@ -30,6 +31,7 @@ export default Backbone.Model.extend({
library_data: "_fieldLibrary",
ftpfile: "_fieldFtp",
upload: "_fieldUpload",
rules: "_fieldRulesEdit",
genomespacefile: "_fieldGenomeSpace"
},

Expand Down Expand Up @@ -215,13 +217,20 @@ export default Backbone.Model.extend({
/** GenomeSpace file select field
*/
_fieldGenomeSpace: function(input_def) {
var self = this;
return new SelectGenomeSpace.View({
id: `field-${input_def.id}`,
onchange: input_def.onchange
});
},

_fieldRulesEdit: function(input_def) {
return new RulesEdit.View({
id: `field-${input_def.id}`,
onchange: input_def.onchange,
target: input_def.target
});
},

/** Upload file field */
_fieldUpload: function(input_def) {
return new Ui.Upload({
Expand Down
5 changes: 4 additions & 1 deletion client/galaxy/scripts/mvc/form/form-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ export default Backbone.View.extend({
var self = this;
this.data.matchModel(new_model, (node, input_id) => {
var input = self.input_list[input_id];
var field = self.field_list[input_id];
if (field.refreshDefinition) {
field.refreshDefinition(node);
}
if (input && input.options) {
if (!_.isEqual(input.options, node.options)) {
input.options = node.options;
var field = self.field_list[input_id];
if (field.update) {
var new_options = [];
if (["data", "data_collection", "drill_down"].indexOf(input.type) != -1) {
Expand Down
Loading