Commit 686ef575 authored by Floreal Cabanettes's avatar Floreal Cabanettes
Browse files

Improve test rules from web interface + add validate function on workflow

parent ed53cc2e
......@@ -72,6 +72,8 @@ def parse_parameters_rules(wf_instance):
# Check rules:
try:
wf_instance.check_parameters_rules(user_params)
wf_instance.set_parameters(user_params)
wf_instance.validate()
except Exception as e:
arg_sub_parser.error(e)
......
......@@ -61,9 +61,6 @@ class ConditionalRule(SimpleRule):
SimpleRule.__init__(self, user_args, wf_instance, src_arg, all_files)
self.conditions = conditions
# Check parameter is correct:
self.check_type_argument()
# Test condition is raised:
self.condition_raised = False
all_raised = True
......@@ -96,13 +93,6 @@ class ConditionalRule(SimpleRule):
if which == "ALL" and all_raised:
self.condition_raised = True
def check_type_argument(self):
if isinstance(self.wf_parameter, InputFile) or isinstance(self.wf_parameter, InputFileList) or \
isinstance(self.wf_parameter, InputDirectory) or isinstance(self.wf_parameter, MultiParameter) or \
isinstance(self.wf_parameter, MultiParameterList):
raise Exception("Rule " + str(self.__class__.__name__) + " (ConditionalRule) is not available on files "
"and directories parameters or multiple parameters")
@abstractmethod
def check(self):
pass
......
......@@ -350,14 +350,60 @@ class JFlowServer (object):
workflow = self.wfmanager.run_workflow(kwargs_modified["workflow_class"], kwargs_modified)
try:
workflow.check_parameters_rules(kwargs_modified)
except Exception as e:
return {"status": 2, "content": str(e)}
return { "status" : 0, "content" : self.jsonify_workflow_status(workflow, True) }
except Exception as err:
return { "status" : 1, "content" : str(err) }
@cherrypy.expose
@jsonify
def validate_workflow(self, **kwargs):
kwargs_modified = {}
# handle MultiParameterList
multi_sub_params = {}
for key in list(kwargs.keys()):
parts = key.split(JFlowServer.MULTIPLE_TYPE_SPLITER)
if len(parts) == 3:
if not parts[0] in kwargs_modified:
kwargs_modified[parts[0]] = []
multi_sub_params[parts[0]] = {}
if parts[2] in multi_sub_params[parts[0]]:
multi_sub_params[parts[0]][parts[2]].append((parts[1], kwargs[key]))
else:
multi_sub_params[parts[0]][parts[2]] = [(parts[1], kwargs[key])]
for key in list(kwargs.keys()):
parts = key.split(JFlowServer.MULTIPLE_TYPE_SPLITER)
# split append values
new_values = kwargs[key].split(JFlowServer.APPEND_PARAM_SPLITER)
if len(new_values) == 1:
new_values = new_values[0]
# if this is a classic Parameter
if len(parts) == 1:
kwargs_modified[key] = new_values
# if this is a MultiParameter
elif len(parts) == 2:
if parts[0] in kwargs_modified:
kwargs_modified[parts[0]].append((parts[1], new_values))
else:
kwargs_modified[parts[0]] = [(parts[1], new_values)]
# handle MultiParameterList
for param in multi_sub_params:
kwargs_modified[param] = []
for sub_param in multi_sub_params[param]:
kwargs_modified[param].append(multi_sub_params[param][sub_param])
workflow = self.wfmanager.get_workflow_by_class(kwargs_modified["workflow_class"])
workflow.set_parameters(kwargs_modified)
try:
workflow.check_parameters_rules(kwargs_modified)
workflow.validate()
except Exception as e:
return {"status": 1, "content": str(e)}
return {"status": 0}
@cherrypy.expose
@jsonify
def delete_workflow(self, **kwargs):
......
......@@ -328,7 +328,7 @@ class Workflow(threading.Thread):
raise Exception( "Unknown class '" + parameter.__class__.__name__ + "' for parameter.")
return new_param
def _set_parameters(self, args):
def set_parameters(self, args):
parameters = self.get_parameters()
for param in parameters:
new_param = None
......@@ -871,7 +871,7 @@ class Workflow(threading.Thread):
self._postprocess_status = self.STATUS_PENDING
self.end_time = None
# if some args are provided, let's fill the parameters
self._set_parameters(self.args)
self.set_parameters(self.args)
self._serialize()
# if pre_processing has not been done yet
if self.__step == 0:
......@@ -1237,7 +1237,6 @@ class Workflow(threading.Thread):
rules = {}
all_files = [] # Store all given files, used later
parameters_used = {} # Parameters given by the user
print(user_params)
for parameter in parameters:
# Get sub-parameters of MultiParameter or MultiParameterLists:
if isinstance(parameter, MultiParameterList) or isinstance(parameter, MultiParameter):
......@@ -1267,9 +1266,9 @@ class Workflow(threading.Thread):
parameters_used[parameter.name] = user_params[parameter.name] if parameter.name in user_params else None
if parameter.rules is not None:
rules[parameter.name] = parameter.rules.split(";")
if isinstance(parameter, InputFile):
if isinstance(parameter, InputFile) and parameter.name in user_params:
all_files.append(user_params[parameter.name])
elif isinstance(parameter, InputFileList):
elif isinstance(parameter, InputFileList) and parameter.name in user_params:
all_files += user_params[parameter.name]
# Check rules:
......@@ -1319,7 +1318,6 @@ class Workflow(threading.Thread):
# Launch validator:
if issubclass(validator_class, j_rules.ConditionalRule): # Check the rule is the same special rule
print(validator_class)
validator = validator_class(user_args, self, src_arg, conditions, which, all_files)
validator.check()
else:
......@@ -1363,3 +1361,5 @@ class Workflow(threading.Thread):
else:
raise Exception("Rule is not a simple rule: " + name)
def validate(self):
pass
......@@ -414,37 +414,6 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
var params = "",
hash_param = {};
// before serializing, all inputs have to be abled, otherwise they are not transmitted
$("[id^=urlfile_btn_]").each(function(){
var parts = $(this).attr("id").split("_"),
tid = parts.slice(2, parts.lenght).join("_");
// do this only if it is a browsefile ... if the field is on readonly
if ($("#"+tid).hasClass('to-readonly')) {
// change the name of the val by the file name with the uniq folder
if ($("#"+tid).val()) {
// if a multiple string, this is a textarea, split by lines
if ($("#"+tid).hasClass("list")) {
var allfiles = $("#"+tid).val().split(/\n/),
newtidval = "";
for (var j = 0; j < allfiles.length; j++) {
newtidval += $this.uploadfiles[tid] + "/" + allfiles[j];
newtidval.replace(/C:\\fakepath\\/i,'').replace(/C:\\fake_path\\/i,'');
newtidval += "::-::";
}
newtidval = newtidval.substring(0, newtidval.length-5);
$("#"+tid).val( newtidval );
// remove list class so it is not a problem with the serialization step
$("#"+tid).removeClass("list");
} else {
$("#"+tid).val( $this.uploadfiles[tid] + "/" + $("#"+tid).val() );
// delete prefix used for security in IE, Chrome and Opera
$("#"+tid).val( $("#"+tid).val().replace(/C:\\fakepath\\/i,'').replace(/C:\\fake_path\\/i,'') );
}
}
}
});
// when serializing, multiple data are repeated, so build a hash to gather values from the same parameter
$.each ( $('#workflow_form').serializeArray(), function(_, kv) {
if ($('#'+kv.name).length == 0 || ($('#'+kv.name).is(":enabled")
&& !$('#'+kv.name).hasClass("hidden-exclude"))) { // not exists or not disabled
......@@ -504,92 +473,123 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
}
}
});
$this.$element.off("uploaded.wfform").on("uploaded.wfform", function() {
$.ajax({
url: $this.options.serverURL + '/run_workflow?' + params + 'callback=?',
dataType: "json",
success: function(data) {
// Ajax success
if( data["status"] == 0 ) {
$this.$element.trigger('run.wfform', data["content"]);
} else if(data["status"] == 2) {
//alert(data["content"]);
var alert_message = ['<div class="alert alert-danger error-wf" role="alert">',
'<strong>Error!</strong>',
data["content"],
'</div>'].join('\n');
$this.$element.prepend(alert_message);
$("#progress").html("");
$("#workflow_form").show();
$("#setAndRunModal").animate({ scrollTop: 0 }, "slow");
$("#run_workflow").closest(".modal-footer").show();
//Reset local input files:
$(".input-group").each(function() {
var input_id = $(this).find("input").attr("id")
if ($("#inputfile_" + input_id).html() == "local file") {
$("#" + input_id).val("");
}
})
// Ajax error
} else {
var alert_message = ['<div class="alert alert-danger" role="alert">',
'<strong>Error!</strong>',
'Jflow failed to connect to the specified server <strong>' + $this.options.serverURL + '</strong>',
'</div>'].join('\n');
$this.$element.html(alert_message);
}
}
});
});
$this.$element.trigger('uploading.wfform');
$("#run_workflow,#reset_workflow").prop("disabled", true);
$.ajax({
url: $this.options.serverURL + '/validate_workflow?' + params,
dataType: "json",
success: function (data) {
$("#run_workflow,#reset_workflow").prop("disabled", false);
if (data["status"] == 0) {
$this.$element.trigger('validated.wfform');
}
else {
var alert_message = ['<div class="alert alert-danger error-wf" role="alert">',
'<strong>Error!</strong>',
data["content"],
'</div>'].join('\n');
$this.$element.prepend(alert_message);
$("#setAndRunModal").animate({scrollTop: 0}, "slow");
}
}
});
$this.$element.off("validated.wfform").on("validated.wfform", function() {
$this.$element.off("uploaded.wfform").on("uploaded.wfform", function () {
$.ajax({
url: $this.options.serverURL + '/run_workflow?' + params + 'callback=?',
dataType: "json",
success: function (data) {
// Ajax success
if (data["status"] == 0) {
$this.$element.trigger('run.wfform', data["content"]);
} else {
var alert_message = ['<div class="alert alert-danger" role="alert">',
'<strong>Error!</strong>',
'Jflow failed to connect to the specified server <strong>' + $this.options.serverURL + '</strong>',
'</div>'].join('\n');
$this.$element.html(alert_message);
}
}
});
});
var nbdata2submit = 0;
// submit the data of each fileupload
$(".fileupload").each(function () {
var tid = $(this).attr("id").split("_"),
iid = tid.slice(1, tid.length).join("_");
if ($("#" + iid).data("data2upload")) {
$("#" + iid).data("data2upload").submit();
nbdata2submit += 1;
}
});
// before serializing, all inputs have to be abled, otherwise they are not transmitted
$("[id^=urlfile_btn_]").each(function(){
var parts = $(this).attr("id").split("_"),
tid = parts.slice(2, parts.lenght).join("_");
// do this only if it is a browsefile ... if the field is on readonly
if ($("#"+tid).hasClass('to-readonly')) {
// change the name of the val by the file name with the uniq folder
if ($("#"+tid).val()) {
// if a multiple string, this is a textarea, split by lines
if ($("#"+tid).hasClass("list")) {
var allfiles = $("#"+tid).val().split(/\n/),
newtidval = "";
for (var j = 0; j < allfiles.length; j++) {
newtidval += $this.uploadfiles[tid] + "/" + allfiles[j];
newtidval.replace(/C:\\fakepath\\/i,'').replace(/C:\\fake_path\\/i,'');
newtidval += "::-::";
}
newtidval = newtidval.substring(0, newtidval.length-5);
$("#"+tid).val( newtidval );
// remove list class so it is not a problem with the serialization step
$("#"+tid).removeClass("list");
} else {
$("#"+tid).val( $this.uploadfiles[tid] + "/" + $("#"+tid).val() );
// delete prefix used for security in IE, Chrome and Opera
$("#"+tid).val( $("#"+tid).val().replace(/C:\\fakepath\\/i,'').replace(/C:\\fake_path\\/i,'') );
}
}
}
});
console.log(nbdata2submit)
if (nbdata2submit > 0) {
if ($this.options.forceIframeTransport) {
// execute _uploadProgressIframe to init the display
_uploadProgressIframe($this, true);
// then loop to follow the file upload
timeriframe = setInterval(function () {
_uploadProgressIframe($this, false)
}, $this.options.timer);
} else {
var upload_file_status = new Array();
$(".fileupload").each(function () {
var tid = $(this).attr("id").split("_"),
iid = tid.slice(1, tid.length).join("_");
upload_file_status.push({
param: iid.split("_").join(" "),
param_id: iid,
loaded: 0,
total: 100
});
});
$("#workflow_form").hide();
$("#progress").html("");
$.tmpl($this.options.progressTemplate, {upload_file_status: upload_file_status}).appendTo($("#progress"));
// loop to follow the file upload
timerclassic = setInterval(function () {
_uploadProgressClassic($this, nbdata2submit)
}, $this.options.timer);
}
} else {
$this.$element.trigger('uploaded.wfform');
}
$this.$element.trigger('uploading.wfform');
var nbdata2submit = 0;
// submit the data of each fileupload
$(".fileupload").each(function () {
var tid = $(this).attr("id").split("_"),
iid = tid.slice(1, tid.length).join("_");
if ($("#" + iid).data("data2upload")) {
$("#" + iid).data("data2upload").submit();
nbdata2submit += 1;
}
});
if (nbdata2submit > 0) {
if ($this.options.forceIframeTransport) {
// execute _uploadProgressIframe to init the display
_uploadProgressIframe($this, true);
// then loop to follow the file upload
timeriframe = setInterval(function () {
_uploadProgressIframe($this, false)
}, $this.options.timer);
} else {
var upload_file_status = new Array();
$(".fileupload").each(function () {
var tid = $(this).attr("id").split("_"),
iid = tid.slice(1, tid.length).join("_");
upload_file_status.push({
param: iid.split("_").join(" "),
param_id: iid,
loaded: 0,
total: 100
});
});
$("#workflow_form").hide();
$("#progress").html("");
$.tmpl($this.options.progressTemplate, {upload_file_status: upload_file_status}).appendTo($("#progress"));
// loop to follow the file upload
timerclassic = setInterval(function () {
_uploadProgressClassic($this, nbdata2submit)
}, $this.options.timer);
}
} else {
$this.$element.trigger('uploaded.wfform');
}
});
}
}
}
......@@ -813,6 +813,7 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
if ((t_obj.attr("initial_requirement") === undefined || t_obj.attr("initial_requirement") == "FALSE")
&& (!_get_param_keep_required(target))) {
t_obj.rules("remove", "required");
t_obj.valid();
}
}
}
......@@ -839,44 +840,24 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
}
}
/**
* Add required target rule if conditions are raised, else remove it
* @param parameter_object: parameter input jquery object
* @param targets: targets to mark required
* @private
*/
/*var __check_required_targets = function(parameter_object, targets) {
var condition_raised = false;
if (parameter_type == "str") {
condition_raised = conditions.indexOf(parameter_object.val()) > -1;
}
else if (parameter_type == "bool") {
var val = parameter_object.is(":checked").toString();
val = val[0].toUpperCase() + val.slice(1);
condition_raised = conditions.indexOf(val) > -1;
}
if (condition_raised) {
__add_required_target(parameter_object, targets);
}
else {
__remove_required_target(parameter_object, targets);
}
}*/
var __check_condition_raised = function() {
var condition_raised = false;
var all_raised = true;
for (var param in conditions_params) {
var obj_param = $("#" + param);
var value;
if (obj_param.length > 0) {
var value = obj_param.val();
value = obj_param.val();
}
else if (param.indexOf(">") > -1) {
var data = $("#handsontable_" + param.split(">")[0]).handsontable("getData");
var column_name = param.replace("_", "-").replace(">", "___")
value = "";
for (var i in data) {
var line = data[i]
value = line[column_name]
if (line[column_name] != null && line[column_name] != "") {
value = "*"
}
}
}
else if (which == "ALL") {
......@@ -914,12 +895,18 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
var condition_raised = __check_condition_raised();
if (condition_raised) {
param_input.closest("div.form-group").show()
param_input.removeClass("hidden-exclude")
param_input.closest("div.form-group").removeClass("hidden-exclude").show();
param_input.removeClass("hidden-exclude");
}
else {
param_input.closest("div.form-group").hide()
param_input.addClass("hidden-exclude")
param_input.closest("div.form-group").addClass("hidden-exclude").hide();
param_input.addClass("hidden-exclude");
}
if (param_input.closest("fieldset").find(".param-field").not(".hidden-exclude").length == 0) {
param_input.closest("fieldset").hide();
}
else {
param_input.closest("fieldset").show();
}
}
......@@ -927,10 +914,11 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
var condition_raised = __check_condition_raised();
if (condition_raised) {
param_input.rules("add", {"required": true})
param_input.rules("add", {"required": true});
}
else {
param_input.rules("remove", "required")
param_input.rules("remove", "required");
param_input.valid();
}
}
......@@ -964,8 +952,7 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
}
else {
$this.$element.on("change_" + param.replace("_", "-").replace(">", "___"), function(e, value) {
//calling_function();
console.log("coucou", value);
calling_function();
});
}
}
......@@ -977,7 +964,6 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
targets.push(parameter_name);
var targets_elems = "#" + targets.join(", #");
$(targets_elems).on("change", function() {
console.log("change");
var excludes = targets.slice(0);
__exclude_targets($(this), excludes);
});
......@@ -1019,8 +1005,6 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
var which = match[1]
var conditions = match[2].split(",");
var conditions_params = __get_conditions_params();
console.log(parameter_name)
console.log(Object.keys(conditions_params))
var tags = "#" + Object.keys(conditions_params).join(", #");
var param_input = $("#" + parameter_name);
/*$(tags).on("change", function() {
......@@ -1412,8 +1396,6 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
$("#error_handsontable_"+param_name).hide();
},
afterValidate: function(isValid, value, row, prop, source) {
console.log(prop)
$this.$element.trigger("change_" + prop, value);
if (!isValid) {
// do not add this error if it's on the last row
if (this.countRows() == 1 || this.countRows()-1 != row) {
......@@ -1486,7 +1468,7 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
, rowColumnSeen = {}
, rowsToFill = {}
, value;
for (i = 0; i < ilen; i++) {
if (changes[i][2] === null && changes[i][3] !== null) { //if oldVal is empty
if (isEmptyRow(instance, changes[i][0])) {
......@@ -1495,7 +1477,7 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
}
}
}
for (var r in rowsToFill) {
for (var r in rowsToFill) {
if (rowsToFill.hasOwnProperty(r)) {
for (c = 0; c < clen; c++) {
if (!rowColumnSeen[r + '/' + instance.colToProp(c)]) { //if it is not provided by user in this change set, take value from template
......@@ -1511,7 +1493,19 @@ Handsontable.cellTypes["bootdate"] = Handsontable.BootstrapDateCell;
}
}
}
},
afterChange: function(changes) {
if (changes) {
var triggered = [];
for (var i = 0; i < changes.length; i++) {
var prop = changes[i][1];
if (triggered.indexOf(prop) == -1) {
$this.$element.trigger("change_" + prop);
triggered.push(prop);
}
}
}
}
});
});
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment